Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenfont/intern/blf_lang.c10
-rw-r--r--source/blender/blenkernel/BKE_DerivedMesh.h15
-rw-r--r--source/blender/blenkernel/BKE_blender.h12
-rw-r--r--source/blender/blenkernel/BKE_brush.h6
-rw-r--r--source/blender/blenkernel/BKE_editmesh_bvh.h13
-rw-r--r--source/blender/blenkernel/BKE_idprop.h24
-rw-r--r--source/blender/blenkernel/BKE_library.h3
-rw-r--r--source/blender/blenkernel/BKE_main.h2
-rw-r--r--source/blender/blenkernel/BKE_material.h4
-rw-r--r--source/blender/blenkernel/BKE_node.h4
-rw-r--r--source/blender/blenkernel/BKE_paint.h24
-rw-r--r--source/blender/blenkernel/BKE_scene.h1
-rw-r--r--source/blender/blenkernel/BKE_shrinkwrap.h51
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c54
-rw-r--r--source/blender/blenkernel/intern/action.c6
-rw-r--r--source/blender/blenkernel/intern/anim_sys.c17
-rw-r--r--source/blender/blenkernel/intern/armature.c9
-rw-r--r--source/blender/blenkernel/intern/blender.c12
-rw-r--r--source/blender/blenkernel/intern/bpath.c12
-rw-r--r--source/blender/blenkernel/intern/brush.c56
-rw-r--r--source/blender/blenkernel/intern/cdderivedmesh.c54
-rw-r--r--source/blender/blenkernel/intern/constraint.c28
-rw-r--r--source/blender/blenkernel/intern/deform.c2
-rw-r--r--source/blender/blenkernel/intern/depsgraph.c55
-rw-r--r--source/blender/blenkernel/intern/displist.c14
-rw-r--r--source/blender/blenkernel/intern/editderivedmesh.c4
-rw-r--r--source/blender/blenkernel/intern/editmesh_bvh.c86
-rw-r--r--source/blender/blenkernel/intern/effect.c2
-rw-r--r--source/blender/blenkernel/intern/fcurve.c31
-rw-r--r--source/blender/blenkernel/intern/gpencil.c2
-rw-r--r--source/blender/blenkernel/intern/idcode.c2
-rw-r--r--source/blender/blenkernel/intern/idprop.c2
-rw-r--r--source/blender/blenkernel/intern/image.c4
-rw-r--r--source/blender/blenkernel/intern/ipo.c8
-rw-r--r--source/blender/blenkernel/intern/library.c30
-rw-r--r--source/blender/blenkernel/intern/mask.c2
-rw-r--r--source/blender/blenkernel/intern/material.c121
-rw-r--r--source/blender/blenkernel/intern/mball.c26
-rw-r--r--source/blender/blenkernel/intern/mesh.c22
-rw-r--r--source/blender/blenkernel/intern/mesh_evaluate.c2
-rw-r--r--source/blender/blenkernel/intern/mesh_mapping.c2
-rw-r--r--source/blender/blenkernel/intern/mesh_validate.c18
-rw-r--r--source/blender/blenkernel/intern/nla.c8
-rw-r--r--source/blender/blenkernel/intern/node.c1
-rw-r--r--source/blender/blenkernel/intern/object.c29
-rw-r--r--source/blender/blenkernel/intern/object_dupli.c4
-rw-r--r--source/blender/blenkernel/intern/paint.c105
-rw-r--r--source/blender/blenkernel/intern/particle.c7
-rw-r--r--source/blender/blenkernel/intern/particle_system.c10
-rw-r--r--source/blender/blenkernel/intern/pbvh.c15
-rw-r--r--source/blender/blenkernel/intern/report.c2
-rw-r--r--source/blender/blenkernel/intern/rigidbody.c6
-rw-r--r--source/blender/blenkernel/intern/scene.c101
-rw-r--r--source/blender/blenkernel/intern/seqeffects.c303
-rw-r--r--source/blender/blenkernel/intern/sequencer.c57
-rw-r--r--source/blender/blenkernel/intern/shrinkwrap.c80
-rw-r--r--source/blender/blenkernel/intern/subsurf_ccg.c50
-rw-r--r--source/blender/blenkernel/intern/text.c4
-rw-r--r--source/blender/blenkernel/intern/texture.c9
-rw-r--r--source/blender/blenkernel/intern/tracking_stabilize.c4
-rw-r--r--source/blender/blenkernel/intern/writeavi.c2
-rw-r--r--source/blender/blenkernel/intern/writeffmpeg.c7
-rw-r--r--source/blender/blenlib/BLI_fileops.h2
-rw-r--r--source/blender/blenlib/BLI_fileops_types.h2
-rw-r--r--source/blender/blenlib/BLI_ghash.h3
-rw-r--r--source/blender/blenlib/BLI_gsqueue.h3
-rw-r--r--source/blender/blenlib/BLI_listbase.h16
-rw-r--r--source/blender/blenlib/BLI_math_base.h13
-rw-r--r--source/blender/blenlib/BLI_math_color_blend.h36
-rw-r--r--source/blender/blenlib/BLI_math_geom.h2
-rw-r--r--source/blender/blenlib/BLI_math_matrix.h51
-rw-r--r--source/blender/blenlib/BLI_math_vector.h2
-rw-r--r--source/blender/blenlib/BLI_path_util.h4
-rw-r--r--source/blender/blenlib/BLI_stackdefines.h11
-rw-r--r--source/blender/blenlib/BLI_sys_types.h124
-rw-r--r--source/blender/blenlib/BLI_utildefines.h108
-rw-r--r--source/blender/blenlib/intern/BLI_ghash.c9
-rw-r--r--source/blender/blenlib/intern/BLI_kdopbvh.c16
-rw-r--r--source/blender/blenlib/intern/BLI_linklist.c15
-rw-r--r--source/blender/blenlib/intern/edgehash.c4
-rw-r--r--source/blender/blenlib/intern/gsqueue.c6
-rw-r--r--source/blender/blenlib/intern/listbase.c10
-rw-r--r--source/blender/blenlib/intern/math_color.c214
-rw-r--r--source/blender/blenlib/intern/math_color_blend_inline.c860
-rw-r--r--source/blender/blenlib/intern/math_color_inline.c16
-rw-r--r--source/blender/blenlib/intern/math_geom.c263
-rw-r--r--source/blender/blenlib/intern/math_matrix.c351
-rw-r--r--source/blender/blenlib/intern/math_rotation.c18
-rw-r--r--source/blender/blenlib/intern/math_vector.c21
-rw-r--r--source/blender/blenlib/intern/math_vector_inline.c8
-rw-r--r--source/blender/blenlib/intern/path_util.c41
-rw-r--r--source/blender/blenlib/intern/polyfill2d.c2
-rw-r--r--source/blender/blenlib/intern/rand.c16
-rw-r--r--source/blender/blenlib/intern/scanfill.c3
-rw-r--r--source/blender/blenlib/intern/storage.c2
-rw-r--r--source/blender/blenlib/intern/string.c4
-rw-r--r--source/blender/blenloader/BLO_readfile.h3
-rw-r--r--source/blender/blenloader/intern/readfile.c68
-rw-r--r--source/blender/blenloader/intern/versioning_260.c6
-rw-r--r--source/blender/blenloader/intern/versioning_270.c16
-rw-r--r--source/blender/blenloader/intern/versioning_defaults.c60
-rw-r--r--source/blender/blenloader/intern/versioning_legacy.c4
-rw-r--r--source/blender/blenloader/intern/writefile.c39
-rw-r--r--source/blender/bmesh/bmesh_class.h8
-rw-r--r--source/blender/bmesh/intern/bmesh_core.c3
-rw-r--r--source/blender/bmesh/intern/bmesh_edgeloop.c4
-rw-r--r--source/blender/bmesh/intern/bmesh_iterators_inline.h10
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh.c37
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh.h6
-rw-r--r--source/blender/bmesh/intern/bmesh_opdefines.c1
-rw-r--r--source/blender/bmesh/intern/bmesh_walkers.c2
-rw-r--r--source/blender/bmesh/operators/bmo_bridge.c4
-rw-r--r--source/blender/bmesh/operators/bmo_connect_pair.c2
-rw-r--r--source/blender/bmesh/operators/bmo_dissolve.c29
-rw-r--r--source/blender/bmesh/operators/bmo_subdivide_edgering.c4
-rw-r--r--source/blender/bmesh/operators/bmo_utils.c2
-rw-r--r--source/blender/bmesh/tools/bmesh_beautify.c13
-rw-r--r--source/blender/bmesh/tools/bmesh_bevel.c6
-rw-r--r--source/blender/bmesh/tools/bmesh_decimate_collapse.c8
-rw-r--r--source/blender/bmesh/tools/bmesh_edgenet.c5
-rw-r--r--source/blender/collada/AnimationImporter.cpp6
-rw-r--r--source/blender/collada/DocumentImporter.cpp10
-rw-r--r--source/blender/collada/TransformWriter.cpp2
-rw-r--r--source/blender/compositor/CMakeLists.txt9
-rw-r--r--source/blender/compositor/COM_compositor.h2
-rw-r--r--source/blender/compositor/SConscript4
-rw-r--r--source/blender/compositor/intern/COM_Converter.cpp4
-rw-r--r--source/blender/compositor/intern/COM_NodeOperation.h2
-rw-r--r--source/blender/compositor/intern/COM_OpenCLDevice.cpp8
-rw-r--r--source/blender/compositor/intern/COM_OpenCLDevice.h2
-rw-r--r--source/blender/compositor/intern/COM_WorkScheduler.cpp6
-rw-r--r--source/blender/compositor/intern/COM_compositor.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_SunBeamsNode.cpp42
-rw-r--r--source/blender/compositor/nodes/COM_SunBeamsNode.h37
-rw-r--r--source/blender/compositor/operations/COM_DirectionalBlurOperation.cpp4
-rw-r--r--source/blender/compositor/operations/COM_MathBaseOperation.cpp9
-rw-r--r--source/blender/compositor/operations/COM_MathBaseOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_SunBeamsOperation.cpp303
-rw-r--r--source/blender/compositor/operations/COM_SunBeamsOperation.h48
-rw-r--r--source/blender/editors/animation/anim_channels_defines.c2
-rw-r--r--source/blender/editors/animation/anim_channels_edit.c14
-rw-r--r--source/blender/editors/animation/anim_deps.c2
-rw-r--r--source/blender/editors/animation/anim_ipo_utils.c2
-rw-r--r--source/blender/editors/animation/anim_markers.c6
-rw-r--r--source/blender/editors/animation/anim_ops.c2
-rw-r--r--source/blender/editors/animation/keyframes_edit.c8
-rw-r--r--source/blender/editors/animation/keyframing.c4
-rw-r--r--source/blender/editors/armature/CMakeLists.txt1
-rw-r--r--source/blender/editors/armature/SConscript1
-rw-r--r--source/blender/editors/armature/armature_edit.c4
-rw-r--r--source/blender/editors/armature/armature_select.c6
-rw-r--r--source/blender/editors/armature/armature_skinning.c16
-rw-r--r--source/blender/editors/armature/editarmature_sketch.c8
-rw-r--r--source/blender/editors/armature/meshlaplacian.c9
-rw-r--r--source/blender/editors/armature/pose_edit.c4
-rw-r--r--source/blender/editors/armature/pose_lib.c4
-rw-r--r--source/blender/editors/armature/pose_select.c88
-rw-r--r--source/blender/editors/armature/pose_slide.c2
-rw-r--r--source/blender/editors/curve/editcurve.c2
-rw-r--r--source/blender/editors/datafiles/CMakeLists.txt2
-rw-r--r--source/blender/editors/datafiles/SConscript2
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_paint.c6
-rw-r--r--source/blender/editors/include/BIF_gl.h20
-rw-r--r--source/blender/editors/include/ED_armature.h2
-rw-r--r--source/blender/editors/include/ED_datafiles.h6
-rw-r--r--source/blender/editors/include/ED_image.h3
-rw-r--r--source/blender/editors/include/ED_paint.h6
-rw-r--r--source/blender/editors/include/ED_transform.h1
-rw-r--r--source/blender/editors/include/ED_uvedit.h2
-rw-r--r--source/blender/editors/include/ED_view3d.h6
-rw-r--r--source/blender/editors/include/UI_icons.h2
-rw-r--r--source/blender/editors/include/UI_interface.h17
-rw-r--r--source/blender/editors/include/UI_resources.h3
-rw-r--r--source/blender/editors/interface/interface.c32
-rw-r--r--source/blender/editors/interface/interface_draw.c10
-rw-r--r--source/blender/editors/interface/interface_handlers.c308
-rw-r--r--source/blender/editors/interface/interface_icons.c2
-rw-r--r--source/blender/editors/interface/interface_intern.h7
-rw-r--r--source/blender/editors/interface/interface_layout.c8
-rw-r--r--source/blender/editors/interface/interface_ops.c197
-rw-r--r--source/blender/editors/interface/interface_panel.c62
-rw-r--r--source/blender/editors/interface/interface_regions.c25
-rw-r--r--source/blender/editors/interface/interface_templates.c73
-rw-r--r--source/blender/editors/interface/interface_utils.c2
-rw-r--r--source/blender/editors/interface/interface_widgets.c14
-rw-r--r--source/blender/editors/interface/resources.c49
-rw-r--r--source/blender/editors/io/io_collada.c2
-rw-r--r--source/blender/editors/mesh/editmesh_knife_project.c2
-rw-r--r--source/blender/editors/mesh/editmesh_select.c46
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c18
-rw-r--r--source/blender/editors/metaball/mball_edit.c2
-rw-r--r--source/blender/editors/object/object_add.c4
-rw-r--r--source/blender/editors/object/object_bake.c2
-rw-r--r--source/blender/editors/object/object_bake_api.c52
-rw-r--r--source/blender/editors/object/object_constraint.c2
-rw-r--r--source/blender/editors/object/object_edit.c23
-rw-r--r--source/blender/editors/object/object_group.c64
-rw-r--r--source/blender/editors/object/object_hook.c3
-rw-r--r--source/blender/editors/object/object_intern.h2
-rw-r--r--source/blender/editors/object/object_modifier.c4
-rw-r--r--source/blender/editors/object/object_ops.c2
-rw-r--r--source/blender/editors/object/object_relations.c14
-rw-r--r--source/blender/editors/object/object_shapekey.c21
-rw-r--r--source/blender/editors/object/object_transform.c4
-rw-r--r--source/blender/editors/render/render_update.c10
-rw-r--r--source/blender/editors/screen/area.c4
-rw-r--r--source/blender/editors/screen/screen_edit.c2
-rw-r--r--source/blender/editors/screen/screen_ops.c15
-rw-r--r--source/blender/editors/sculpt_paint/CMakeLists.txt1
-rw-r--r--source/blender/editors/sculpt_paint/paint_cursor.c164
-rw-r--r--source/blender/editors/sculpt_paint/paint_curve.c801
-rw-r--r--source/blender/editors/sculpt_paint/paint_image.c681
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_2d.c872
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_proj.c1005
-rw-r--r--source/blender/editors/sculpt_paint/paint_intern.h63
-rw-r--r--source/blender/editors/sculpt_paint/paint_mask.c6
-rw-r--r--source/blender/editors/sculpt_paint/paint_ops.c176
-rw-r--r--source/blender/editors/sculpt_paint/paint_stroke.c486
-rw-r--r--source/blender/editors/sculpt_paint/paint_undo.c54
-rw-r--r--source/blender/editors/sculpt_paint/paint_utils.c296
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex.c28
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c225
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_intern.h7
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_undo.c12
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_uv.c10
-rw-r--r--source/blender/editors/space_action/action_draw.c2
-rw-r--r--source/blender/editors/space_action/action_select.c15
-rw-r--r--source/blender/editors/space_api/spacetypes.c1
-rw-r--r--source/blender/editors/space_buttons/buttons_context.c8
-rw-r--r--source/blender/editors/space_buttons/space_buttons.c2
-rw-r--r--source/blender/editors/space_clip/clip_draw.c2
-rw-r--r--source/blender/editors/space_clip/space_clip.c2
-rw-r--r--source/blender/editors/space_clip/tracking_ops.c4
-rw-r--r--source/blender/editors/space_file/space_file.c2
-rw-r--r--source/blender/editors/space_graph/graph_edit.c4
-rw-r--r--source/blender/editors/space_image/image_buttons.c16
-rw-r--r--source/blender/editors/space_image/image_edit.c39
-rw-r--r--source/blender/editors/space_image/image_ops.c18
-rw-r--r--source/blender/editors/space_image/space_image.c17
-rw-r--r--source/blender/editors/space_logic/logic_window.c2
-rw-r--r--source/blender/editors/space_node/drawnode.c9
-rw-r--r--source/blender/editors/space_node/node_edit.c4
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c2
-rw-r--r--source/blender/editors/space_outliner/outliner_edit.c10
-rw-r--r--source/blender/editors/space_outliner/outliner_select.c2
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.c2
-rw-r--r--source/blender/editors/space_outliner/outliner_tree.c10
-rw-r--r--source/blender/editors/space_outliner/space_outliner.c4
-rw-r--r--source/blender/editors/space_sequencer/sequencer_draw.c22
-rw-r--r--source/blender/editors/space_sequencer/sequencer_edit.c8
-rw-r--r--source/blender/editors/space_sequencer/sequencer_select.c4
-rw-r--r--source/blender/editors/space_sequencer/space_sequencer.c157
-rw-r--r--source/blender/editors/space_text/text_draw.c2
-rw-r--r--source/blender/editors/space_view3d/drawarmature.c61
-rw-r--r--source/blender/editors/space_view3d/drawmesh.c108
-rw-r--r--source/blender/editors/space_view3d/drawobject.c25
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c34
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c10
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c23
-rw-r--r--source/blender/editors/space_view3d/view3d_header.c7
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c61
-rw-r--r--source/blender/editors/space_view3d/view3d_view.c178
-rw-r--r--source/blender/editors/transform/CMakeLists.txt1
-rw-r--r--source/blender/editors/transform/SConscript1
-rw-r--r--source/blender/editors/transform/transform.c112
-rw-r--r--source/blender/editors/transform/transform.h11
-rw-r--r--source/blender/editors/transform/transform_constraints.c5
-rw-r--r--source/blender/editors/transform/transform_conversions.c220
-rw-r--r--source/blender/editors/transform/transform_generics.c54
-rw-r--r--source/blender/editors/transform/transform_manipulator.c96
-rw-r--r--source/blender/editors/transform/transform_orientations.c2
-rw-r--r--source/blender/editors/transform/transform_snap.c80
-rw-r--r--source/blender/editors/util/ed_transverts.c2
-rw-r--r--source/blender/editors/util/ed_util.c2
-rw-r--r--source/blender/editors/util/numinput.c10
-rw-r--r--source/blender/editors/uvedit/uvedit_draw.c53
-rw-r--r--source/blender/editors/uvedit/uvedit_ops.c10
-rw-r--r--source/blender/editors/uvedit/uvedit_unwrap_ops.c4
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp6
-rw-r--r--source/blender/freestyle/intern/geometry/Grid.h2
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp15
-rw-r--r--source/blender/freestyle/intern/stroke/StrokeRep.h2
-rw-r--r--source/blender/gpu/CMakeLists.txt2
-rw-r--r--source/blender/gpu/GPU_buffers.h1
-rw-r--r--source/blender/gpu/GPU_draw.h2
-rw-r--r--source/blender/gpu/GPU_select.h61
-rw-r--r--source/blender/gpu/intern/gpu_buffers.c128
-rw-r--r--source/blender/gpu/intern/gpu_codegen.c4
-rw-r--r--source/blender/gpu/intern/gpu_draw.c8
-rw-r--r--source/blender/gpu/intern/gpu_select.c246
-rw-r--r--source/blender/gpu/shaders/gpu_shader_material.glsl5
-rw-r--r--source/blender/ikplugin/intern/iksolver_plugin.c4
-rw-r--r--source/blender/ikplugin/intern/itasc_plugin.cpp2
-rw-r--r--source/blender/imbuf/IMB_imbuf.h20
-rw-r--r--source/blender/imbuf/intern/cineon/cineonlib.c4
-rw-r--r--source/blender/imbuf/intern/cineon/dpxlib.c4
-rw-r--r--source/blender/imbuf/intern/openexr/openexr_api.cpp8
-rw-r--r--source/blender/imbuf/intern/rectop.c270
-rw-r--r--source/blender/imbuf/intern/scaling.c2
-rw-r--r--source/blender/imbuf/intern/util.c4
-rw-r--r--source/blender/makesdna/DNA_ID.h12
-rw-r--r--source/blender/makesdna/DNA_brush_types.h94
-rw-r--r--source/blender/makesdna/DNA_constraint_types.h3
-rw-r--r--source/blender/makesdna/DNA_material_types.h15
-rw-r--r--source/blender/makesdna/DNA_node_types.h6
-rw-r--r--source/blender/makesdna/DNA_object_types.h6
-rw-r--r--source/blender/makesdna/DNA_scene_types.h32
-rw-r--r--source/blender/makesdna/DNA_screen_types.h12
-rw-r--r--source/blender/makesdna/DNA_sequence_types.h10
-rw-r--r--source/blender/makesdna/DNA_space_types.h2
-rw-r--r--source/blender/makesdna/DNA_texture_types.h2
-rw-r--r--source/blender/makesdna/DNA_userdef_types.h14
-rw-r--r--source/blender/makesdna/DNA_vfont_types.h2
-rw-r--r--source/blender/makesrna/RNA_access.h16
-rw-r--r--source/blender/makesrna/intern/makesrna.c37
-rw-r--r--source/blender/makesrna/intern/rna_ID.c9
-rw-r--r--source/blender/makesrna/intern/rna_access.c118
-rw-r--r--source/blender/makesrna/intern/rna_actuator.c2
-rw-r--r--source/blender/makesrna/intern/rna_brush.c400
-rw-r--r--source/blender/makesrna/intern/rna_color.c6
-rw-r--r--source/blender/makesrna/intern/rna_constraint.c8
-rw-r--r--source/blender/makesrna/intern/rna_internal.h21
-rw-r--r--source/blender/makesrna/intern/rna_linestyle.c2
-rw-r--r--source/blender/makesrna/intern/rna_material.c101
-rw-r--r--source/blender/makesrna/intern/rna_mesh.c2
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c21
-rw-r--r--source/blender/makesrna/intern/rna_object_force.c8
-rw-r--r--source/blender/makesrna/intern/rna_particle.c236
-rw-r--r--source/blender/makesrna/intern/rna_scene.c23
-rw-r--r--source/blender/makesrna/intern/rna_sculpt_paint.c83
-rw-r--r--source/blender/makesrna/intern/rna_sequencer.c22
-rw-r--r--source/blender/makesrna/intern/rna_sequencer_api.c1
-rw-r--r--source/blender/makesrna/intern/rna_space.c71
-rw-r--r--source/blender/makesrna/intern/rna_tracking.c1
-rw-r--r--source/blender/makesrna/intern/rna_ui_api.c5
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c114
-rw-r--r--source/blender/modifiers/intern/MOD_array.c5
-rw-r--r--source/blender/modifiers/intern/MOD_hook.c3
-rw-r--r--source/blender/modifiers/intern/MOD_mask.c2
-rw-r--r--source/blender/modifiers/intern/MOD_meshcache_mdd.c4
-rw-r--r--source/blender/modifiers/intern/MOD_meshcache_pc2.c3
-rw-r--r--source/blender/modifiers/intern/MOD_shrinkwrap.c1
-rw-r--r--source/blender/modifiers/intern/MOD_simpledeform.c11
-rw-r--r--source/blender/modifiers/intern/MOD_util.c2
-rw-r--r--source/blender/modifiers/intern/MOD_weightvg_util.c6
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgproximity.c19
-rw-r--r--source/blender/nodes/CMakeLists.txt1
-rw-r--r--source/blender/nodes/NOD_composite.h2
-rw-r--r--source/blender/nodes/NOD_static_types.h1
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_sunbeams.c63
-rw-r--r--source/blender/nodes/intern/node_common.c34
-rw-r--r--source/blender/nodes/intern/node_exec.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_glass.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_uvmap.c9
-rw-r--r--source/blender/python/bmesh/bmesh_py_utils.c4
-rw-r--r--source/blender/python/generic/bgl.c2
-rw-r--r--source/blender/python/intern/bpy_rna.c6
-rw-r--r--source/blender/python/mathutils/mathutils_Euler.c23
-rw-r--r--source/blender/python/mathutils/mathutils_Vector.c9
-rw-r--r--source/blender/python/mathutils/mathutils_geometry.c70
-rw-r--r--source/blender/render/extern/include/RE_bake.h18
-rw-r--r--source/blender/render/intern/source/bake.c4
-rw-r--r--source/blender/render/intern/source/bake_api.c42
-rw-r--r--source/blender/render/intern/source/convertblender.c15
-rw-r--r--source/blender/render/intern/source/external_engine.c2
-rw-r--r--source/blender/render/intern/source/pipeline.c16
-rw-r--r--source/blender/render/intern/source/render_texture.c4
-rw-r--r--source/blender/render/intern/source/shadbuf.c2
-rw-r--r--source/blender/render/intern/source/volumetric.c2
-rw-r--r--source/blender/windowmanager/WM_api.h4
-rw-r--r--source/blender/windowmanager/WM_types.h7
-rw-r--r--source/blender/windowmanager/intern/wm.c3
-rw-r--r--source/blender/windowmanager/intern/wm_dragdrop.c19
-rw-r--r--source/blender/windowmanager/intern/wm_draw.c6
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c31
-rw-r--r--source/blender/windowmanager/intern/wm_files.c6
-rw-r--r--source/blender/windowmanager/intern/wm_gesture.c2
-rw-r--r--source/blender/windowmanager/intern/wm_keymap.c4
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c35
-rw-r--r--source/blender/windowmanager/intern/wm_subwindow.c2
-rw-r--r--source/blender/windowmanager/intern/wm_window.c4
-rw-r--r--source/blender/windowmanager/wm_event_types.h2
-rw-r--r--source/blenderplayer/CMakeLists.txt6
-rw-r--r--source/blenderplayer/bad_level_call_stubs/stubs.c3
-rw-r--r--source/creator/CMakeLists.txt78
-rw-r--r--source/creator/creator_launch_win.c69
-rw-r--r--source/creator/osx_locals.map2
-rw-r--r--source/gameengine/Converter/BL_ArmatureObject.cpp4
-rw-r--r--source/gameengine/Converter/BL_BlenderDataConversion.cpp2
-rw-r--r--source/gameengine/Ketsji/KX_BlenderMaterial.cpp2
-rw-r--r--source/gameengine/Ketsji/KX_GameObject.cpp4
-rw-r--r--source/gameengine/Ketsji/KX_Light.cpp2
-rw-r--r--source/gameengine/Ketsji/KX_MouseFocusSensor.cpp4
-rw-r--r--source/gameengine/Ketsji/KX_MouseFocusSensor.h2
-rw-r--r--source/gameengine/Ketsji/KX_NavMeshObject.cpp2
-rw-r--r--source/gameengine/Ketsji/KX_PyConstraintBinding.cpp1
-rw-r--r--source/gameengine/Ketsji/KX_PythonInit.cpp13
-rw-r--r--source/gameengine/Ketsji/KX_SteeringActuator.cpp2
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp2
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageIM.cpp2
-rw-r--r--source/gameengine/VideoTexture/ImageBuff.cpp4
402 files changed, 12000 insertions, 3570 deletions
diff --git a/source/blender/blenfont/intern/blf_lang.c b/source/blender/blenfont/intern/blf_lang.c
index 2852b8161c8..12d71827136 100644
--- a/source/blender/blenfont/intern/blf_lang.c
+++ b/source/blender/blenfont/intern/blf_lang.c
@@ -235,15 +235,11 @@ void BLF_lang_set(const char *str)
else {
short_locale_utf8 = BLI_sprintfN("%s.UTF-8", short_locale);
}
+ bl_locale_set(short_locale_utf8);
+ MEM_freeN((void *)short_locale_utf8);
}
else {
- short_locale_utf8 = short_locale;
- }
-
- bl_locale_set(short_locale_utf8);
-
- if (short_locale[0]) {
- MEM_freeN((void *)short_locale_utf8);
+ bl_locale_set(short_locale);
}
#else
(void)str;
diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h
index 1ab5ec51de8..c8fa3a4e202 100644
--- a/source/blender/blenkernel/BKE_DerivedMesh.h
+++ b/source/blender/blenkernel/BKE_DerivedMesh.h
@@ -150,8 +150,10 @@ typedef DMDrawOption (*DMSetDrawOptions)(void *userData, int index);
typedef DMDrawOption (*DMSetDrawOptionsTex)(struct MTFace *tface, const bool has_vcol, int matnr);
typedef enum DMDrawFlag {
- DM_DRAW_USE_COLORS = 1,
- DM_DRAW_ALWAYS_SMOOTH = 2
+ DM_DRAW_USE_COLORS = (1 << 0),
+ DM_DRAW_ALWAYS_SMOOTH = (1 << 1),
+ DM_DRAW_USE_ACTIVE_UV = (1 << 2),
+ DM_DRAW_USE_TEXPAINT_UV = (1 << 3),
} DMDrawFlag;
typedef enum DMForeachFlag {
@@ -389,7 +391,7 @@ struct DerivedMesh {
void (*drawFacesTex)(DerivedMesh *dm,
DMSetDrawOptionsTex setDrawOptions,
DMCompareDrawOptions compareDrawOptions,
- void *userData);
+ void *userData, DMDrawFlag uvflag);
/** Draw all faces with GLSL materials
* o setMaterial is called for every different material nr
@@ -423,7 +425,7 @@ struct DerivedMesh {
void (*drawMappedFacesTex)(DerivedMesh *dm,
DMSetDrawOptions setDrawOptions,
DMCompareDrawOptions compareDrawOptions,
- void *userData);
+ void *userData, DMDrawFlag uvflag);
/** Draw mapped faces with GLSL materials
* - setMaterial is called for every different material nr
@@ -593,6 +595,8 @@ void DM_ensure_tessface(DerivedMesh *dm);
void DM_update_tessface_data(DerivedMesh *dm);
void DM_update_materials(DerivedMesh *dm, struct Object *ob);
+struct MTFace *DM_paint_uvlayer_active_get(DerivedMesh *dm, int mat_nr);
+
/** interpolates vertex data from the vertices indexed by src_indices in the
* source mesh using the given weights and stores the result in the vertex
* indexed by dest_index in the dest mesh
@@ -687,6 +691,9 @@ DerivedMesh *editbmesh_get_derived_cage(struct Scene *scene, struct Object *,
DerivedMesh *editbmesh_get_derived_cage_and_final(struct Scene *scene, struct Object *,
struct BMEditMesh *em, DerivedMesh **r_final,
CustomDataMask dataMask);
+
+DerivedMesh *object_get_derived_final(struct Object *ob, const bool for_render);
+
float (*editbmesh_get_vertex_cos(struct BMEditMesh *em, int *r_numVerts))[3];
bool editbmesh_modifier_is_enabled(struct Scene *scene, struct ModifierData *md, DerivedMesh *dm);
void makeDerivedMesh(struct Scene *scene, struct Object *ob, struct BMEditMesh *em,
diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h
index 19fa60f5827..50639ba7ed7 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 271
-#define BLENDER_SUBVERSION 2
+#define BLENDER_SUBVERSION 3
/* 262 was the last editmesh release but it has compatibility code for bmesh data */
#define BLENDER_MINVERSION 270
#define BLENDER_MINSUBVERSION 5
@@ -69,10 +69,12 @@ int BKE_read_file(struct bContext *C, const char *filepath, struct ReportList *r
#define BKE_READ_FILE_OK 1 /* OK */
#define BKE_READ_FILE_OK_USERPREFS 2 /* OK, and with new user settings */
-int BKE_read_file_from_memory(struct bContext *C, const void *filebuf,
- int filelength, struct ReportList *reports, int update_defaults);
-int BKE_read_file_from_memfile(struct bContext *C, struct MemFile *memfile,
- struct ReportList *reports);
+bool BKE_read_file_from_memory(
+ struct bContext *C, const void *filebuf,
+ int filelength, struct ReportList *reports, bool update_defaults);
+bool BKE_read_file_from_memfile(
+ struct bContext *C, struct MemFile *memfile,
+ struct ReportList *reports);
int BKE_read_file_userdef(const char *filepath, struct ReportList *reports);
int BKE_write_file_userdef(const char *filepath, struct ReportList *reports);
diff --git a/source/blender/blenkernel/BKE_brush.h b/source/blender/blenkernel/BKE_brush.h
index 104e80e815c..d48753590bb 100644
--- a/source/blender/blenkernel/BKE_brush.h
+++ b/source/blender/blenkernel/BKE_brush.h
@@ -81,7 +81,11 @@ unsigned int *BKE_brush_gen_texture_cache(struct Brush *br, int half_side, bool
/* radial control */
struct ImBuf *BKE_brush_gen_radial_control_imbuf(struct Brush *br, bool secondary);
-/* unified strength and size */
+/* unified strength size and color */
+
+float *BKE_brush_color_get(const struct Scene *scene, struct Brush *brush);
+float *BKE_brush_secondary_color_get(const struct Scene *scene, struct Brush *brush);
+void BKE_brush_color_set(struct Scene *scene, struct Brush *brush, const float color[3]);
int BKE_brush_size_get(const struct Scene *scene, struct Brush *brush);
void BKE_brush_size_set(struct Scene *scene, struct Brush *brush, int value);
diff --git a/source/blender/blenkernel/BKE_editmesh_bvh.h b/source/blender/blenkernel/BKE_editmesh_bvh.h
index 355e817f621..168f700d132 100644
--- a/source/blender/blenkernel/BKE_editmesh_bvh.h
+++ b/source/blender/blenkernel/BKE_editmesh_bvh.h
@@ -43,9 +43,16 @@ struct Scene;
typedef struct BMBVHTree BMBVHTree;
-BMBVHTree *BKE_bmbvh_new_from_editmesh(struct BMEditMesh *em, int flag, const float (*cos_cage)[3], const bool cos_cage_free);
-BMBVHTree *BKE_bmbvh_new(struct BMesh *bm, struct BMLoop *(*looptris)[3], int looptris_tot, int flag,
- const float (*cos_cage)[3], const bool cos_cage_free);
+BMBVHTree *BKE_bmbvh_new_from_editmesh(
+ struct BMEditMesh *em, int flag,
+ const float (*cos_cage)[3], const bool cos_cage_free);
+BMBVHTree *BKE_bmbvh_new_ex(
+ struct BMesh *bm, struct BMLoop *(*looptris)[3], int looptris_tot, int flag,
+ const float (*cos_cage)[3], const bool cos_cage_free,
+ bool (*test_fn)(struct BMFace *, void *user_data), void *user_data);
+BMBVHTree *BKE_bmbvh_new(
+ struct BMesh *bm, struct BMLoop *(*looptris)[3], int looptris_tot, int flag,
+ const float (*cos_cage)[3], const bool cos_cage_free);
void BKE_bmbvh_free(BMBVHTree *tree);
struct BVHTree *BKE_bmbvh_tree_get(BMBVHTree *tree);
struct BMFace *BKE_bmbvh_ray_cast(BMBVHTree *tree, const float co[3], const float dir[3], const float radius,
diff --git a/source/blender/blenkernel/BKE_idprop.h b/source/blender/blenkernel/BKE_idprop.h
index 3cf944fa236..0230eaf92bc 100644
--- a/source/blender/blenkernel/BKE_idprop.h
+++ b/source/blender/blenkernel/BKE_idprop.h
@@ -121,11 +121,27 @@ void IDP_ClearProperty(IDProperty *prop);
void IDP_UnlinkProperty(struct IDProperty *prop);
#define IDP_Int(prop) ((prop)->data.val)
-#define IDP_Float(prop) (*(float *)&(prop)->data.val)
-#define IDP_Double(prop) (*(double *)&(prop)->data.val)
-#define IDP_String(prop) ((char *) (prop)->data.pointer)
#define IDP_Array(prop) ((prop)->data.pointer)
-#define IDP_IDPArray(prop) ((IDProperty *) (prop)->data.pointer)
+/* C11 const correctness for casts */
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
+# define IDP_Float(prop) _Generic((prop), \
+ IDProperty *: (*(float *)&(prop)->data.val), \
+ const IDProperty *: (*(const float *)&(prop)->data.val))
+# define IDP_Double(prop) _Generic((prop), \
+ IDProperty *: (*(double *)&(prop)->data.val), \
+ const IDProperty *: (*(const double *)&(prop)->data.val))
+# define IDP_String(prop) _Generic((prop), \
+ IDProperty *: ((char *) (prop)->data.pointer), \
+ const IDProperty *: ((const char *) (prop)->data.pointer))
+# define IDP_IDPArray(prop) _Generic((prop), \
+ IDProperty *: ((IDProperty *) (prop)->data.pointer), \
+ const IDProperty *: ((const IDProperty *) (prop)->data.pointer))
+#else
+# define IDP_Float(prop) (*(float *)&(prop)->data.val)
+# define IDP_Double(prop) (*(double *)&(prop)->data.val)
+# define IDP_String(prop) ((char *) (prop)->data.pointer)
+# define IDP_IDPArray(prop) ((IDProperty *) (prop)->data.pointer)
+#endif
#ifdef DEBUG
/* for printout only */
diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h
index 0372931dc49..1d37f9e64e1 100644
--- a/source/blender/blenkernel/BKE_library.h
+++ b/source/blender/blenkernel/BKE_library.h
@@ -71,7 +71,7 @@ void id_clear_lib_data(struct Main *bmain, struct ID *id);
struct ListBase *which_libbase(struct Main *mainlib, short type);
-#define MAX_LIBARRAY 41
+#define MAX_LIBARRAY 43
int set_listbasepointers(struct Main *main, struct ListBase **lb);
void BKE_libblock_free(struct Main *bmain, void *idv);
@@ -104,6 +104,7 @@ void test_idbutton(char *name);
void BKE_library_make_local(struct Main *bmain, struct Library *lib, bool untagged_only);
+struct ID *BKE_libblock_find_name_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 *) );
diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h
index 82b03127237..ec654ea4b71 100644
--- a/source/blender/blenkernel/BKE_main.h
+++ b/source/blender/blenkernel/BKE_main.h
@@ -87,6 +87,8 @@ typedef struct Main {
ListBase nodetree;
ListBase brush;
ListBase particle;
+ ListBase palettes;
+ ListBase paintcurves;
ListBase wm;
ListBase gpencil;
ListBase movieclip;
diff --git a/source/blender/blenkernel/BKE_material.h b/source/blender/blenkernel/BKE_material.h
index 89d310753fc..e69299a36bf 100644
--- a/source/blender/blenkernel/BKE_material.h
+++ b/source/blender/blenkernel/BKE_material.h
@@ -86,6 +86,10 @@ short find_material_index(struct Object *ob, struct Material *ma);
bool object_add_material_slot(struct Object *ob);
bool object_remove_material_slot(struct Object *ob);
+void BKE_texpaint_slot_refresh_cache(struct Material *ma, bool use_nodes);
+void BKE_texpaint_slots_refresh_object(struct Object *ob, bool use_nodes);
+void BKE_texpaint_slots_clear(struct Material *ma);
+
/* rna api */
void BKE_material_resize_id(struct ID *id, short totcol, bool do_id_user);
void BKE_material_append_id(struct ID *id, struct Material *ma);
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index c81133a85fa..5e786cbfb53 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -585,6 +585,9 @@ void node_type_gpu(struct bNodeType *ntype, NodeGPUExecFunction gpufu
void node_type_internal_links(struct bNodeType *ntype, void (*update_internal_links)(struct bNodeTree *, struct bNode *));
void node_type_compatibility(struct bNodeType *ntype, short compatibility);
+/* ************** GENERIC NODE FUNCTIONS *************** */
+bool BKE_node_is_connected_to_output(struct bNodeTree *ntree, struct bNode *node);
+
/* ************** COMMON NODES *************** */
#define NODE_UNDEFINED -2 /* node type is not registered */
@@ -891,6 +894,7 @@ void ntreeGPUMaterialNodes(struct bNodeTree *ntree, struct GPUMateria
#define CMP_NODE_GLARE 301
#define CMP_NODE_TONEMAP 302
#define CMP_NODE_LENSDIST 303
+#define CMP_NODE_SUNBEAMS 304
#define CMP_NODE_COLORCORRECTION 312
#define CMP_NODE_MASK_BOX 313
diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index 43813300850..0bdac6822f1 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -40,11 +40,15 @@ struct CurveMapping;
struct MDisps;
struct MeshElemMap;
struct GridPaintMask;
+struct Main;
struct MFace;
struct MultireModifierData;
struct MVert;
struct Object;
struct Paint;
+struct PaintCurve;
+struct Palette;
+struct PaletteColor;
struct PBVH;
struct Scene;
struct Sculpt;
@@ -52,6 +56,7 @@ struct StrokeCache;
struct Tex;
struct ImagePool;
struct UnifiedPaintSettings;
+struct wmOperator;
enum OverlayFlags;
@@ -91,6 +96,19 @@ OverlayControlFlags BKE_paint_get_overlay_flags(void);
void BKE_paint_reset_overlay_invalid(OverlayControlFlags flag);
void BKE_paint_set_overlay_override(enum OverlayFlags flag);
+/* palettes */
+void BKE_palette_free(struct Palette *palette);
+struct Palette *BKE_palette_add(struct Main *bmain, const char *name);
+struct PaletteColor *BKE_palette_color_add(struct Palette *palette);
+void BKE_palette_color_delete(struct Palette *palette);
+bool BKE_palette_is_empty(const struct Palette *palette);
+void BKE_palette_color_remove(struct Palette *palette, struct PaletteColor *color);
+void BKE_palette_cleanup(struct Palette *palette);
+
+/* paint curves */
+struct PaintCurve *BKE_paint_curve_add(struct Main *bmain, const char *name);
+void BKE_paint_curve_free(struct PaintCurve *pc);
+
void BKE_paint_init(struct Paint *p, const char col[3]);
void BKE_paint_free(struct Paint *p);
void BKE_paint_copy(struct Paint *src, struct Paint *tar);
@@ -100,6 +118,9 @@ struct Paint *BKE_paint_get_active_from_context(const struct bContext *C);
PaintMode BKE_paintmode_get_active_from_context(const struct bContext *C);
struct Brush *BKE_paint_brush(struct Paint *paint);
void BKE_paint_brush_set(struct Paint *paint, struct Brush *br);
+struct Palette *BKE_paint_palette(struct Paint *paint);
+void BKE_paint_palette_set(struct Paint *p, struct Palette *palette);
+void BKE_paint_curve_set(struct Brush *br, struct PaintCurve *pc);
/* testing face select mode
* Texture paint could be removed since selected faces are not used
@@ -117,7 +138,10 @@ bool paint_is_bmesh_face_hidden(struct BMFace *f);
/* paint masks */
float paint_grid_paint_mask(const struct GridPaintMask *gpm, unsigned level,
unsigned x, unsigned y);
+
+/* stroke related */
void paint_calculate_rake_rotation(struct UnifiedPaintSettings *ups, const float mouse_pos[2]);
+
/* Session data (mode-specific) */
typedef struct SculptSession {
diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h
index a10a3f3f59f..452e23bdcb8 100644
--- a/source/blender/blenkernel/BKE_scene.h
+++ b/source/blender/blenkernel/BKE_scene.h
@@ -84,6 +84,7 @@ typedef struct SceneBaseIter {
struct ListBase *duplilist;
struct DupliObject *dupob;
float omat[4][4];
+ struct Object *dupli_refob;
int phase;
} SceneBaseIter;
diff --git a/source/blender/blenkernel/BKE_shrinkwrap.h b/source/blender/blenkernel/BKE_shrinkwrap.h
index 59de43af907..070cd4a9cf0 100644
--- a/source/blender/blenkernel/BKE_shrinkwrap.h
+++ b/source/blender/blenkernel/BKE_shrinkwrap.h
@@ -31,52 +31,6 @@
* \ingroup bke
*/
-/* mesh util */
-
-//TODO: move this somewhere else
-#include "BKE_customdata.h"
-struct DerivedMesh;
-struct Object;
-struct DerivedMesh *object_get_derived_final(struct Object *ob, bool for_render);
-
-
-/* SpaceTransform stuff */
-/*
- * TODO: move this somewhere else
- *
- * this structs encapsulates all needed data to convert between 2 coordinate spaces
- * (where conversion can be represented by a matrix multiplication)
- *
- * This is used to reduce the number of arguments to pass to functions that need to perform
- * this kind of operation and make it easier for the coder, as he/she doenst needs to recode
- * the matrix calculation.
- *
- * A SpaceTransform is initialized using:
- * SPACE_TRANSFORM_SETUP( &data, ob1, ob2 )
- *
- * After that the following calls can be used:
- * space_transform_apply (&data, co); //converts a coordinate in ob1 coords space to the corresponding ob2 coords
- * space_transform_invert(&data, co); //converts a coordinate in ob2 coords space to the corresponding ob1 coords
- *
- * //Same Concept as space_transform_apply and space_transform_invert, but no is normalized after conversion
- * space_transform_apply_normal (&data, &no);
- * space_transform_invert_normal(&data, &no);
- *
- */
-struct Object;
-
-typedef struct SpaceTransform {
- float local2target[4][4];
- float target2local[4][4];
-
-} SpaceTransform;
-
-void space_transform_from_matrixs(struct SpaceTransform *data, float local[4][4], float target[4][4]);
-void space_transform_apply(const struct SpaceTransform *data, float co[3]);
-void space_transform_invert(const struct SpaceTransform *data, float co[3]);
-
-#define SPACE_TRANSFORM_SETUP(data, local, target) space_transform_from_matrixs(data, (local)->obmat, (target)->obmat)
-
/* Shrinkwrap stuff */
#include "BKE_bvhutils.h"
@@ -100,6 +54,7 @@ struct MDeformVert;
struct ShrinkwrapModifierData;
struct MDeformVert;
struct BVHTree;
+struct SpaceTransform;
typedef struct ShrinkwrapCalcData {
@@ -115,7 +70,7 @@ typedef struct ShrinkwrapCalcData {
int vgroup; //Vertex group num
struct DerivedMesh *target; //mesh we are shrinking to
- SpaceTransform local2target; //transform to move between local and target space
+ struct SpaceTransform local2target; //transform to move between local and target space
float keepDist; //Distance to keep above target surface (units are in local space)
@@ -136,7 +91,7 @@ void shrinkwrapModifier_deform(struct ShrinkwrapModifierData *smd, struct Object
*/
bool BKE_shrinkwrap_project_normal(
char options, const float vert[3], const float dir[3],
- const SpaceTransform *transf, BVHTree *tree, BVHTreeRayHit *hit,
+ const struct SpaceTransform *transf, BVHTree *tree, BVHTreeRayHit *hit,
BVHTree_RayCastCallback callback, void *userdata);
/*
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index d9af6ac3454..46f04ff03b2 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -37,6 +37,7 @@
#include "DNA_cloth_types.h"
#include "DNA_key_types.h"
+#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
@@ -501,11 +502,36 @@ void DM_update_materials(DerivedMesh *dm, Object *ob)
dm->mat = MEM_callocN(totmat * sizeof(*dm->mat), "DerivedMesh.mat");
- for (i = 1; i < totmat; i++) {
- dm->mat[i] = give_current_material(ob, i);
+ /* we leave last material as empty - rationale here is being able to index
+ * the materials by using the mf->mat_nr directly and leaving the last
+ * material as NULL in case no materials exist on mesh, so indexing will not fail */
+ for (i = 0; i < totmat - 1; i++) {
+ dm->mat[i] = give_current_material(ob, i + 1);
}
}
+MTFace *DM_paint_uvlayer_active_get(DerivedMesh *dm, int mat_nr)
+{
+ MTFace *tf_base;
+
+ BLI_assert(mat_nr < dm->totmat);
+
+ if (dm->mat[mat_nr] && dm->mat[mat_nr]->texpaintslot &&
+ dm->mat[mat_nr]->texpaintslot[dm->mat[mat_nr]->paint_active_slot].uvname)
+ {
+ tf_base = CustomData_get_layer_named(&dm->faceData, CD_MTFACE,
+ dm->mat[mat_nr]->texpaintslot[dm->mat[mat_nr]->paint_active_slot].uvname);
+ /* This can fail if we have changed the name in the UV layer list and have assigned the old name in the material
+ * texture slot.*/
+ if (!tf_base)
+ tf_base = CustomData_get_layer(&dm->faceData, CD_MTFACE);
+ }
+ else {
+ tf_base = CustomData_get_layer(&dm->faceData, CD_MTFACE);
+ }
+
+ return tf_base;
+}
void DM_to_mesh(DerivedMesh *dm, Mesh *me, Object *ob, CustomDataMask mask)
{
@@ -2474,6 +2500,28 @@ DerivedMesh *editbmesh_get_derived_base(Object *obedit, BMEditMesh *em)
return getEditDerivedBMesh(em, obedit, NULL);
}
+/***/
+
+/* get derived mesh from an object, using editbmesh if available. */
+DerivedMesh *object_get_derived_final(Object *ob, const bool for_render)
+{
+ Mesh *me = ob->data;
+ BMEditMesh *em = me->edit_btmesh;
+
+ if (for_render) {
+ /* TODO(sergey): use proper derived render here in the future. */
+ return ob->derivedFinal;
+ }
+
+ if (em) {
+ DerivedMesh *dm = em->derivedFinal;
+ return dm;
+ }
+
+ return ob->derivedFinal;
+}
+
+
/* UNUSED */
#if 0
@@ -3091,7 +3139,7 @@ static void navmesh_drawColored(DerivedMesh *dm)
static void navmesh_DM_drawFacesTex(DerivedMesh *dm,
DMSetDrawOptionsTex setDrawOptions,
DMCompareDrawOptions compareDrawOptions,
- void *userData)
+ void *userData, DMDrawFlag UNUSED(flag))
{
(void) setDrawOptions;
(void) compareDrawOptions;
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index 8f1382dacc3..c6dcca576fb 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -315,7 +315,7 @@ bActionGroup *action_groups_add_new(bAction *act, const char name[])
void action_groups_add_channel(bAction *act, bActionGroup *agrp, FCurve *fcurve)
{
/* sanity checks */
- if (ELEM3(NULL, act, agrp, fcurve))
+ if (ELEM(NULL, act, agrp, fcurve))
return;
/* if no channels anywhere, just add to two lists at the same time */
@@ -417,7 +417,7 @@ void action_groups_remove_channel(bAction *act, FCurve *fcu)
bActionGroup *BKE_action_group_find_name(bAction *act, const char name[])
{
/* sanity checks */
- if (ELEM3(NULL, act, act->groups.first, name) || (name[0] == 0))
+ if (ELEM(NULL, act, act->groups.first, name) || (name[0] == 0))
return NULL;
/* do string comparisons */
@@ -526,7 +526,7 @@ bPoseChannel *BKE_pose_channel_active(Object *ob)
bArmature *arm = (ob) ? ob->data : NULL;
bPoseChannel *pchan;
- if (ELEM3(NULL, ob, ob->pose, arm)) {
+ if (ELEM(NULL, ob, ob->pose, arm)) {
return NULL;
}
diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c
index 995b2ac5321..5ee82bb5842 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -405,7 +405,7 @@ void action_move_fcurves_by_basepath(bAction *srcAct, bAction *dstAct, const cha
FCurve *fcu, *fcn = NULL;
/* sanity checks */
- if (ELEM3(NULL, srcAct, dstAct, basepath)) {
+ if (ELEM(NULL, srcAct, dstAct, basepath)) {
if (G.debug & G_DEBUG) {
printf("ERROR: action_partition_fcurves_by_basepath(%p, %p, %p) has insufficient info to work with\n",
(void *)srcAct, (void *)dstAct, (void *)basepath);
@@ -1062,7 +1062,7 @@ KS_Path *BKE_keyingset_find_path(KeyingSet *ks, ID *id, const char group_name[],
KS_Path *ksp;
/* sanity checks */
- if (ELEM3(NULL, ks, rna_path, id))
+ if (ELEM(NULL, ks, rna_path, id))
return NULL;
/* loop over paths in the current KeyingSet, finding the first one where all settings match
@@ -2338,6 +2338,17 @@ static void animsys_evaluate_nla(ListBase *echannels, PointerRNA *ptr, AnimData
/* 3. free temporary evaluation data that's not used elsewhere */
BLI_freelistN(&estrips);
+
+ /* Tag ID as updated so render engines will recognize changes in data
+ * which is animated but doesn't have actions.
+ */
+ if (ptr->id.data != NULL) {
+ ID *id = ptr->id.data;
+ if (!(id->flag & LIB_ANIM_NO_RECALC)) {
+ id->flag |= LIB_ID_RECALC;
+ DAG_id_type_tag(G.main, GS(id->name));
+ }
+ }
}
/* NLA Evaluation function (mostly for use through do_animdata)
@@ -2392,7 +2403,7 @@ static void animsys_evaluate_overrides(PointerRNA *ptr, AnimData *adt)
/* Overview of how this system works:
* 1) Depsgraph sorts data as necessary, so that data is in an order that means
- * that all dependencies are resolved before dependants.
+ * that all dependencies are resolved before dependents.
* 2) All normal animation is evaluated, so that drivers have some basis values to
* work with
* a. NLA stacks are done first, as the Active Actions act as 'tweaking' tracks
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index 95f8426872d..16b5574709e 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -574,7 +574,7 @@ void b_bone_spline_setup(bPoseChannel *pchan, int rest, Mat4 result_array[MAX_BB
if (do_scale) {
/* correct for scaling when this matrix is used in scaled space */
- mul_serie_m4(result_array[a].mat, iscalemat, result_array[a].mat, scalemat, NULL, NULL, NULL, NULL, NULL);
+ mul_m4_series(result_array[a].mat, iscalemat, result_array[a].mat, scalemat);
}
}
}
@@ -622,8 +622,7 @@ static void pchan_b_bone_defmats(bPoseChannel *pchan, bPoseChanDeform *pdef_info
invert_m4_m4(tmat, b_bone_rest[a].mat);
- mul_serie_m4(b_bone_mats[a + 1].mat, pchan->chan_mat, bone->arm_mat, b_bone[a].mat, tmat, b_bone_mats[0].mat,
- NULL, NULL, NULL);
+ mul_m4_series(b_bone_mats[a + 1].mat, pchan->chan_mat, bone->arm_mat, b_bone[a].mat, tmat, b_bone_mats[0].mat);
if (use_quaternion)
mat4_to_dquat(&b_bone_dual_quats[a], bone->arm_mat, b_bone_mats[a + 1].mat);
@@ -1042,7 +1041,7 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm, float
if (!use_quaternion) /* quaternion already is scale corrected */
mul_m3_fl(smat, armature_weight / contrib);
- mul_serie_m3(defMats[i], tmpmat, pre, smat, post, NULL, NULL, NULL, NULL);
+ mul_m3_series(defMats[i], post, smat, pre, tmpmat);
}
}
@@ -1881,7 +1880,7 @@ static void splineik_init_tree_from_pchan(Scene *scene, Object *UNUSED(ob), bPos
*/
/* only happens on reload file, but violates depsgraph still... fix! */
- if (ELEM3(NULL, ikData->tar->curve_cache, ikData->tar->curve_cache->path, ikData->tar->curve_cache->path->data)) {
+ if (ELEM(NULL, ikData->tar->curve_cache, ikData->tar->curve_cache->path, ikData->tar->curve_cache->path->data)) {
BKE_displist_make_curveTypes(scene, ikData->tar, 0);
/* path building may fail in EditMode after removing verts [#33268]*/
diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c
index 9be9db77d39..fff8265a158 100644
--- a/source/blender/blenkernel/intern/blender.c
+++ b/source/blender/blenkernel/intern/blender.c
@@ -170,7 +170,7 @@ static void clear_global(void)
static bool clean_paths_visit_cb(void *UNUSED(userdata), char *path_dst, const char *path_src)
{
strcpy(path_dst, path_src);
- BLI_clean(path_dst);
+ BLI_path_native_slash(path_dst);
return !STREQ(path_dst, path_src);
}
@@ -182,7 +182,7 @@ static void clean_paths(Main *main)
BKE_bpath_traverse_main(main, clean_paths_visit_cb, BKE_BPATH_TRAVERSE_SKIP_MULTIFILE, NULL);
for (scene = main->scene.first; scene; scene = scene->id.next) {
- BLI_clean(scene->r.pic);
+ BLI_path_native_slash(scene->r.pic);
}
}
@@ -479,7 +479,9 @@ int BKE_read_file(bContext *C, const char *filepath, ReportList *reports)
return (bfd ? retval : BKE_READ_FILE_FAIL);
}
-int BKE_read_file_from_memory(bContext *C, const void *filebuf, int filelength, ReportList *reports, int update_defaults)
+bool BKE_read_file_from_memory(
+ bContext *C, const void *filebuf, int filelength,
+ ReportList *reports, bool update_defaults)
{
BlendFileData *bfd;
@@ -496,7 +498,9 @@ int BKE_read_file_from_memory(bContext *C, const void *filebuf, int filelength,
}
/* memfile is the undo buffer */
-int BKE_read_file_from_memfile(bContext *C, MemFile *memfile, ReportList *reports)
+bool BKE_read_file_from_memfile(
+ bContext *C, MemFile *memfile,
+ ReportList *reports)
{
BlendFileData *bfd;
diff --git a/source/blender/blenkernel/intern/bpath.c b/source/blender/blenkernel/intern/bpath.c
index dc2d0924bba..3cd26dacebd 100644
--- a/source/blender/blenkernel/intern/bpath.c
+++ b/source/blender/blenkernel/intern/bpath.c
@@ -107,7 +107,7 @@ typedef struct BPathRemap_Data {
int count_failed;
} BPathRemap_Data;
-static bool makeFilesRelative_visit_cb(void *userdata, char *path_dst, const char *path_src)
+static bool bpath_relative_convert_visit_cb(void *userdata, char *path_dst, const char *path_src)
{
BPathRemap_Data *data = (BPathRemap_Data *)userdata;
@@ -133,6 +133,7 @@ static bool makeFilesRelative_visit_cb(void *userdata, char *path_dst, const cha
void BKE_bpath_relative_convert(Main *bmain, const char *basedir, ReportList *reports)
{
BPathRemap_Data data = {NULL};
+ const int flag = BKE_BPATH_TRAVERSE_SKIP_LIBRARY;
if (basedir[0] == '\0') {
printf("%s: basedir='', this is a bug\n", __func__);
@@ -142,14 +143,14 @@ void BKE_bpath_relative_convert(Main *bmain, const char *basedir, ReportList *re
data.basedir = basedir;
data.reports = reports;
- BKE_bpath_traverse_main(bmain, makeFilesRelative_visit_cb, 0, (void *)&data);
+ BKE_bpath_traverse_main(bmain, bpath_relative_convert_visit_cb, flag, (void *)&data);
BKE_reportf(reports, data.count_failed ? RPT_WARNING : RPT_INFO,
"Total files %d | Changed %d | Failed %d",
data.count_tot, data.count_changed, data.count_failed);
}
-static bool makeFilesAbsolute_visit_cb(void *userdata, char *path_dst, const char *path_src)
+static bool bpath_absolute_convert_visit_cb(void *userdata, char *path_dst, const char *path_src)
{
BPathRemap_Data *data = (BPathRemap_Data *)userdata;
@@ -176,6 +177,7 @@ static bool makeFilesAbsolute_visit_cb(void *userdata, char *path_dst, const cha
void BKE_bpath_absolute_convert(Main *bmain, const char *basedir, ReportList *reports)
{
BPathRemap_Data data = {NULL};
+ const int flag = BKE_BPATH_TRAVERSE_SKIP_LIBRARY;
if (basedir[0] == '\0') {
printf("%s: basedir='', this is a bug\n", __func__);
@@ -185,7 +187,7 @@ void BKE_bpath_absolute_convert(Main *bmain, const char *basedir, ReportList *re
data.basedir = basedir;
data.reports = reports;
- BKE_bpath_traverse_main(bmain, makeFilesAbsolute_visit_cb, 0, (void *)&data);
+ BKE_bpath_traverse_main(bmain, bpath_absolute_convert_visit_cb, flag, (void *)&data);
BKE_reportf(reports, data.count_failed ? RPT_WARNING : RPT_INFO,
"Total files %d | Changed %d | Failed %d",
@@ -422,7 +424,7 @@ void BKE_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int
Image *ima;
ima = (Image *)id;
if (ima->packedfile == NULL || (flag & BKE_BPATH_TRAVERSE_SKIP_PACKED) == 0) {
- if (ELEM3(ima->source, IMA_SRC_FILE, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) {
+ if (ELEM(ima->source, IMA_SRC_FILE, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) {
if (rewrite_path_fixed(ima->name, visit_cb, absbase, bpath_user_data)) {
if (!ima->packedfile) {
BKE_image_signal(ima, NULL, IMA_SIGNAL_RELOAD);
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index 967e89e0dd1..cfdb1aa7a96 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -83,6 +83,7 @@ static void brush_defaults(Brush *brush)
brush->plane_trim = 0.5f;
brush->clone.alpha = 0.5f;
brush->normal_weight = 0.0f;
+ brush->fill_threshold = 0.2f;
brush->flag |= BRUSH_ALPHA_PRESSURE;
/* BRUSH PAINT TOOL SETTINGS */
@@ -90,6 +91,8 @@ static void brush_defaults(Brush *brush)
brush->rgb[1] = 1.0f;
brush->rgb[2] = 1.0f;
+ zero_v3(brush->secondary_rgb);
+
/* BRUSH STROKE SETTINGS */
brush->flag |= (BRUSH_SPACE | BRUSH_SPACE_ATTEN);
brush->spacing = 10; /* how far each brush dot should be spaced as a percentage of brush diameter */
@@ -161,6 +164,9 @@ Brush *BKE_brush_copy(Brush *brush)
if (brush->mask_mtex.tex)
id_us_plus((ID *)brush->mask_mtex.tex);
+ if (brush->paint_curve)
+ id_us_plus((ID *)brush->paint_curve);
+
if (brush->icon_imbuf)
brushn->icon_imbuf = IMB_dupImBuf(brush->icon_imbuf);
@@ -180,11 +186,9 @@ Brush *BKE_brush_copy(Brush *brush)
/* not brush itself */
void BKE_brush_free(Brush *brush)
{
- if (brush->mtex.tex)
- brush->mtex.tex->id.us--;
-
- if (brush->mask_mtex.tex)
- brush->mask_mtex.tex->id.us--;
+ id_us_min((ID *)brush->mtex.tex);
+ id_us_min((ID *)brush->mask_mtex.tex);
+ id_us_min((ID *)brush->paint_curve);
if (brush->icon_imbuf)
IMB_freeImBuf(brush->icon_imbuf);
@@ -192,6 +196,9 @@ void BKE_brush_free(Brush *brush)
BKE_previewimg_free(&(brush->preview));
curvemapping_free(brush->curve);
+
+ if (brush->gradient)
+ MEM_freeN(brush->gradient);
}
static void extern_local_brush(Brush *brush)
@@ -199,6 +206,7 @@ static void extern_local_brush(Brush *brush)
id_lib_extern((ID *)brush->mtex.tex);
id_lib_extern((ID *)brush->mask_mtex.tex);
id_lib_extern((ID *)brush->clone.image);
+ id_lib_extern((ID *)brush->paint_curve);
}
void BKE_brush_make_local(Brush *brush)
@@ -742,10 +750,23 @@ float BKE_brush_sample_masktex(const Scene *scene, Brush *br,
rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool);
}
+ CLAMP(intensity, 0.0f, 1.0f);
+
+ switch (br->mask_pressure) {
+ case BRUSH_MASK_PRESSURE_CUTOFF:
+ intensity = ((1.0f - intensity) < ups->size_pressure_value) ? 1.0f : 0.0f;
+ break;
+ case BRUSH_MASK_PRESSURE_RAMP:
+ intensity = ups->size_pressure_value + intensity * (1.0f - ups->size_pressure_value);
+ break;
+ default:
+ break;
+ }
+
return intensity;
}
-/* Unified Size and Strength */
+/* Unified Size / Strength / Color */
/* XXX: be careful about setting size and unprojected radius
* because they depend on one another
@@ -760,6 +781,29 @@ float BKE_brush_sample_masktex(const Scene *scene, Brush *br,
* In any case, a better solution is needed to prevent
* inconsistency. */
+
+float *BKE_brush_color_get(const struct Scene *scene, struct Brush *brush)
+{
+ UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
+ return (ups->flag & UNIFIED_PAINT_COLOR) ? ups->rgb : brush->rgb;
+}
+
+float *BKE_brush_secondary_color_get(const struct Scene *scene, struct Brush *brush)
+{
+ UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
+ return (ups->flag & UNIFIED_PAINT_COLOR) ? ups->secondary_rgb : brush->secondary_rgb;
+}
+
+void BKE_brush_color_set(struct Scene *scene, struct Brush *brush, const float color[3])
+{
+ UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
+
+ if (ups->flag & UNIFIED_PAINT_COLOR)
+ copy_v3_v3(ups->rgb, color);
+ else
+ copy_v3_v3(brush->rgb, color);
+}
+
void BKE_brush_size_set(Scene *scene, Brush *brush, int size)
{
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c
index 3f8edbcf1be..ca4a4b3196c 100644
--- a/source/blender/blenkernel/intern/cdderivedmesh.c
+++ b/source/blender/blenkernel/intern/cdderivedmesh.c
@@ -51,6 +51,7 @@
#include "BKE_editmesh.h"
#include "BKE_curve.h"
+#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
@@ -669,7 +670,7 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
DMSetDrawOptionsTex drawParams,
DMSetDrawOptions drawParamsMapped,
DMCompareDrawOptions compareDrawOptions,
- void *userData)
+ void *userData, DMDrawFlag uvflag)
{
CDDerivedMesh *cddm = (CDDerivedMesh *) dm;
MVert *mv = cddm->mvert;
@@ -680,6 +681,7 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
MCol *mcol;
int i, orig;
int colType, startFace = 0;
+ bool use_tface = (uvflag & DM_DRAW_USE_ACTIVE_UV) != 0;
/* double lookup */
const int *index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
@@ -718,14 +720,35 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
cdDM_update_normals_from_pbvh(dm);
if (GPU_buffer_legacy(dm)) {
+ int mat_nr_cache = -1;
+ MTFace *tf_base = DM_get_tessface_data_layer(dm, CD_MTFACE);
+ MTFace *tf_stencil_base = NULL;
+ MTFace *tf_stencil = NULL;
+
+ if (uvflag & DM_DRAW_USE_TEXPAINT_UV) {
+ int stencil = CustomData_get_stencil_layer(&dm->faceData, CD_MTFACE);
+ tf_stencil_base = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, stencil);
+ }
+
DEBUG_VBO("Using legacy code. cdDM_drawFacesTex_common\n");
for (i = 0; i < dm->numTessFaceData; i++, mf++) {
MVert *mvert;
DMDrawOption draw_option;
unsigned char *cp = NULL;
+ if (uvflag & DM_DRAW_USE_TEXPAINT_UV) {
+ if (mf->mat_nr != mat_nr_cache) {
+ tf_base = DM_paint_uvlayer_active_get(dm, mf->mat_nr);
+
+ mat_nr_cache = mf->mat_nr;
+ }
+ }
+
+ tf = tf_base ? tf_base + i : NULL;
+ tf_stencil = tf_stencil_base ? tf_stencil_base + i : NULL;
+
if (drawParams) {
- draw_option = drawParams(tf ? &tf[i] : NULL, (mcol != NULL), mf->mat_nr);
+ draw_option = drawParams(use_tface ? tf : NULL, (mcol != NULL), mf->mat_nr);
}
else {
if (index_mf_to_mpoly) {
@@ -778,21 +801,24 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
}
glBegin(mf->v4 ? GL_QUADS : GL_TRIANGLES);
- if (tf) glTexCoord2fv(tf[i].uv[0]);
+ if (tf) glTexCoord2fv(tf->uv[0]);
+ if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE1, tf->uv[0]);
if (cp) glColor3ub(cp[3], cp[2], cp[1]);
mvert = &mv[mf->v1];
if (lnors) glNormal3sv((const GLshort *)lnors[0][0]);
else if (mf->flag & ME_SMOOTH) glNormal3sv(mvert->no);
glVertex3fv(mvert->co);
- if (tf) glTexCoord2fv(tf[i].uv[1]);
+ if (tf) glTexCoord2fv(tf->uv[1]);
+ if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE1, tf->uv[1]);
if (cp) glColor3ub(cp[7], cp[6], cp[5]);
mvert = &mv[mf->v2];
if (lnors) glNormal3sv((const GLshort *)lnors[0][1]);
else if (mf->flag & ME_SMOOTH) glNormal3sv(mvert->no);
glVertex3fv(mvert->co);
- if (tf) glTexCoord2fv(tf[i].uv[2]);
+ if (tf) glTexCoord2fv(tf->uv[2]);
+ if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE1, tf->uv[2]);
if (cp) glColor3ub(cp[11], cp[10], cp[9]);
mvert = &mv[mf->v3];
if (lnors) glNormal3sv((const GLshort *)lnors[0][2]);
@@ -800,7 +826,8 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
glVertex3fv(mvert->co);
if (mf->v4) {
- if (tf) glTexCoord2fv(tf[i].uv[3]);
+ if (tf) glTexCoord2fv(tf->uv[3]);
+ if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE1, tf->uv[3]);
if (cp) glColor3ub(cp[15], cp[14], cp[13]);
mvert = &mv[mf->v4];
if (lnors) glNormal3sv((const GLshort *)lnors[0][3]);
@@ -819,7 +846,10 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
GPU_vertex_setup(dm);
GPU_normal_setup(dm);
- GPU_uv_setup(dm);
+ if (uvflag & DM_DRAW_USE_TEXPAINT_UV)
+ GPU_texpaint_uv_setup(dm);
+ else
+ GPU_uv_setup(dm);
if (mcol) {
GPU_color_setup(dm, colType);
}
@@ -839,7 +869,7 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
next_actualFace = dm->drawObject->triangle_to_mface[i + 1];
if (drawParams) {
- draw_option = drawParams(tf ? &tf[actualFace] : NULL, (mcol != NULL), mf[actualFace].mat_nr);
+ draw_option = drawParams(use_tface && tf ? &tf[actualFace] : NULL, (mcol != NULL), mf[actualFace].mat_nr);
}
else {
if (index_mf_to_mpoly) {
@@ -895,9 +925,9 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
static void cdDM_drawFacesTex(DerivedMesh *dm,
DMSetDrawOptionsTex setDrawOptions,
DMCompareDrawOptions compareDrawOptions,
- void *userData)
+ void *userData, DMDrawFlag uvflag)
{
- cdDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData);
+ cdDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData, uvflag);
}
static void cdDM_drawMappedFaces(DerivedMesh *dm,
@@ -1123,9 +1153,9 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm,
static void cdDM_drawMappedFacesTex(DerivedMesh *dm,
DMSetDrawOptions setDrawOptions,
DMCompareDrawOptions compareDrawOptions,
- void *userData)
+ void *userData, DMDrawFlag flag)
{
- cdDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData);
+ cdDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData, flag);
}
static void cddm_draw_attrib_vertex(DMVertexAttribs *attribs, MVert *mvert, int a, int index, int vert,
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index b27655c8c19..d80529ee780 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -3375,7 +3375,7 @@ static void shrinkwrap_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstra
unit_m4(ct->matrix);
if (target != NULL) {
- space_transform_from_matrixs(&transform, cob->matrix, ct->tar->obmat);
+ BLI_space_transform_from_matrices(&transform, cob->matrix, ct->tar->obmat);
switch (scon->shrinkType) {
case MOD_SHRINKWRAP_NEAREST_SURFACE:
@@ -3397,7 +3397,7 @@ static void shrinkwrap_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstra
break;
}
- space_transform_apply(&transform, co);
+ BLI_space_transform_apply(&transform, co);
BLI_bvhtree_find_nearest(treeData.tree, co, &nearest, treeData.nearest_callback, &treeData);
@@ -3405,7 +3405,7 @@ static void shrinkwrap_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstra
if (dist != 0.0f) {
interp_v3_v3v3(co, co, nearest.co, (dist - scon->dist) / dist); /* linear interpolation */
}
- space_transform_invert(&transform, co);
+ BLI_space_transform_invert(&transform, co);
break;
}
case MOD_SHRINKWRAP_PROJECT:
@@ -3909,7 +3909,7 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase
BKE_tracking_camera_get_reconstructed_interpolate(tracking, tracking_object, framenr, imat);
invert_m4(imat);
- mul_serie_m4(cob->matrix, obmat, mat, imat, NULL, NULL, NULL, NULL, NULL);
+ mul_m4_series(cob->matrix, obmat, mat, imat);
translate_m4(cob->matrix, track->bundle_pos[0], track->bundle_pos[1], track->bundle_pos[2]);
}
else {
@@ -3943,19 +3943,31 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase
if (len > FLT_EPSILON) {
CameraParams params;
+ int width, height;
float pos[2], rmat[4][4];
+ BKE_movieclip_get_size(clip, NULL, &width, &height);
+
marker = BKE_tracking_marker_get(track, framenr);
add_v2_v2v2(pos, marker->pos, track->offset);
+ if (data->flag & FOLLOWTRACK_USE_UNDISTORTION) {
+ /* Undistortion need to happen in pixel space. */
+ pos[0] *= width;
+ pos[1] *= height;
+
+ BKE_tracking_undistort_v2(tracking, pos, pos);
+
+ /* Normalize pixel coordinates back. */
+ pos[0] /= width;
+ pos[1] /= height;
+ }
+
/* aspect correction */
if (data->frame_method != FOLLOWTRACK_FRAME_STRETCH) {
- int width, height;
float w_src, h_src, w_dst, h_dst, asp_src, asp_dst;
- BKE_movieclip_get_size(clip, NULL, &width, &height);
-
/* apply clip display aspect */
w_src = width * clip->aspx;
h_src = height * clip->aspy;
@@ -4187,7 +4199,7 @@ static void objectsolver_evaluate(bConstraint *con, bConstraintOb *cob, ListBase
invert_m4_m4(imat, mat);
- mul_serie_m4(cob->matrix, cammat, imat, camimat, parmat, obmat, NULL, NULL, NULL);
+ mul_m4_series(cob->matrix, cammat, imat, camimat, parmat, obmat);
}
}
}
diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c
index d072088ac8e..f6da41252a7 100644
--- a/source/blender/blenkernel/intern/deform.c
+++ b/source/blender/blenkernel/intern/deform.c
@@ -559,7 +559,7 @@ void defgroup_unique_name(bDeformGroup *dg, Object *ob)
static bool is_char_sep(const char c)
{
- return ELEM4(c, '.', ' ', '-', '_');
+ return ELEM(c, '.', ' ', '-', '_');
}
/* based on BLI_split_dirfile() / os.path.splitext(), "a.b.c" -> ("a.b", ".c") */
diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c
index 95e608a5d4d..5e01f9add1e 100644
--- a/source/blender/blenkernel/intern/depsgraph.c
+++ b/source/blender/blenkernel/intern/depsgraph.c
@@ -59,6 +59,7 @@
#include "DNA_movieclip_types.h"
#include "DNA_mask_types.h"
+#include "BKE_anim.h"
#include "BKE_animsys.h"
#include "BKE_action.h"
#include "BKE_effect.h"
@@ -524,7 +525,7 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O
if (ct->tar->type == OB_MESH)
node3->customdata_mask |= CD_MASK_MDEFORMVERT;
}
- else if (ELEM3(con->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO, CONSTRAINT_TYPE_SPLINEIK))
+ else if (ELEM(con->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO, CONSTRAINT_TYPE_SPLINEIK))
dag_add_relation(dag, node3, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, cti->name);
else
dag_add_relation(dag, node3, node, DAG_RL_OB_DATA, cti->name);
@@ -688,6 +689,29 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O
dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Curve Taper");
}
if (ob->type == OB_FONT) {
+ /* Really rather dirty hack. needs to support font family to work
+ * reliably on render export.
+ *
+ * This totally mimics behavior of regular verts duplication with
+ * parenting. The only tricky thing here is to get list of objects
+ * used for the custom "font".
+ *
+ * This shouldn't harm so much because this code only runs on DAG
+ * rebuild and this feature is not that commonly used.
+ *
+ * - sergey -
+ */
+ if (cu->family[0] != '\n') {
+ ListBase *duplilist;
+ DupliObject *dob;
+ duplilist = object_duplilist(G.main->eval_ctx, scene, ob);
+ for (dob = duplilist->first; dob; dob = dob->next) {
+ node2 = dag_get_node(dag, dob->ob);
+ dag_add_relation(dag, node, node2, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Object Font");
+ }
+ free_object_duplilist(duplilist);
+ }
+
if (cu->textoncurve) {
node2 = dag_get_node(dag, cu->textoncurve);
/* Text on curve requires path to be evaluated for the target curve. */
@@ -803,7 +827,7 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O
continue;
/* special case for camera tracking -- it doesn't use targets to define relations */
- if (ELEM3(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER, CONSTRAINT_TYPE_OBJECTSOLVER)) {
+ if (ELEM(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER, CONSTRAINT_TYPE_OBJECTSOLVER)) {
int depends_on_camera = 0;
if (cti->type == CONSTRAINT_TYPE_FOLLOWTRACK) {
@@ -843,7 +867,7 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O
if (ELEM(con->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO))
dag_add_relation(dag, node2, node, DAG_RL_DATA_OB | DAG_RL_OB_OB, cti->name);
else {
- if (ELEM3(obt->type, OB_ARMATURE, OB_MESH, OB_LATTICE) && (ct->subtarget[0])) {
+ if (ELEM(obt->type, OB_ARMATURE, OB_MESH, OB_LATTICE) && (ct->subtarget[0])) {
dag_add_relation(dag, node2, node, DAG_RL_DATA_OB | DAG_RL_OB_OB, cti->name);
if (obt->type == OB_MESH)
node2->customdata_mask |= CD_MASK_MDEFORMVERT;
@@ -1386,7 +1410,7 @@ static bool check_object_needs_evaluation(Object *object)
if (object->type == OB_MESH) {
return object->derivedFinal == NULL;
}
- else if (ELEM5(object->type, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) {
+ else if (ELEM(object->type, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) {
return object->curve_cache == NULL;
}
@@ -1400,7 +1424,7 @@ static bool check_object_tagged_for_update(Object *object)
return true;
}
- if (ELEM6(object->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) {
+ if (ELEM(object->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) {
ID *data_id = object->data;
return (data_id->flag & (LIB_ID_RECALC_DATA | LIB_ID_RECALC)) != 0;
}
@@ -1983,7 +2007,7 @@ static void dag_object_time_update_flags(Main *bmain, Scene *scene, Object *ob)
if (cti) {
/* special case for camera tracking -- it doesn't use targets to define relations */
- if (ELEM3(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER, CONSTRAINT_TYPE_OBJECTSOLVER)) {
+ if (ELEM(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER, CONSTRAINT_TYPE_OBJECTSOLVER)) {
ob->recalc |= OB_RECALC_OB;
}
else if (cti->get_constraint_targets) {
@@ -2272,7 +2296,7 @@ static void dag_group_on_visible_update(Group *group)
group->id.flag |= LIB_DOIT;
for (go = group->gobject.first; go; go = go->next) {
- if (ELEM6(go->ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) {
+ if (ELEM(go->ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) {
go->ob->recalc |= OB_RECALC_DATA;
go->ob->id.flag |= LIB_DOIT;
lib_id_recalc_tag(G.main, &go->ob->id);
@@ -2319,7 +2343,7 @@ void DAG_on_visible_update(Main *bmain, const bool do_time)
oblay = (node) ? node->lay : ob->lay;
if ((oblay & lay) & ~scene->lay_updated) {
- if (ELEM6(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) {
+ if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) {
ob->recalc |= OB_RECALC_DATA;
lib_id_recalc_tag(bmain, &ob->id);
}
@@ -2472,6 +2496,17 @@ static void dag_id_flush_update(Main *bmain, Scene *sce, ID *id)
BKE_ptcache_object_reset(sce, obt, PTCACHE_RESET_DEPSGRAPH);
}
+ if (ELEM(idtype, ID_MA, ID_TE)) {
+ const bool new_shading_nodes = BKE_scene_use_new_shading_nodes(sce);
+ for (obt = bmain->object.first; obt; obt = obt->id.next) {
+ if (obt->mode & OB_MODE_TEXTURE_PAINT) {
+ obt->recalc |= OB_RECALC_DATA;
+ BKE_texpaint_slots_refresh_object(obt, new_shading_nodes);
+ lib_id_recalc_data_tag(bmain, &obt->id);
+ }
+ }
+ }
+
if (idtype == ID_MC) {
MovieClip *clip = (MovieClip *) id;
@@ -2481,7 +2516,7 @@ static void dag_id_flush_update(Main *bmain, Scene *sce, ID *id)
bConstraint *con;
for (con = obt->constraints.first; con; con = con->next) {
bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
- if (ELEM3(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER,
+ if (ELEM(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER,
CONSTRAINT_TYPE_OBJECTSOLVER))
{
obt->recalc |= OB_RECALC_OB;
@@ -2759,7 +2794,7 @@ void DAG_id_tag_update_ex(Main *bmain, ID *id, short flag)
if (ob->type == OB_FONT) {
Curve *cu = ob->data;
- if (ELEM4((struct VFont *)id, cu->vfont, cu->vfontb, cu->vfonti, cu->vfontbi)) {
+ if (ELEM((struct VFont *)id, cu->vfont, cu->vfontb, cu->vfonti, cu->vfontbi)) {
ob->recalc |= (flag & OB_RECALC_ALL);
}
}
diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c
index d494115821a..43c13f1c896 100644
--- a/source/blender/blenkernel/intern/displist.c
+++ b/source/blender/blenkernel/intern/displist.c
@@ -122,7 +122,7 @@ bool BKE_displist_has_faces(ListBase *lb)
DispList *dl;
for (dl = lb->first; dl; dl = dl->next) {
- if (ELEM3(dl->type, DL_INDEX3, DL_INDEX4, DL_SURF)) {
+ if (ELEM(dl->type, DL_INDEX3, DL_INDEX4, DL_SURF)) {
return true;
}
}
@@ -653,8 +653,8 @@ static void curve_to_filledpoly(Curve *cu, ListBase *UNUSED(nurb), ListBase *dis
bevels_to_filledpoly(cu, dispbase);
}
else {
- /* TODO, investigate passing zup instead of NULL */
- BKE_displist_fill(dispbase, dispbase, NULL, false);
+ const float z_up[3] = {0.0f, 0.0f, 1.0f};
+ BKE_displist_fill(dispbase, dispbase, z_up, false);
}
}
@@ -766,7 +766,7 @@ static ModifierData *curve_get_tessellate_point(Scene *scene, Object *ob,
if (mti->type == eModifierTypeType_Constructive)
return pretessellatePoint;
- if (ELEM3(md->type, eModifierType_Hook, eModifierType_Softbody, eModifierType_MeshDeform)) {
+ if (ELEM(md->type, eModifierType_Hook, eModifierType_Softbody, eModifierType_MeshDeform)) {
pretessellatePoint = md;
/* this modifiers are moving point of tessellation automatically
@@ -1566,7 +1566,7 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba
Curve *cu = ob->data;
/* we do allow duplis... this is only displist on curve level */
- if (!ELEM3(ob->type, OB_SURF, OB_CURVE, OB_FONT)) return;
+ if (!ELEM(ob->type, OB_SURF, OB_CURVE, OB_FONT)) return;
if (ob->type == OB_SURF) {
BKE_displist_make_surf(scene, ob, dispbase, r_dm_final, for_render, for_orco, use_render_resolution);
@@ -1809,7 +1809,7 @@ void BKE_displist_make_curveTypes(Scene *scene, Object *ob, const bool for_orco)
/* The same check for duplis as in do_makeDispListCurveTypes.
* Happens when curve used for constraint/bevel was converted to mesh.
* check there is still needed for render displist and orco displists. */
- if (!ELEM3(ob->type, OB_SURF, OB_CURVE, OB_FONT))
+ if (!ELEM(ob->type, OB_SURF, OB_CURVE, OB_FONT))
return;
BKE_object_free_derived_caches(ob);
@@ -1894,7 +1894,7 @@ void BKE_displist_minmax(ListBase *dispbase, float min[3], float max[3])
/* this is confusing, there's also min_max_object, appplying the obmat... */
static void boundbox_displist_object(Object *ob)
{
- if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
+ if (ELEM(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
/* Curve's BB is already calculated as a part of modifier stack,
* here we only calculate object BB based on final display list.
*/
diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c
index 3a11b3431ae..40a4bc22ce9 100644
--- a/source/blender/blenkernel/intern/editderivedmesh.c
+++ b/source/blender/blenkernel/intern/editderivedmesh.c
@@ -911,7 +911,7 @@ static void emDM_drawFacesTex_common(DerivedMesh *dm,
static void emDM_drawFacesTex(DerivedMesh *dm,
DMSetDrawOptionsTex setDrawOptions,
DMCompareDrawOptions compareDrawOptions,
- void *userData)
+ void *userData, DMDrawFlag UNUSED(flag))
{
emDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData);
}
@@ -919,7 +919,7 @@ static void emDM_drawFacesTex(DerivedMesh *dm,
static void emDM_drawMappedFacesTex(DerivedMesh *dm,
DMSetDrawOptions setDrawOptions,
DMCompareDrawOptions compareDrawOptions,
- void *userData)
+ void *userData, DMDrawFlag UNUSED(flag))
{
emDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData);
}
diff --git a/source/blender/blenkernel/intern/editmesh_bvh.c b/source/blender/blenkernel/intern/editmesh_bvh.c
index 76ea340ecbd..442ab26ffc8 100644
--- a/source/blender/blenkernel/intern/editmesh_bvh.c
+++ b/source/blender/blenkernel/intern/editmesh_bvh.c
@@ -53,13 +53,17 @@ struct BMBVHTree {
int flag;
};
-BMBVHTree *BKE_bmbvh_new_from_editmesh(BMEditMesh *em, int flag, const float (*cos_cage)[3], const bool cos_cage_free)
+BMBVHTree *BKE_bmbvh_new_from_editmesh(
+ BMEditMesh *em, int flag,
+ const float (*cos_cage)[3], const bool cos_cage_free)
{
return BKE_bmbvh_new(em->bm, em->looptris, em->tottri, flag, cos_cage, cos_cage_free);
}
-BMBVHTree *BKE_bmbvh_new(BMesh *bm, BMLoop *(*looptris)[3], int looptris_tot, int flag, const float (*cos_cage)[3],
-const bool cos_cage_free)
+BMBVHTree *BKE_bmbvh_new_ex(
+ BMesh *bm, BMLoop *(*looptris)[3], int looptris_tot, int flag,
+ const float (*cos_cage)[3], const bool cos_cage_free,
+ bool (*test_fn)(BMFace *, void *user_data), void *user_data)
{
/* could become argument */
const float epsilon = FLT_EPSILON * 2.0f;
@@ -69,6 +73,10 @@ const bool cos_cage_free)
int i;
int tottri;
+ /* avoid testing every tri */
+ BMFace *f_test, *f_test_prev;
+ bool test_fn_ret;
+
/* BKE_editmesh_tessface_calc() must be called already */
BLI_assert(looptris_tot != 0 || bm->totface == 0);
@@ -83,18 +91,22 @@ const bool cos_cage_free)
bmtree->cos_cage_free = cos_cage_free;
bmtree->flag = flag;
- if (flag & (BMBVH_RESPECT_SELECT)) {
+ if (test_fn) {
+ /* callback must do... */
+ BLI_assert(!(flag & (BMBVH_RESPECT_SELECT | BMBVH_RESPECT_HIDDEN)));
+
+ f_test_prev = NULL;
+ test_fn_ret = false;
+
tottri = 0;
for (i = 0; i < looptris_tot; i++) {
- if (BM_elem_flag_test(looptris[i][0]->f, BM_ELEM_SELECT)) {
- tottri++;
+ f_test = looptris[i][0]->f;
+ if (f_test != f_test_prev) {
+ test_fn_ret = test_fn(f_test, user_data);
+ f_test_prev = f_test;
}
- }
- }
- else if (flag & (BMBVH_RESPECT_HIDDEN)) {
- tottri = 0;
- for (i = 0; i < looptris_tot; i++) {
- if (!BM_elem_flag_test(looptris[i][0]->f, BM_ELEM_HIDDEN)) {
+
+ if (test_fn_ret) {
tottri++;
}
}
@@ -105,17 +117,19 @@ const bool cos_cage_free)
bmtree->tree = BLI_bvhtree_new(tottri, epsilon, 8, 8);
- for (i = 0; i < looptris_tot; i++) {
+ f_test_prev = NULL;
+ test_fn_ret = false;
- if (flag & BMBVH_RESPECT_SELECT) {
+ for (i = 0; i < looptris_tot; i++) {
+ if (test_fn) {
/* note, the arrays wont align now! take care */
- if (!BM_elem_flag_test(looptris[i][0]->f, BM_ELEM_SELECT)) {
- continue;
+ f_test = looptris[i][0]->f;
+ if (f_test != f_test_prev) {
+ test_fn_ret = test_fn(f_test, user_data);
+ f_test_prev = f_test;
}
- }
- else if (flag & BMBVH_RESPECT_HIDDEN) {
- /* note, the arrays wont align now! take care */
- if (BM_elem_flag_test(looptris[i][0]->f, BM_ELEM_HIDDEN)) {
+
+ if (!test_fn_ret) {
continue;
}
}
@@ -139,6 +153,38 @@ const bool cos_cage_free)
return bmtree;
}
+static bool bm_face_is_select(BMFace *f, void *UNUSED(user_data))
+{
+ return (BM_elem_flag_test(f, BM_ELEM_SELECT) != 0);
+}
+
+static bool bm_face_is_not_hidden(BMFace *f, void *UNUSED(user_data))
+{
+ return (BM_elem_flag_test(f, BM_ELEM_HIDDEN) == 0);
+}
+
+BMBVHTree *BKE_bmbvh_new(
+ BMesh *bm, BMLoop *(*looptris)[3], int looptris_tot, int flag,
+ const float (*cos_cage)[3], const bool cos_cage_free)
+{
+ bool (*test_fn)(BMFace *, void *user_data);
+
+ if (flag & BMBVH_RESPECT_SELECT) {
+ test_fn = bm_face_is_select;
+ }
+ else if (flag & BMBVH_RESPECT_HIDDEN) {
+ test_fn = bm_face_is_not_hidden;
+ }
+ else {
+ test_fn = NULL;
+ }
+
+ flag &= ~(BMBVH_RESPECT_SELECT | BMBVH_RESPECT_HIDDEN);
+
+ return BKE_bmbvh_new_ex(bm, looptris, looptris_tot, flag, cos_cage, cos_cage_free, test_fn, NULL);
+}
+
+
void BKE_bmbvh_free(BMBVHTree *bmtree)
{
BLI_bvhtree_free(bmtree->tree);
diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c
index e28152dbc1a..4859aa8f791 100644
--- a/source/blender/blenkernel/intern/effect.c
+++ b/source/blender/blenkernel/intern/effect.c
@@ -935,7 +935,7 @@ static void do_physical_effector(EffectorCache *eff, EffectorData *efd, Effected
if (pd->flag & PFIELD_DO_LOCATION) {
madd_v3_v3fl(total_force, force, 1.0f/point->vel_to_sec);
- if (ELEM3(pd->forcefield, PFIELD_HARMONIC, PFIELD_DRAG, PFIELD_SMOKEFLOW)==0 && pd->f_flow != 0.0f) {
+ if (ELEM(pd->forcefield, PFIELD_HARMONIC, PFIELD_DRAG, PFIELD_SMOKEFLOW)==0 && pd->f_flow != 0.0f) {
madd_v3_v3fl(total_force, point->vel, -pd->f_flow * efd->falloff);
}
}
diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c
index a8de9b69fbe..09c1dcf701d 100644
--- a/source/blender/blenkernel/intern/fcurve.c
+++ b/source/blender/blenkernel/intern/fcurve.c
@@ -276,7 +276,7 @@ int list_find_data_fcurves(ListBase *dst, ListBase *src, const char *dataPrefix,
int matches = 0;
/* sanity checks */
- if (ELEM4(NULL, dst, src, dataPrefix, dataName))
+ if (ELEM(NULL, dst, src, dataPrefix, dataName))
return 0;
else if ((dataPrefix[0] == 0) || (dataName[0] == 0))
return 0;
@@ -522,17 +522,28 @@ bool calc_fcurve_bounds(FCurve *fcu, float *xmin, float *xmax, float *ymin, floa
/* only loop over keyframes to find extents for values if needed */
if (ymin || ymax) {
- BezTriple *bezt;
+ BezTriple *bezt, *prevbezt = NULL;
- for (bezt = fcu->bezt, i = 0; i < fcu->totvert; bezt++, i++) {
- if ((do_sel_only == false) || BEZSELECTED(bezt)) {
+ for (bezt = fcu->bezt, i = 0; i < fcu->totvert; prevbezt = bezt, bezt++, i++) {
+ if ((do_sel_only == false) || BEZSELECTED(bezt)) {
+ /* keyframe itself */
+ yminv = min_ff(yminv, bezt->vec[1][1]);
+ ymaxv = max_ff(ymaxv, bezt->vec[1][1]);
+
if (include_handles) {
- yminv = min_ffff(yminv, bezt->vec[1][1], bezt->vec[0][1], bezt->vec[2][1]);
- ymaxv = max_ffff(ymaxv, bezt->vec[1][1], bezt->vec[0][1], bezt->vec[2][1]);
- }
- else {
- yminv = min_ff(yminv, bezt->vec[1][1]);
- ymaxv = max_ff(ymaxv, bezt->vec[1][1]);
+ /* left handle - only if applicable
+ * NOTE: for the very first keyframe, the left handle actually has no bearings on anything
+ */
+ if (prevbezt && (prevbezt->ipo == BEZT_IPO_BEZ)) {
+ yminv = min_ff(yminv, bezt->vec[0][1]);
+ ymaxv = max_ff(ymaxv, bezt->vec[0][1]);
+ }
+
+ /* right handle - only if applicable */
+ if (bezt->ipo == BEZT_IPO_BEZ) {
+ yminv = min_ff(yminv, bezt->vec[2][1]);
+ ymaxv = max_ff(ymaxv, bezt->vec[2][1]);
+ }
}
foundvert = true;
diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c
index c381084cfd2..e226e9d9797 100644
--- a/source/blender/blenkernel/intern/gpencil.c
+++ b/source/blender/blenkernel/intern/gpencil.c
@@ -506,7 +506,7 @@ void gpencil_layer_setactive(bGPdata *gpd, bGPDlayer *active)
bGPDlayer *gpl;
/* error checking */
- if (ELEM3(NULL, gpd, gpd->layers.first, active))
+ if (ELEM(NULL, gpd, gpd->layers.first, active))
return;
/* loop over layers deactivating all */
diff --git a/source/blender/blenkernel/intern/idcode.c b/source/blender/blenkernel/intern/idcode.c
index 2e201a0b8e8..1b7a03ec80e 100644
--- a/source/blender/blenkernel/intern/idcode.c
+++ b/source/blender/blenkernel/intern/idcode.c
@@ -73,6 +73,8 @@ static IDType idtypes[] = {
{ ID_NT, "NodeTree", "node_groups", IDTYPE_FLAGS_ISLINKABLE },
{ ID_OB, "Object", "objects", IDTYPE_FLAGS_ISLINKABLE },
{ ID_PA, "ParticleSettings", "particles", 0 },
+ { ID_PAL, "Palettes", "palettes", IDTYPE_FLAGS_ISLINKABLE },
+ { ID_PC, "PaintCurve", "paint_curves", IDTYPE_FLAGS_ISLINKABLE },
{ ID_SCE, "Scene", "scenes", IDTYPE_FLAGS_ISLINKABLE },
{ ID_SCR, "Screen", "screens", 0 },
{ ID_SEQ, "Sequence", "sequences", 0 }, /* not actually ID data */
diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c
index 3188676fb6c..95bfd72c9df 100644
--- a/source/blender/blenkernel/intern/idprop.c
+++ b/source/blender/blenkernel/intern/idprop.c
@@ -64,7 +64,7 @@ static char idp_size_table[] = {
/** \name IDP Array API
* \{ */
-#define GETPROP(prop, i) (((IDProperty *)(prop)->data.pointer) + (i))
+#define GETPROP(prop, i) &(IDP_IDPArray(prop)[i])
/* --------- property array type -------------*/
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index db5c212d1db..805c1250c5d 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -1257,7 +1257,7 @@ static bool do_add_image_extension(char *string, const char imtype, const ImageF
extension = extension_test;
}
#endif
- else if (ELEM5(imtype, R_IMF_IMTYPE_PNG, R_IMF_IMTYPE_FFMPEG, R_IMF_IMTYPE_H264, R_IMF_IMTYPE_THEORA, R_IMF_IMTYPE_XVID)) {
+ else if (ELEM(imtype, R_IMF_IMTYPE_PNG, R_IMF_IMTYPE_FFMPEG, R_IMF_IMTYPE_H264, R_IMF_IMTYPE_THEORA, R_IMF_IMTYPE_XVID)) {
if (!BLI_testextensie(string, extension_test = ".png"))
extension = extension_test;
}
@@ -1900,7 +1900,7 @@ int BKE_imbuf_write(ImBuf *ibuf, const char *name, ImageFormatData *imf)
ibuf->ftype = RADHDR;
}
#endif
- else if (ELEM5(imtype, R_IMF_IMTYPE_PNG, R_IMF_IMTYPE_FFMPEG, R_IMF_IMTYPE_H264, R_IMF_IMTYPE_THEORA, R_IMF_IMTYPE_XVID)) {
+ else if (ELEM(imtype, R_IMF_IMTYPE_PNG, R_IMF_IMTYPE_FFMPEG, R_IMF_IMTYPE_H264, R_IMF_IMTYPE_THEORA, R_IMF_IMTYPE_XVID)) {
ibuf->ftype = PNG;
if (imtype == R_IMF_IMTYPE_PNG) {
diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c
index 7385322ddeb..51cf26063c7 100644
--- a/source/blender/blenkernel/intern/ipo.c
+++ b/source/blender/blenkernel/intern/ipo.c
@@ -1308,8 +1308,8 @@ static void icu_to_fcurves(ID *id, ListBase *groups, ListBase *list, IpoCurve *i
* - they were degrees/10
* - we need radians for RNA to do the right thing
*/
- if ( ((icu->blocktype == ID_OB) && ELEM3(icu->adrcode, OB_ROT_X, OB_ROT_Y, OB_ROT_Z)) ||
- ((icu->blocktype == ID_PO) && ELEM3(icu->adrcode, AC_EUL_X, AC_EUL_Y, AC_EUL_Z)) )
+ if ( ((icu->blocktype == ID_OB) && ELEM(icu->adrcode, OB_ROT_X, OB_ROT_Y, OB_ROT_Z)) ||
+ ((icu->blocktype == ID_PO) && ELEM(icu->adrcode, AC_EUL_X, AC_EUL_Y, AC_EUL_Z)) )
{
const float fac = (float)M_PI / 18.0f; //10.0f * M_PI/180.0f;
@@ -1341,7 +1341,7 @@ static void icu_to_fcurves(ID *id, ListBase *groups, ListBase *list, IpoCurve *i
DriverVar *dvar = fcu->driver->variables.first;
DriverTarget *dtar = &dvar->targets[0];
- if (ELEM3(dtar->transChan, DTAR_TRANSCHAN_ROTX, DTAR_TRANSCHAN_ROTY, DTAR_TRANSCHAN_ROTZ)) {
+ if (ELEM(dtar->transChan, DTAR_TRANSCHAN_ROTX, DTAR_TRANSCHAN_ROTY, DTAR_TRANSCHAN_ROTZ)) {
const float fac = (float)M_PI / 18.0f;
dst->vec[0][0] *= fac;
@@ -1388,7 +1388,7 @@ static void ipo_to_animato(ID *id, Ipo *ipo, char actname[], char constname[], S
IpoCurve *icu;
/* sanity check */
- if (ELEM3(NULL, ipo, anim, drivers))
+ if (ELEM(NULL, ipo, anim, drivers))
return;
if (G.debug & G_DEBUG) printf("ipo_to_animato\n");
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index df343459d2f..515287de336 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -104,6 +104,7 @@
#include "BKE_mask.h"
#include "BKE_node.h"
#include "BKE_object.h"
+#include "BKE_paint.h"
#include "BKE_particle.h"
#include "BKE_packedFile.h"
#include "BKE_speaker.h"
@@ -515,6 +516,10 @@ ListBase *which_libbase(Main *mainlib, short type)
return &(mainlib->mask);
case ID_LS:
return &(mainlib->linestyle);
+ case ID_PAL:
+ return &(mainlib->palettes);
+ case ID_PC:
+ return &(mainlib->paintcurves);
}
return NULL;
}
@@ -596,6 +601,8 @@ int set_listbasepointers(Main *main, ListBase **lb)
lb[a++] = &(main->text);
lb[a++] = &(main->sound);
lb[a++] = &(main->group);
+ lb[a++] = &(main->palettes);
+ lb[a++] = &(main->paintcurves);
lb[a++] = &(main->brush);
lb[a++] = &(main->script);
lb[a++] = &(main->particle);
@@ -731,6 +738,12 @@ static ID *alloc_libblock_notest(short type)
case ID_LS:
id = MEM_callocN(sizeof(FreestyleLineStyle), "Freestyle Line Style");
break;
+ case ID_PAL:
+ id = MEM_callocN(sizeof(Palette), "Palette");
+ break;
+ case ID_PC:
+ id = MEM_callocN(sizeof(PaintCurve), "Paint Curve");
+ break;
}
return id;
}
@@ -1007,6 +1020,12 @@ void BKE_libblock_free_ex(Main *bmain, void *idv, bool do_id_user)
case ID_LS:
BKE_linestyle_free((FreestyleLineStyle *)id);
break;
+ case ID_PAL:
+ BKE_palette_free((Palette *)id);
+ break;
+ case ID_PC:
+ BKE_paint_curve_free((PaintCurve *)id);
+ break;
}
/* avoid notifying on removed data */
@@ -1131,14 +1150,17 @@ void BKE_main_unlock(struct Main *bmain)
}
/* ***************** ID ************************ */
-
-
-ID *BKE_libblock_find_name(const short type, const char *name) /* type: "OB" or "MA" etc */
+ID *BKE_libblock_find_name_ex(struct Main *bmain, const short type, const char *name)
{
- ListBase *lb = which_libbase(G.main, type);
+ ListBase *lb = which_libbase(bmain, type);
BLI_assert(lb != NULL);
return BLI_findstring(lb, name, offsetof(ID, name) + 2);
}
+ID *BKE_libblock_find_name(const short type, const char *name)
+{
+ return BKE_libblock_find_name_ex(G.main, type, name);
+}
+
void id_sort_by_name(ListBase *lb, ID *id)
{
diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c
index 4147750c356..1c40446c217 100644
--- a/source/blender/blenkernel/intern/mask.c
+++ b/source/blender/blenkernel/intern/mask.c
@@ -1212,7 +1212,7 @@ void BKE_mask_point_parent_matrix_get(MaskSplinePoint *point, float ctime, float
}
invert_m3_m3(mask_to_clip_matrix, mask_from_clip_matrix);
- mul_serie_m3(parent_matrix, mask_to_clip_matrix, H, mask_from_clip_matrix, NULL, NULL, NULL, NULL, NULL);
+ mul_m3_series(parent_matrix, mask_from_clip_matrix, H, mask_to_clip_matrix);
}
}
}
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index 971db1997de..b4ab464838e 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -111,6 +111,9 @@ void BKE_material_free_ex(Material *ma, bool do_id_user)
MEM_freeN(ma->nodetree);
}
+ if (ma->texpaintslot)
+ MEM_freeN(ma->texpaintslot);
+
if (ma->gpumaterial.first)
GPU_material_free(ma);
}
@@ -269,7 +272,9 @@ Material *localize_material(Material *ma)
if (ma->ramp_col) man->ramp_col = MEM_dupallocN(ma->ramp_col);
if (ma->ramp_spec) man->ramp_spec = MEM_dupallocN(ma->ramp_spec);
-
+
+ if (ma->texpaintslot) man->texpaintslot = MEM_dupallocN(man->texpaintslot);
+
man->preview = NULL;
if (ma->nodetree)
@@ -467,7 +472,7 @@ Material ***give_matarar(Object *ob)
me = ob->data;
return &(me->mat);
}
- else if (ELEM3(ob->type, OB_CURVE, OB_FONT, OB_SURF)) {
+ else if (ELEM(ob->type, OB_CURVE, OB_FONT, OB_SURF)) {
cu = ob->data;
return &(cu->mat);
}
@@ -488,7 +493,7 @@ short *give_totcolp(Object *ob)
me = ob->data;
return &(me->totcol);
}
- else if (ELEM3(ob->type, OB_CURVE, OB_FONT, OB_SURF)) {
+ else if (ELEM(ob->type, OB_CURVE, OB_FONT, OB_SURF)) {
cu = ob->data;
return &(cu->totcol);
}
@@ -1291,7 +1296,7 @@ bool object_remove_material_slot(Object *ob)
}
/* check indices from mesh */
- if (ELEM4(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT)) {
+ if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT)) {
material_data_index_remove_id((ID *)ob->data, actcol - 1);
if (ob->curve_cache) {
BKE_displist_free(&ob->curve_cache->disp);
@@ -1301,6 +1306,114 @@ bool object_remove_material_slot(Object *ob)
return true;
}
+void BKE_texpaint_slots_clear(struct Material *ma)
+{
+
+ if (ma->texpaintslot) {
+ MEM_freeN(ma->texpaintslot);
+ ma->texpaintslot = NULL;
+ }
+ ma->tot_slots = 0;
+ ma->paint_active_slot = 0;
+ ma->paint_clone_slot = 0;
+}
+
+
+static bool get_mtex_slot_valid_texpaint(struct MTex *mtex)
+{
+ return (mtex && (mtex->texco == TEXCO_UV) &&
+ mtex->tex && (mtex->tex->type == TEX_IMAGE) &&
+ mtex->tex->ima);
+}
+
+void BKE_texpaint_slot_refresh_cache(Material *ma, bool use_nodes)
+{
+ MTex **mtex;
+ short count = 0;
+ short index = 0, i;
+
+ if (!ma)
+ return;
+
+ if (ma->texpaintslot) {
+ MEM_freeN(ma->texpaintslot);
+ ma->texpaintslot = NULL;
+ }
+
+ if (use_nodes) {
+ bNode *node, *active_node;
+
+ if (!(ma->use_nodes && ma->nodetree))
+ return;
+
+ for (node = ma->nodetree->nodes.first; node; node = node->next) {
+ if (node->typeinfo->nclass == NODE_CLASS_TEXTURE && node->typeinfo->type == SH_NODE_TEX_IMAGE && node->id)
+ count++;
+ }
+
+ ma->tot_slots = count;
+
+ if (count == 0) {
+ ma->paint_active_slot = 0;
+ return;
+ }
+ ma->texpaintslot = MEM_callocN(sizeof(*ma->texpaintslot) * count, "texpaint_slots");
+
+ active_node = nodeGetActiveTexture(ma->nodetree);
+
+ for (node = ma->nodetree->nodes.first; node; node = node->next) {
+ if (node->typeinfo->nclass == NODE_CLASS_TEXTURE && node->typeinfo->type == SH_NODE_TEX_IMAGE && node->id) {
+ if (active_node == node)
+ ma->paint_active_slot = index;
+ ma->texpaintslot[index++].ima = (Image *)node->id;
+ }
+ }
+ }
+ else {
+ for (mtex = ma->mtex, i = 0; i < MAX_MTEX; i++, mtex++) {
+ if (get_mtex_slot_valid_texpaint(*mtex)) {
+ count++;
+ }
+ }
+
+ ma->tot_slots = count;
+
+ if (count == 0) {
+ ma->paint_active_slot = 0;
+ return;
+ }
+
+ ma->texpaintslot = MEM_callocN(sizeof(*ma->texpaintslot) * count, "texpaint_slots");
+
+ for (mtex = ma->mtex, i = 0; i < MAX_MTEX; i++, mtex++) {
+ if (get_mtex_slot_valid_texpaint(*mtex)) {
+ ma->texpaintslot[index].ima = (*mtex)->tex->ima;
+ ma->texpaintslot[index++].uvname = (*mtex)->uvname;
+ }
+ }
+ }
+
+ if (ma->paint_active_slot >= count) {
+ ma->paint_active_slot = count - 1;
+ }
+
+ if (ma->paint_clone_slot >= count) {
+ ma->paint_clone_slot = count - 1;
+ }
+
+ return;
+}
+
+void BKE_texpaint_slots_refresh_object(struct Object *ob, bool use_nodes)
+{
+ int i;
+
+ for (i = 1; i < ob->totcol + 1; i++) {
+ Material *ma = give_current_material(ob, i);
+ BKE_texpaint_slot_refresh_cache(ma, use_nodes);
+ }
+}
+
/* r_col = current value, col = new value, (fac == 0) is no change */
void ramp_blend(int type, float r_col[3], const float fac, const float col[3])
diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c
index 43b19f0c869..5a045606d15 100644
--- a/source/blender/blenkernel/intern/mball.c
+++ b/source/blender/blenkernel/intern/mball.c
@@ -491,10 +491,7 @@ void BKE_mball_properties_copy(Scene *scene, Object *active_object)
BLI_split_name_num(basisname, &basisnr, active_object->id.name + 2, '.');
- /* XXX recursion check, see scene.c, just too simple code this BKE_scene_base_iter_next() */
- if (F_ERROR == BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 0, NULL, NULL))
- return;
-
+ BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 0, NULL, NULL);
while (BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 1, &base, &ob)) {
if (ob->type == OB_MBALL) {
if (ob != active_object) {
@@ -537,23 +534,17 @@ Object *BKE_mball_basis_find(Scene *scene, Object *basis)
BLI_split_name_num(basisname, &basisnr, basis->id.name + 2, '.');
- /* XXX recursion check, see scene.c, just too simple code this BKE_scene_base_iter_next() */
- if (F_ERROR == BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 0, NULL, NULL))
- return NULL;
-
+ BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 0, NULL, NULL);
while (BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 1, &base, &ob)) {
- if (ob->type == OB_MBALL) {
+ if ((ob->type == OB_MBALL) && !(base->flag & OB_FROMDUPLI)) {
if (ob != bob) {
BLI_split_name_num(obname, &obnr, ob->id.name + 2, '.');
- /* object ob has to be in same "group" ... it means, that it has to have
- * same base of its name */
+ /* object ob has to be in same "group" ... it means, that it has to have same base of its name */
if (strcmp(obname, basisname) == 0) {
if (obnr < basisnr) {
- if (!(ob->flag & OB_FROMDUPLI)) {
- basis = ob;
- basisnr = obnr;
- }
+ basis = ob;
+ basisnr = obnr;
}
}
}
@@ -2227,10 +2218,7 @@ static void mball_count(EvaluationContext *eval_ctx, PROCESS *process, Scene *sc
BLI_split_name_num(basisname, &basisnr, basis->id.name + 2, '.');
process->totelem = 0;
- /* XXX recursion check, see scene.c, just too simple code this BKE_scene_base_iter_next() */
- if (F_ERROR == BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 0, NULL, NULL))
- return;
-
+ BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 0, NULL, NULL);
while (BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 1, &base, &ob)) {
if (ob->type == OB_MBALL) {
if (ob == bob) {
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index 2bf33b97a70..66c383ef0d3 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -115,16 +115,16 @@ static int customdata_compare(CustomData *c1, CustomData *c2, Mesh *m1, Mesh *m2
int i, i1 = 0, i2 = 0, tot, j;
for (i = 0; i < c1->totlayer; i++) {
- if (ELEM7(c1->layers[i].type, CD_MVERT, CD_MEDGE, CD_MPOLY,
- CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT))
+ if (ELEM(c1->layers[i].type, CD_MVERT, CD_MEDGE, CD_MPOLY,
+ CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT))
{
i1++;
}
}
for (i = 0; i < c2->totlayer; i++) {
- if (ELEM7(c2->layers[i].type, CD_MVERT, CD_MEDGE, CD_MPOLY,
- CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT))
+ if (ELEM(c2->layers[i].type, CD_MVERT, CD_MEDGE, CD_MPOLY,
+ CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT))
{
i2++;
}
@@ -135,16 +135,16 @@ static int customdata_compare(CustomData *c1, CustomData *c2, Mesh *m1, Mesh *m2
l1 = c1->layers; l2 = c2->layers;
tot = i1;
- i1 = 0; i2 = 0;
+ i1 = 0; i2 = 0;
for (i = 0; i < tot; i++) {
- while (i1 < c1->totlayer && !ELEM7(l1->type, CD_MVERT, CD_MEDGE, CD_MPOLY,
- CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT))
+ while (i1 < c1->totlayer && !ELEM(l1->type, CD_MVERT, CD_MEDGE, CD_MPOLY,
+ CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT))
{
i1++, l1++;
}
- while (i2 < c2->totlayer && !ELEM7(l2->type, CD_MVERT, CD_MEDGE, CD_MPOLY,
- CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT))
+ while (i2 < c2->totlayer && !ELEM(l2->type, CD_MVERT, CD_MEDGE, CD_MPOLY,
+ CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT))
{
i2++, l2++;
}
@@ -2041,7 +2041,7 @@ int BKE_mesh_mselect_find(Mesh *me, int index, int type)
{
int i;
- BLI_assert(ELEM3(type, ME_VSEL, ME_ESEL, ME_FSEL));
+ BLI_assert(ELEM(type, ME_VSEL, ME_ESEL, ME_FSEL));
for (i = 0; i < me->totselect; i++) {
if ((me->mselect[i].index == index) &&
@@ -2059,7 +2059,7 @@ int BKE_mesh_mselect_find(Mesh *me, int index, int type)
*/
int BKE_mesh_mselect_active_get(Mesh *me, int type)
{
- BLI_assert(ELEM3(type, ME_VSEL, ME_ESEL, ME_FSEL));
+ BLI_assert(ELEM(type, ME_VSEL, ME_ESEL, ME_FSEL));
if (me->totselect) {
if (me->mselect[me->totselect - 1].type == type) {
diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c
index 83b6d6c61d6..d244dcc931f 100644
--- a/source/blender/blenkernel/intern/mesh_evaluate.c
+++ b/source/blender/blenkernel/intern/mesh_evaluate.c
@@ -731,7 +731,7 @@ void BKE_mesh_loop_tangents(Mesh *mesh, const char *uvmap, float (*r_looptangent
}
BKE_mesh_loop_tangents_ex(mesh->mvert, mesh->totvert, mesh->mloop, r_looptangents,
- loopnors, loopuvs, mesh->totloop, mesh->mpoly, mesh->totpoly, reports);
+ loopnors, loopuvs, mesh->totloop, mesh->mpoly, mesh->totpoly, reports);
}
/** \} */
diff --git a/source/blender/blenkernel/intern/mesh_mapping.c b/source/blender/blenkernel/intern/mesh_mapping.c
index 65c576dd6a0..82065750791 100644
--- a/source/blender/blenkernel/intern/mesh_mapping.c
+++ b/source/blender/blenkernel/intern/mesh_mapping.c
@@ -442,7 +442,7 @@ int *BKE_mesh_calc_smoothgroups(const MEdge *medge, const int totedge,
/* Find contiguous smooth groups already assigned, these are the values we can't reuse! */
for (; i--; p++) {
int bit = poly_groups[*p];
- if (!ELEM3(bit, 0, poly_group_id, poly_group_id_overflowed) &&
+ if (!ELEM(bit, 0, poly_group_id, poly_group_id_overflowed) &&
!(bit_poly_group_mask & bit))
{
bit_poly_group_mask |= bit;
diff --git a/source/blender/blenkernel/intern/mesh_validate.c b/source/blender/blenkernel/intern/mesh_validate.c
index e14bb9377da..dd2c6f42c4a 100644
--- a/source/blender/blenkernel/intern/mesh_validate.c
+++ b/source/blender/blenkernel/intern/mesh_validate.c
@@ -164,16 +164,20 @@ static int search_poly_cmp(const void *v1, const void *v2)
{
const SortPoly *sp1 = v1, *sp2 = v2;
const int max_idx = sp1->numverts > sp2->numverts ? sp2->numverts : sp1->numverts;
- int idx = 0;
+ int idx;
/* Reject all invalid polys at end of list! */
if (sp1->invalid || sp2->invalid)
- return sp1->invalid && sp2->invalid ? 0 : sp1->invalid ? 1 : -1;
- /* Else, sort on first non-egal verts (remember verts of valid polys are sorted). */
- while (idx < max_idx && sp1->verts[idx] == sp2->verts[idx])
- idx++;
- return sp1->verts[idx] > sp2->verts[idx] ? 1 : sp1->verts[idx] < sp2->verts[idx] ? -1 :
- sp1->numverts > sp2->numverts ? 1 : sp1->numverts < sp2->numverts ? -1 : 0;
+ return sp1->invalid ? (sp2->invalid ? 0 : 1) : -1;
+ /* Else, sort on first non-equal verts (remember verts of valid polys are sorted). */
+ for (idx = 0; idx < max_idx; idx++) {
+ const int v1 = sp1->verts[idx];
+ const int v2 = sp2->verts[idx];
+ if (v1 != v2) {
+ return (v1 > v2) ? 1 : -1;
+ }
+ }
+ return sp1->numverts > sp2->numverts ? 1 : sp1->numverts < sp2->numverts ? -1 : 0;
}
static int search_polyloop_cmp(const void *v1, const void *v2)
diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c
index d0114d52a06..19e45142960 100644
--- a/source/blender/blenkernel/intern/nla.c
+++ b/source/blender/blenkernel/intern/nla.c
@@ -430,7 +430,7 @@ static float nlastrip_get_frame_actionclip(NlaStrip *strip, float cframe, short
return (strip->end + (strip->actstart * scale - cframe)) / scale;
}
else { /* if (mode == NLATIME_CONVERT_EVAL) */
- if (IS_EQF(cframe, strip->end) && IS_EQF(strip->repeat, ((int)strip->repeat))) {
+ if (IS_EQF((float)cframe, strip->end) && IS_EQF(strip->repeat, floorf(strip->repeat))) {
/* this case prevents the motion snapping back to the first frame at the end of the strip
* by catching the case where repeats is a whole number, which means that the end of the strip
* could also be interpreted as the end of the start of a repeat
@@ -453,7 +453,7 @@ static float nlastrip_get_frame_actionclip(NlaStrip *strip, float cframe, short
return strip->actstart + (cframe - strip->start) / scale;
}
else { /* if (mode == NLATIME_CONVERT_EVAL) */
- if (IS_EQF(cframe, strip->end) && IS_EQF(strip->repeat, ((int)strip->repeat))) {
+ if (IS_EQF(cframe, strip->end) && IS_EQF(strip->repeat, floorf(strip->repeat))) {
/* this case prevents the motion snapping back to the first frame at the end of the strip
* by catching the case where repeats is a whole number, which means that the end of the strip
* could also be interpreted as the end of the start of a repeat
@@ -1637,7 +1637,7 @@ bool BKE_nla_tweakmode_enter(AnimData *adt)
}
}
- if (ELEM3(NULL, activeTrack, activeStrip, activeStrip->act)) {
+ if (ELEM(NULL, activeTrack, activeStrip, activeStrip->act)) {
if (G.debug & G_DEBUG) {
printf("NLA tweakmode enter - neither active requirement found\n");
printf("\tactiveTrack = %p, activeStrip = %p\n", (void *)activeTrack, (void *)activeStrip);
@@ -1744,7 +1744,7 @@ static void UNUSED_FUNCTION(BKE_nla_bake) (Scene *scene, ID *UNUSED(id), AnimDat
* 1) Scene and AnimData must be provided
* 2) there must be tracks to merge...
*/
- if (ELEM3(NULL, scene, adt, adt->nla_tracks.first))
+ if (ELEM(NULL, scene, adt, adt->nla_tracks.first))
return;
/* if animdata currently has an action, 'push down' this onto the stack first */
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index 56a76a54955..0dee80e27cd 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -3406,6 +3406,7 @@ static void registerCompositNodes(void)
register_node_type_cmp_inpaint();
register_node_type_cmp_despeckle();
register_node_type_cmp_defocus();
+ register_node_type_cmp_sunbeams();
register_node_type_cmp_valtorgb();
register_node_type_cmp_rgbtobw();
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 42128a9b364..98a197b9e02 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -246,7 +246,7 @@ void BKE_object_link_modifiers(struct Object *ob_dst, struct Object *ob_src)
ModifierData *md;
BKE_object_free_modifiers(ob_dst);
- if (!ELEM5(ob_dst->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE)) {
+ if (!ELEM(ob_dst->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE)) {
/* only objects listed above can have modifiers and linking them to objects
* which doesn't have modifiers stack is quite silly */
return;
@@ -255,11 +255,11 @@ void BKE_object_link_modifiers(struct Object *ob_dst, struct Object *ob_src)
for (md = ob_src->modifiers.first; md; md = md->next) {
ModifierData *nmd = NULL;
- if (ELEM4(md->type,
- eModifierType_Hook,
- eModifierType_Softbody,
- eModifierType_ParticleInstance,
- eModifierType_Collision))
+ if (ELEM(md->type,
+ eModifierType_Hook,
+ eModifierType_Softbody,
+ eModifierType_ParticleInstance,
+ eModifierType_Collision))
{
continue;
}
@@ -296,7 +296,7 @@ void BKE_object_free_derived_caches(Object *ob)
me->bb->flag |= BOUNDBOX_DIRTY;
}
}
- else if (ELEM3(ob->type, OB_SURF, OB_CURVE, OB_FONT)) {
+ else if (ELEM(ob->type, OB_SURF, OB_CURVE, OB_FONT)) {
Curve *cu = ob->data;
if (cu->bb) {
@@ -977,7 +977,7 @@ Object *BKE_object_add_only_object(Main *bmain, int type, const char *name)
ob->empty_drawtype = OB_PLAINAXES;
ob->empty_drawsize = 1.0;
- if (ELEM3(type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
+ if (ELEM(type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
ob->trackflag = OB_NEGZ;
ob->upflag = OB_POSY;
}
@@ -1978,7 +1978,7 @@ static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[4][4])
unit_m4(mat);
cu = par->data;
- if (ELEM3(NULL, par->curve_cache, par->curve_cache->path, par->curve_cache->path->data)) /* only happens on reload file, but violates depsgraph still... fix! */
+ if (ELEM(NULL, par->curve_cache, par->curve_cache->path, par->curve_cache->path->data)) /* only happens on reload file, but violates depsgraph still... fix! */
BKE_displist_make_curveTypes(scene, par, 0);
if (par->curve_cache->path == NULL) return;
@@ -1994,17 +1994,20 @@ static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[4][4])
* we divide the curvetime calculated in the previous step by the length of the path, to get a time
* factor, which then gets clamped to lie within 0.0 - 1.0 range
*/
- if (IS_EQF(cu->pathlen, 0.0f) == 0)
+ if (cu->pathlen) {
ctime = cu->ctime / cu->pathlen;
- else
+ }
+ else {
ctime = cu->ctime;
+ }
CLAMP(ctime, 0.0f, 1.0f);
}
else {
ctime = BKE_scene_frame_get(scene);
- if (IS_EQF(cu->pathlen, 0.0f) == 0)
+ if (cu->pathlen) {
ctime /= cu->pathlen;
+ }
CLAMP(ctime, 0.0f, 1.0f);
}
@@ -2473,7 +2476,7 @@ BoundBox *BKE_object_boundbox_get(Object *ob)
if (ob->type == OB_MESH) {
bb = BKE_mesh_boundbox_get(ob);
}
- else if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
+ else if (ELEM(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
bb = BKE_curve_boundbox_get(ob);
}
else if (ob->type == OB_MBALL) {
diff --git a/source/blender/blenkernel/intern/object_dupli.c b/source/blender/blenkernel/intern/object_dupli.c
index 707438bc673..0d82c6e89a1 100644
--- a/source/blender/blenkernel/intern/object_dupli.c
+++ b/source/blender/blenkernel/intern/object_dupli.c
@@ -754,14 +754,14 @@ static void make_child_duplis_faces(const DupliContext *ctx, void *userdata, Obj
if (orco) {
int j;
- for (j = 0; j < mpoly->totloop; j++) {
+ for (j = 0; j < mp->totloop; j++) {
madd_v3_v3fl(dob->orco, orco[loopstart[j].v], w);
}
}
if (mloopuv) {
int j;
- for (j = 0; j < mpoly->totloop; j++) {
+ for (j = 0; j < mp->totloop; j++) {
madd_v2_v2fl(dob->uv, mloopuv[mp->loopstart + j].uv, w);
}
}
diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c
index 8ff8ee39a7a..27fd3fc4908 100644
--- a/source/blender/blenkernel/intern/paint.c
+++ b/source/blender/blenkernel/intern/paint.c
@@ -45,8 +45,10 @@
#include "BLI_bitmap.h"
#include "BLI_utildefines.h"
#include "BLI_math_vector.h"
+#include "BLI_listbase.h"
#include "BKE_brush.h"
+#include "BKE_main.h"
#include "BKE_context.h"
#include "BKE_crazyspace.h"
#include "BKE_depsgraph.h"
@@ -269,6 +271,105 @@ void BKE_paint_brush_set(Paint *p, Brush *br)
}
}
+void BKE_paint_curve_free(PaintCurve *pc)
+{
+ if (pc->points) {
+ MEM_freeN(pc->points);
+ pc->points = NULL;
+ pc->tot_points = 0;
+ }
+}
+
+PaintCurve *BKE_paint_curve_add(Main *bmain, const char *name)
+{
+ PaintCurve *pc;
+
+ pc = BKE_libblock_alloc(bmain, ID_PC, name);
+
+ return pc;
+}
+
+Palette *BKE_paint_palette(Paint *p)
+{
+ return p ? p->palette : NULL;
+}
+
+void BKE_paint_palette_set(Paint *p, Palette *palette)
+{
+ if (p) {
+ id_us_min((ID *)p->palette);
+ id_us_plus((ID *)palette);
+ p->palette = palette;
+ }
+}
+
+void BKE_paint_curve_set(Brush *br, PaintCurve *pc)
+{
+ if (br) {
+ id_us_min((ID *)br->paint_curve);
+ id_us_plus((ID *)pc);
+ br->paint_curve = pc;
+ }
+}
+
+/* remove colour from palette. Must be certain color is inside the palette! */
+void BKE_palette_color_remove(Palette *palette, PaletteColor *color)
+{
+ BLI_remlink(&palette->colors, color);
+ BLI_addhead(&palette->deleted, color);
+}
+
+void BKE_palette_cleanup(Palette *palette)
+{
+ BLI_freelistN(&palette->deleted);
+}
+
+
+Palette *BKE_palette_add(Main *bmain, const char *name)
+{
+ Palette *palette;
+
+ palette = BKE_libblock_alloc(bmain, ID_PAL, name);
+
+ /* enable fake user by default */
+ palette->id.flag |= LIB_FAKEUSER;
+
+ return palette;
+}
+
+void BKE_palette_free(Palette *palette)
+{
+ BLI_freelistN(&palette->colors);
+}
+
+PaletteColor *BKE_palette_color_add(Palette *palette)
+{
+ PaletteColor *color = MEM_callocN(sizeof(*color), "Pallete Color");
+ BLI_addtail(&palette->colors, color);
+ palette->active_color = BLI_countlist(&palette->colors) - 1;
+ return color;
+}
+
+void BKE_palette_color_delete(struct Palette *palette)
+{
+ PaletteColor *color = BLI_findlink(&palette->colors, palette->active_color);
+
+ if (color) {
+ if ((color == palette->colors.last) && (palette->colors.last != palette->colors.first))
+ palette->active_color--;
+
+ BLI_remlink(&palette->colors, color);
+ BLI_addhead(&palette->deleted, color);
+ }
+}
+
+
+bool BKE_palette_is_empty(const struct Palette *palette)
+{
+ return BLI_listbase_is_empty(&palette->colors);
+}
+
+
/* are we in vertex paint or weight pain face select mode? */
bool BKE_paint_select_face_test(Object *ob)
{
@@ -318,6 +419,7 @@ void BKE_paint_init(Paint *p, const char col[3])
void BKE_paint_free(Paint *paint)
{
id_us_min((ID *)paint->brush);
+ id_us_min((ID *)paint->palette);
}
/* called when copying scene settings, so even if 'src' and 'tar' are the same
@@ -328,6 +430,7 @@ void BKE_paint_copy(Paint *src, Paint *tar)
{
tar->brush = src->brush;
id_us_plus((ID *)tar->brush);
+ id_us_plus((ID *)tar->palette);
}
/* returns non-zero if any of the face's vertices
@@ -378,7 +481,7 @@ float paint_grid_paint_mask(const GridPaintMask *gpm, unsigned level,
return gpm->data[(y * factor) * gridsize + (x * factor)];
}
-/* threshhold to move before updating the brush rotation */
+/* threshold to move before updating the brush rotation */
#define RAKE_THRESHHOLD 20
void paint_calculate_rake_rotation(UnifiedPaintSettings *ups, const float mouse_pos[2])
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index 8161f9d8875..27d346f65b9 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -1657,11 +1657,14 @@ int psys_particle_dm_face_lookup(Object *ob, DerivedMesh *dm, int index, const f
index_mp_to_orig = NULL;
}
+ totface = dm->getNumTessFaces(dm);
+ if (!totface) {
+ return DMCACHE_NOTFOUND;
+ }
+
mpoly = dm->getPolyArray(dm);
osface = dm->getTessFaceDataArray(dm, CD_ORIGSPACE);
- totface = dm->getNumTessFaces(dm);
-
if (osface == NULL || index_mf_to_mpoly == NULL) {
/* Assume we don't need osface data */
if (index < totface) {
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index 5237eeda108..82818baaed0 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -117,7 +117,7 @@ static int particles_are_dynamic(ParticleSystem *psys)
if (psys->part->type == PART_HAIR)
return psys->flag & PSYS_HAIR_DYNAMICS;
else
- return ELEM3(psys->part->phystype, PART_PHYS_NEWTON, PART_PHYS_BOIDS, PART_PHYS_FLUID);
+ return ELEM(psys->part->phystype, PART_PHYS_NEWTON, PART_PHYS_BOIDS, PART_PHYS_FLUID);
}
float psys_get_current_display_percentage(ParticleSystem *psys)
@@ -1079,7 +1079,7 @@ static int distribute_threads_init_data(ParticleThread *threads, Scene *scene, D
float *element_weight=NULL,*element_sum=NULL,*jitter_offset=NULL, *vweight=NULL;
float cur, maxweight=0.0, tweight, totweight, inv_totweight, co[3], nor[3], orco[3];
- if (ELEM3(NULL, ob, psys, psys->part))
+ if (ELEM(NULL, ob, psys, psys->part))
return 0;
part=psys->part;
@@ -3153,7 +3153,7 @@ static void basic_rotate(ParticleSettings *part, ParticleData *pa, float dfra, f
extrotfac = 0.0f;
}
- if ((part->flag & PART_ROT_DYN) && ELEM3(part->avemode, PART_AVE_VELOCITY, PART_AVE_HORIZONTAL, PART_AVE_VERTICAL)) {
+ if ((part->flag & PART_ROT_DYN) && ELEM(part->avemode, PART_AVE_VELOCITY, PART_AVE_HORIZONTAL, PART_AVE_VERTICAL)) {
float angle;
float len1 = len_v3(pa->prev_state.vel);
float len2 = len_v3(pa->state.vel);
@@ -4846,13 +4846,13 @@ void psys_changed_type(Object *ob, ParticleSystem *psys)
psys->flag &= ~PSYS_KEYED;
if (part->type == PART_HAIR) {
- if (ELEM4(part->ren_as, PART_DRAW_NOT, PART_DRAW_PATH, PART_DRAW_OB, PART_DRAW_GR)==0)
+ if (ELEM(part->ren_as, PART_DRAW_NOT, PART_DRAW_PATH, PART_DRAW_OB, PART_DRAW_GR)==0)
part->ren_as = PART_DRAW_PATH;
if (part->distr == PART_DISTR_GRID)
part->distr = PART_DISTR_JIT;
- if (ELEM3(part->draw_as, PART_DRAW_NOT, PART_DRAW_REND, PART_DRAW_PATH)==0)
+ if (ELEM(part->draw_as, PART_DRAW_NOT, PART_DRAW_REND, PART_DRAW_PATH)==0)
part->draw_as = PART_DRAW_REND;
CLAMP(part->path_start, 0.0f, 100.0f);
diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index e4e6105fe8c..ccedb6f6b71 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -50,6 +50,15 @@
#define STACK_FIXED_DEPTH 100
+/* Setting zero so we can catch bugs in OpenMP/PBVH. */
+#ifdef _OPENMP
+# ifdef DEBUG
+# define PBVH_OMP_LIMIT 0
+# else
+# define PBVH_OMP_LIMIT 8
+# endif
+#endif
+
typedef struct PBVHStack {
PBVHNode *node;
int revisiting;
@@ -965,7 +974,7 @@ static void pbvh_update_normals(PBVH *bvh, PBVHNode **nodes,
* can only update vertices marked with ME_VERT_PBVH_UPDATE.
*/
-#pragma omp parallel for private(n) schedule(static)
+#pragma omp parallel for private(n) schedule(static) if (totnode > PBVH_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
PBVHNode *node = nodes[n];
@@ -1009,7 +1018,7 @@ static void pbvh_update_normals(PBVH *bvh, PBVHNode **nodes,
}
}
-#pragma omp parallel for private(n) schedule(static)
+#pragma omp parallel for private(n) schedule(static) if (totnode > PBVH_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
PBVHNode *node = nodes[n];
@@ -1046,7 +1055,7 @@ void pbvh_update_BB_redraw(PBVH *bvh, PBVHNode **nodes, int totnode, int flag)
int n;
/* update BB, redraw flag */
-#pragma omp parallel for private(n) schedule(static)
+#pragma omp parallel for private(n) schedule(static) if (totnode > PBVH_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
PBVHNode *node = nodes[n];
diff --git a/source/blender/blenkernel/intern/report.c b/source/blender/blenkernel/intern/report.c
index 90b5d8cf1a1..b2178fe69b3 100644
--- a/source/blender/blenkernel/intern/report.c
+++ b/source/blender/blenkernel/intern/report.c
@@ -284,7 +284,7 @@ Report *BKE_reports_last_displayable(ReportList *reports)
Report *report;
for (report = reports->list.last; report; report = report->prev) {
- if (ELEM3(report->type, RPT_ERROR, RPT_WARNING, RPT_INFO))
+ if (ELEM(report->type, RPT_ERROR, RPT_WARNING, RPT_INFO))
return report;
}
diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c
index 98bcdfabad3..3d61b0bdefb 100644
--- a/source/blender/blenkernel/intern/rigidbody.c
+++ b/source/blender/blenkernel/intern/rigidbody.c
@@ -395,7 +395,7 @@ static void rigidbody_validate_sim_shape(Object *ob, bool rebuild)
}
mul_v3_fl(size, 0.5f);
- if (ELEM3(rbo->shape, RB_SHAPE_CAPSULE, RB_SHAPE_CYLINDER, RB_SHAPE_CONE)) {
+ if (ELEM(rbo->shape, RB_SHAPE_CAPSULE, RB_SHAPE_CYLINDER, RB_SHAPE_CONE)) {
/* take radius as largest x/y dimension, and height as z-dimension */
radius = MAX2(size[0], size[1]);
height = size[2];
@@ -477,7 +477,7 @@ void BKE_rigidbody_calc_volume(Object *ob, float *r_vol)
// XXX: all dimensions are auto-determined now... later can add stored settings for this
BKE_object_dimensions_get(ob, size);
- if (ELEM3(rbo->shape, RB_SHAPE_CAPSULE, RB_SHAPE_CYLINDER, RB_SHAPE_CONE)) {
+ if (ELEM(rbo->shape, RB_SHAPE_CAPSULE, RB_SHAPE_CYLINDER, RB_SHAPE_CONE)) {
/* take radius as largest x/y dimension, and height as z-dimension */
radius = MAX2(size[0], size[1]) * 0.5f;
height = size[2];
@@ -720,7 +720,7 @@ static void rigidbody_validate_sim_constraint(RigidBodyWorld *rbw, Object *ob, b
return;
}
- if (ELEM4(NULL, rbc->ob1, rbc->ob1->rigidbody_object, rbc->ob2, rbc->ob2->rigidbody_object)) {
+ if (ELEM(NULL, rbc->ob1, rbc->ob1->rigidbody_object, rbc->ob2, rbc->ob2->rigidbody_object)) {
if (rbc->physics_constraint) {
RB_dworld_remove_constraint(rbw->physics_world, rbc->physics_constraint);
RB_constraint_delete(rbc->physics_constraint);
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index f8ce31f1b8a..a6e23edba56 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -39,6 +39,7 @@
#include "DNA_anim_types.h"
#include "DNA_group_types.h"
#include "DNA_linestyle_types.h"
+#include "DNA_mesh_types.h"
#include "DNA_node_types.h"
#include "DNA_object_types.h"
#include "DNA_rigidbody_types.h"
@@ -46,6 +47,8 @@
#include "DNA_screen_types.h"
#include "DNA_sequence_types.h"
#include "DNA_space_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_windowmanager_types.h"
#include "BLI_math.h"
#include "BLI_blenlib.h"
@@ -62,6 +65,7 @@
#include "BKE_action.h"
#include "BKE_colortools.h"
#include "BKE_depsgraph.h"
+#include "BKE_editmesh.h"
#include "BKE_fcurve.h"
#include "BKE_freestyle.h"
#include "BKE_global.h"
@@ -86,6 +90,8 @@
#include "IMB_colormanagement.h"
+#include "bmesh.h"
+
//XXX #include "BIF_previewrender.h"
//XXX #include "BIF_editseq.h"
@@ -510,6 +516,8 @@ Scene *BKE_scene_add(Main *bmain, const char *name)
sce->r.border.ymin = 0.0f;
sce->r.border.xmax = 1.0f;
sce->r.border.ymax = 1.0f;
+
+ sce->r.preview_start_resolution = 64;
sce->toolsettings = MEM_callocN(sizeof(struct ToolSettings), "Tool Settings Struct");
sce->toolsettings->doublimit = 0.001;
@@ -719,14 +727,14 @@ void BKE_scene_set_background(Main *bmain, Scene *scene)
/* called from creator.c */
Scene *BKE_scene_set_name(Main *bmain, const char *name)
{
- Scene *sce = (Scene *)BKE_libblock_find_name(ID_SCE, name);
+ Scene *sce = (Scene *)BKE_libblock_find_name_ex(bmain, ID_SCE, name);
if (sce) {
BKE_scene_set_background(bmain, sce);
- printf("Scene switch: '%s' in file: '%s'\n", name, G.main->name);
+ printf("Scene switch: '%s' in file: '%s'\n", name, bmain->name);
return sce;
}
- printf("Can't find scene: '%s' in file: '%s'\n", name, G.main->name);
+ printf("Can't find scene: '%s' in file: '%s'\n", name, bmain->name);
return NULL;
}
@@ -804,9 +812,7 @@ void BKE_scene_unlink(Main *bmain, Scene *sce, Scene *newsce)
BKE_libblock_free(bmain, sce);
}
-/* used by metaballs
- * doesn't return the original duplicated object, only dupli's
- */
+/* Used by metaballs, return *all* objects (including duplis) existing in the scene (including scene's sets) */
int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter,
Scene **scene, int val, Base **base, Object **ob)
{
@@ -817,11 +823,12 @@ int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter,
iter->phase = F_START;
iter->dupob = NULL;
iter->duplilist = NULL;
+ iter->dupli_refob = NULL;
}
else {
/* run_again is set when a duplilist has been ended */
while (run_again) {
- run_again = 0;
+ run_again = false;
/* the first base */
if (iter->phase == F_START) {
@@ -879,34 +886,46 @@ int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter,
iter->dupob = iter->duplilist->first;
- if (!iter->dupob)
+ if (!iter->dupob) {
free_object_duplilist(iter->duplilist);
+ iter->duplilist = NULL;
+ }
+ iter->dupli_refob = NULL;
}
}
}
/* handle dupli's */
if (iter->dupob) {
-
- copy_m4_m4(iter->omat, iter->dupob->ob->obmat);
- copy_m4_m4(iter->dupob->ob->obmat, iter->dupob->mat);
-
(*base)->flag |= OB_FROMDUPLI;
*ob = iter->dupob->ob;
iter->phase = F_DUPLI;
-
+
+ if (iter->dupli_refob != *ob) {
+ if (iter->dupli_refob) {
+ /* Restore previous object's real matrix. */
+ copy_m4_m4(iter->dupli_refob->obmat, iter->omat);
+ }
+ /* Backup new object's real matrix. */
+ iter->dupli_refob = *ob;
+ copy_m4_m4(iter->omat, iter->dupli_refob->obmat);
+ }
+ copy_m4_m4((*ob)->obmat, iter->dupob->mat);
+
iter->dupob = iter->dupob->next;
}
else if (iter->phase == F_DUPLI) {
iter->phase = F_SCENE;
(*base)->flag &= ~OB_FROMDUPLI;
- for (iter->dupob = iter->duplilist->first; iter->dupob; iter->dupob = iter->dupob->next) {
- copy_m4_m4(iter->dupob->ob->obmat, iter->omat);
+ if (iter->dupli_refob) {
+ /* Restore last object's real matrix. */
+ copy_m4_m4(iter->dupli_refob->obmat, iter->omat);
+ iter->dupli_refob = NULL;
}
free_object_duplilist(iter->duplilist);
iter->duplilist = NULL;
- run_again = 1;
+ run_again = true;
}
}
}
@@ -1541,6 +1560,53 @@ static void scene_update_tagged_recursive(EvaluationContext *eval_ctx, Main *bma
}
+static bool check_rendered_viewport_visible(Main *bmain)
+{
+ wmWindowManager *wm = bmain->wm.first;
+ wmWindow *window;
+ for (window = wm->windows.first; window != NULL; window = window->next) {
+ bScreen *screen = window->screen;
+ ScrArea *area;
+ for (area = screen->areabase.first; area != NULL; area = area->next) {
+ View3D *v3d = area->spacedata.first;
+ if (area->spacetype != SPACE_VIEW3D) {
+ continue;
+ }
+ if (v3d->drawtype == OB_RENDER) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+static void prepare_mesh_for_viewport_render(Main *bmain, Scene *scene)
+{
+ /* This is needed to prepare mesh to be used by the render
+ * engine from the viewport rendering. We do loading here
+ * so all the objects which shares the same mesh datablock
+ * are nicely tagged for update and updated.
+ *
+ * This makes it so viewport render engine doesn't need to
+ * call loading of the edit data for the mesh objects.
+ */
+
+ Object *obedit = scene->obedit;
+ if (obedit) {
+ Mesh *mesh = obedit->data;
+ /* TODO(sergey): Check object recalc flags as well? */
+ if ((obedit->type == OB_MESH) &&
+ (mesh->id.flag & (LIB_ID_RECALC | LIB_ID_RECALC_DATA)))
+ {
+ if (check_rendered_viewport_visible(bmain)) {
+ BMesh *bm = mesh->edit_btmesh->bm;
+ BM_mesh_bm_to_me(bm, mesh, false);
+ DAG_id_tag_update(&mesh->id, 0);
+ }
+ }
+ }
+}
+
void BKE_scene_update_tagged(EvaluationContext *eval_ctx, Main *bmain, Scene *scene)
{
Scene *sce_iter;
@@ -1552,6 +1618,9 @@ void BKE_scene_update_tagged(EvaluationContext *eval_ctx, Main *bmain, Scene *sc
for (sce_iter = scene; sce_iter; sce_iter = sce_iter->set)
DAG_scene_relations_update(bmain, sce_iter);
+ /* flush editing data if needed */
+ prepare_mesh_for_viewport_render(bmain, scene);
+
/* flush recalc flags to dependencies */
DAG_ids_flush_tagged(bmain);
diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c
index 2b14b92217b..d2dc9da47f9 100644
--- a/source/blender/blenkernel/intern/seqeffects.c
+++ b/source/blender/blenkernel/intern/seqeffects.c
@@ -52,6 +52,11 @@
#include "RNA_access.h"
+/* TODO(sergey): Could be considered a bad level call, but
+ * need this for gaussian table.
+ */
+#include "RE_pipeline.h"
+
static void slice_get_byte_buffers(const SeqRenderData *context, const ImBuf *ibuf1, const ImBuf *ibuf2,
const ImBuf *ibuf3, const ImBuf *out, int start_line, unsigned char **rect1,
unsigned char **rect2, unsigned char **rect3, unsigned char **rect_out)
@@ -2579,6 +2584,295 @@ static void do_overdrop_effect(const SeqRenderData *context, Sequence *UNUSED(se
}
}
+/*********************** Gaussian Blur *************************/
+
+/* NOTE: This gaussian blur implementation accumulates values in the square
+ * kernel rather that doing X direction and then Y direction because of the
+ * lack of using multiple-staged filters.
+ *
+ * Once we can we'll implement a way to apply filter as multiple stages we
+ * can optimize hell of a lot in here.
+ */
+
+static void init_gaussian_blur_effect(Sequence *seq)
+{
+ if (seq->effectdata)
+ MEM_freeN(seq->effectdata);
+
+ seq->effectdata = MEM_callocN(sizeof(WipeVars), "wipevars");
+}
+
+static int num_inputs_gaussian_blur(void)
+{
+ return 1;
+}
+
+static void free_gaussian_blur_effect(Sequence *seq)
+{
+ if (seq->effectdata)
+ MEM_freeN(seq->effectdata);
+
+ seq->effectdata = NULL;
+}
+
+static void copy_gaussian_blur_effect(Sequence *dst, Sequence *src)
+{
+ dst->effectdata = MEM_dupallocN(src->effectdata);
+}
+
+static int early_out_gaussian_blur(Sequence *seq, float UNUSED(facf0), float UNUSED(facf1))
+{
+ GaussianBlurVars *data = seq->effectdata;
+ if (data->size_x == 0.0f && data->size_y == 0) {
+ return EARLY_USE_INPUT_1;
+ }
+ return EARLY_DO_EFFECT;
+}
+
+/* TODO(sergey): De-duplicate with compositor. */
+static float *make_gaussian_blur_kernel(float rad, int size)
+{
+ float *gausstab, sum, val;
+ float fac;
+ int i, n;
+
+ n = 2 * size + 1;
+
+ gausstab = (float *)MEM_mallocN(sizeof(float) * n, __func__);
+
+ sum = 0.0f;
+ fac = (rad > 0.0f ? 1.0f / rad : 0.0f);
+ for (i = -size; i <= size; i++) {
+ val = RE_filter_value(R_FILTER_GAUSS, (float)i * fac);
+ sum += val;
+ gausstab[i + size] = val;
+ }
+
+ sum = 1.0f / sum;
+ for (i = 0; i < n; i++)
+ gausstab[i] *= sum;
+
+ return gausstab;
+}
+
+static void do_gaussian_blur_effect_byte(Sequence *seq,
+ int start_line,
+ int x, int y,
+ int frame_width, int frame_height,
+ unsigned char *rect,
+ unsigned char *out)
+{
+#define INDEX(_x, _y) (((_y) * (x) + (_x)) * 4)
+ GaussianBlurVars *data = seq->effectdata;
+ const int size_x = (int) (data->size_x + 0.5f),
+ size_y = (int) (data->size_y + 0.5f);
+ int i, j;
+
+ /* Make gaussian weight tabke. */
+ float *gausstab_x, *gausstab_y;
+ gausstab_x = make_gaussian_blur_kernel(data->size_x, size_x);
+ if (data->size_x == data->size_y) {
+ gausstab_y = gausstab_x;
+ }
+ else {
+ gausstab_y = make_gaussian_blur_kernel(data->size_y, size_y);
+ }
+
+ for (i = 0; i < y; ++i) {
+ for (j = 0; j < x; ++j) {
+ int out_index = INDEX(j, i);
+ int current_x, current_y;
+ float accum[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ float accum_weight = 0.0f;
+ for (current_y = i - size_y;
+ current_y <= i + size_y;
+ ++current_y)
+ {
+ if (current_y < -start_line ||
+ current_y + start_line >= frame_height)
+ {
+ /* Out of bounds. */
+ continue;
+ }
+
+ for (current_x = j - size_x;
+ current_x <= j + size_x;
+ ++current_x)
+ {
+ float weight;
+ int index = INDEX(current_x, current_y + start_line);
+ if (current_x < 0 || current_x >= frame_width) {
+ /* Out of bounds. */
+ continue;
+ }
+ BLI_assert(index >= 0);
+ BLI_assert(index < frame_width * frame_height * 4);
+
+ if (size_x != 0 && size_y != 0) {
+ weight = gausstab_x[current_x - j + size_x] *
+ gausstab_y[current_y - i + size_y];
+ }
+ else if (size_x == 0) {
+ weight = gausstab_y[current_y - i + size_y];
+ }
+ else {
+ weight = gausstab_x[current_x - j + size_x];
+ }
+ accum[0] += rect[index] * weight;
+ accum[1] += rect[index + 1] * weight;
+ accum[2] += rect[index + 2] * weight;
+ accum[3] += rect[index + 3] * weight;
+ accum_weight += weight;
+ }
+ }
+ out[out_index + 0] = accum[0] / accum_weight;
+ out[out_index + 1] = accum[1] / accum_weight;
+ out[out_index + 2] = accum[2] / accum_weight;
+ out[out_index + 3] = accum[3] / accum_weight;
+ }
+ }
+
+ MEM_freeN(gausstab_x);
+ if (gausstab_x != gausstab_y) {
+ MEM_freeN(gausstab_y);
+ }
+#undef INDEX
+}
+
+static void do_gaussian_blur_effect_float(Sequence *seq,
+ int start_line,
+ int x, int y,
+ int frame_width, int frame_height,
+ float *rect,
+ float *out)
+{
+#define INDEX(_x, _y) (((_y) * (x) + (_x)) * 4)
+ GaussianBlurVars *data = seq->effectdata;
+ const int size_x = (int) (data->size_x + 0.5f),
+ size_y = (int) (data->size_y + 0.5f);
+ int i, j;
+
+ /* Make gaussian weight tabke. */
+ float *gausstab_x, *gausstab_y;
+ gausstab_x = make_gaussian_blur_kernel(data->size_x, size_x);
+ if (data->size_x == data->size_y) {
+ gausstab_y = gausstab_x;
+ }
+ else {
+ gausstab_y = make_gaussian_blur_kernel(data->size_y, size_y);
+ }
+
+ for (i = 0; i < y; ++i) {
+ for (j = 0; j < x; ++j) {
+ int out_index = INDEX(j, i);
+ int current_x, current_y;
+ float accum[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ float accum_weight = 0.0f;
+ for (current_y = i - size_y;
+ current_y <= i + size_y;
+ ++current_y)
+ {
+ float weight;
+ if (current_y < -start_line ||
+ current_y + start_line >= frame_height)
+ {
+ /* Out of bounds. */
+ continue;
+ }
+
+ for (current_x = j - size_x;
+ current_x <= j + size_x;
+ ++current_x)
+ {
+ int index = INDEX(current_x, current_y + start_line);
+ if (current_x < 0 || current_x >= frame_width) {
+ /* Out of bounds. */
+ continue;
+ }
+
+ if (size_x != 0 && size_y != 0) {
+ weight = gausstab_x[current_x - j + size_x] *
+ gausstab_y[current_y - i + size_y];
+ }
+ else if (size_x == 0) {
+ weight = gausstab_y[current_y - i + size_y];
+ }
+ else {
+ weight = gausstab_x[current_x - j + size_x];
+ }
+ madd_v4_v4fl(accum, &rect[index], weight);
+ accum_weight += weight;
+ }
+ }
+ mul_v4_v4fl(&out[out_index], accum, 1.0f / accum_weight);
+ }
+ }
+
+ MEM_freeN(gausstab_x);
+ if (gausstab_x != gausstab_y) {
+ MEM_freeN(gausstab_y);
+ }
+#undef INDEX
+}
+
+static void do_gaussian_blur_effect(const SeqRenderData *context,
+ Sequence *seq,
+ float UNUSED(cfra),
+ float UNUSED(facf0),
+ float UNUSED(facf1),
+ ImBuf *ibuf1,
+ ImBuf *ibuf2,
+ ImBuf *UNUSED(ibuf3),
+ int start_line,
+ int total_lines,
+ ImBuf *out)
+{
+ if (out->rect_float) {
+ float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
+
+ slice_get_float_buffers(context,
+ ibuf1, ibuf2,
+ NULL,
+ out,
+ start_line,
+ &rect1,
+ &rect2,
+ NULL,
+ &rect_out);
+
+ do_gaussian_blur_effect_float(seq,
+ start_line,
+ context->rectx,
+ total_lines,
+ context->rectx,
+ context->recty,
+ ibuf1->rect_float,
+ rect_out);
+ }
+ else {
+ unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
+
+ slice_get_byte_buffers(context,
+ ibuf1, ibuf2,
+ NULL,
+ out,
+ start_line,
+ &rect1,
+ &rect2,
+ NULL,
+ &rect_out);
+
+ do_gaussian_blur_effect_byte(seq,
+ start_line,
+ context->rectx,
+ total_lines,
+ context->rectx,
+ context->recty,
+ (unsigned char *) ibuf1->rect,
+ rect_out);
+ }
+}
+
/*********************** sequence effect factory *************************/
static void init_noop(Sequence *UNUSED(seq))
@@ -2767,6 +3061,15 @@ static struct SeqEffectHandle get_sequence_effect_impl(int seq_type)
rval.early_out = early_out_adjustment;
rval.execute = do_adjustment;
break;
+ case SEQ_TYPE_GAUSSIAN_BLUR:
+ rval.multithreaded = true;
+ rval.init = init_gaussian_blur_effect;
+ rval.num_inputs = num_inputs_gaussian_blur;
+ rval.free = free_gaussian_blur_effect;
+ rval.copy = copy_gaussian_blur_effect;
+ rval.early_out = early_out_gaussian_blur;
+ rval.execute_slice = do_gaussian_blur_effect;
+ break;
}
return rval;
diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c
index f5efe04951f..dedf5e8bd72 100644
--- a/source/blender/blenkernel/intern/sequencer.c
+++ b/source/blender/blenkernel/intern/sequencer.c
@@ -758,7 +758,7 @@ void BKE_sequence_reload_new_file(Scene *scene, Sequence *seq, const bool lock_r
int prev_startdisp = 0, prev_enddisp = 0;
/* note: don't rename the strip, will break animation curves */
- if (ELEM7(seq->type,
+ if (ELEM(seq->type,
SEQ_TYPE_MOVIE, SEQ_TYPE_IMAGE, SEQ_TYPE_SOUND_RAM,
SEQ_TYPE_SCENE, SEQ_TYPE_META, SEQ_TYPE_MOVIECLIP, SEQ_TYPE_MASK) == 0)
{
@@ -994,28 +994,29 @@ void BKE_sequence_base_unique_name_recursive(ListBase *seqbasep, Sequence *seq)
static const char *give_seqname_by_type(int type)
{
switch (type) {
- case SEQ_TYPE_META: return "Meta";
- case SEQ_TYPE_IMAGE: return "Image";
- case SEQ_TYPE_SCENE: return "Scene";
- case SEQ_TYPE_MOVIE: return "Movie";
- case SEQ_TYPE_MOVIECLIP: return "Clip";
- case SEQ_TYPE_MASK: return "Mask";
- case SEQ_TYPE_SOUND_RAM: return "Audio";
- case SEQ_TYPE_CROSS: return "Cross";
- case SEQ_TYPE_GAMCROSS: return "Gamma Cross";
- case SEQ_TYPE_ADD: return "Add";
- case SEQ_TYPE_SUB: return "Sub";
- case SEQ_TYPE_MUL: return "Mul";
- case SEQ_TYPE_ALPHAOVER: return "Alpha Over";
- case SEQ_TYPE_ALPHAUNDER: return "Alpha Under";
- case SEQ_TYPE_OVERDROP: return "Over Drop";
- case SEQ_TYPE_WIPE: return "Wipe";
- case SEQ_TYPE_GLOW: return "Glow";
- case SEQ_TYPE_TRANSFORM: return "Transform";
- case SEQ_TYPE_COLOR: return "Color";
- case SEQ_TYPE_MULTICAM: return "Multicam";
- case SEQ_TYPE_ADJUSTMENT: return "Adjustment";
- case SEQ_TYPE_SPEED: return "Speed";
+ case SEQ_TYPE_META: return "Meta";
+ case SEQ_TYPE_IMAGE: return "Image";
+ case SEQ_TYPE_SCENE: return "Scene";
+ case SEQ_TYPE_MOVIE: return "Movie";
+ case SEQ_TYPE_MOVIECLIP: return "Clip";
+ case SEQ_TYPE_MASK: return "Mask";
+ case SEQ_TYPE_SOUND_RAM: return "Audio";
+ case SEQ_TYPE_CROSS: return "Cross";
+ case SEQ_TYPE_GAMCROSS: return "Gamma Cross";
+ case SEQ_TYPE_ADD: return "Add";
+ case SEQ_TYPE_SUB: return "Sub";
+ case SEQ_TYPE_MUL: return "Mul";
+ case SEQ_TYPE_ALPHAOVER: return "Alpha Over";
+ case SEQ_TYPE_ALPHAUNDER: return "Alpha Under";
+ case SEQ_TYPE_OVERDROP: return "Over Drop";
+ case SEQ_TYPE_WIPE: return "Wipe";
+ case SEQ_TYPE_GLOW: return "Glow";
+ case SEQ_TYPE_TRANSFORM: return "Transform";
+ case SEQ_TYPE_COLOR: return "Color";
+ case SEQ_TYPE_MULTICAM: return "Multicam";
+ case SEQ_TYPE_ADJUSTMENT: return "Adjustment";
+ case SEQ_TYPE_SPEED: return "Speed";
+ case SEQ_TYPE_GAUSSIAN_BLUR: return "Gaussian Blur";
default:
return NULL;
}
@@ -2224,7 +2225,7 @@ static ImBuf *seq_render_effect_execute_threaded(struct SeqEffectHandle *sh, con
init_data.out = out;
IMB_processor_apply_threaded(out->y, sizeof(RenderEffectThread), &init_data,
- render_effect_execute_init_handle, render_effect_execute_do_thread);
+ render_effect_execute_init_handle, render_effect_execute_do_thread);
return out;
}
@@ -2808,7 +2809,7 @@ static ImBuf *seq_render_strip(const SeqRenderData *context, Sequence *seq, floa
float nr = give_stripelem_index(seq, cfra);
/* all effects are handled similarly with the exception of speed effect */
int type = (seq->type & SEQ_TYPE_EFFECT && seq->type != SEQ_TYPE_SPEED) ? SEQ_TYPE_EFFECT : seq->type;
- bool is_preprocessed = !ELEM3(type, SEQ_TYPE_IMAGE, SEQ_TYPE_MOVIE, SEQ_TYPE_SCENE);
+ bool is_preprocessed = !ELEM(type, SEQ_TYPE_IMAGE, SEQ_TYPE_MOVIE, SEQ_TYPE_SCENE);
ibuf = BKE_sequencer_cache_get(context, seq, cfra, SEQ_STRIPELEM_IBUF);
@@ -2875,7 +2876,7 @@ static bool seq_must_swap_input_in_blend_mode(Sequence *seq)
/* bad hack, to fix crazy input ordering of
* those two effects */
- if (ELEM3(seq->blend_mode, SEQ_TYPE_ALPHAOVER, SEQ_TYPE_ALPHAUNDER, SEQ_TYPE_OVERDROP)) {
+ if (ELEM(seq->blend_mode, SEQ_TYPE_ALPHAOVER, SEQ_TYPE_ALPHAUNDER, SEQ_TYPE_OVERDROP)) {
swap_input = true;
}
@@ -2960,7 +2961,7 @@ static ImBuf *seq_render_strip_stack(const SeqRenderData *context, ListBase *seq
/* Some of the blend modes are unclear how to apply with only single input,
* or some of them will just produce an empty result..
*/
- if (ELEM3(seq->blend_mode, SEQ_BLEND_REPLACE, SEQ_TYPE_CROSS, SEQ_TYPE_ALPHAOVER)) {
+ if (ELEM(seq->blend_mode, SEQ_BLEND_REPLACE, SEQ_TYPE_CROSS, SEQ_TYPE_ALPHAOVER)) {
int early_out;
if (seq->blend_mode == SEQ_BLEND_REPLACE) {
early_out = EARLY_NO_INPUT;
@@ -3688,7 +3689,7 @@ Sequence *BKE_sequencer_foreground_frame_get(Scene *scene, int frame)
if (seq->flag & SEQ_MUTE || seq->startdisp > frame || seq->enddisp <= frame)
continue;
/* only use elements you can see - not */
- if (ELEM5(seq->type, SEQ_TYPE_IMAGE, SEQ_TYPE_META, SEQ_TYPE_SCENE, SEQ_TYPE_MOVIE, SEQ_TYPE_COLOR)) {
+ if (ELEM(seq->type, SEQ_TYPE_IMAGE, SEQ_TYPE_META, SEQ_TYPE_SCENE, SEQ_TYPE_MOVIE, SEQ_TYPE_COLOR)) {
if (seq->machine > best_machine) {
best_seq = seq;
best_machine = seq->machine;
diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c
index e2cc7b84f95..d2a4d15a2c6 100644
--- a/source/blender/blenkernel/intern/shrinkwrap.c
+++ b/source/blender/blenkernel/intern/shrinkwrap.c
@@ -50,6 +50,7 @@
#include "BKE_lattice.h"
#include "BKE_deform.h"
+#include "BKE_mesh.h" /* for OMP limits. */
#include "BKE_subsurf.h"
#include "BKE_editmesh.h"
@@ -65,57 +66,6 @@
/* Util macros */
#define OUT_OF_MEMORY() ((void)printf("Shrinkwrap: Out of memory\n"))
-/* get derived mesh */
-/* TODO is anyfunction that does this? returning the derivedFinal without we caring if its in edit mode or not? */
-DerivedMesh *object_get_derived_final(Object *ob, bool for_render)
-{
- Mesh *me = ob->data;
- BMEditMesh *em = me->edit_btmesh;
-
- if (for_render) {
- /* TODO(sergey): use proper derived render here in the future. */
- return ob->derivedFinal;
- }
-
- if (em) {
- DerivedMesh *dm = em->derivedFinal;
- return dm;
- }
-
- return ob->derivedFinal;
-}
-
-/* Space transform */
-void space_transform_from_matrixs(SpaceTransform *data, float local[4][4], float target[4][4])
-{
- float itarget[4][4];
- invert_m4_m4(itarget, target);
- mul_m4_m4m4(data->local2target, itarget, local);
- invert_m4_m4(data->target2local, data->local2target);
-}
-
-void space_transform_apply(const SpaceTransform *data, float co[3])
-{
- mul_v3_m4v3(co, ((SpaceTransform *)data)->local2target, co);
-}
-
-void space_transform_invert(const SpaceTransform *data, float co[3])
-{
- mul_v3_m4v3(co, ((SpaceTransform *)data)->target2local, co);
-}
-
-static void space_transform_apply_normal(const SpaceTransform *data, float no[3])
-{
- mul_mat3_m4_v3(((SpaceTransform *)data)->local2target, no);
- normalize_v3(no); /* TODO: could we just determine de scale value from the matrix? */
-}
-
-static void space_transform_invert_normal(const SpaceTransform *data, float no[3])
-{
- mul_mat3_m4_v3(((SpaceTransform *)data)->target2local, no);
- normalize_v3(no); /* TODO: could we just determine de scale value from the matrix? */
-}
-
/*
* Shrinkwrap to the nearest vertex
*
@@ -135,12 +85,12 @@ static void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *calc)
OUT_OF_MEMORY();
return;
}
-
+
/* Setup nearest */
nearest.index = -1;
nearest.dist_sq = FLT_MAX;
#ifndef __APPLE__
-#pragma omp parallel for default(none) private(i) firstprivate(nearest) shared(treeData, calc) schedule(static)
+#pragma omp parallel for default(none) private(i) firstprivate(nearest) shared(treeData, calc) schedule(static) if(calc->numVerts > BKE_MESH_OMP_LIMIT)
#endif
for (i = 0; i < calc->numVerts; ++i) {
float *co = calc->vertexCos[i];
@@ -158,7 +108,7 @@ static void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *calc)
else {
copy_v3_v3(tmp_co, co);
}
- space_transform_apply(&calc->local2target, tmp_co);
+ BLI_space_transform_apply(&calc->local2target, tmp_co);
/* Use local proximity heuristics (to reduce the nearest search)
*
@@ -184,7 +134,7 @@ static void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *calc)
/* Convert the coordinates back to mesh coordinates */
copy_v3_v3(tmp_co, nearest.co);
- space_transform_invert(&calc->local2target, tmp_co);
+ BLI_space_transform_invert(&calc->local2target, tmp_co);
interp_v3_v3v3(co, co, tmp_co, weight); /* linear interpolation */
}
@@ -223,11 +173,11 @@ bool BKE_shrinkwrap_project_normal(
/* Apply space transform (TODO readjust dist) */
if (transf) {
copy_v3_v3(tmp_co, vert);
- space_transform_apply(transf, tmp_co);
+ BLI_space_transform_apply(transf, tmp_co);
co = tmp_co;
copy_v3_v3(tmp_no, dir);
- space_transform_apply_normal(transf, tmp_no);
+ BLI_space_transform_apply_normal(transf, tmp_no);
no = tmp_no;
#ifdef USE_DIST_CORRECT
@@ -246,7 +196,7 @@ bool BKE_shrinkwrap_project_normal(
if (hit_tmp.index != -1) {
/* invert the normal first so face culling works on rotated objects */
if (transf) {
- space_transform_invert_normal(transf, hit_tmp.no);
+ BLI_space_transform_invert_normal(transf, hit_tmp.no);
}
if (options & (MOD_SHRINKWRAP_CULL_TARGET_FRONTFACE | MOD_SHRINKWRAP_CULL_TARGET_BACKFACE)) {
@@ -261,7 +211,7 @@ bool BKE_shrinkwrap_project_normal(
if (transf) {
/* Inverting space transform (TODO make coeherent with the initial dist readjust) */
- space_transform_invert(transf, hit_tmp.co);
+ BLI_space_transform_invert(transf, hit_tmp.co);
#ifdef USE_DIST_CORRECT
hit_tmp.dist = len_v3v3(vert, hit_tmp.co);
#endif
@@ -326,7 +276,7 @@ static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc, bool for
auxMesh = object_get_derived_final(calc->smd->auxTarget, for_render);
if (!auxMesh)
return;
- SPACE_TRANSFORM_SETUP(&local2aux, calc->ob, calc->smd->auxTarget);
+ BLI_SPACE_TRANSFORM_SETUP(&local2aux, calc->ob, calc->smd->auxTarget);
}
/* After sucessufuly build the trees, start projection vertexs */
@@ -335,7 +285,7 @@ static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc, bool for
{
#ifndef __APPLE__
-#pragma omp parallel for private(i, hit) schedule(static)
+#pragma omp parallel for private(i, hit) schedule(static) if (calc->numVerts > BKE_MESH_OMP_LIMIT)
#endif
for (i = 0; i < calc->numVerts; ++i) {
float *co = calc->vertexCos[i];
@@ -445,7 +395,7 @@ static void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc)
/* Find the nearest vertex */
#ifndef __APPLE__
-#pragma omp parallel for default(none) private(i) firstprivate(nearest) shared(calc, treeData) schedule(static)
+#pragma omp parallel for default(none) private(i) firstprivate(nearest) shared(calc, treeData) schedule(static) if(calc->numVerts > BKE_MESH_OMP_LIMIT)
#endif
for (i = 0; i < calc->numVerts; ++i) {
float *co = calc->vertexCos[i];
@@ -460,7 +410,7 @@ static void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc)
else {
copy_v3_v3(tmp_co, co);
}
- space_transform_apply(&calc->local2target, tmp_co);
+ BLI_space_transform_apply(&calc->local2target, tmp_co);
/* Use local proximity heuristics (to reduce the nearest search)
*
@@ -494,7 +444,7 @@ static void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc)
}
/* Convert the coordinates back to mesh coordinates */
- space_transform_invert(&calc->local2target, tmp_co);
+ BLI_space_transform_invert(&calc->local2target, tmp_co);
interp_v3_v3v3(co, co, tmp_co, weight); /* linear interpolation */
}
}
@@ -537,7 +487,7 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Object *ob, DerivedM
/* TODO there might be several "bugs" on non-uniform scales matrixs
* because it will no longer be nearest surface, not sphere projection
* because space has been deformed */
- SPACE_TRANSFORM_SETUP(&calc.local2target, ob, smd->target);
+ BLI_SPACE_TRANSFORM_SETUP(&calc.local2target, ob, smd->target);
/* TODO: smd->keepDist is in global units.. must change to local */
calc.keepDist = smd->keepDist;
diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c
index 11dc9150d8f..79c348ac181 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -41,6 +41,7 @@
#include "MEM_guardedalloc.h"
+#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_modifier_types.h"
@@ -2291,18 +2292,23 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
DMSetDrawOptionsTex drawParams,
DMSetDrawOptions drawParamsMapped,
DMCompareDrawOptions compareDrawOptions,
- void *userData)
+ void *userData, DMDrawFlag flag)
{
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
CCGSubSurf *ss = ccgdm->ss;
CCGKey key;
MCol *mcol = dm->getTessFaceDataArray(dm, CD_PREVIEW_MCOL);
MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
+ MTFace *tf_stencil_base = NULL;
+ MTFace *tf_stencil = NULL;
+ MTFace *tf_base;
short (*lnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL);
DMFlagMat *faceFlags = ccgdm->faceFlags;
DMDrawOption draw_option;
int i, totface, gridSize = ccgSubSurf_getGridSize(ss);
int gridFaces = gridSize - 1;
+ int gridOffset = 0;
+ int mat_nr_cache = -1;
(void) compareDrawOptions;
@@ -2316,6 +2322,12 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
mcol = dm->getTessFaceDataArray(dm, CD_TEXTURE_MCOL);
totface = ccgSubSurf_getNumFaces(ss);
+
+ if (flag & DM_DRAW_USE_TEXPAINT_UV) {
+ int stencil = CustomData_get_stencil_layer(&dm->faceData, CD_MTFACE);
+ tf_stencil_base = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, stencil);
+ }
+
for (i = 0; i < totface; i++) {
CCGFace *f = ccgdm->faceMap[i].face;
int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
@@ -2334,6 +2346,18 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
mat_nr = 0;
}
+ /* texture painting, handle the correct uv layer here */
+ if (flag & DM_DRAW_USE_TEXPAINT_UV) {
+ if (mat_nr != mat_nr_cache) {
+ tf_base = DM_paint_uvlayer_active_get(dm, mat_nr);
+
+ mat_nr_cache = mat_nr;
+ }
+ tf = tf_base + gridOffset;
+ tf_stencil = tf_stencil_base + gridOffset;
+ gridOffset += gridFaces * gridFaces * numVerts;
+ }
+
if (drawParams)
draw_option = drawParams(tf, (mcol != NULL), mat_nr);
else if (index != ORIGINDEX_NONE)
@@ -2374,26 +2398,31 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
float *d_co = CCG_grid_elem_co(&key, faceGridData, x, y + 1);
if (tf) glTexCoord2fv(tf->uv[1]);
+ if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE1, tf_stencil->uv[1]);
if (cp) glColor3ub(cp[7], cp[6], cp[5]);
glNormal3sv(ln[0][1]);
glVertex3fv(d_co);
if (tf) glTexCoord2fv(tf->uv[2]);
+ if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE1, tf_stencil->uv[2]);
if (cp) glColor3ub(cp[11], cp[10], cp[9]);
glNormal3sv(ln[0][2]);
glVertex3fv(c_co);
if (tf) glTexCoord2fv(tf->uv[3]);
+ if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE1, tf_stencil->uv[3]);
if (cp) glColor3ub(cp[15], cp[14], cp[13]);
glNormal3sv(ln[0][3]);
glVertex3fv(b_co);
if (tf) glTexCoord2fv(tf->uv[0]);
+ if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE1, tf_stencil->uv[0]);
if (cp) glColor3ub(cp[3], cp[2], cp[1]);
glNormal3sv(ln[0][0]);
glVertex3fv(a_co);
if (tf) tf++;
+ if (tf_stencil) tf_stencil++;
if (cp) cp += 16;
ln++;
}
@@ -2409,17 +2438,20 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
b = CCG_grid_elem(&key, faceGridData, x, y + 1);
if (tf) glTexCoord2fv(tf->uv[0]);
+ if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE1, tf_stencil->uv[0]);
if (cp) glColor3ub(cp[3], cp[2], cp[1]);
glNormal3fv(CCG_elem_no(&key, a));
glVertex3fv(CCG_elem_co(&key, a));
if (tf) glTexCoord2fv(tf->uv[1]);
+ if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE1, tf_stencil->uv[1]);
if (cp) glColor3ub(cp[7], cp[6], cp[5]);
glNormal3fv(CCG_elem_no(&key, b));
glVertex3fv(CCG_elem_co(&key, b));
if (x != gridFaces - 1) {
if (tf) tf++;
+ if (tf_stencil) tf_stencil++;
if (cp) cp += 16;
}
}
@@ -2428,16 +2460,19 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
b = CCG_grid_elem(&key, faceGridData, x, y + 1);
if (tf) glTexCoord2fv(tf->uv[3]);
+ if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE1, tf_stencil->uv[3]);
if (cp) glColor3ub(cp[15], cp[14], cp[13]);
glNormal3fv(CCG_elem_no(&key, a));
glVertex3fv(CCG_elem_co(&key, a));
if (tf) glTexCoord2fv(tf->uv[2]);
+ if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE1, tf_stencil->uv[2]);
if (cp) glColor3ub(cp[11], cp[10], cp[9]);
glNormal3fv(CCG_elem_no(&key, b));
glVertex3fv(CCG_elem_co(&key, b));
if (tf) tf++;
+ if (tf_stencil) tf_stencil++;
if (cp) cp += 16;
glEnd();
@@ -2456,22 +2491,27 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
ccgDM_glNormalFast(a_co, b_co, c_co, d_co);
if (tf) glTexCoord2fv(tf->uv[1]);
+ if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE1, tf_stencil->uv[1]);
if (cp) glColor3ub(cp[7], cp[6], cp[5]);
glVertex3fv(d_co);
if (tf) glTexCoord2fv(tf->uv[2]);
+ if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE1, tf_stencil->uv[2]);
if (cp) glColor3ub(cp[11], cp[10], cp[9]);
glVertex3fv(c_co);
if (tf) glTexCoord2fv(tf->uv[3]);
+ if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE1, tf_stencil->uv[3]);
if (cp) glColor3ub(cp[15], cp[14], cp[13]);
glVertex3fv(b_co);
if (tf) glTexCoord2fv(tf->uv[0]);
+ if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE1, tf_stencil->uv[0]);
if (cp) glColor3ub(cp[3], cp[2], cp[1]);
glVertex3fv(a_co);
if (tf) tf++;
+ if (tf_stencil) tf_stencil++;
if (cp) cp += 16;
}
}
@@ -2484,17 +2524,17 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
static void ccgDM_drawFacesTex(DerivedMesh *dm,
DMSetDrawOptionsTex setDrawOptions,
DMCompareDrawOptions compareDrawOptions,
- void *userData)
+ void *userData, DMDrawFlag flag)
{
- ccgDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData);
+ ccgDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData, flag);
}
static void ccgDM_drawMappedFacesTex(DerivedMesh *dm,
DMSetDrawOptions setDrawOptions,
DMCompareDrawOptions compareDrawOptions,
- void *userData)
+ void *userData, DMDrawFlag flag)
{
- ccgDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData);
+ ccgDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData, flag);
}
static void ccgDM_drawUVEdges(DerivedMesh *dm)
diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c
index 90687ef9916..47b615c2573 100644
--- a/source/blender/blenkernel/intern/text.c
+++ b/source/blender/blenkernel/intern/text.c
@@ -2697,7 +2697,7 @@ void txt_indent(Text *text)
/* hardcoded: TXT_TABSIZE = 4 spaces: */
int spaceslen = TXT_TABSIZE;
- if (ELEM3(NULL, text, text->curl, text->sell)) {
+ if (ELEM(NULL, text, text->curl, text->sell)) {
return;
}
@@ -2764,7 +2764,7 @@ void txt_unindent(Text *text)
/* hardcoded: TXT_TABSIZE = 4 spaces: */
int spaceslen = TXT_TABSIZE;
- if (ELEM3(NULL, text, text->curl, text->sell)) {
+ if (ELEM(NULL, text, text->curl, text->sell)) {
return;
}
diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c
index bb956cb085c..77f62771360 100644
--- a/source/blender/blenkernel/intern/texture.c
+++ b/source/blender/blenkernel/intern/texture.c
@@ -145,12 +145,12 @@ void init_tex_mapping(TexMapping *texmap)
if (texmap->type == TEXMAP_TYPE_TEXTURE) {
/* to transform a texture, the inverse transform needs
* to be applied to the texture coordinate */
- mul_serie_m4(texmap->mat, tmat, rmat, smat, 0, 0, 0, 0, 0);
+ mul_m4_series(texmap->mat, tmat, rmat, smat);
invert_m4(texmap->mat);
}
else if (texmap->type == TEXMAP_TYPE_POINT) {
/* forward transform */
- mul_serie_m4(texmap->mat, tmat, rmat, smat, 0, 0, 0, 0, 0);
+ mul_m4_series(texmap->mat, tmat, rmat, smat);
}
else if (texmap->type == TEXMAP_TYPE_VECTOR) {
/* no translation for vectors */
@@ -474,7 +474,8 @@ void BKE_texture_free(Tex *tex)
void default_tex(Tex *tex)
{
- tex->type = TEX_CLOUDS;
+ tex->type = TEX_IMAGE;
+ tex->ima = NULL;
tex->stype = 0;
tex->flag = TEX_CHECKER_ODD;
tex->imaflag = TEX_INTERPOL | TEX_MIPMAP | TEX_USEALPHA;
@@ -592,7 +593,7 @@ Tex *add_texture(Main *bmain, const char *name)
void default_mtex(MTex *mtex)
{
- mtex->texco = TEXCO_ORCO;
+ mtex->texco = TEXCO_UV;
mtex->mapto = MAP_COL;
mtex->object = NULL;
mtex->projx = PROJ_X;
diff --git a/source/blender/blenkernel/intern/tracking_stabilize.c b/source/blender/blenkernel/intern/tracking_stabilize.c
index 9ede39fd666..eb224020977 100644
--- a/source/blender/blenkernel/intern/tracking_stabilize.c
+++ b/source/blender/blenkernel/intern/tracking_stabilize.c
@@ -439,6 +439,6 @@ void BKE_tracking_stabilization_data_to_mat4(int width, int height, float aspect
rotate_m4(rotation_mat, 'Z', angle); /* rotation matrix */
/* compose transformation matrix */
- mul_serie_m4(mat, translation_mat, center_mat, aspect_mat, rotation_mat, inv_aspect_mat,
- scale_mat, inv_center_mat, NULL);
+ mul_m4_series(mat, translation_mat, center_mat, aspect_mat, rotation_mat, inv_aspect_mat,
+ scale_mat, inv_center_mat);
}
diff --git a/source/blender/blenkernel/intern/writeavi.c b/source/blender/blenkernel/intern/writeavi.c
index a9f040b8650..aef44993912 100644
--- a/source/blender/blenkernel/intern/writeavi.c
+++ b/source/blender/blenkernel/intern/writeavi.c
@@ -110,7 +110,7 @@ bMovieHandle *BKE_movie_handle_get(const char imtype)
}
#endif
#ifdef WITH_FFMPEG
- if (ELEM4(imtype, R_IMF_IMTYPE_FFMPEG, R_IMF_IMTYPE_H264, R_IMF_IMTYPE_XVID, R_IMF_IMTYPE_THEORA)) {
+ if (ELEM(imtype, R_IMF_IMTYPE_FFMPEG, R_IMF_IMTYPE_H264, R_IMF_IMTYPE_XVID, R_IMF_IMTYPE_THEORA)) {
mh.start_movie = BKE_ffmpeg_start;
mh.append_movie = BKE_ffmpeg_append;
mh.end_movie = BKE_ffmpeg_end;
diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c
index 00dfae9e72a..ef3c84f661d 100644
--- a/source/blender/blenkernel/intern/writeffmpeg.c
+++ b/source/blender/blenkernel/intern/writeffmpeg.c
@@ -30,13 +30,6 @@
#include <string.h>
#include <stdio.h>
-#if defined(_WIN32) && defined(DEBUG) && !defined(__MINGW32__) && !defined(__CYGWIN__)
-/* This does not seem necessary or present on MSVC 8, but may be needed in earlier versions? */
-# if _MSC_VER < 1400
-# include <stdint.h>
-# endif
-#endif
-
#include <stdlib.h>
#include <libavformat/avformat.h>
diff --git a/source/blender/blenlib/BLI_fileops.h b/source/blender/blenlib/BLI_fileops.h
index 2d1e1d84882..b574447558c 100644
--- a/source/blender/blenlib/BLI_fileops.h
+++ b/source/blender/blenlib/BLI_fileops.h
@@ -62,7 +62,7 @@ int BLI_create_symlink(const char *path, const char *to);
/* keep in sync with the definition of struct direntry in BLI_fileops_types.h */
#ifdef WIN32
-# if (defined(_MSC_VER) && (_MSC_VER >= 1500)) || defined(__MINGW64__)
+# if defined(_MSC_VER) || defined(__MINGW64__)
typedef struct _stat64 BLI_stat_t;
# elif defined(__MINGW32__)
typedef struct _stati64 BLI_stat_t;
diff --git a/source/blender/blenlib/BLI_fileops_types.h b/source/blender/blenlib/BLI_fileops_types.h
index 53c9fa16b70..0e6eab687ad 100644
--- a/source/blender/blenlib/BLI_fileops_types.h
+++ b/source/blender/blenlib/BLI_fileops_types.h
@@ -46,7 +46,7 @@ struct direntry {
char *relname;
char *path;
#ifdef WIN32 /* keep in sync with the definition of BLI_stat_t in BLI_fileops.h */
-# if (defined(_MSC_VER) && (_MSC_VER >= 1500)) || defined(__MINGW64__)
+# if defined(_MSC_VER) || defined(__MINGW64__)
struct _stat64 s;
# elif defined(__MINGW32__)
struct _stati64 s;
diff --git a/source/blender/blenlib/BLI_ghash.h b/source/blender/blenlib/BLI_ghash.h
index dc29a129dbf..313c4190a30 100644
--- a/source/blender/blenlib/BLI_ghash.h
+++ b/source/blender/blenlib/BLI_ghash.h
@@ -139,6 +139,9 @@ unsigned int BLI_ghashutil_uinthash(unsigned int key);
unsigned int BLI_ghashutil_uinthash_v4(const unsigned int key[4]);
#define BLI_ghashutil_inthash_v4_p \
((GSetHashFP)BLI_ghashutil_uinthash_v4)
+int BLI_ghashutil_uinthash_v4_cmp(const void *a, const void *b);
+#define BLI_ghashutil_inthash_v4_cmp \
+ BLI_ghashutil_uinthash_v4_cmp
unsigned int BLI_ghashutil_inthash_p(const void *ptr);
int BLI_ghashutil_intcmp(const void *a, const void *b);
diff --git a/source/blender/blenlib/BLI_gsqueue.h b/source/blender/blenlib/BLI_gsqueue.h
index d17897df665..4600d6f6325 100644
--- a/source/blender/blenlib/BLI_gsqueue.h
+++ b/source/blender/blenlib/BLI_gsqueue.h
@@ -30,8 +30,6 @@
/** \file BLI_gsqueue.h
* \ingroup bli
- * \brief A generic structure queue (a queue for fixed length
- * (generally small) structures.
*/
typedef struct _GSQueue GSQueue;
@@ -46,4 +44,3 @@ void BLI_gsqueue_pushback(GSQueue *gq, const void *item);
void BLI_gsqueue_free(GSQueue *gq);
#endif /* __BLI_GSQUEUE_H__ */
-
diff --git a/source/blender/blenlib/BLI_listbase.h b/source/blender/blenlib/BLI_listbase.h
index 94f5303e705..0a6e2eae1ed 100644
--- a/source/blender/blenlib/BLI_listbase.h
+++ b/source/blender/blenlib/BLI_listbase.h
@@ -76,8 +76,8 @@ void BLI_freelinkN(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1);
void BLI_movelisttolist(struct ListBase *dst, struct ListBase *src) ATTR_NONNULL(1, 2);
void BLI_duplicatelist(struct ListBase *dst, const struct ListBase *src) ATTR_NONNULL(1, 2);
void BLI_listbase_reverse(struct ListBase *lb) ATTR_NONNULL(1);
-void BLI_rotatelist_first(struct ListBase *lb, void *vlink) ATTR_NONNULL(1, 2);
-void BLI_rotatelist_last(struct ListBase *lb, void *vlink) ATTR_NONNULL(1, 2);
+void BLI_listbase_rotate_first(struct ListBase *lb, void *vlink) ATTR_NONNULL(1, 2);
+void BLI_listbase_rotate_last(struct ListBase *lb, void *vlink) ATTR_NONNULL(1, 2);
/**
* Utility functions to avoid first/last references inline all over.
@@ -111,27 +111,27 @@ for ((lb_iter) = (lb).first, (indexvar) = BLI_countlist(lb); (lb_iter); (lb_iter
*
* \code{.c}
*
- * LISTBASE_CIRCULAR_FORWARD_BEGIN (listbase, item, item_init) {
+ * BLI_LISTBASE_CIRCULAR_FORWARD_BEGIN (listbase, item, item_init) {
* ...operate on marker...
* }
- * LISTBASE_CIRCULAR_FORWARD_END (listbase, item, item_init);
+ * BLI_LISTBASE_CIRCULAR_FORWARD_END (listbase, item, item_init);
*
* \endcode
*/
-#define LISTBASE_CIRCULAR_FORWARD_BEGIN(lb, lb_iter, lb_init) \
+#define BLI_LISTBASE_CIRCULAR_FORWARD_BEGIN(lb, lb_iter, lb_init) \
if ((lb)->first && (lb_init || (lb_init = (lb)->first))) { \
lb_iter = lb_init; \
do {
-#define LISTBASE_CIRCULAR_FORWARD_END(lb, lb_iter, lb_init) \
+#define BLI_LISTBASE_CIRCULAR_FORWARD_END(lb, lb_iter, lb_init) \
} while ((lb_iter = (lb_iter)->next ? (lb_iter)->next : (lb)->first), \
(lb_iter != lb_init)); \
}
-#define LISTBASE_CIRCULAR_BACKWARD_BEGIN(lb, lb_iter, lb_init) \
+#define BLI_LISTBASE_CIRCULAR_BACKWARD_BEGIN(lb, lb_iter, lb_init) \
if ((lb)->last && (lb_init || (lb_init = (lb)->last))) { \
lb_iter = lb_init; \
do {
-#define LISTBASE_CIRCULAR_BACKWARD_END(lb, lb_iter, lb_init) \
+#define BLI_LISTBASE_CIRCULAR_BACKWARD_END(lb, lb_iter, lb_init) \
} while ((lb_iter = (lb_iter)->prev ? (lb_iter)->prev : (lb)->last), \
(lb_iter != lb_init)); \
}
diff --git a/source/blender/blenlib/BLI_math_base.h b/source/blender/blenlib/BLI_math_base.h
index 54e9349f1f8..b639df4da84 100644
--- a/source/blender/blenlib/BLI_math_base.h
+++ b/source/blender/blenlib/BLI_math_base.h
@@ -147,13 +147,7 @@ static const int NAN_INT = 0x7FC00000;
#ifdef WIN32
# if defined(_MSC_VER)
-# if (_MSC_VER < 1800) && !defined(isnan)
-# define isnan(n) _isnan(n)
-# endif
# define finite(n) _finite(n)
-# if (_MSC_VER < 1800) && !defined(hypot)
-# define hypot(a, b) _hypot(a, b)
-# endif
# endif
#endif
@@ -163,7 +157,7 @@ static const int NAN_INT = 0x7FC00000;
#ifndef CHECK_TYPE
#ifdef __GNUC__
#define CHECK_TYPE(var, type) { \
- __typeof(var) *__tmp; \
+ typeof(var) *__tmp; \
__tmp = (type *)NULL; \
(void)__tmp; \
} (void)0
@@ -241,11 +235,6 @@ 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);
-#if defined(_MSC_VER) && (_MSC_VER < 1800)
-extern double copysign(double x, double y);
-extern double round(double x);
-#endif
-
double double_round(double x, int ndigits);
#ifdef BLI_MATH_GCC_WARN_PRAGMA
diff --git a/source/blender/blenlib/BLI_math_color_blend.h b/source/blender/blenlib/BLI_math_color_blend.h
index d7e9bf50eae..2535a31ccc4 100644
--- a/source/blender/blenlib/BLI_math_color_blend.h
+++ b/source/blender/blenlib/BLI_math_color_blend.h
@@ -49,6 +49,24 @@ MINLINE void blend_color_lighten_byte(unsigned char dst[4], const unsigned char
MINLINE void blend_color_darken_byte(unsigned char dst[4], const unsigned char src1[4], const unsigned char src2[4]);
MINLINE void blend_color_erase_alpha_byte(unsigned char dst[4], const unsigned char src1[4], const unsigned char src2[4]);
MINLINE void blend_color_add_alpha_byte(unsigned char dst[4], const unsigned char src1[4], const unsigned char src2[4]);
+
+MINLINE void blend_color_overlay_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]);
+MINLINE void blend_color_hardlight_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]);
+MINLINE void blend_color_burn_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]);
+MINLINE void blend_color_linearburn_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]);
+MINLINE void blend_color_dodge_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]);
+MINLINE void blend_color_screen_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]);
+MINLINE void blend_color_softlight_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]);
+MINLINE void blend_color_pinlight_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]);
+MINLINE void blend_color_linearlight_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]);
+MINLINE void blend_color_vividlight_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]);
+MINLINE void blend_color_difference_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]);
+MINLINE void blend_color_exclusion_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]);
+MINLINE void blend_color_color_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]);
+MINLINE void blend_color_hue_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]);
+MINLINE void blend_color_saturation_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]);
+MINLINE void blend_color_luminosity_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]);
+
MINLINE void blend_color_interpolate_byte(unsigned char dst[4], const unsigned char src1[4], const unsigned char src2[4], float t);
MINLINE void blend_color_mix_float(float dst[4], const float src1[4], const float src2[4]);
@@ -59,6 +77,24 @@ MINLINE void blend_color_lighten_float(float dst[4], const float src1[4], const
MINLINE void blend_color_darken_float(float dst[4], const float src1[4], const float src2[4]);
MINLINE void blend_color_erase_alpha_float(float dst[4], const float src1[4], const float src2[4]);
MINLINE void blend_color_add_alpha_float(float dst[4], const float src1[4], const float src2[4]);
+
+MINLINE void blend_color_overlay_float(float dst[4], const float src1[4], const float src2[2]);
+MINLINE void blend_color_hardlight_float(float dst[4], const float src1[4], const float src2[2]);
+MINLINE void blend_color_burn_float(float dst[4], const float src1[4], const float src2[2]);
+MINLINE void blend_color_linearburn_float(float dst[4], const float src1[4], const float src2[2]);
+MINLINE void blend_color_dodge_float(float dst[4], const float src1[4], const float src2[2]);
+MINLINE void blend_color_screen_float(float dst[4], const float src1[4], const float src2[2]);
+MINLINE void blend_color_softlight_float(float dst[4], const float src1[4], const float src2[2]);
+MINLINE void blend_color_pinlight_float(float dst[4], const float src1[4], const float src2[2]);
+MINLINE void blend_color_linearlight_float(float dst[4], const float src1[4], const float src2[2]);
+MINLINE void blend_color_vividlight_float(float dst[4], const float src1[4], const float src2[2]);
+MINLINE void blend_color_difference_float(float dst[4], const float src1[4], const float src2[2]);
+MINLINE void blend_color_exclusion_float(float dst[4], const float src1[4], const float src2[2]);
+MINLINE void blend_color_color_float(float dst[4], const float src1[4], const float src2[2]);
+MINLINE void blend_color_hue_float(float dst[4], const float src1[4], const float src2[2]);
+MINLINE void blend_color_saturation_float(float dst[4], const float src1[4], const float src2[2]);
+MINLINE void blend_color_luminosity_float(float dst[4], const float src1[4], const float src2[2]);
+
MINLINE void blend_color_interpolate_float(float dst[4], const float src1[4], const float src2[4], float t);
#if BLI_MATH_DO_INLINE
diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h
index ed0777aceea..57cde5637d3 100644
--- a/source/blender/blenlib/BLI_math_geom.h
+++ b/source/blender/blenlib/BLI_math_geom.h
@@ -169,6 +169,8 @@ int isect_point_tri_v2(const float pt[2], const float v1[2], const float v2[2],
bool isect_point_tri_v2_cw(const float pt[2], const float v1[2], const float v2[2], const float v3[2]);
int isect_point_tri_v2_int(const int x1, const int y1, const int x2, const int y2, const int a, const int b);
bool isect_point_tri_prism_v3(const float p[3], const float v1[3], const float v2[3], const float v3[3]);
+bool isect_point_tri_v3(const float p[3], const float v1[3], const float v2[3], const float v3[3],
+ float r_vi[3]);
/* axis-aligned bounding box */
bool isect_aabb_aabb_v3(const float min1[3], const float max1[3], const float min2[3], const float max2[3]);
diff --git a/source/blender/blenlib/BLI_math_matrix.h b/source/blender/blenlib/BLI_math_matrix.h
index 49183934412..7bcaab1f939 100644
--- a/source/blender/blenlib/BLI_math_matrix.h
+++ b/source/blender/blenlib/BLI_math_matrix.h
@@ -34,6 +34,8 @@
extern "C" {
#endif
+#include "BLI_compiler_attrs.h"
+
/********************************* Init **************************************/
void zero_m3(float R[3][3]);
@@ -67,12 +69,33 @@ void mul_m4_m4m3(float R[4][4], float A[4][4], float B[3][3]);
void mul_m4_m4m4(float R[4][4], float A[4][4], float B[4][4]);
void mul_m3_m3m4(float R[3][3], float A[4][4], float B[3][3]);
-void mul_serie_m3(float R[3][3],
- float M1[3][3], float M2[3][3], float M3[3][3], float M4[3][3],
- float M5[3][3], float M6[3][3], float M7[3][3], float M8[3][3]);
-void mul_serie_m4(float R[4][4],
- float M1[4][4], float M2[4][4], float M3[4][4], float M4[4][4],
- float M5[4][4], float M6[4][4], float M7[4][4], float M8[4][4]);
+/* mul_m3_series */
+void _va_mul_m3_series_3(float R[3][3], float M1[3][3], float M2[3][3]) ATTR_NONNULL();
+void _va_mul_m3_series_4(float R[3][3], float M1[3][3], float M2[3][3], float M3[3][3]) ATTR_NONNULL();
+void _va_mul_m3_series_5(float R[3][3], float M1[3][3], float M2[3][3], float M3[3][3], float M4[3][3]) ATTR_NONNULL();
+void _va_mul_m3_series_6(float R[3][3], float M1[3][3], float M2[3][3], float M3[3][3], float M4[3][3],
+ float M5[3][3]) ATTR_NONNULL();
+void _va_mul_m3_series_7(float R[3][3], float M1[3][3], float M2[3][3], float M3[3][3], float M4[3][3],
+ float M5[3][3], float M6[3][3]) ATTR_NONNULL();
+void _va_mul_m3_series_8(float R[3][3], float M1[3][3], float M2[3][3], float M3[3][3], float M4[3][3],
+ float M5[3][3], float M6[3][3], float M7[3][3]) ATTR_NONNULL();
+void _va_mul_m3_series_9(float R[3][3], float M1[3][3], float M2[3][3], float M3[3][3], float M4[3][3],
+ float M5[3][3], float M6[3][3], float M7[3][3], float M8[3][3]) ATTR_NONNULL();
+/* mul_m4_series */
+void _va_mul_m4_series_3(float R[4][4], float M1[4][4], float M2[4][4]) ATTR_NONNULL();
+void _va_mul_m4_series_4(float R[4][4], float M1[4][4], float M2[4][4], float M3[4][4]) ATTR_NONNULL();
+void _va_mul_m4_series_5(float R[4][4], float M1[4][4], float M2[4][4], float M3[4][4], float M4[4][4]) ATTR_NONNULL();
+void _va_mul_m4_series_6(float R[4][4], float M1[4][4], float M2[4][4], float M3[4][4], float M4[4][4],
+ float M5[4][4]) ATTR_NONNULL();
+void _va_mul_m4_series_7(float R[4][4], float M1[4][4], float M2[4][4], float M3[4][4], float M4[4][4],
+ float M5[4][4], float M6[4][4]) ATTR_NONNULL();
+void _va_mul_m4_series_8(float R[4][4], float M1[4][4], float M2[4][4], float M3[4][4], float M4[4][4],
+ float M5[4][4], float M6[4][4], float M7[4][4]) ATTR_NONNULL();
+void _va_mul_m4_series_9(float R[4][4], float M1[4][4], float M2[4][4], float M3[4][4], float M4[4][4],
+ float M5[4][4], float M6[4][4], float M7[4][4], float M8[4][4]) ATTR_NONNULL();
+
+#define mul_m3_series(...) VA_NARGS_CALL_OVERLOAD(_va_mul_m3_series_, __VA_ARGS__)
+#define mul_m4_series(...) VA_NARGS_CALL_OVERLOAD(_va_mul_m4_series_, __VA_ARGS__)
void mul_m4_v3(float M[4][4], float r[3]);
void mul_v3_m4v3(float r[3], float M[4][4], const float v[3]);
@@ -201,6 +224,22 @@ bool is_negative_m4(float mat[4][4]);
bool is_zero_m3(float mat[3][3]);
bool is_zero_m4(float mat[4][4]);
+/* SpaceTransform helper */
+typedef struct SpaceTransform {
+ float local2target[4][4];
+ float target2local[4][4];
+
+} SpaceTransform;
+
+void BLI_space_transform_from_matrices(struct SpaceTransform *data, float local[4][4], float target[4][4]);
+void BLI_space_transform_apply(const struct SpaceTransform *data, float co[3]);
+void BLI_space_transform_invert(const struct SpaceTransform *data, float co[3]);
+void BLI_space_transform_apply_normal(const struct SpaceTransform *data, float no[3]);
+void BLI_space_transform_invert_normal(const struct SpaceTransform *data, float no[3]);
+
+#define BLI_SPACE_TRANSFORM_SETUP(data, local, target) \
+ BLI_space_transform_from_matrices((data), (local)->obmat, (target)->obmat)
+
/*********************************** Other ***********************************/
void print_m3(const char *str, float M[3][3]);
diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h
index 942097e1ed6..6885a5aa351 100644
--- a/source/blender/blenlib/BLI_math_vector.h
+++ b/source/blender/blenlib/BLI_math_vector.h
@@ -65,6 +65,7 @@ MINLINE void swap_v4_v4(float a[4], float b[4]);
MINLINE void copy_v2_v2_char(char r[2], const char a[2]);
MINLINE void copy_v3_v3_char(char r[3], const char a[3]);
MINLINE void copy_v4_v4_char(char r[4], const char a[4]);
+
/* short */
MINLINE void copy_v2_v2_short(short r[2], const short a[2]);
MINLINE void copy_v3_v3_short(short r[3], const short a[3]);
@@ -231,6 +232,7 @@ MINLINE bool equals_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_R
MINLINE bool compare_v2v2(const float a[2], const float b[2], const float limit) ATTR_WARN_UNUSED_RESULT;
MINLINE bool compare_v3v3(const float a[3], const float b[3], const float limit) ATTR_WARN_UNUSED_RESULT;
MINLINE bool compare_len_v3v3(const float a[3], const float b[3], const float limit) ATTR_WARN_UNUSED_RESULT;
+MINLINE bool compare_len_squared_v3v3(const float a[3], const float b[3], const float limit) ATTR_WARN_UNUSED_RESULT;
MINLINE bool compare_v4v4(const float a[4], const float b[4], const float limit) ATTR_WARN_UNUSED_RESULT;
MINLINE bool equals_v4v4(const float a[4], const float b[4]) ATTR_WARN_UNUSED_RESULT;
diff --git a/source/blender/blenlib/BLI_path_util.h b/source/blender/blenlib/BLI_path_util.h
index 244c308a05c..3d82480d050 100644
--- a/source/blender/blenlib/BLI_path_util.h
+++ b/source/blender/blenlib/BLI_path_util.h
@@ -111,6 +111,7 @@ const char *BLI_last_slash(const char *string) ATTR_NONNULL() ATTR_WARN_UNUSED_R
int BLI_add_slash(char *string) ATTR_NONNULL();
void BLI_del_slash(char *string) ATTR_NONNULL();
const char *BLI_first_slash(const char *string) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
+void BLI_path_native_slash(char *path) ATTR_NONNULL();
void BLI_getlastdir(const char *dir, char *last, const size_t maxlen);
bool BLI_testextensie(const char *str, const char *ext) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
@@ -128,9 +129,6 @@ int BLI_stringdec(const char *string, char *head, char *start, unsigned short *n
void BLI_stringenc(char *string, const char *head, const char *tail, unsigned short numlen, int pic);
int BLI_split_name_num(char *left, int *nr, const char *name, const char delim);
-/* make sure path separators conform to system one */
-void BLI_clean(char *path) ATTR_NONNULL();
-
/**
* dir can be any input, like from buttons, and this function
* converts it to a regular full path.
diff --git a/source/blender/blenlib/BLI_stackdefines.h b/source/blender/blenlib/BLI_stackdefines.h
index 24cb043cd43..da9bf5ea04c 100644
--- a/source/blender/blenlib/BLI_stackdefines.h
+++ b/source/blender/blenlib/BLI_stackdefines.h
@@ -36,7 +36,7 @@
# define _STACK_SWAP_TOTALLOC(stack_a, stack_b) SWAP(unsigned int, _##stack_a##_totalloc, _##stack_b##_totalloc)
#else
# define STACK_DECLARE(stack) unsigned int _##stack##_index
-# define STACK_INIT(stack, tot) ((void)stack, (void)((_##stack##_index) = 0), (void)(tot))
+# define STACK_INIT(stack, tot) ((void)stack, (void)((_##stack##_index) = 0), (void)(0 ? tot : 0))
# define _STACK_SIZETEST(stack, off) (void)(stack), (void)(off)
# define _STACK_SWAP_TOTALLOC(stack_a, stack_b) (void)(stack_a), (void)(stack_b)
#endif
@@ -57,9 +57,12 @@
#define STACK_PEEK_PTR(stack) (BLI_assert(_##stack##_index), &((stack)[_##stack##_index - 1]))
/** remove any item from the stack, take care, re-orders */
#define STACK_REMOVE(stack, i) \
- _STACK_BOUNDSTEST(stack, i); \
- if (--_##stack##_index != i) { \
- stack[i] = stack[_##stack##_index]; \
+ { \
+ const unsigned int _i = i; \
+ _STACK_BOUNDSTEST(stack, _i); \
+ if (--_##stack##_index != _i) { \
+ stack[_i] = stack[_##stack##_index]; \
+ } \
} (void)0
#ifdef __GNUC__
#define STACK_SWAP(stack_a, stack_b) { \
diff --git a/source/blender/blenlib/BLI_sys_types.h b/source/blender/blenlib/BLI_sys_types.h
index fcbed1daf66..c9cf33f2f69 100644
--- a/source/blender/blenlib/BLI_sys_types.h
+++ b/source/blender/blenlib/BLI_sys_types.h
@@ -47,127 +47,7 @@
extern "C" {
#endif
-/* MSVC 2010 and 2012 (>=1600) have stdint.h so we should use this for consistency */
-#if defined(_WIN32) && defined(_MSC_VER) && _MSC_VER <= 1500
-
-/* The __intXX are built-in types of the visual compiler! So we don't
- * need to include anything else here. */
-
-
-typedef signed __int8 int8_t;
-typedef signed __int16 int16_t;
-typedef signed __int32 int32_t;
-typedef signed __int64 int64_t;
-
-typedef unsigned __int8 uint8_t;
-typedef unsigned __int16 uint16_t;
-typedef unsigned __int32 uint32_t;
-typedef unsigned __int64 uint64_t;
-
-// 7.18.2 Limits of specified-width integer types
-
-#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259
-
-// 7.18.2.1 Limits of exact-width integer types
-#define INT8_MIN ((int8_t)_I8_MIN)
-#define INT8_MAX _I8_MAX
-#define INT16_MIN ((int16_t)_I16_MIN)
-#define INT16_MAX _I16_MAX
-#define INT32_MIN ((int32_t)_I32_MIN)
-#define INT32_MAX _I32_MAX
-#define INT64_MIN ((int64_t)_I64_MIN)
-#define INT64_MAX _I64_MAX
-#define UINT8_MAX _UI8_MAX
-#define UINT16_MAX _UI16_MAX
-#define UINT32_MAX _UI32_MAX
-#define UINT64_MAX _UI64_MAX
-
-// 7.18.2.2 Limits of minimum-width integer types
-#define INT_LEAST8_MIN INT8_MIN
-#define INT_LEAST8_MAX INT8_MAX
-#define INT_LEAST16_MIN INT16_MIN
-#define INT_LEAST16_MAX INT16_MAX
-#define INT_LEAST32_MIN INT32_MIN
-#define INT_LEAST32_MAX INT32_MAX
-#define INT_LEAST64_MIN INT64_MIN
-#define INT_LEAST64_MAX INT64_MAX
-#define UINT_LEAST8_MAX UINT8_MAX
-#define UINT_LEAST16_MAX UINT16_MAX
-#define UINT_LEAST32_MAX UINT32_MAX
-#define UINT_LEAST64_MAX UINT64_MAX
-
-// 7.18.2.3 Limits of fastest minimum-width integer types
-#define INT_FAST8_MIN INT8_MIN
-#define INT_FAST8_MAX INT8_MAX
-#define INT_FAST16_MIN INT16_MIN
-#define INT_FAST16_MAX INT16_MAX
-#define INT_FAST32_MIN INT32_MIN
-#define INT_FAST32_MAX INT32_MAX
-#define INT_FAST64_MIN INT64_MIN
-#define INT_FAST64_MAX INT64_MAX
-#define UINT_FAST8_MAX UINT8_MAX
-#define UINT_FAST16_MAX UINT16_MAX
-#define UINT_FAST32_MAX UINT32_MAX
-#define UINT_FAST64_MAX UINT64_MAX
-
-// 7.18.2.4 Limits of integer types capable of holding object pointers
-#ifdef _WIN64 // [
-# define INTPTR_MIN INT64_MIN
-# define INTPTR_MAX INT64_MAX
-# define UINTPTR_MAX UINT64_MAX
-#else // _WIN64 ][
-# define INTPTR_MIN INT32_MIN
-# define INTPTR_MAX INT32_MAX
-# define UINTPTR_MAX UINT32_MAX
-#endif // _WIN64 ]
-
-// 7.18.2.5 Limits of greatest-width integer types
-#define INTMAX_MIN INT64_MIN
-#define INTMAX_MAX INT64_MAX
-#define UINTMAX_MAX UINT64_MAX
-
-// 7.18.3 Limits of other integer types
-
-#ifdef _WIN64 // [
-# define PTRDIFF_MIN _I64_MIN
-# define PTRDIFF_MAX _I64_MAX
-#else // _WIN64 ][
-# define PTRDIFF_MIN _I32_MIN
-# define PTRDIFF_MAX _I32_MAX
-#endif // _WIN64 ]
-
-#define SIG_ATOMIC_MIN INT_MIN
-#define SIG_ATOMIC_MAX INT_MAX
-
-#ifndef SIZE_MAX // [
-# ifdef _WIN64 // [
-# define SIZE_MAX _UI64_MAX
-# else // _WIN64 ][
-# define SIZE_MAX _UI32_MAX
-# endif // _WIN64 ]
-#endif // SIZE_MAX ]
-
-#endif // __STDC_LIMIT_MACROS ]
-
-#ifndef _INTPTR_T_DEFINED
-#ifdef _WIN64
-typedef __int64 intptr_t;
-#else
-typedef long intptr_t;
-#endif
-#define _INTPTR_T_DEFINED
-#endif
-
-#ifndef _UINTPTR_T_DEFINED
-#ifdef _WIN64
-typedef unsigned __int64 uintptr_t;
-#else
-typedef unsigned long uintptr_t;
-#endif
-#define _UINTPTR_T_DEFINED
-#endif
-
-#elif defined(__linux__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD_kernel__) || defined(__GNU__)
+#if defined(__linux__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD_kernel__) || defined(__GNU__)
/* Linux-i386, Linux-Alpha, Linux-ppc */
#include <stdint.h>
@@ -186,7 +66,7 @@ typedef uint64_t u_int64_t;
#include <inttypes.h>
/* MinGW and MSVC >= 2010 */
-#elif defined(FREE_WINDOWS) || (defined(_MSC_VER) && _MSC_VER >= 1600)
+#elif defined(FREE_WINDOWS) || defined(_MSC_VER)
#include <stdint.h>
#else
diff --git a/source/blender/blenlib/BLI_utildefines.h b/source/blender/blenlib/BLI_utildefines.h
index b6bdf26d5b6..683b3c4c438 100644
--- a/source/blender/blenlib/BLI_utildefines.h
+++ b/source/blender/blenlib/BLI_utildefines.h
@@ -40,6 +40,25 @@
#include <stdio.h>
#endif
+
+/* varargs macros (keep first so others can use) */
+/* --- internal helpers --- */
+#define _VA_NARGS_GLUE(x, y) x y
+#define _VA_NARGS_RETURN_COUNT(\
+ _1_, _2_, _3_, _4_, _5_, _6_, _7_, _8_, _9_, _10_, _11_, _12_, _13_, _14_, _15_, _16_, \
+ _17_, _18_, _19_, _20_, _21_, _22_, _23_, _24_, _25_, _26_, _27_, _28_, _29_, _30_, _31_, _32_, \
+ count, ...) count
+#define _VA_NARGS_EXPAND(args) _VA_NARGS_RETURN_COUNT args
+#define _VA_NARGS_COUNT_MAX32(...) _VA_NARGS_EXPAND((__VA_ARGS__, \
+ 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, \
+ 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0))
+#define _VA_NARGS_OVERLOAD_MACRO2(name, count) name##count
+#define _VA_NARGS_OVERLOAD_MACRO1(name, count) _VA_NARGS_OVERLOAD_MACRO2(name, count)
+#define _VA_NARGS_OVERLOAD_MACRO(name, count) _VA_NARGS_OVERLOAD_MACRO1(name, count)
+/* --- expose for re-use --- */
+#define VA_NARGS_CALL_OVERLOAD(name, ...) \
+ _VA_NARGS_GLUE(_VA_NARGS_OVERLOAD_MACRO(name, _VA_NARGS_COUNT_MAX32(__VA_ARGS__)), (__VA_ARGS__))
+
/* useful for finding bad use of min/max */
#if 0
/* gcc only */
@@ -137,20 +156,20 @@
* ... the compiler optimizes away the temp var */
#ifdef __GNUC__
#define CHECK_TYPE(var, type) { \
- __typeof(var) *__tmp; \
+ typeof(var) *__tmp; \
__tmp = (type *)NULL; \
(void)__tmp; \
} (void)0
#define CHECK_TYPE_PAIR(var_a, var_b) { \
- __typeof(var_a) *__tmp; \
- __tmp = (__typeof(var_b) *)NULL; \
+ typeof(var_a) *__tmp; \
+ __tmp = (typeof(var_b) *)NULL; \
(void)__tmp; \
} (void)0
#define CHECK_TYPE_PAIR_INLINE(var_a, var_b) ((void)({ \
- __typeof(var_a) *__tmp; \
- __tmp = (__typeof(var_b) *)NULL; \
+ typeof(var_a) *__tmp; \
+ __tmp = (typeof(var_b) *)NULL; \
(void)__tmp; \
}))
@@ -161,8 +180,19 @@
#endif
/* can be used in simple macros */
-#define CHECK_TYPE_INLINE(val, type) \
- ((void)(((type)0) != (val)))
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
+# define CHECK_TYPE_INLINE(val, type) \
+ (void)((void)(((type)0) != (0 ? (val) : ((type)0))), \
+ _Generic((val), type: 0, const type: 0))
+#else
+# define CHECK_TYPE_INLINE(val, type) \
+ ((void)(((type)0) != (0 ? (val) : ((type)0))))
+#endif
+
+#define CHECK_TYPE_NONCONST(var) { \
+ void *non_const = 0 ? (var) : NULL; \
+ (void)non_const; \
+} (void)0
#define SWAP(type, a, b) { \
type sw_ap; \
@@ -182,17 +212,42 @@
(b) = (tval); \
} (void)0
-/* ELEM#(a, ...): is the first arg equal any of the others */
-#define ELEM(a, b, c) ((a) == (b) || (a) == (c))
-#define ELEM3(a, b, c, d) (ELEM(a, b, c) || (a) == (d) )
-#define ELEM4(a, b, c, d, e) (ELEM(a, b, c) || ELEM(a, d, e) )
-#define ELEM5(a, b, c, d, e, f) (ELEM(a, b, c) || ELEM3(a, d, e, f) )
-#define ELEM6(a, b, c, d, e, f, g) (ELEM(a, b, c) || ELEM4(a, d, e, f, g) )
-#define ELEM7(a, b, c, d, e, f, g, h) (ELEM3(a, b, c, d) || ELEM4(a, e, f, g, h) )
-#define ELEM8(a, b, c, d, e, f, g, h, i) (ELEM4(a, b, c, d, e) || ELEM4(a, f, g, h, i) )
-#define ELEM9(a, b, c, d, e, f, g, h, i, j) (ELEM4(a, b, c, d, e) || ELEM5(a, f, g, h, i, j) )
-#define ELEM10(a, b, c, d, e, f, g, h, i, j, k) (ELEM4(a, b, c, d, e) || ELEM6(a, f, g, h, i, j, k) )
-#define ELEM11(a, b, c, d, e, f, g, h, i, j, k, l) (ELEM4(a, b, c, d, e) || ELEM7(a, f, g, h, i, j, k, l) )
+/* ELEM#(v, ...): is the first arg equal any others? */
+/* internal helpers*/
+#define _VA_ELEM3(v, a, b) \
+ (((v) == (a)) || ((v) == (b)))
+#define _VA_ELEM4(v, a, b, c) \
+ (_VA_ELEM3(v, a, b) || ((v) == (c)))
+#define _VA_ELEM5(v, a, b, c, d) \
+ (_VA_ELEM4(v, a, b, c) || ((v) == (d)))
+#define _VA_ELEM6(v, a, b, c, d, e) \
+ (_VA_ELEM5(v, a, b, c, d) || ((v) == (e)))
+#define _VA_ELEM7(v, a, b, c, d, e, f) \
+ (_VA_ELEM6(v, a, b, c, d, e) || ((v) == (f)))
+#define _VA_ELEM8(v, a, b, c, d, e, f, g) \
+ (_VA_ELEM7(v, a, b, c, d, e, f) || ((v) == (g)))
+#define _VA_ELEM9(v, a, b, c, d, e, f, g, h) \
+ (_VA_ELEM8(v, a, b, c, d, e, f, g) || ((v) == (h)))
+#define _VA_ELEM10(v, a, b, c, d, e, f, g, h, i) \
+ (_VA_ELEM9(v, a, b, c, d, e, f, g, h) || ((v) == (i)))
+#define _VA_ELEM11(v, a, b, c, d, e, f, g, h, i, j) \
+ (_VA_ELEM10(v, a, b, c, d, e, f, g, h, i) || ((v) == (j)))
+#define _VA_ELEM12(v, a, b, c, d, e, f, g, h, i, j, k) \
+ (_VA_ELEM11(v, a, b, c, d, e, f, g, h, i, j) || ((v) == (k)))
+#define _VA_ELEM13(v, a, b, c, d, e, f, g, h, i, j, k, l) \
+ (_VA_ELEM12(v, a, b, c, d, e, f, g, h, i, j, k) || ((v) == (l)))
+#define _VA_ELEM14(v, a, b, c, d, e, f, g, h, i, j, k, l, m) \
+ (_VA_ELEM13(v, a, b, c, d, e, f, g, h, i, j, k, l) || ((v) == (m)))
+#define _VA_ELEM15(v, a, b, c, d, e, f, g, h, i, j, k, l, m, n) \
+ (_VA_ELEM14(v, a, b, c, d, e, f, g, h, i, j, k, l, m) || ((v) == (n)))
+#define _VA_ELEM16(v, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) \
+ (_VA_ELEM15(v, a, b, c, d, e, f, g, h, i, j, k, l, m, n) || ((v) == (o)))
+#define _VA_ELEM17(v, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) \
+ (_VA_ELEM16(v, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) || ((v) == (p)))
+
+/* reusable ELEM macro */
+#define ELEM(...) VA_NARGS_CALL_OVERLOAD(_VA_ELEM, __VA_ARGS__)
+
/* shift around elements */
#define SHIFT3(type, a, b, c) { \
@@ -324,13 +379,13 @@
#define IN_RANGE_INCL(a, b, c) ((b < c) ? ((b <= a && a <= c) ? 1 : 0) : ((c <= a && a <= b) ? 1 : 0))
/* unpack vector for args */
-#define UNPACK2(a) ((a)[0]), ((a)[1])
-#define UNPACK3(a) ((a)[0]), ((a)[1]), ((a)[2])
-#define UNPACK4(a) ((a)[0]), ((a)[1]), ((a)[2]), ((a)[3])
-/* op may be '&' or '*' */
-#define UNPACK2OP(op, a) op((a)[0]), op((a)[1])
-#define UNPACK3OP(op, a) op((a)[0]), op((a)[1]), op((a)[2])
-#define UNPACK4OP(op, a) op((a)[0]), op((a)[1]), op((a)[2]), op((a)[3])
+#define UNPACK2(a) ((a)[0]), ((a)[1])
+#define UNPACK3(a) UNPACK2(a), ((a)[2])
+#define UNPACK4(a) UNPACK3(a), ((a)[3])
+/* pre may be '&', '*' or func, post may be '->member' */
+#define UNPACK2_EX(pre, a, post) (pre((a)[0])post), (pre((a)[1])post)
+#define UNPACK3_EX(pre, a, post) UNPACK2_EX(pre, a, post), (pre((a)[2])post)
+#define UNPACK4_EX(pre, a, post) UNPACK3_EX(pre, a, post), (pre((a)[3])post)
/* array helpers */
#define ARRAY_LAST_ITEM(arr_start, arr_dtype, tot) \
@@ -363,8 +418,7 @@
/* memcpy, skipping the first part of a struct,
* ensures 'struct_dst' isn't const and that the offset can be computed at compile time */
#define MEMCPY_STRUCT_OFS(struct_dst, struct_src, member) { \
- void *_not_const = struct_dst; \
- (void)_not_const; \
+ CHECK_TYPE_NONCONST(struct_dst); \
((void)(struct_dst == struct_src), \
memcpy((char *)(struct_dst) + OFFSETOF_STRUCT(struct_dst, member), \
(char *)(struct_src) + OFFSETOF_STRUCT(struct_dst, member), \
diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c
index d24c180dae6..b209e6803f8 100644
--- a/source/blender/blenlib/intern/BLI_ghash.c
+++ b/source/blender/blenlib/intern/BLI_ghash.c
@@ -570,12 +570,12 @@ void BLI_ghashIterator_init(GHashIterator *ghi, GHash *gh)
ghi->curEntry = NULL;
ghi->curBucket = UINT_MAX; /* wraps to zero */
if (gh->nentries) {
- while (!ghi->curEntry) {
+ do {
ghi->curBucket++;
if (UNLIKELY(ghi->curBucket == ghi->gh->nbuckets))
break;
ghi->curEntry = ghi->gh->buckets[ghi->curBucket];
- }
+ } while (!ghi->curEntry);
}
}
@@ -704,6 +704,11 @@ unsigned int BLI_ghashutil_uinthash_v4(const unsigned int key[4])
return hash;
}
+int BLI_ghashutil_uinthash_v4_cmp(const void *a, const void *b)
+{
+ return memcmp(a, b, sizeof(unsigned int[4]));
+}
+
unsigned int BLI_ghashutil_uinthash(unsigned int key)
{
key += ~(key << 16);
diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c
index e4f9df5c27e..17ab55e58f4 100644
--- a/source/blender/blenlib/intern/BLI_kdopbvh.c
+++ b/source/blender/blenlib/intern/BLI_kdopbvh.c
@@ -45,6 +45,17 @@
#define MAX_TREETYPE 32
+/* Setting zero so we can catch bugs in OpenMP/KDOPBVH.
+ * TODO(sergey): Deduplicate the limits with PBVH from BKE.
+ */
+#ifdef _OPENMP
+# ifdef DEBUG
+# define KDOPBVH_OMP_LIMIT 0
+# else
+# define KDOPBVH_OMP_LIMIT 1024
+# endif
+#endif
+
typedef unsigned char axis_t;
typedef struct BVHNode {
@@ -749,7 +760,8 @@ static void non_recursive_bvh_div_nodes(BVHTree *tree, BVHNode *branches_array,
int j;
/* Loop all branches on this level */
-#pragma omp parallel for private(j) schedule(static)
+
+#pragma omp parallel for private(j) schedule(static) if (num_leafs > KDOPBVH_OMP_LIMIT)
for (j = i; j < end_j; j++) {
int k;
const int parent_level_index = j - i;
@@ -1102,7 +1114,7 @@ BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, unsigned int
data[j]->stop_axis = min_axis(tree1->stop_axis, tree2->stop_axis);
}
-#pragma omp parallel for private(j) schedule(static)
+#pragma omp parallel for private(j) schedule(static) if (tree1->totleaf > KDOPBVH_OMP_LIMIT)
for (j = 0; j < MIN2(tree1->tree_type, tree1->nodes[tree1->totleaf]->totnode); j++) {
traverse(data[j], tree1->nodes[tree1->totleaf]->children[j], tree2->nodes[tree2->totleaf]);
}
diff --git a/source/blender/blenlib/intern/BLI_linklist.c b/source/blender/blenlib/intern/BLI_linklist.c
index 66fcfd21fbb..a0b61e7945c 100644
--- a/source/blender/blenlib/intern/BLI_linklist.c
+++ b/source/blender/blenlib/intern/BLI_linklist.c
@@ -38,17 +38,12 @@
int BLI_linklist_length(LinkNode *list)
{
- if (0) {
- return list ? (1 + BLI_linklist_length(list->next)) : 0;
- }
- else {
- int len;
+ int len;
- for (len = 0; list; list = list->next)
- len++;
-
- return len;
- }
+ for (len = 0; list; list = list->next)
+ len++;
+
+ return len;
}
int BLI_linklist_index(LinkNode *list, void *ptr)
diff --git a/source/blender/blenlib/intern/edgehash.c b/source/blender/blenlib/intern/edgehash.c
index 27c5457370b..f6e4aec9624 100644
--- a/source/blender/blenlib/intern/edgehash.c
+++ b/source/blender/blenlib/intern/edgehash.c
@@ -463,14 +463,14 @@ void BLI_edgehashIterator_init(EdgeHashIterator *ehi, EdgeHash *eh)
ehi->curEntry = NULL;
ehi->curBucket = UINT_MAX; /* wraps to zero */
if (eh->nentries) {
- while (!ehi->curEntry) {
+ do {
ehi->curBucket++;
if (UNLIKELY(ehi->curBucket == ehi->eh->nbuckets)) {
break;
}
ehi->curEntry = ehi->eh->buckets[ehi->curBucket];
- }
+ } while (!ehi->curEntry);
}
}
diff --git a/source/blender/blenlib/intern/gsqueue.c b/source/blender/blenlib/intern/gsqueue.c
index 67703c3f033..94d18ce3c77 100644
--- a/source/blender/blenlib/intern/gsqueue.c
+++ b/source/blender/blenlib/intern/gsqueue.c
@@ -27,6 +27,12 @@
/** \file blender/blenlib/intern/gsqueue.c
* \ingroup bli
+ *
+ * \brief A generic structure queue
+ * (a queue for fixed length generally small) structures.
+ *
+ * \note Only use this if you need (first-in-first-out),
+ * otherwise #BLI_stack is more efficient (first-in-last-out).
*/
#include <string.h>
diff --git a/source/blender/blenlib/intern/listbase.c b/source/blender/blenlib/intern/listbase.c
index b0c24899bd1..abf15d57cf7 100644
--- a/source/blender/blenlib/intern/listbase.c
+++ b/source/blender/blenlib/intern/listbase.c
@@ -354,7 +354,7 @@ int BLI_countlist(const ListBase *listbase)
}
/**
- * Returns the nth element of \a listbase, numbering from 1.
+ * Returns the nth element of \a listbase, numbering from 0.
*/
void *BLI_findlink(const ListBase *listbase, int number)
{
@@ -372,7 +372,7 @@ void *BLI_findlink(const ListBase *listbase, int number)
}
/**
- * Returns the nth-last element of \a listbase, numbering from 1.
+ * Returns the nth-last element of \a listbase, numbering from 0.
*/
void *BLI_rfindlink(const ListBase *listbase, int number)
{
@@ -390,7 +390,7 @@ void *BLI_rfindlink(const ListBase *listbase, int number)
}
/**
- * Returns the position of \a vlink within \a listbase, numbering from 1, or -1 if not found.
+ * Returns the position of \a vlink within \a listbase, numbering from 0, or -1 if not found.
*/
int BLI_findindex(const ListBase *listbase, const void *vlink)
{
@@ -599,7 +599,7 @@ void BLI_listbase_reverse(ListBase *lb)
/**
* \param vlink Link to make first.
*/
-void BLI_rotatelist_first(ListBase *lb, void *vlink)
+void BLI_listbase_rotate_first(ListBase *lb, void *vlink)
{
/* make circular */
((Link *)lb->first)->prev = lb->last;
@@ -615,7 +615,7 @@ void BLI_rotatelist_first(ListBase *lb, void *vlink)
/**
* \param vlink Link to make last.
*/
-void BLI_rotatelist_last(ListBase *lb, void *vlink)
+void BLI_listbase_rotate_last(ListBase *lb, void *vlink)
{
/* make circular */
((Link *)lb->first)->prev = lb->last;
diff --git a/source/blender/blenlib/intern/math_color.c b/source/blender/blenlib/intern/math_color.c
index 57a48bb5fa8..828a84da6e1 100644
--- a/source/blender/blenlib/intern/math_color.c
+++ b/source/blender/blenlib/intern/math_color.c
@@ -37,112 +37,38 @@
void hsv_to_rgb(float h, float s, float v, float *r, float *g, float *b)
{
- if (s != 0.0f) {
- float i, f, p;
- h = (h - floorf(h)) * 6.0f;
-
- i = floorf(h);
- f = h - i;
-
- /* avoid computing q/t when not needed */
- p = (v * (1.0f - s));
-#define q (v * (1.0f - (s * f)))
-#define t (v * (1.0f - (s * (1.0f - f))))
-
- /* faster to compare floats then int conversion */
- if (i < 1.0f) {
- *r = v;
- *g = t;
- *b = p;
- }
- else if (i < 2.0f) {
- *r = q;
- *g = v;
- *b = p;
- }
- else if (i < 3.0f) {
- *r = p;
- *g = v;
- *b = t;
- }
- else if (i < 4.0f) {
- *r = p;
- *g = q;
- *b = v;
- }
- else if (i < 5.0f) {
- *r = t;
- *g = p;
- *b = v;
- }
- else {
- *r = v;
- *g = p;
- *b = q;
- }
+ float nr, ng, nb;
-#undef q
-#undef t
+ nr = fabsf(h * 6.0f - 3.0f) - 1.0f;
+ ng = 2.0f - fabsf(h * 6.0f - 2.0f);
+ nb = 2.0f - fabsf(h * 6.0f - 4.0f);
- }
- else {
- *r = v;
- *g = v;
- *b = v;
- }
+ CLAMP(nr, 0.0f, 1.0f);
+ CLAMP(nb, 0.0f, 1.0f);
+ CLAMP(ng, 0.0f, 1.0f);
+
+ *r = ((nr - 1.0f) * s + 1.0f) * v;
+ *g = ((ng - 1.0f) * s + 1.0f) * v;
+ *b = ((nb - 1.0f) * s + 1.0f) * v;
}
-/* HSL to rgb conversion from https://en.wikipedia.org/wiki/HSL_and_HSV */
void hsl_to_rgb(float h, float s, float l, float *r, float *g, float *b)
{
- float i, f, c;
- h = (h - floorf(h)) * 6.0f;
- c = (l > 0.5f) ? (2.0f * (1.0f - l) * s) : (2.0f * l * s);
- i = floorf(h);
- f = h - i;
+ float nr, ng, nb, chroma;
-#define x2 (c * f)
-#define x1 (c * (1.0f - f))
+ nr = fabsf(h * 6.0f - 3.0f) - 1.0f;
+ ng = 2.0f - fabsf(h * 6.0f - 2.0f);
+ nb = 2.0f - fabsf(h * 6.0f - 4.0f);
- /* faster to compare floats then int conversion */
- if (i < 1.0f) {
- *r = c;
- *g = x2;
- *b = 0;
- }
- else if (i < 2.0f) {
- *r = x1;
- *g = c;
- *b = 0;
- }
- else if (i < 3.0f) {
- *r = 0;
- *g = c;
- *b = x2;
- }
- else if (i < 4.0f) {
- *r = 0;
- *g = x1;
- *b = c;
- }
- else if (i < 5.0f) {
- *r = x2;
- *g = 0;
- *b = c;
- }
- else {
- *r = c;
- *g = 0;
- *b = x1;
- }
+ CLAMP(nr, 0.0f, 1.0f);
+ CLAMP(nb, 0.0f, 1.0f);
+ CLAMP(ng, 0.0f, 1.0f);
-#undef x1
-#undef x2
+ chroma = (1.0f - fabsf(2.0f * l - 1.0f)) * s;
- f = l - 0.5f * c;
- *r += f;
- *g += f;
- *b += f;
+ *r = (nr - 0.5f) * chroma + l;
+ *g = (ng - 0.5f) * chroma + l;
+ *b = (nb - 0.5f) * chroma + l;
}
/* convenience function for now */
@@ -187,7 +113,7 @@ void yuv_to_rgb(float y, float u, float v, float *lr, float *lg, float *lb)
void rgb_to_ycc(float r, float g, float b, float *ly, float *lcb, float *lcr, int colorspace)
{
float sr, sg, sb;
- float y = 128.f, cr = 128.f, cb = 128.f;
+ float y = 128.0f, cr = 128.0f, cb = 128.0f;
sr = 255.0f * r;
sg = 255.0f * g;
@@ -226,7 +152,7 @@ void rgb_to_ycc(float r, float g, float b, float *ly, float *lcb, float *lcr, in
/* FIXME comment above must be wrong because BLI_YCC_ITU_BT601 y 16.0 cr 16.0 -> r -0.7009 */
void ycc_to_rgb(float y, float cb, float cr, float *lr, float *lg, float *lb, int colorspace)
{
- float r = 128.f, g = 128.f, b = 128.f;
+ float r = 128.0f, g = 128.0f, b = 128.0f;
switch (colorspace) {
case BLI_YCC_ITU_BT601:
@@ -284,57 +210,26 @@ void hex_to_rgb(char *hexcol, float *r, float *g, float *b)
void rgb_to_hsv(float r, float g, float b, float *lh, float *ls, float *lv)
{
- float h, s, v;
- float cmax, cmin;
-
- cmax = r;
- cmin = r;
- cmax = (g > cmax ? g : cmax);
- cmin = (g < cmin ? g : cmin);
- cmax = (b > cmax ? b : cmax);
- cmin = (b < cmin ? b : cmin);
-
- v = cmax; /* value */
- if (cmax != 0.0f) {
- float cdelta;
-
- cdelta = cmax - cmin;
- s = cdelta / cmax;
-
- if (s != 0.0f) {
- float rc, gc, bc;
-
- rc = (cmax - r) / cdelta;
- gc = (cmax - g) / cdelta;
- bc = (cmax - b) / cdelta;
-
- if (r == cmax) {
- h = bc - gc;
- if (h < 0.0f) {
- h += 6.0f;
- }
- }
- else if (g == cmax) {
- h = 2.0f + rc - bc;
- }
- else {
- h = 4.0f + gc - rc;
- }
-
- h *= (1.0f / 6.0f);
- }
- else {
- h = 0.0f;
- }
+ float k = 0.0f;
+ float chroma;
+ float min_gb;
+
+ if (g < b) {
+ SWAP(float, g, b);
+ k = -1.0f;
}
- else {
- h = 0.0f;
- s = 0.0f;
+ min_gb = b;
+ if (r < g) {
+ SWAP(float, r, g);
+ k = -2.0f / 6.0f - k;
+ min_gb = min_ff(g, b);
}
- *lh = h;
- *ls = s;
- *lv = v;
+ chroma = r - min_gb;
+
+ *lh = fabsf(k + (g - b) / (6.0f * chroma + 1e-20f));
+ *ls = chroma / (r + 1e-20f);
+ *lv = r;
}
/* convenience function for now */
@@ -374,8 +269,8 @@ void rgb_to_hsl(float r, float g, float b, float *lh, float *ls, float *ll)
void rgb_to_hsl_compat(float r, float g, float b, float *lh, float *ls, float *ll)
{
- float orig_s = *ls;
- float orig_h = *lh;
+ const float orig_s = *ls;
+ const float orig_h = *lh;
rgb_to_hsl(r, g, b, lh, ls, ll);
@@ -407,8 +302,8 @@ void rgb_to_hsl_v(const float rgb[3], float r_hsl[3])
void rgb_to_hsv_compat(float r, float g, float b, float *lh, float *ls, float *lv)
{
- float orig_h = *lh;
- float orig_s = *ls;
+ const float orig_h = *lh;
+ const float orig_s = *ls;
rgb_to_hsv(r, g, b, lh, ls, lv);
@@ -703,11 +598,12 @@ static float index_to_float(const unsigned short i)
void BLI_init_srgb_conversion(void)
{
- static int initialized = 0;
+ static bool initialized = false;
unsigned int i, b;
- if (initialized) return;
- initialized = 1;
+ if (initialized)
+ return;
+ initialized = true;
/* Fill in the lookup table to convert floats to bytes: */
for (i = 0; i < 0x10000; i++) {
@@ -762,13 +658,13 @@ static float xyz_to_lab_component(float v)
void xyz_to_lab(float x, float y, float z, float *l, float *a, float *b)
{
- float xr = x / 95.047f;
- float yr = y / 100.0f;
- float zr = z / 108.883f;
+ const float xr = x / 95.047f;
+ const float yr = y / 100.0f;
+ const float zr = z / 108.883f;
- float fx = xyz_to_lab_component(xr);
- float fy = xyz_to_lab_component(yr);
- float fz = xyz_to_lab_component(zr);
+ const float fx = xyz_to_lab_component(xr);
+ const float fy = xyz_to_lab_component(yr);
+ const float fz = xyz_to_lab_component(zr);
*l = 116.0f * fy - 16.0f;
*a = 500.0f * (fx - fy);
diff --git a/source/blender/blenlib/intern/math_color_blend_inline.c b/source/blender/blenlib/intern/math_color_blend_inline.c
index 4810fe757fa..2522fe5f6c9 100644
--- a/source/blender/blenlib/intern/math_color_blend_inline.c
+++ b/source/blender/blenlib/intern/math_color_blend_inline.c
@@ -30,11 +30,16 @@
#include "BLI_math_base.h"
#include "BLI_math_color.h"
#include "BLI_math_color_blend.h"
+#include "BLI_math_vector.h"
#include "BLI_utildefines.h"
#ifndef __MATH_COLOR_BLEND_INLINE_C__
#define __MATH_COLOR_BLEND_INLINE_C__
+/* don't add any saturation to a completly black and white image */
+#define EPS_SATURATION 0.0005f
+#define EPS_ALPHA 0.0005f
+
/***************************** Color Blending ********************************
*
* - byte colors are assumed to be straight alpha
@@ -67,10 +72,7 @@ MINLINE void blend_color_mix_byte(unsigned char dst[4], const unsigned char src1
}
else {
/* no op */
- dst[0] = src1[0];
- dst[1] = src1[1];
- dst[2] = src1[2];
- dst[3] = src1[3];
+ copy_v4_v4_char((char *)dst, (char *)src1);
}
}
@@ -92,10 +94,7 @@ MINLINE void blend_color_add_byte(unsigned char dst[4], const unsigned char src1
}
else {
/* no op */
- dst[0] = src1[0];
- dst[1] = src1[1];
- dst[2] = src1[2];
- dst[3] = src1[3];
+ copy_v4_v4_char((char *)dst, (char *)src1);
}
}
@@ -117,10 +116,7 @@ MINLINE void blend_color_sub_byte(unsigned char dst[4], const unsigned char src1
}
else {
/* no op */
- dst[0] = src1[0];
- dst[1] = src1[1];
- dst[2] = src1[2];
- dst[3] = src1[3];
+ copy_v4_v4_char((char *)dst, (char *)src1);
}
}
@@ -143,10 +139,7 @@ MINLINE void blend_color_mul_byte(unsigned char dst[4], const unsigned char src1
}
else {
/* no op */
- dst[0] = src1[0];
- dst[1] = src1[1];
- dst[2] = src1[2];
- dst[3] = src1[3];
+ copy_v4_v4_char((char *)dst, (char *)src1);
}
}
@@ -169,10 +162,7 @@ MINLINE void blend_color_lighten_byte(unsigned char dst[4], const unsigned char
}
else {
/* no op */
- dst[0] = src1[0];
- dst[1] = src1[1];
- dst[2] = src1[2];
- dst[3] = src1[3];
+ copy_v4_v4_char((char *)dst, (char *)src1);
}
}
@@ -195,10 +185,7 @@ MINLINE void blend_color_darken_byte(unsigned char dst[4], const unsigned char s
}
else {
/* no op */
- dst[0] = src1[0];
- dst[1] = src1[1];
- dst[2] = src1[2];
- dst[3] = src1[3];
+ copy_v4_v4_char((char *)dst, (char *)src1);
}
}
@@ -215,10 +202,7 @@ MINLINE void blend_color_erase_alpha_byte(unsigned char dst[4], const unsigned c
}
else {
/* no op */
- dst[0] = src1[0];
- dst[1] = src1[1];
- dst[2] = src1[2];
- dst[3] = src1[3];
+ copy_v4_v4_char((char *)dst, (char *)src1);
}
}
@@ -235,11 +219,391 @@ MINLINE void blend_color_add_alpha_byte(unsigned char dst[4], const unsigned cha
}
else {
/* no op */
- dst[0] = src1[0];
- dst[1] = src1[1];
- dst[2] = src1[2];
- dst[3] = src1[3];
+ copy_v4_v4_char((char *)dst, (char *)src1);
+ }
+}
+
+MINLINE void blend_color_overlay_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4])
+{
+ const int fac = (int)src2[3];
+ if (fac != 0) {
+ const int mfac = 255 - fac;
+ int i = 3;
+
+ while (i--) {
+ int temp;
+
+ if (src1[i] > 127) {
+ temp = 255 - ((255 - 2 * (src1[i] - 127)) * (255 - src2[i]) / 255);
+ }
+ else {
+ temp = (2 * src1[i] * src2[i]) >> 8;
+ }
+ dst[i] = (unsigned char)min_ii((temp * fac + src1[i] * mfac) / 255, 255);
+ }
+ }
+ else {
+ /* no op */
+ copy_v4_v4_char((char *)dst, (char *)src1);
+ }
+}
+
+
+MINLINE void blend_color_hardlight_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4])
+{
+ const int fac = (int)src2[3];
+ if (fac != 0) {
+ const int mfac = 255 - fac;
+ int i = 3;
+
+ while (i--) {
+ int temp;
+
+ if (src2[i] > 127) {
+ temp = 255 - ((255 - 2 * (src2[i] - 127)) * (255 - src1[i]) / 255);
+ }
+ else {
+ temp = (2 * src2[i] * src1[i]) >> 8;
+ }
+ dst[i] = (unsigned char)min_ii((temp * fac + src1[i] * mfac) / 255, 255);
+ }
+ }
+ else {
+ /* no op */
+ copy_v4_v4_char((char *)dst, (char *)src1);
+ }
+}
+
+
+MINLINE void blend_color_burn_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4])
+{
+ const int fac = src2[3];
+ if (fac != 0) {
+ const int mfac = 255 - fac;
+ int i = 3;
+
+ while (i--) {
+ const int temp = (src2[i] == 0) ? 0 : max_ii(255 - ((255 - src1[i]) * 255) / src2[i], 0);
+ dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255);
+ }
+ }
+ else {
+ /* no op */
+ copy_v4_v4_char((char *)dst, (char *)src1);
+ }
+}
+
+
+MINLINE void blend_color_linearburn_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4])
+{
+ const int fac = src2[3];
+ if (fac != 0) {
+ const int mfac = 255 - fac;
+ int i = 3;
+
+ while (i--) {
+ const int temp = max_ii(src1[i] + src2[i] - 255, 0);
+ dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255);
+ }
+ }
+ else {
+ /* no op */
+ copy_v4_v4_char((char *)dst, (char *)src1);
+ }
+}
+
+
+MINLINE void blend_color_dodge_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4])
+{
+ const int fac = src2[3];
+ if (fac != 0) {
+ const int mfac = 255 - fac;
+ int i = 3;
+
+ while (i--) {
+ const int temp = (src2[i] == 255) ? 255 : min_ii((src1[i] * 255) / (255 - src2[i]), 255);
+ dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255);
+ }
+ }
+ else {
+ /* no op */
+ copy_v4_v4_char((char *)dst, (char *)src1);
+ }
+}
+
+MINLINE void blend_color_screen_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4])
+{
+ const int fac = src2[3];
+ if (fac != 0) {
+ const int mfac = 255 - fac;
+ int i = 3;
+
+ while (i--) {
+ const int temp = max_ii(255 - (((255 - src1[i]) * (255 - src2[i])) / 255), 0);
+ dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255);
+ }
+ }
+ else {
+ /* no op */
+ copy_v4_v4_char((char *)dst, (char *)src1);
+ }
+}
+
+
+MINLINE void blend_color_softlight_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4])
+{
+ const int fac = src2[3];
+ if (fac != 0) {
+ const int mfac = 255 - fac;
+ int i = 3;
+
+ while (i--) {
+ int temp;
+
+ if (src1[i] < 127) {
+ temp = ((2 * ((src2[i] / 2) + 64)) * src1[i]) / 255;
+ }
+ else {
+ temp = 255 - (2 * (255 - ((src2[i] / 2) + 64)) * (255 - src1[i]) / 255);
+ }
+ dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255);
+ }
+ }
+ else {
+ /* no op */
+ copy_v4_v4_char((char *)dst, (char *)src1);
+ }
+}
+
+
+MINLINE void blend_color_pinlight_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4])
+{
+ const int fac = src2[3];
+ if (fac != 0) {
+ const int mfac = 255 - fac;
+ int i = 3;
+
+ while (i--) {
+ int temp;
+
+ if (src2[i] > 127) {
+ temp = max_ii(2 * (src2[i] - 127), src1[i]);
+ }
+ else {
+ temp = min_ii(2 * src2[i], src1[i]);
+ }
+ dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255);
+ }
+ }
+ else {
+ /* no op */
+ copy_v4_v4_char((char *)dst, (char *)src1);
+ }
+}
+
+
+MINLINE void blend_color_linearlight_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4])
+{
+ const int fac = src2[3];
+ if (fac != 0) {
+ const int mfac = 255 - fac;
+ int i = 3;
+
+ while (i--) {
+ int temp;
+
+ if (src2[i] > 127) {
+ temp = min_ii(src1[i] + 2 * (src2[i] - 127), 255);
+ }
+ else {
+ temp = max_ii(src1[i] + 2 * src2[i] - 255, 0);
+ }
+ dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255);
+ }
+ }
+ else {
+ /* no op */
+ copy_v4_v4_char((char *)dst, (char *)src1);
+ }
+}
+
+
+MINLINE void blend_color_vividlight_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4])
+{
+ const int fac = src2[3];
+ if (fac != 0) {
+ const int mfac = 255 - fac;
+ int i = 3;
+
+ while (i--) {
+ int temp;
+
+ if (src2[i] == 255) {
+ temp = 255;
+ }
+ else if (src2[i] == 0) {
+ temp = 0;
+ }
+ else if (src2[i] > 127) {
+ temp = min_ii(((src1[i]) * 255) / (2 * (255 - src2[i])), 255);
+ }
+ else {
+ temp = max_ii(255 - ((255 - src1[i]) * 255 / (2 * src2[i])), 0);
+ }
+ dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255);
+ }
+ }
+ else {
+ /* no op */
+ copy_v4_v4_char((char *)dst, (char *)src1);
+ }
+}
+
+
+
+MINLINE void blend_color_difference_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4])
+{
+ const int fac = src2[3];
+ if (fac != 0) {
+ const int mfac = 255 - fac;
+ int i = 3;
+
+ while (i--) {
+ const int temp = abs(src1[i] - src2[i]);
+ dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255);
+ }
+ }
+ else {
+ /* no op */
+ copy_v4_v4_char((char *)dst, (char *)src1);
+ }
+}
+
+
+MINLINE void blend_color_exclusion_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4])
+{
+ const int fac = src2[3];
+ if (fac != 0) {
+ const int mfac = 255 - fac;
+ int i = 3;
+
+ while (i--) {
+ const int temp = 127 - ((2 * (src1[i] - 127) * (src2[i] - 127)) / 255);
+ dst[i] = (unsigned char)((temp * fac + src1[i] * mfac) / 255);
+ }
+ }
+ else {
+ /* no op */
+ copy_v4_v4_char((char *)dst, (char *)src1);
+ }
+}
+
+MINLINE void blend_color_color_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4])
+{
+ const int fac = src2[3];
+ if (fac != 0) {
+ const int mfac = 255 - fac;
+ float h1, s1, v1;
+ float h2, s2, v2;
+ float r, g, b;
+ rgb_to_hsv(src1[0] / 255.0f, src1[1] / 255.0f, src1[2] / 255.0f, &h1, &s1, &v1);
+ rgb_to_hsv(src2[0] / 255.0f, src2[1] / 255.0f, src2[2] / 255.0f, &h2, &s2, &v2);
+
+
+ h1 = h2;
+ s1 = s2;
+
+ hsv_to_rgb(h1, s1, v1, &r, &g, &b);
+
+ dst[0] = (unsigned char)(((int)(r * 255.0f) * fac + src1[0] * mfac) / 255);
+ dst[1] = (unsigned char)(((int)(g * 255.0f) * fac + src1[1] * mfac) / 255);
+ dst[2] = (unsigned char)(((int)(b * 255.0f) * fac + src1[2] * mfac) / 255);
+ }
+ else {
+ /* no op */
+ copy_v4_v4_char((char *)dst, (char *)src1);
+ }
+}
+
+MINLINE void blend_color_hue_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4])
+{
+ const int fac = src2[3];
+ if (fac != 0) {
+ const int mfac = 255 - fac;
+ float h1, s1, v1;
+ float h2, s2, v2;
+ float r, g, b;
+ rgb_to_hsv(src1[0] / 255.0f, src1[1] / 255.0f, src1[2] / 255.0f, &h1, &s1, &v1);
+ rgb_to_hsv(src2[0] / 255.0f, src2[1] / 255.0f, src2[2] / 255.0f, &h2, &s2, &v2);
+
+
+ h1 = h2;
+
+ hsv_to_rgb(h1, s1, v1, &r, &g, &b);
+
+ dst[0] = (unsigned char)(((int)(r * 255.0f) * fac + src1[0] * mfac) / 255);
+ dst[1] = (unsigned char)(((int)(g * 255.0f) * fac + src1[1] * mfac) / 255);
+ dst[2] = (unsigned char)(((int)(b * 255.0f) * fac + src1[2] * mfac) / 255);
+ }
+ else {
+ /* no op */
+ copy_v4_v4_char((char *)dst, (char *)src1);
+ }
+
+}
+
+MINLINE void blend_color_saturation_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4])
+{
+ const int fac = src2[3];
+ if (fac != 0) {
+ const int mfac = 255 - fac;
+ float h1, s1, v1;
+ float h2, s2, v2;
+ float r, g, b;
+ rgb_to_hsv(src1[0] / 255.0f, src1[1] / 255.0f, src1[2] / 255.0f, &h1, &s1, &v1);
+ rgb_to_hsv(src2[0] / 255.0f, src2[1] / 255.0f, src2[2] / 255.0f, &h2, &s2, &v2);
+
+ if (s1 > EPS_SATURATION) {
+ s1 = s2;
+ }
+
+ hsv_to_rgb(h1, s1, v1, &r, &g, &b);
+
+ dst[0] = (unsigned char)(((int)(r * 255.0f) * fac + src1[0] * mfac) / 255);
+ dst[1] = (unsigned char)(((int)(g * 255.0f) * fac + src1[1] * mfac) / 255);
+ dst[2] = (unsigned char)(((int)(b * 255.0f) * fac + src1[2] * mfac) / 255);
+ }
+ else {
+ /* no op */
+ copy_v4_v4_char((char *)dst, (char *)src1);
+ }
+}
+
+MINLINE void blend_color_luminosity_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4])
+{
+ const int fac = src2[3];
+ if (fac != 0) {
+ const int mfac = 255 - fac;
+ float h1, s1, v1;
+ float h2, s2, v2;
+ float r, g, b;
+ rgb_to_hsv(src1[0] / 255.0f, src1[1] / 255.0f, src1[2] / 255.0f, &h1, &s1, &v1);
+ rgb_to_hsv(src2[0] / 255.0f, src2[1] / 255.0f, src2[2] / 255.0f, &h2, &s2, &v2);
+
+ v1 = v2;
+
+ hsv_to_rgb(h1, s1, v1, &r, &g, &b);
+
+ dst[0] = (unsigned char)(((int)(r * 255.0f) * fac + src1[0] * mfac) / 255);
+ dst[1] = (unsigned char)(((int)(g * 255.0f) * fac + src1[1] * mfac) / 255);
+ dst[2] = (unsigned char)(((int)(b * 255.0f) * fac + src1[2] * mfac) / 255);
+
+ }
+ else {
+ /* no op */
+ copy_v4_v4_char((char *)dst, (char *)src1);
}
+
}
MINLINE void blend_color_interpolate_byte(unsigned char dst[4], const unsigned char src1[4], const unsigned char src2[4], float ft)
@@ -257,10 +621,7 @@ MINLINE void blend_color_interpolate_byte(unsigned char dst[4], const unsigned c
dst[3] = (unsigned char)divide_round_i(tmp, 255);
}
else {
- dst[0] = src1[0];
- dst[1] = src1[1];
- dst[2] = src1[2];
- dst[3] = src1[3];
+ copy_v4_v4_char((char *)dst, (char *)src1);
}
}
@@ -280,10 +641,7 @@ MINLINE void blend_color_mix_float(float dst[4], const float src1[4], const floa
}
else {
/* no op */
- dst[0] = src1[0];
- dst[1] = src1[1];
- dst[2] = src1[2];
- dst[3] = src1[3];
+ copy_v4_v4(dst, src1);
}
}
@@ -298,10 +656,7 @@ MINLINE void blend_color_add_float(float dst[4], const float src1[4], const floa
}
else {
/* no op */
- dst[0] = src1[0];
- dst[1] = src1[1];
- dst[2] = src1[2];
- dst[3] = src1[3];
+ copy_v4_v4(dst, src1);
}
}
@@ -316,10 +671,7 @@ MINLINE void blend_color_sub_float(float dst[4], const float src1[4], const floa
}
else {
/* no op */
- dst[0] = src1[0];
- dst[1] = src1[1];
- dst[2] = src1[2];
- dst[3] = src1[3];
+ copy_v4_v4(dst, src1);
}
}
@@ -337,10 +689,7 @@ MINLINE void blend_color_mul_float(float dst[4], const float src1[4], const floa
}
else {
/* no op */
- dst[0] = src1[0];
- dst[1] = src1[1];
- dst[2] = src1[2];
- dst[3] = src1[3];
+ copy_v4_v4(dst, src1);
}
}
@@ -360,10 +709,7 @@ MINLINE void blend_color_lighten_float(float dst[4], const float src1[4], const
}
else {
/* no op */
- dst[0] = src1[0];
- dst[1] = src1[1];
- dst[2] = src1[2];
- dst[3] = src1[3];
+ copy_v4_v4(dst, src1);
}
}
@@ -383,10 +729,7 @@ MINLINE void blend_color_darken_float(float dst[4], const float src1[4], const f
}
else {
/* no op */
- dst[0] = src1[0];
- dst[1] = src1[1];
- dst[2] = src1[2];
- dst[3] = src1[3];
+ copy_v4_v4(dst, src1);
}
}
@@ -397,8 +740,9 @@ MINLINE void blend_color_erase_alpha_float(float dst[4], const float src1[4], co
float alpha = max_ff(src1[3] - src2[3], 0.0f);
float map_alpha;
- if (alpha <= 0.0005f)
+ if (alpha <= EPS_ALPHA) {
alpha = 0.0f;
+ }
map_alpha = alpha / src1[3];
@@ -409,10 +753,7 @@ MINLINE void blend_color_erase_alpha_float(float dst[4], const float src1[4], co
}
else {
/* no op */
- dst[0] = src1[0];
- dst[1] = src1[1];
- dst[2] = src1[2];
- dst[3] = src1[3];
+ copy_v4_v4(dst, src1);
}
}
@@ -423,8 +764,9 @@ MINLINE void blend_color_add_alpha_float(float dst[4], const float src1[4], cons
float alpha = min_ff(src1[3] + src2[3], 1.0f);
float map_alpha;
- if (alpha >= 1.0f - 0.0005f)
+ if (alpha >= 1.0f - EPS_ALPHA) {
alpha = 1.0f;
+ }
map_alpha = (src1[3] > 0.0f) ? alpha / src1[3] : 1.0f;
@@ -435,17 +777,390 @@ MINLINE void blend_color_add_alpha_float(float dst[4], const float src1[4], cons
}
else {
/* no op */
- dst[0] = src1[0];
- dst[1] = src1[1];
- dst[2] = src1[2];
- dst[3] = src1[3];
+ copy_v4_v4(dst, src1);
+ }
+}
+
+MINLINE void blend_color_overlay_float(float dst[3], const float src1[3], const float src2[3])
+{
+ const float fac = src2[3];
+ if (fac != 0.0f && fac < 1.0f) {
+ const float mfac = 1.0f - fac;
+ int i = 3;
+
+ while (i--) {
+ float temp;
+
+ if (src1[i] > 0.5f) {
+ temp = 1.0f - (1.0f - 2.0f * (src1[i] - 0.5f)) * (1.0f - src2[i]);
+ }
+ else {
+ temp = 2.0f * src1[i] * src2[i];
+ }
+ dst[i] = min_ff(temp * fac + src1[i] * mfac, 1.0f);
+ }
+ }
+ else {
+ /* no op */
+ copy_v4_v4(dst, src1);
+ }
+}
+
+
+MINLINE void blend_color_hardlight_float(float dst[4], const float src1[4], const float src2[2])
+{
+ const float fac = src2[3];
+ if (fac != 0.0f && fac < 1.0f) {
+ const float mfac = 1.0f - fac;
+ int i = 3;
+
+ while (i--) {
+ float temp;
+
+ if (src2[i] > 0.5f) {
+ temp = 1.0f - ((1.0f - 2.0f * (src2[i] - 0.5f)) * (1.0f - src1[i]));
+ }
+ else {
+ temp = 2.0f * src2[i] * src1[i];
+ }
+ dst[i] = min_ff((temp * fac + src1[i] * mfac) / 1.0f, 1.0f);
+ }
+ }
+ else {
+ /* no op */
+ copy_v4_v4(dst, src1);
+ }
+}
+
+MINLINE void blend_color_burn_float(float dst[3], const float src1[3], const float src2[3])
+{
+ const float fac = src2[3];
+ if (fac != 0.0f && fac < 1.0f) {
+ const float mfac = 1.0f - fac;
+ int i = 3;
+
+ while (i--) {
+ const float temp = (src2[i] == 0.0f) ? 0.0f : max_ff(1.0f - ((1.0f - src1[i]) / src2[i]), 0.0f);
+ dst[i] = (temp * fac + src1[i] * mfac);
+ }
+ }
+ else {
+ /* no op */
+ copy_v4_v4(dst, src1);
+ }
+}
+
+MINLINE void blend_color_linearburn_float(float dst[3], const float src1[3], const float src2[3])
+{
+ const float fac = src2[3];
+ if (fac != 0.0f && fac < 1.0f) {
+ const float mfac = 1.0f - fac;
+ int i = 3;
+
+ while (i--) {
+ const float temp = max_ff(src1[i] + src2[i] - 1.0f, 0.0f);
+ dst[i] = (temp * fac + src1[i] * mfac);
+ }
+ }
+ else {
+ /* no op */
+ copy_v4_v4(dst, src1);
+ }
+}
+
+
+MINLINE void blend_color_dodge_float(float dst[3], const float src1[3], const float src2[3])
+{
+ const float fac = src2[3];
+ if (fac != 0.0f && fac < 1.0f) {
+ const float mfac = 1.0f - fac;
+ int i = 3;
+
+ while (i--) {
+ const float temp = (src2[i] >= 1.0f) ? 1.0f : min_ff(src1[i] / (1.0f - src2[i]), 1.0f);
+ dst[i] = (temp * fac + src1[i] * mfac);
+ }
+ }
+ else {
+ /* no op */
+ copy_v4_v4(dst, src1);
+ }
+}
+
+MINLINE void blend_color_screen_float(float dst[3], const float src1[3], const float src2[3])
+{
+ const float fac = src2[3];
+ if (fac != 0.0f && fac < 1.0f) {
+ const float mfac = 1.0f - fac;
+ int i = 3;
+
+ while (i--) {
+ const float temp = max_ff(1.0f - ((1.0f - src1[i]) * (1.0f - src2[i])), 0.0f);
+ dst[i] = (temp * fac + src1[i] * mfac);
+ }
+ }
+ else {
+ /* no op */
+ copy_v4_v4(dst, src1);
+ }
+}
+
+MINLINE void blend_color_softlight_float(float dst[3], const float src1[3], const float src2[3])
+{
+ const float fac = src2[3];
+ if (fac != 0.0f && fac < 1.0f) {
+ const float mfac = 1.0f - fac;
+ int i = 3;
+
+ while (i--) {
+ float temp;
+
+ if (src1[i] < 0.5f) {
+ temp = (src2[i] + 0.5f) * src1[i];
+ }
+ else {
+ temp = 1.0f - ((1.0f - (src2[i] + 0.5f)) * (1.0f - src1[i]));
+ }
+ dst[i] = (temp * fac + src1[i] * mfac);
+ }
+ }
+ else {
+ /* no op */
+ copy_v4_v4(dst, src1);
+ }
+}
+
+MINLINE void blend_color_pinlight_float(float dst[3], const float src1[3], const float src2[3])
+{
+ const float fac = src2[3];
+ if (fac != 0.0f && fac < 1.0f) {
+ const float mfac = 1.0f - fac;
+ int i = 3;
+
+ while (i--) {
+ float temp;
+
+ if (src2[i] > 0.5f) {
+ temp = max_ff(2.0f * (src2[i] - 0.5f), src1[i]);
+ }
+ else {
+ temp = min_ff(2.0f * src2[i], src1[i]);
+ }
+ dst[i] = (temp * fac + src1[i] * mfac);
+ }
+ }
+ else {
+ /* no op */
+ copy_v4_v4(dst, src1);
+ }
+}
+
+
+MINLINE void blend_color_linearlight_float(float dst[3], const float src1[3], const float src2[3])
+{
+ const float fac = src2[3];
+ if (fac != 0.0f && fac < 1.0f) {
+ const float mfac = 1.0f - fac;
+ int i = 3;
+
+ while (i--) {
+ float temp;
+
+ if (src2[i] > 0.5f) {
+ temp = min_ff(src1[i] + 2.0f * (src2[i] - 0.5f), 1.0f);
+ }
+ else {
+ temp = max_ff(src1[i] + 2.0f * src2[i] - 1.0f, 0.0f);
+ }
+ dst[i] = (temp * fac + src1[i] * mfac);
+ }
+ }
+ else {
+ /* no op */
+ copy_v4_v4(dst, src1);
+ }
+}
+
+
+MINLINE void blend_color_vividlight_float(float dst[3], const float src1[3], const float src2[3])
+{
+ const float fac = src2[3];
+ if (fac != 0.0f && fac < 1.0f) {
+ const float mfac = 1.0f - fac;
+ int i = 3;
+
+ while (i--) {
+ float temp;
+
+ if (src2[i] == 1.0f) {
+ temp = 1.0f;
+ }
+ else if (src2[i] == 0.0f) {
+ temp = 0.0f;
+ }
+ else if (src2[i] > 0.5f) {
+ temp = min_ff(((src1[i]) * 1.0f) / (2.0f * (1.0f - src2[i])), 1.0f);
+ }
+ else {
+ temp = max_ff(1.0f - ((1.0f - src1[i]) * 1.0f / (2.0f * src2[i])), 0.0f);
+ }
+ dst[i] = (temp * fac + src1[i] * mfac);
+ }
+ }
+ else {
+ /* no op */
+ copy_v4_v4(dst, src1);
+ }
+}
+
+MINLINE void blend_color_difference_float(float dst[3], const float src1[3], const float src2[3])
+{
+ const float fac = src2[3];
+ if (fac != 0.0f && fac < 1.0f) {
+ const float mfac = 1.0f - fac;
+ int i = 3;
+
+ while (i--) {
+ dst[i] = (fabsf(src1[i] - src2[i]) * fac + src1[i] * mfac);
+ }
+ }
+ else {
+ /* no op */
+ copy_v4_v4(dst, src1);
}
}
+
+MINLINE void blend_color_exclusion_float(float dst[3], const float src1[3], const float src2[3])
+{
+ const float fac = src2[3];
+ if (fac != 0.0f && fac < 1.0f) {
+ const float mfac = 1.0f - fac;
+ int i = 3;
+
+ while (i--) {
+ const float temp = 0.5f - ((2 * (src1[i] - 0.5f) * (src2[i] - 0.5f)));
+ dst[i] = (temp * fac + src1[i] * mfac);
+ }
+ }
+ else {
+ /* no op */
+ copy_v4_v4(dst, src1);
+ }
+
+}
+
+MINLINE void blend_color_color_float(float dst[3], const float src1[3], const float src2[3])
+{
+ const float fac = src2[3];
+ if (fac != 0.0f && fac < 1.0f) {
+ const float mfac = 1.0f - fac;
+ float h1, s1, v1;
+ float h2, s2, v2;
+ float r, g, b;
+
+ rgb_to_hsv(src1[0], src1[1], src1[2], &h1, &s1, &v1);
+ rgb_to_hsv(src2[0], src2[1], src2[2], &h2, &s2, &v2);
+
+ h1 = h2;
+ s1 = s2;
+
+ hsv_to_rgb(h1, s1, v1, &r, &g, &b);
+
+ dst[0] = (r * fac + src1[0] * mfac);
+ dst[1] = (g * fac + src1[1] * mfac);
+ dst[2] = (b * fac + src1[2] * mfac);
+ }
+ else {
+ /* no op */
+ copy_v4_v4(dst, src1);
+ }
+}
+
+
+MINLINE void blend_color_hue_float(float dst[3], const float src1[3], const float src2[3])
+{
+ const float fac = src2[3];
+ if (fac != 0.0f && fac < 1.0f) {
+ const float mfac = 1.0f - fac;
+ float h1, s1, v1;
+ float h2, s2, v2;
+ float r, g, b;
+
+ rgb_to_hsv(src1[0], src1[1], src1[2], &h1, &s1, &v1);
+ rgb_to_hsv(src2[0], src2[1], src2[2], &h2, &s2, &v2);
+
+ h1 = h2;
+
+ hsv_to_rgb(h1, s1, v1, &r, &g, &b);
+
+ dst[0] = (r * fac + src1[0] * mfac);
+ dst[1] = (g * fac + src1[1] * mfac);
+ dst[2] = (b * fac + src1[2] * mfac);
+ }
+ else {
+ /* no op */
+ copy_v4_v4(dst, src1);
+ }
+}
+
+MINLINE void blend_color_saturation_float(float dst[3], const float src1[3], const float src2[3])
+{
+ const float fac = src2[3];
+ if (fac != 0.0f && fac < 1.0f) {
+ const float mfac = 1.0f - fac;
+ float h1, s1, v1;
+ float h2, s2, v2;
+ float r, g, b;
+
+ rgb_to_hsv(src1[0], src1[1], src1[2], &h1, &s1, &v1);
+ rgb_to_hsv(src2[0], src2[1], src2[2], &h2, &s2, &v2);
+
+ if (s1 > EPS_SATURATION) {
+ s1 = s2;
+ }
+ hsv_to_rgb(h1, s1, v1, &r, &g, &b);
+
+ dst[0] = (r * fac + src1[0] * mfac);
+ dst[1] = (g * fac + src1[1] * mfac);
+ dst[2] = (b * fac + src1[2] * mfac);
+ }
+ else {
+ /* no op */
+ copy_v4_v4(dst, src1);
+ }
+}
+
+MINLINE void blend_color_luminosity_float(float dst[3], const float src1[3], const float src2[3])
+{
+ const float fac = src2[3];
+ if (fac != 0.0f && fac < 1.0f) {
+ const float mfac = 1.0f - fac;
+ float h1, s1, v1;
+ float h2, s2, v2;
+ float r, g, b;
+
+ rgb_to_hsv(src1[0], src1[1], src1[2], &h1, &s1, &v1);
+ rgb_to_hsv(src2[0], src2[1], src2[2], &h2, &s2, &v2);
+
+ v1 = v2;
+ hsv_to_rgb(h1, s1, v1, &r, &g, &b);
+
+ dst[0] = (r * fac + src1[0] * mfac);
+ dst[1] = (g * fac + src1[1] * mfac);
+ dst[2] = (b * fac + src1[2] * mfac);
+ }
+ else {
+ /* no op */
+ copy_v4_v4(dst, src1);
+ }
+}
+
+
MINLINE void blend_color_interpolate_float(float dst[4], const float src1[4], const float src2[4], float t)
{
/* interpolation, colors are premultiplied so it goes fine */
- float mt = 1.0f - t;
+ const float mt = 1.0f - t;
dst[0] = mt * src1[0] + t * src2[0];
dst[1] = mt * src1[1] + t * src2[1];
@@ -453,4 +1168,7 @@ MINLINE void blend_color_interpolate_float(float dst[4], const float src1[4], co
dst[3] = mt * src1[3] + t * src2[3];
}
+#undef EPS_SATURATION
+#undef EPS_ALPHA
+
#endif /* __MATH_COLOR_BLEND_INLINE_C__ */
diff --git a/source/blender/blenlib/intern/math_color_inline.c b/source/blender/blenlib/intern/math_color_inline.c
index bb2201541d9..9233749d5df 100644
--- a/source/blender/blenlib/intern/math_color_inline.c
+++ b/source/blender/blenlib/intern/math_color_inline.c
@@ -255,11 +255,11 @@ MINLINE float rgb_to_luma_y(const float rgb[3])
MINLINE int compare_rgb_uchar(const unsigned char col_a[3], const unsigned char col_b[3], const int limit)
{
- int r = (int)col_a[0] - (int)col_b[0];
+ const int r = (int)col_a[0] - (int)col_b[0];
if (ABS(r) < limit) {
- int g = (int)col_a[1] - (int)col_b[1];
+ const int g = (int)col_a[1] - (int)col_b[1];
if (ABS(g) < limit) {
- int b = (int)col_a[2] - (int)col_b[2];
+ const int b = (int)col_a[2] - (int)col_b[2];
if (ABS(b) < limit) {
return 1;
}
@@ -280,7 +280,7 @@ MINLINE void premul_to_straight_v4_v4(float straight[4], const float premul[4])
straight[3] = premul[3];
}
else {
- float alpha_inv = 1.0f / premul[3];
+ const float alpha_inv = 1.0f / premul[3];
straight[0] = premul[0] * alpha_inv;
straight[1] = premul[1] * alpha_inv;
straight[2] = premul[2] * alpha_inv;
@@ -295,7 +295,7 @@ MINLINE void premul_to_straight_v4(float color[4])
MINLINE void straight_to_premul_v4_v4(float premul[4], const float straight[4])
{
- float alpha = straight[3];
+ const float alpha = straight[3];
premul[0] = straight[0] * alpha;
premul[1] = straight[1] * alpha;
premul[2] = straight[2] * alpha;
@@ -309,8 +309,8 @@ MINLINE void straight_to_premul_v4(float color[4])
MINLINE void straight_uchar_to_premul_float(float result[4], const unsigned char color[4])
{
- float alpha = color[3] * (1.0f / 255.0f);
- float fac = alpha * (1.0f / 255.0f);
+ const float alpha = color[3] * (1.0f / 255.0f);
+ const float fac = alpha * (1.0f / 255.0f);
result[0] = color[0] * fac;
result[1] = color[1] * fac;
@@ -327,7 +327,7 @@ MINLINE void premul_float_to_straight_uchar(unsigned char *result, const float c
result[3] = FTOCHAR(color[3]);
}
else {
- float alpha_inv = 1.0f / color[3];
+ const float alpha_inv = 1.0f / color[3];
/* hopefully this would be optimized */
result[0] = FTOCHAR(color[0] * alpha_inv);
diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c
index efb881cde1b..54e3545a3f1 100644
--- a/source/blender/blenlib/intern/math_geom.c
+++ b/source/blender/blenlib/intern/math_geom.c
@@ -568,7 +568,7 @@ int isect_seg_seg_v2_point(const float v1[2], const float v2[2], const float v3[
{
float a1, a2, b1, b2, c1, c2, d;
float u, v;
- const float eps = 0.000001f;
+ const float eps = 1e-6f;
const float eps_sq = eps * eps;
a1 = v2[0] - v1[0];
@@ -1278,13 +1278,13 @@ bool isect_plane_plane_v3(float r_isect_co[3], float r_isect_no[3],
static bool getLowestRoot(const float a, const float b, const float c, const float maxR, float *root)
{
/* Check if a solution exists */
- float determinant = b * b - 4.0f * a * c;
+ const float determinant = b * b - 4.0f * a * c;
/* If determinant is negative it means no solutions. */
if (determinant >= 0.0f) {
/* calculate the two roots: (if determinant == 0 then
* x1==x2 but lets disregard that slight optimization) */
- float sqrtD = sqrtf(determinant);
+ const float sqrtD = sqrtf(determinant);
float r1 = (-b - sqrtD) / (2.0f * a);
float r2 = (-b + sqrtD) / (2.0f * a);
@@ -1295,18 +1295,18 @@ static bool getLowestRoot(const float a, const float b, const float c, const flo
/* Get lowest root: */
if (r1 > 0.0f && r1 < maxR) {
*root = r1;
- return 1;
+ return true;
}
/* It is possible that we want x2 - this can happen */
/* if x1 < 0 */
if (r2 > 0.0f && r2 < maxR) {
*root = r2;
- return 1;
+ return true;
}
}
/* No (valid) solutions */
- return 0;
+ return false;
}
bool isect_sweeping_sphere_tri_v3(const float p1[3], const float p2[3], const float radius,
@@ -1335,7 +1335,7 @@ bool isect_sweeping_sphere_tri_v3(const float p1[3], const float p2[3], const fl
if (fabsf(nordotv) < 0.000001f) {
if (fabsf(a) >= radius) {
- return 0;
+ return false;
}
}
else {
@@ -1377,7 +1377,7 @@ bool isect_sweeping_sphere_tri_v3(const float p1[3], const float p2[3], const fl
//(((unsigned int)z)& ~(((unsigned int)x)|((unsigned int)y))) & 0x80000000) {
*r_lambda = t0;
copy_v3_v3(ipoint, point);
- return 1;
+ return true;
}
}
@@ -1394,7 +1394,7 @@ bool isect_sweeping_sphere_tri_v3(const float p1[3], const float p2[3], const fl
if (getLowestRoot(a, b, c, *r_lambda, r_lambda)) {
copy_v3_v3(ipoint, v0);
- found_by_sweep = 1;
+ found_by_sweep = true;
}
/*v1*/
@@ -1404,7 +1404,7 @@ bool isect_sweeping_sphere_tri_v3(const float p1[3], const float p2[3], const fl
if (getLowestRoot(a, b, c, *r_lambda, r_lambda)) {
copy_v3_v3(ipoint, v1);
- found_by_sweep = 1;
+ found_by_sweep = true;
}
/*v2*/
@@ -1414,7 +1414,7 @@ bool isect_sweeping_sphere_tri_v3(const float p1[3], const float p2[3], const fl
if (getLowestRoot(a, b, c, *r_lambda, r_lambda)) {
copy_v3_v3(ipoint, v2);
- found_by_sweep = 1;
+ found_by_sweep = true;
}
/*---test edges---*/
@@ -1440,7 +1440,7 @@ bool isect_sweeping_sphere_tri_v3(const float p1[3], const float p2[3], const fl
copy_v3_v3(ipoint, e1);
mul_v3_fl(ipoint, e);
add_v3_v3(ipoint, v0);
- found_by_sweep = 1;
+ found_by_sweep = true;
}
}
@@ -1462,7 +1462,7 @@ bool isect_sweeping_sphere_tri_v3(const float p1[3], const float p2[3], const fl
copy_v3_v3(ipoint, e2);
mul_v3_fl(ipoint, e);
add_v3_v3(ipoint, v0);
- found_by_sweep = 1;
+ found_by_sweep = true;
}
}
@@ -1489,7 +1489,7 @@ bool isect_sweeping_sphere_tri_v3(const float p1[3], const float p2[3], const fl
copy_v3_v3(ipoint, e3);
mul_v3_fl(ipoint, e);
add_v3_v3(ipoint, v1);
- found_by_sweep = 1;
+ found_by_sweep = true;
}
}
@@ -1508,10 +1508,10 @@ bool isect_axial_line_tri_v3(const int axis, const float p1[3], const float p2[3
return isect_line_tri_v3(p1, p2, v0, v1, v2, lambda);
/* first a simple bounding box test */
- if (min_fff(v0[a1], v1[a1], v2[a1]) > p1[a1]) return 0;
- if (min_fff(v0[a2], v1[a2], v2[a2]) > p1[a2]) return 0;
- if (max_fff(v0[a1], v1[a1], v2[a1]) < p1[a1]) return 0;
- if (max_fff(v0[a2], v1[a2], v2[a2]) < p1[a2]) return 0;
+ if (min_fff(v0[a1], v1[a1], v2[a1]) > p1[a1]) return false;
+ if (min_fff(v0[a2], v1[a2], v2[a2]) > p1[a2]) return false;
+ if (max_fff(v0[a1], v1[a1], v2[a1]) < p1[a1]) return false;
+ if (max_fff(v0[a2], v1[a2], v2[a2]) < p1[a2]) return false;
/* then a full intersection test */
#endif
@@ -1521,7 +1521,7 @@ bool isect_axial_line_tri_v3(const int axis, const float p1[3], const float p2[3
sub_v3_v3v3(p, v0, p1);
f = (e2[a1] * e1[a2] - e2[a2] * e1[a1]);
- if ((f > -0.000001f) && (f < 0.000001f)) return 0;
+ if ((f > -0.000001f) && (f < 0.000001f)) return false;
v = (p[a2] * e1[a1] - p[a1] * e1[a2]) / f;
if ((v < 0.0f) || (v > 1.0f)) return 0;
@@ -1529,7 +1529,7 @@ bool isect_axial_line_tri_v3(const int axis, const float p1[3], const float p2[3
f = e1[a1];
if ((f > -0.000001f) && (f < 0.000001f)) {
f = e1[a2];
- if ((f > -0.000001f) && (f < 0.000001f)) return 0;
+ if ((f > -0.000001f) && (f < 0.000001f)) return false;
u = (-p[a2] - v * e2[a2]) / f;
}
else
@@ -1539,9 +1539,9 @@ bool isect_axial_line_tri_v3(const int axis, const float p1[3], const float p2[3
*r_lambda = (p[a0] + u * e1[a0] + v * e2[a0]) / (p2[a0] - p1[a0]);
- if ((*r_lambda < 0.0f) || (*r_lambda > 1.0f)) return 0;
+ if ((*r_lambda < 0.0f) || (*r_lambda > 1.0f)) return false;
- return 1;
+ return true;
}
/**
@@ -1616,9 +1616,9 @@ int isect_line_line_v3(const float v1[3], const float v2[3], const float v3[3],
}
}
-/* Intersection point strictly between the two lines
- * 0 when no intersection is found
- * */
+/** Intersection point strictly between the two lines
+ * \return false when no intersection is found
+ */
bool isect_line_line_strict_v3(const float v1[3], const float v2[3],
const float v3[3], const float v4[3],
float vi[3], float *r_lambda)
@@ -1635,7 +1635,7 @@ bool isect_line_line_strict_v3(const float v1[3], const float v2[3],
d = dot_v3v3(dir1, dir2);
if (d == 1.0f || d == -1.0f || d == 0) {
/* colinear or one vector is zero-length*/
- return 0;
+ return false;
}
cross_v3_v3v3(ab, a, b);
@@ -1644,7 +1644,7 @@ bool isect_line_line_strict_v3(const float v1[3], const float v2[3],
/* test zero length line */
if (UNLIKELY(div == 0.0f)) {
- return 0;
+ return false;
}
/* test if the two lines are coplanar */
else if (d > -0.000001f && d < 0.000001f) {
@@ -1663,14 +1663,14 @@ bool isect_line_line_strict_v3(const float v1[3], const float v2[3],
if (r_lambda) *r_lambda = f1;
- return 1; /* intersection found */
+ return true; /* intersection found */
}
else {
- return 0;
+ return false;
}
}
else {
- return 0;
+ return false;
}
}
@@ -1688,9 +1688,9 @@ void isect_ray_aabb_initialize(IsectRayAABBData *data, const float ray_start[3],
data->ray_inv_dir[1] = 1.0f / ray_direction[1];
data->ray_inv_dir[2] = 1.0f / ray_direction[2];
- data->sign[0] = data->ray_inv_dir[0] < 0;
- data->sign[1] = data->ray_inv_dir[1] < 0;
- data->sign[2] = data->ray_inv_dir[2] < 0;
+ data->sign[0] = data->ray_inv_dir[0] < 0.0f;
+ data->sign[1] = data->ray_inv_dir[1] < 0.0f;
+ data->sign[2] = data->ray_inv_dir[2] < 0.0f;
}
/* Adapted from http://www.gamedev.net/community/forums/topic.asp?topic_id=459973 */
@@ -1808,8 +1808,9 @@ float line_plane_factor_v3(const float plane_co[3], const float plane_no[3],
return (dot != 0.0f) ? -dot_v3v3(plane_no, h) / dot : 0.0f;
}
-/* ensure the distance between these points is no greater then 'dist'
- * if it is, scale then both into the center */
+/** Ensure the distance between these points is no greater then 'dist'.
+ * If it is, scale then both into the center.
+ */
void limit_dist_v3(float v1[3], float v2[3], const float dist)
{
const float dist_old = len_v3v3(v1, v2);
@@ -1874,8 +1875,7 @@ static bool point_in_slice(const float p[3], const float v1[3], const float l1[3
sub_v3_v3v3(rp, p, v1);
h = dot_v3v3(q, rp) / dot_v3v3(q, q);
- if (h < 0.0f || h > 1.0f) return 0;
- return 1;
+ return (h < 0.0f || h > 1.0f) ? false : true;
}
#if 0
@@ -1904,10 +1904,43 @@ static int point_in_slice_m(float p[3], float origin[3], float normal[3], float
bool isect_point_tri_prism_v3(const float p[3], const float v1[3], const float v2[3], const float v3[3])
{
- if (!point_in_slice(p, v1, v2, v3)) return 0;
- if (!point_in_slice(p, v2, v3, v1)) return 0;
- if (!point_in_slice(p, v3, v1, v2)) return 0;
- return 1;
+ if (!point_in_slice(p, v1, v2, v3)) return false;
+ if (!point_in_slice(p, v2, v3, v1)) return false;
+ if (!point_in_slice(p, v3, v1, v2)) return false;
+ return true;
+}
+
+/**
+ * \param r_vi The point \a p projected onto the triangle.
+ * \return True when \a p is inside the triangle.
+ * \note Its up to the caller to check the distance between \a p and \a r_vi against an error margin.
+ */
+bool isect_point_tri_v3(const float p[3], const float v1[3], const float v2[3], const float v3[3],
+ float r_vi[3])
+{
+ if (isect_point_tri_prism_v3(p, v1, v2, v3)) {
+ float no[3], n1[3], n2[3];
+
+ /* Could use normal_tri_v3, but doesn't have to be unit-length */
+ sub_v3_v3v3(n1, v1, v2);
+ sub_v3_v3v3(n2, v2, v3);
+ cross_v3_v3v3(no, n1, n2);
+
+ if (LIKELY(len_squared_v3(no) != 0.0f)) {
+ float plane[4];
+ plane_from_point_normal_v3(plane, v1, no);
+ closest_to_plane_v3(r_vi, plane, p);
+ }
+ else {
+ /* degenerate */
+ copy_v3_v3(r_vi, p);
+ }
+
+ return true;
+ }
+ else {
+ return false;
+ }
}
bool clip_segment_v3_plane(float p1[3], float p2[3], const float plane[4])
@@ -1918,7 +1951,7 @@ bool clip_segment_v3_plane(float p1[3], float p2[3], const float plane[4])
div = dot_v3v3(dp, plane);
if (div == 0.0f) /* parallel */
- return 1;
+ return true;
t = -plane_point_side_v3(plane, p1) / div;
@@ -1927,34 +1960,34 @@ bool clip_segment_v3_plane(float p1[3], float p2[3], const float plane[4])
if (t >= 1.0f) {
zero_v3(p1);
zero_v3(p2);
- return 0;
+ return false;
}
/* intersect plane */
if (t > 0.0f) {
madd_v3_v3v3fl(pc, p1, dp, t);
copy_v3_v3(p1, pc);
- return 1;
+ return true;
}
- return 1;
+ return true;
}
else {
/* behind plane, completely clipped */
if (t <= 0.0f) {
zero_v3(p1);
zero_v3(p2);
- return 0;
+ return false;
}
/* intersect plane */
if (t < 1.0f) {
madd_v3_v3v3fl(pc, p1, dp, t);
copy_v3_v3(p2, pc);
- return 1;
+ return true;
}
- return 1;
+ return true;
}
}
@@ -2183,12 +2216,12 @@ static bool barycentric_weights(const float v1[3], const float v2[3], const floa
if (fabsf(wtot) > FLT_EPSILON) {
mul_v3_fl(w, 1.0f / wtot);
- return 0;
+ return false;
}
else {
/* zero area triangle */
copy_v3_fl(w, 1.0f / 3.0f);
- return 1;
+ return true;
}
}
@@ -2239,8 +2272,9 @@ void interp_weights_face_v3(float w[4], const float v1[3], const float v2[3], co
}
}
}
- else
+ else {
barycentric_weights(v1, v2, v3, co, n, w);
+ }
}
}
@@ -2266,11 +2300,11 @@ int barycentric_inside_triangle_v2(const float w[3])
/* returns 0 for degenerated triangles */
bool barycentric_coords_v2(const float v1[2], const float v2[2], const float v3[2], const float co[2], float w[3])
{
- float x = co[0], y = co[1];
- float x1 = v1[0], y1 = v1[1];
- float x2 = v2[0], y2 = v2[1];
- float x3 = v3[0], y3 = v3[1];
- float det = (y2 - y3) * (x1 - x3) + (x3 - x2) * (y1 - y3);
+ const float x = co[0], y = co[1];
+ const float x1 = v1[0], y1 = v1[1];
+ const float x2 = v2[0], y2 = v2[1];
+ const float x3 = v3[0], y3 = v3[1];
+ const float det = (y2 - y3) * (x1 - x3) + (x3 - x2) * (y1 - y3);
if (fabsf(det) > FLT_EPSILON) {
w[0] = ((y2 - y3) * (x - x3) + (x3 - x2) * (y - y3)) / det;
@@ -2319,8 +2353,9 @@ void barycentric_weights_v2_persp(const float v1[4], const float v2[4], const fl
if (wtot != 0.0f) {
mul_v3_fl(w, 1.0f / wtot);
}
- else /* dummy values for zero area face */
+ else { /* dummy values for zero area face */
w[0] = w[1] = w[2] = 1.0f / 3.0f;
+ }
}
/* same as #barycentric_weights_v2 but works with a quad,
@@ -2355,8 +2390,7 @@ void barycentric_weights_v2_quad(const float v1[2], const float v2[2], const flo
if (UNLIKELY(lens[0] < FLT_EPSILON)) { w[0] = 1.0f; w[1] = w[2] = w[3] = 0.0f; }
else if (UNLIKELY(lens[1] < FLT_EPSILON)) { w[1] = 1.0f; w[0] = w[2] = w[3] = 0.0f; }
else if (UNLIKELY(lens[2] < FLT_EPSILON)) { w[2] = 1.0f; w[0] = w[1] = w[3] = 0.0f; }
- else if (UNLIKELY(lens[3] < FLT_EPSILON)) { w[3] = 1.0f; w[0] = w[1] = w[2] = 0.0f;
- }
+ else if (UNLIKELY(lens[3] < FLT_EPSILON)) { w[3] = 1.0f; w[0] = w[1] = w[2] = 0.0f; }
else {
float wtot, area;
@@ -2563,7 +2597,7 @@ static float mean_value_half_tan_v2(const float v1[2], const float v2[2], const
void interp_weights_poly_v3(float *w, float v[][3], const int n, const float co[3])
{
- const float eps = 0.00001f; /* take care, low values cause [#36105] */
+ const float eps = 1e-5f; /* take care, low values cause [#36105] */
const float eps_sq = eps * eps;
const float *v_curr, *v_next;
float ht_prev, ht; /* half tangents */
@@ -2632,7 +2666,7 @@ void interp_weights_poly_v3(float *w, float v[][3], const int n, const float co[
void interp_weights_poly_v2(float *w, float v[][2], const int n, const float co[2])
{
- const float eps = 0.00001f; /* take care, low values cause [#36105] */
+ const float eps = 1e-5f; /* take care, low values cause [#36105] */
const float eps_sq = eps * eps;
const float *v_curr, *v_next;
float ht_prev, ht; /* half tangents */
@@ -2702,8 +2736,8 @@ void interp_weights_poly_v2(float *w, float v[][2], const int n, const float co[
void interp_cubic_v3(float x[3], float v[3], const float x1[3], const float v1[3], const float x2[3], const float v2[3], const float t)
{
float a[3], b[3];
- float t2 = t * t;
- float t3 = t2 * t;
+ const float t2 = t * t;
+ const float t3 = t2 * t;
/* cubic interpolation */
a[0] = v1[0] + v2[0] + 2 * (x1[0] - x2[0]);
@@ -2928,11 +2962,9 @@ void orthographic_m4(float matrix[4][4], const float left, const float right, co
void perspective_m4(float mat[4][4], const float left, const float right, const float bottom, const float top,
const float nearClip, const float farClip)
{
- float Xdelta, Ydelta, Zdelta;
-
- Xdelta = right - left;
- Ydelta = top - bottom;
- Zdelta = farClip - nearClip;
+ const float Xdelta = right - left;
+ const float Ydelta = top - bottom;
+ const float Zdelta = farClip - nearClip;
if (Xdelta == 0.0f || Ydelta == 0.0f || Zdelta == 0.0f) {
return;
@@ -2946,7 +2978,7 @@ void perspective_m4(float mat[4][4], const float left, const float right, const
mat[3][2] = (-2.0f * nearClip * farClip) / Zdelta;
mat[0][1] = mat[0][2] = mat[0][3] =
mat[1][0] = mat[1][2] = mat[1][3] =
- mat[3][0] = mat[3][1] = mat[3][3] = 0.0;
+ mat[3][0] = mat[3][1] = mat[3][3] = 0.0f;
}
@@ -2995,7 +3027,6 @@ static void i_multmatrix(float icand[4][4], float Vm[4][4])
void polarview_m4(float Vm[4][4], float dist, float azimuth, float incidence, float twist)
{
-
unit_m4(Vm);
translate_m4(Vm, 0.0, 0.0, -dist);
@@ -3017,16 +3048,16 @@ void lookat_m4(float mat[4][4], float vx, float vy, float vz, float px, float py
dx = px - vx;
dy = py - vy;
dz = pz - vz;
- hyp = dx * dx + dz * dz; /* hyp squared */
+ hyp = dx * dx + dz * dz; /* hyp squared */
hyp1 = sqrtf(dy * dy + hyp);
- hyp = sqrtf(hyp); /* the real hyp */
+ hyp = sqrtf(hyp); /* the real hyp */
- if (hyp1 != 0.0f) { /* rotate X */
+ if (hyp1 != 0.0f) { /* rotate X */
sine = -dy / hyp1;
cosine = hyp / hyp1;
}
else {
- sine = 0;
+ sine = 0.0f;
cosine = 1.0f;
}
mat1[1][1] = cosine;
@@ -3036,16 +3067,16 @@ void lookat_m4(float mat[4][4], float vx, float vy, float vz, float px, float py
i_multmatrix(mat1, mat);
- mat1[1][1] = mat1[2][2] = 1.0f; /* be careful here to reinit */
- mat1[1][2] = mat1[2][1] = 0.0; /* those modified by the last */
+ mat1[1][1] = mat1[2][2] = 1.0f; /* be careful here to reinit */
+ mat1[1][2] = mat1[2][1] = 0.0f; /* those modified by the last */
- /* paragraph */
- if (hyp != 0.0f) { /* rotate Y */
+ /* paragraph */
+ if (hyp != 0.0f) { /* rotate Y */
sine = dx / hyp;
cosine = -dz / hyp;
}
else {
- sine = 0;
+ sine = 0.0f;
cosine = 1.0f;
}
mat1[0][0] = cosine;
@@ -3226,10 +3257,10 @@ void accumulate_vertex_normals_poly(float **vertnos, const float polyno[3],
void tangent_from_uv(float uv1[2], float uv2[2], float uv3[3], float co1[3], float co2[3], float co3[3], float n[3], float tang[3])
{
- float s1 = uv2[0] - uv1[0];
- float s2 = uv3[0] - uv1[0];
- float t1 = uv2[1] - uv1[1];
- float t2 = uv3[1] - uv1[1];
+ const float s1 = uv2[0] - uv1[0];
+ const float s2 = uv3[0] - uv1[0];
+ const float t1 = uv2[1] - uv1[1];
+ const float t2 = uv3[1] - uv1[1];
float det = (s1 * t2 - s2 * t1);
if (det != 0.0f) { /* otherwise 'tang' becomes nan */
@@ -3254,7 +3285,7 @@ void tangent_from_uv(float uv1[2], float uv2[2], float uv3[3], float co1[3], flo
}
}
else {
- tang[0] = tang[1] = tang[2] = 0.0;
+ tang[0] = tang[1] = tang[2] = 0.0f;
}
}
@@ -3287,7 +3318,8 @@ void vcloud_estimate_transform(int list_size, float (*pos)[3], float *weight, fl
float lloc[3], float rloc[3], float lrot[3][3], float lscale[3][3])
{
float accu_com[3] = {0.0f, 0.0f, 0.0f}, accu_rcom[3] = {0.0f, 0.0f, 0.0f};
- float accu_weight = 0.0f, accu_rweight = 0.0f, eps = 0.000001f;
+ float accu_weight = 0.0f, accu_rweight = 0.0f;
+ const float eps = 1e-6f;
int a;
/* first set up a nice default response */
@@ -3381,7 +3413,7 @@ void vcloud_estimate_transform(int list_size, float (*pos)[3], float *weight, fl
/* this is pretty much Polardecompose 'inline' the algo based on Higham's thesis */
/* without the far case ... but seems to work here pretty neat */
- odet = 0.f;
+ odet = 0.0f;
ndet = determinant_m3_array(q);
while ((odet - ndet) * (odet - ndet) > eps && i < imax) {
invert_m3_m3(qi, q);
@@ -3422,9 +3454,8 @@ bool form_factor_visible_quad(const float p[3], const float n[3],
float q0[3], float q1[3], float q2[3], float q3[3])
{
static const float epsilon = 1e-6f;
- float c, sd[3];
-
- c = dot_v3v3(n, p);
+ float sd[3];
+ const float c = dot_v3v3(n, p);
/* signed distances from the vertices to the plane. */
sd[0] = dot_v3v3(n, v0) - c;
@@ -3435,16 +3466,16 @@ bool form_factor_visible_quad(const float p[3], const float n[3],
if (fabsf(sd[1]) < epsilon) sd[1] = 0.0f;
if (fabsf(sd[2]) < epsilon) sd[2] = 0.0f;
- if (sd[0] > 0) {
- if (sd[1] > 0) {
- if (sd[2] > 0) {
+ if (sd[0] > 0.0f) {
+ if (sd[1] > 0.0f) {
+ if (sd[2] > 0.0f) {
/* +++ */
copy_v3_v3(q0, v0);
copy_v3_v3(q1, v1);
copy_v3_v3(q2, v2);
copy_v3_v3(q3, q2);
}
- else if (sd[2] < 0) {
+ else if (sd[2] < 0.0f) {
/* ++- */
copy_v3_v3(q0, v0);
copy_v3_v3(q1, v1);
@@ -3459,15 +3490,15 @@ bool form_factor_visible_quad(const float p[3], const float n[3],
copy_v3_v3(q3, q2);
}
}
- else if (sd[1] < 0) {
- if (sd[2] > 0) {
+ else if (sd[1] < 0.0f) {
+ if (sd[2] > 0.0f) {
/* +-+ */
copy_v3_v3(q0, v0);
vec_add_dir(q1, v0, v1, (sd[0] / (sd[0] - sd[1])));
vec_add_dir(q2, v1, v2, (sd[1] / (sd[1] - sd[2])));
copy_v3_v3(q3, v2);
}
- else if (sd[2] < 0) {
+ else if (sd[2] < 0.0f) {
/* +-- */
copy_v3_v3(q0, v0);
vec_add_dir(q1, v0, v1, (sd[0] / (sd[0] - sd[1])));
@@ -3483,14 +3514,14 @@ bool form_factor_visible_quad(const float p[3], const float n[3],
}
}
else {
- if (sd[2] > 0) {
+ if (sd[2] > 0.0f) {
/* +0+ */
copy_v3_v3(q0, v0);
copy_v3_v3(q1, v1);
copy_v3_v3(q2, v2);
copy_v3_v3(q3, q2);
}
- else if (sd[2] < 0) {
+ else if (sd[2] < 0.0f) {
/* +0- */
copy_v3_v3(q0, v0);
copy_v3_v3(q1, v1);
@@ -3506,16 +3537,16 @@ bool form_factor_visible_quad(const float p[3], const float n[3],
}
}
}
- else if (sd[0] < 0) {
- if (sd[1] > 0) {
- if (sd[2] > 0) {
+ else if (sd[0] < 0.0f) {
+ if (sd[1] > 0.0f) {
+ if (sd[2] > 0.0f) {
/* -++ */
vec_add_dir(q0, v0, v1, (sd[0] / (sd[0] - sd[1])));
copy_v3_v3(q1, v1);
copy_v3_v3(q2, v2);
vec_add_dir(q3, v0, v2, (sd[0] / (sd[0] - sd[2])));
}
- else if (sd[2] < 0) {
+ else if (sd[2] < 0.0f) {
/* -+- */
vec_add_dir(q0, v0, v1, (sd[0] / (sd[0] - sd[1])));
copy_v3_v3(q1, v1);
@@ -3530,15 +3561,15 @@ bool form_factor_visible_quad(const float p[3], const float n[3],
copy_v3_v3(q3, q2);
}
}
- else if (sd[1] < 0) {
- if (sd[2] > 0) {
+ else if (sd[1] < 0.0f) {
+ if (sd[2] > 0.0f) {
/* --+ */
vec_add_dir(q0, v0, v2, (sd[0] / (sd[0] - sd[2])));
vec_add_dir(q1, v1, v2, (sd[1] / (sd[1] - sd[2])));
copy_v3_v3(q2, v2);
copy_v3_v3(q3, q2);
}
- else if (sd[2] < 0) {
+ else if (sd[2] < 0.0f) {
/* --- */
return false;
}
@@ -3548,14 +3579,14 @@ bool form_factor_visible_quad(const float p[3], const float n[3],
}
}
else {
- if (sd[2] > 0) {
+ if (sd[2] > 0.0f) {
/* -0+ */
vec_add_dir(q0, v0, v2, (sd[0] / (sd[0] - sd[2])));
copy_v3_v3(q1, v1);
copy_v3_v3(q2, v2);
copy_v3_v3(q3, q2);
}
- else if (sd[2] < 0) {
+ else if (sd[2] < 0.0f) {
/* -0- */
return false;
}
@@ -3566,15 +3597,15 @@ bool form_factor_visible_quad(const float p[3], const float n[3],
}
}
else {
- if (sd[1] > 0) {
- if (sd[2] > 0) {
+ if (sd[1] > 0.0f) {
+ if (sd[2] > 0.0f) {
/* 0++ */
copy_v3_v3(q0, v0);
copy_v3_v3(q1, v1);
copy_v3_v3(q2, v2);
copy_v3_v3(q3, q2);
}
- else if (sd[2] < 0) {
+ else if (sd[2] < 0.0f) {
/* 0+- */
copy_v3_v3(q0, v0);
copy_v3_v3(q1, v1);
@@ -3589,15 +3620,15 @@ bool form_factor_visible_quad(const float p[3], const float n[3],
copy_v3_v3(q3, q2);
}
}
- else if (sd[1] < 0) {
- if (sd[2] > 0) {
+ else if (sd[1] < 0.0f) {
+ if (sd[2] > 0.0f) {
/* 0-+ */
copy_v3_v3(q0, v0);
vec_add_dir(q1, v1, v2, (sd[1] / (sd[1] - sd[2])));
copy_v3_v3(q2, v2);
copy_v3_v3(q3, q2);
}
- else if (sd[2] < 0) {
+ else if (sd[2] < 0.0f) {
/* 0-- */
return false;
}
@@ -3607,14 +3638,14 @@ bool form_factor_visible_quad(const float p[3], const float n[3],
}
}
else {
- if (sd[2] > 0) {
+ if (sd[2] > 0.0f) {
/* 00+ */
copy_v3_v3(q0, v0);
copy_v3_v3(q1, v1);
copy_v3_v3(q2, v2);
copy_v3_v3(q3, q2);
}
- else if (sd[2] < 0) {
+ else if (sd[2] < 0.0f) {
/* 00- */
return false;
}
@@ -3769,7 +3800,7 @@ static void ff_normalize(float n[3])
d = dot_v3v3(n, n);
- if (d > 1.0e-35F) {
+ if (d > 1.0e-35f) {
d = 1.0f / sqrtf(d);
n[0] *= d;
diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c
index 7fc30e3112b..152b31754bb 100644
--- a/source/blender/blenlib/intern/math_matrix.c
+++ b/source/blender/blenlib/intern/math_matrix.c
@@ -47,19 +47,19 @@ void zero_m4(float m[4][4])
void unit_m3(float m[3][3])
{
- m[0][0] = m[1][1] = m[2][2] = 1.0;
- m[0][1] = m[0][2] = 0.0;
- m[1][0] = m[1][2] = 0.0;
- m[2][0] = m[2][1] = 0.0;
+ m[0][0] = m[1][1] = m[2][2] = 1.0f;
+ m[0][1] = m[0][2] = 0.0f;
+ m[1][0] = m[1][2] = 0.0f;
+ m[2][0] = m[2][1] = 0.0f;
}
void unit_m4(float m[4][4])
{
- m[0][0] = m[1][1] = m[2][2] = m[3][3] = 1.0;
- m[0][1] = m[0][2] = m[0][3] = 0.0;
- m[1][0] = m[1][2] = m[1][3] = 0.0;
- m[2][0] = m[2][1] = m[2][3] = 0.0;
- m[3][0] = m[3][1] = m[3][2] = 0.0;
+ m[0][0] = m[1][1] = m[2][2] = m[3][3] = 1.0f;
+ m[0][1] = m[0][2] = m[0][3] = 0.0f;
+ m[1][0] = m[1][2] = m[1][3] = 0.0f;
+ m[2][0] = m[2][1] = m[2][3] = 0.0f;
+ m[3][0] = m[3][1] = m[3][2] = 0.0f;
}
void copy_m3_m3(float m1[3][3], float m2[3][3])
@@ -103,14 +103,14 @@ void copy_m4_m3(float m1[4][4], float m2[3][3]) /* no clear */
m1[2][2] = m2[2][2];
/* Reevan's Bugfix */
- m1[0][3] = 0.0F;
- m1[1][3] = 0.0F;
- m1[2][3] = 0.0F;
+ m1[0][3] = 0.0f;
+ m1[1][3] = 0.0f;
+ m1[2][3] = 0.0f;
- m1[3][0] = 0.0F;
- m1[3][1] = 0.0F;
- m1[3][2] = 0.0F;
- m1[3][3] = 1.0F;
+ m1[3][0] = 0.0f;
+ m1[3][1] = 0.0f;
+ m1[3][2] = 0.0f;
+ m1[3][3] = 1.0f;
}
@@ -274,71 +274,148 @@ void mul_m4_m3m4(float m1[4][4], float m3_[3][3], float m2_[4][4])
m1[2][2] = m2[2][0] * m3[0][2] + m2[2][1] * m3[1][2] + m2[2][2] * m3[2][2];
}
-void mul_serie_m3(float answ[3][3],
- float m1[3][3], float m2[3][3], float m3[3][3],
- float m4[3][3], float m5[3][3], float m6[3][3],
- float m7[3][3], float m8[3][3])
-{
- float temp[3][3];
-
- if (m1 == NULL || m2 == NULL) return;
-
- mul_m3_m3m3(answ, m2, m1);
- if (m3) {
- mul_m3_m3m3(temp, m3, answ);
- if (m4) {
- mul_m3_m3m3(answ, m4, temp);
- if (m5) {
- mul_m3_m3m3(temp, m5, answ);
- if (m6) {
- mul_m3_m3m3(answ, m6, temp);
- if (m7) {
- mul_m3_m3m3(temp, m7, answ);
- if (m8) {
- mul_m3_m3m3(answ, m8, temp);
- }
- else copy_m3_m3(answ, temp);
- }
- }
- else copy_m3_m3(answ, temp);
- }
- }
- else copy_m3_m3(answ, temp);
- }
-}
-void mul_serie_m4(float answ[4][4], float m1[4][4],
- float m2[4][4], float m3[4][4], float m4[4][4],
- float m5[4][4], float m6[4][4], float m7[4][4],
- float m8[4][4])
-{
- float temp[4][4];
-
- if (m1 == NULL || m2 == NULL) return;
-
- mul_m4_m4m4(answ, m1, m2);
- if (m3) {
- mul_m4_m4m4(temp, answ, m3);
- if (m4) {
- mul_m4_m4m4(answ, temp, m4);
- if (m5) {
- mul_m4_m4m4(temp, answ, m5);
- if (m6) {
- mul_m4_m4m4(answ, temp, m6);
- if (m7) {
- mul_m4_m4m4(temp, answ, m7);
- if (m8) {
- mul_m4_m4m4(answ, temp, m8);
- }
- else copy_m4_m4(answ, temp);
- }
- }
- else copy_m4_m4(answ, temp);
- }
- }
- else copy_m4_m4(answ, temp);
- }
-}
+/** \name Macro helpers for: mul_m3_series
+ * \{ */
+void _va_mul_m3_series_3(
+ float r[3][3],
+ float m1[3][3], float m2[3][3])
+{
+ mul_m3_m3m3(r, m1, m2);
+}
+void _va_mul_m3_series_4(
+ float r[3][3],
+ float m1[3][3], float m2[3][3], float m3[3][3])
+{
+ mul_m3_m3m3(r, m1, m2);
+ mul_m3_m3m3(r, r, m3);
+}
+void _va_mul_m3_series_5(
+ float r[3][3],
+ float m1[3][3], float m2[3][3], float m3[3][3], float m4[3][3])
+{
+ mul_m3_m3m3(r, m1, m2);
+ mul_m3_m3m3(r, r, m3);
+ mul_m3_m3m3(r, r, m4);
+}
+void _va_mul_m3_series_6(
+ float r[3][3],
+ float m1[3][3], float m2[3][3], float m3[3][3], float m4[3][3],
+ float m5[3][3])
+{
+ mul_m3_m3m3(r, m1, m2);
+ mul_m3_m3m3(r, r, m3);
+ mul_m3_m3m3(r, r, m4);
+ mul_m3_m3m3(r, r, m5);
+}
+void _va_mul_m3_series_7(
+ float r[3][3],
+ float m1[3][3], float m2[3][3], float m3[3][3], float m4[3][3],
+ float m5[3][3], float m6[3][3])
+{
+ mul_m3_m3m3(r, m1, m2);
+ mul_m3_m3m3(r, r, m3);
+ mul_m3_m3m3(r, r, m4);
+ mul_m3_m3m3(r, r, m5);
+ mul_m3_m3m3(r, r, m6);
+}
+void _va_mul_m3_series_8(
+ float r[3][3],
+ float m1[3][3], float m2[3][3], float m3[3][3], float m4[3][3],
+ float m5[3][3], float m6[3][3], float m7[3][3])
+{
+ mul_m3_m3m3(r, m1, m2);
+ mul_m3_m3m3(r, r, m3);
+ mul_m3_m3m3(r, r, m4);
+ mul_m3_m3m3(r, r, m5);
+ mul_m3_m3m3(r, r, m6);
+ mul_m3_m3m3(r, r, m7);
+}
+void _va_mul_m3_series_9(
+ float r[3][3],
+ float m1[3][3], float m2[3][3], float m3[3][3], float m4[3][3],
+ float m5[3][3], float m6[3][3], float m7[3][3], float m8[3][3])
+{
+ mul_m3_m3m3(r, m1, m2);
+ mul_m3_m3m3(r, r, m3);
+ mul_m3_m3m3(r, r, m4);
+ mul_m3_m3m3(r, r, m5);
+ mul_m3_m3m3(r, r, m6);
+ mul_m3_m3m3(r, r, m7);
+ mul_m3_m3m3(r, r, m8);
+}
+/** \} */
+
+/** \name Macro helpers for: mul_m4_series
+ * \{ */
+void _va_mul_m4_series_3(
+ float r[4][4],
+ float m1[4][4], float m2[4][4])
+{
+ mul_m4_m4m4(r, m1, m2);
+}
+void _va_mul_m4_series_4(
+ float r[4][4],
+ float m1[4][4], float m2[4][4], float m3[4][4])
+{
+ mul_m4_m4m4(r, m1, m2);
+ mul_m4_m4m4(r, r, m3);
+}
+void _va_mul_m4_series_5(
+ float r[4][4],
+ float m1[4][4], float m2[4][4], float m3[4][4], float m4[4][4])
+{
+ mul_m4_m4m4(r, m1, m2);
+ mul_m4_m4m4(r, r, m3);
+ mul_m4_m4m4(r, r, m4);
+}
+void _va_mul_m4_series_6(
+ float r[4][4],
+ float m1[4][4], float m2[4][4], float m3[4][4], float m4[4][4],
+ float m5[4][4])
+{
+ mul_m4_m4m4(r, m1, m2);
+ mul_m4_m4m4(r, r, m3);
+ mul_m4_m4m4(r, r, m4);
+ mul_m4_m4m4(r, r, m5);
+}
+void _va_mul_m4_series_7(
+ float r[4][4],
+ float m1[4][4], float m2[4][4], float m3[4][4], float m4[4][4],
+ float m5[4][4], float m6[4][4])
+{
+ mul_m4_m4m4(r, m1, m2);
+ mul_m4_m4m4(r, r, m3);
+ mul_m4_m4m4(r, r, m4);
+ mul_m4_m4m4(r, r, m5);
+ mul_m4_m4m4(r, r, m6);
+}
+void _va_mul_m4_series_8(
+ float r[4][4],
+ float m1[4][4], float m2[4][4], float m3[4][4], float m4[4][4],
+ float m5[4][4], float m6[4][4], float m7[4][4])
+{
+ mul_m4_m4m4(r, m1, m2);
+ mul_m4_m4m4(r, r, m3);
+ mul_m4_m4m4(r, r, m4);
+ mul_m4_m4m4(r, r, m5);
+ mul_m4_m4m4(r, r, m6);
+ mul_m4_m4m4(r, r, m7);
+}
+void _va_mul_m4_series_9(
+ float r[4][4],
+ float m1[4][4], float m2[4][4], float m3[4][4], float m4[4][4],
+ float m5[4][4], float m6[4][4], float m7[4][4], float m8[4][4])
+{
+ mul_m4_m4m4(r, m1, m2);
+ mul_m4_m4m4(r, r, m3);
+ mul_m4_m4m4(r, r, m4);
+ mul_m4_m4m4(r, r, m5);
+ mul_m4_m4m4(r, r, m6);
+ mul_m4_m4m4(r, r, m7);
+ mul_m4_m4m4(r, r, m8);
+}
+/** \} */
void mul_v2_m3v2(float r[2], float m[3][3], float v[2])
{
@@ -360,10 +437,9 @@ void mul_m3_v2(float m[3][3], float r[2])
void mul_m4_v3(float mat[4][4], float vec[3])
{
- float x, y;
+ const float x = vec[0];
+ const float y = vec[1];
- x = vec[0];
- y = vec[1];
vec[0] = x * mat[0][0] + y * mat[1][0] + mat[2][0] * vec[2] + mat[3][0];
vec[1] = x * mat[0][1] + y * mat[1][1] + mat[2][1] * vec[2] + mat[3][1];
vec[2] = x * mat[0][2] + y * mat[1][2] + mat[2][2] * vec[2] + mat[3][2];
@@ -371,10 +447,9 @@ void mul_m4_v3(float mat[4][4], float vec[3])
void mul_v3_m4v3(float r[3], float mat[4][4], const float vec[3])
{
- float x, y;
+ const float x = vec[0];
+ const float y = vec[1];
- x = vec[0];
- y = vec[1];
r[0] = x * mat[0][0] + y * mat[1][0] + mat[2][0] * vec[2] + mat[3][0];
r[1] = x * mat[0][1] + y * mat[1][1] + mat[2][1] * vec[2] + mat[3][1];
r[2] = x * mat[0][2] + y * mat[1][2] + mat[2][2] * vec[2] + mat[3][2];
@@ -382,18 +457,16 @@ void mul_v3_m4v3(float r[3], float mat[4][4], const float vec[3])
void mul_v2_m4v3(float r[2], float mat[4][4], const float vec[3])
{
- float x;
+ const float x = vec[0];
- x = vec[0];
r[0] = x * mat[0][0] + vec[1] * mat[1][0] + mat[2][0] * vec[2] + mat[3][0];
r[1] = x * mat[0][1] + vec[1] * mat[1][1] + mat[2][1] * vec[2] + mat[3][1];
}
void mul_v2_m2v2(float r[2], float mat[2][2], const float vec[2])
{
- float x;
+ const float x = vec[0];
- x = vec[0];
r[0] = mat[0][0] * x + mat[1][0] * vec[1];
r[1] = mat[0][1] * x + mat[1][1] * vec[1];
}
@@ -406,10 +479,9 @@ void mul_m2v2(float mat[2][2], float vec[2])
/* same as mul_m4_v3() but doesnt apply translation component */
void mul_mat3_m4_v3(float mat[4][4], float vec[3])
{
- float x, y;
+ const float x = vec[0];
+ const float y = vec[1];
- x = vec[0];
- y = vec[1];
vec[0] = x * mat[0][0] + y * mat[1][0] + mat[2][0] * vec[2];
vec[1] = x * mat[0][1] + y * mat[1][1] + mat[2][1] * vec[2];
vec[2] = x * mat[0][2] + y * mat[1][2] + mat[2][2] * vec[2];
@@ -436,11 +508,9 @@ void mul_v2_project_m4_v3(float r[2], float mat[4][4], const float vec[3])
void mul_v4_m4v4(float r[4], float mat[4][4], const float v[4])
{
- float x, y, z;
-
- x = v[0];
- y = v[1];
- z = v[2];
+ const float x = v[0];
+ const float y = v[1];
+ const float z = v[2];
r[0] = x * mat[0][0] + y * mat[1][0] + z * mat[2][0] + mat[3][0] * v[3];
r[1] = x * mat[0][1] + y * mat[1][1] + z * mat[2][1] + mat[3][1] * v[3];
@@ -455,11 +525,9 @@ void mul_m4_v4(float mat[4][4], float r[4])
void mul_v4d_m4v4d(double r[4], float mat[4][4], double v[4])
{
- double x, y, z;
-
- x = v[0];
- y = v[1];
- z = v[2];
+ const double x = v[0];
+ const double y = v[1];
+ const double z = v[2];
r[0] = x * (double)mat[0][0] + y * (double)mat[1][0] + z * (double)mat[2][0] + (double)mat[3][0] * v[3];
r[1] = x * (double)mat[0][1] + y * (double)mat[1][1] + z * (double)mat[2][1] + (double)mat[3][1] * v[3];
@@ -499,10 +567,9 @@ void mul_m3_v3(float M[3][3], float r[3])
void mul_transposed_m3_v3(float mat[3][3], float vec[3])
{
- float x, y;
+ const float x = vec[0];
+ const float y = vec[1];
- x = vec[0];
- y = vec[1];
vec[0] = x * mat[0][0] + y * mat[0][1] + mat[0][2] * vec[2];
vec[1] = x * mat[1][0] + y * mat[1][1] + mat[1][2] * vec[2];
vec[2] = x * mat[2][0] + y * mat[2][1] + mat[2][2] * vec[2];
@@ -510,10 +577,9 @@ void mul_transposed_m3_v3(float mat[3][3], float vec[3])
void mul_transposed_mat3_m4_v3(float mat[4][4], float vec[3])
{
- float x, y;
+ const float x = vec[0];
+ const float y = vec[1];
- x = vec[0];
- y = vec[1];
vec[0] = x * mat[0][0] + y * mat[0][1] + mat[0][2] * vec[2];
vec[1] = x * mat[1][0] + y * mat[1][1] + mat[1][2] * vec[2];
vec[2] = x * mat[2][0] + y * mat[2][1] + mat[2][2] * vec[2];
@@ -566,10 +632,9 @@ void negate_m4(float m[4][4])
void mul_m3_v3_double(float mat[3][3], double vec[3])
{
- double x, y;
+ const double x = vec[0];
+ const double y = vec[1];
- x = vec[0];
- y = vec[1];
vec[0] = x * (double)mat[0][0] + y * (double)mat[1][0] + (double)mat[2][0] * vec[2];
vec[1] = x * (double)mat[0][1] + y * (double)mat[1][1] + (double)mat[2][1] * vec[2];
vec[2] = x * (double)mat[0][2] + y * (double)mat[1][2] + (double)mat[2][2] * vec[2];
@@ -621,11 +686,9 @@ float determinant_m3_array(float m[3][3])
bool invert_m3_ex(float m[3][3], const float epsilon)
{
float tmp[3][3];
- bool success;
+ const bool success = invert_m3_m3_ex(tmp, m, epsilon);
- success = invert_m3_m3_ex(tmp, m, epsilon);
copy_m3_m3(m, tmp);
-
return success;
}
@@ -659,11 +722,9 @@ bool invert_m3_m3_ex(float m1[3][3], float m2[3][3], const float epsilon)
bool invert_m3(float m[3][3])
{
float tmp[3][3];
- bool success;
+ const bool success = invert_m3_m3(tmp, m);
- success = invert_m3_m3(tmp, m);
copy_m3_m3(m, tmp);
-
return success;
}
@@ -696,11 +757,9 @@ bool invert_m3_m3(float m1[3][3], float m2[3][3])
bool invert_m4(float m[4][4])
{
float tmp[4][4];
- bool success;
+ const bool success = invert_m4_m4(tmp, m);
- success = invert_m4_m4(tmp, m);
copy_m4_m4(m, tmp);
-
return success;
}
@@ -2115,7 +2174,7 @@ void pseudoinverse_m4_m4(float Ainv[4][4], float A[4][4], float epsilon)
transpose_m4(V);
- mul_serie_m4(Ainv, U, Wm, V, NULL, NULL, NULL, NULL, NULL);
+ mul_m4_series(Ainv, U, Wm, V);
}
void pseudoinverse_m3_m3(float Ainv[3][3], float A[3][3], float epsilon)
@@ -2156,3 +2215,51 @@ void invert_m4_m4_safe(float Ainv[4][4], float A[4][4])
}
}
}
+
+/**
+ * SpaceTransform struct encapsulates all needed data to convert between two coordinate spaces
+ * (where conversion can be represented by a matrix multiplication).
+ *
+ * A SpaceTransform is initialized using:
+ * BLI_SPACE_TRANSFORM_SETUP(&data, ob1, ob2)
+ *
+ * After that the following calls can be used:
+ * BLI_space_transform_apply(&data, co); // converts a coordinate in ob1 space to the corresponding ob2 space
+ * BLI_space_transform_invert(&data, co); // converts a coordinate in ob2 space to the corresponding ob1 space
+ *
+ * Same concept as BLI_space_transform_apply and BLI_space_transform_invert, but no is normalized after conversion
+ * (and not translated at all!):
+ * BLI_space_transform_apply_normal(&data, no);
+ * BLI_space_transform_invert_normal(&data, no);
+ *
+ */
+
+void BLI_space_transform_from_matrices(SpaceTransform *data, float local[4][4], float target[4][4])
+{
+ float itarget[4][4];
+ invert_m4_m4(itarget, target);
+ mul_m4_m4m4(data->local2target, itarget, local);
+ invert_m4_m4(data->target2local, data->local2target);
+}
+
+void BLI_space_transform_apply(const SpaceTransform *data, float co[3])
+{
+ mul_v3_m4v3(co, ((SpaceTransform *)data)->local2target, co);
+}
+
+void BLI_space_transform_invert(const SpaceTransform *data, float co[3])
+{
+ mul_v3_m4v3(co, ((SpaceTransform *)data)->target2local, co);
+}
+
+void BLI_space_transform_apply_normal(const SpaceTransform *data, float no[3])
+{
+ mul_mat3_m4_v3(((SpaceTransform *)data)->local2target, no);
+ normalize_v3(no);
+}
+
+void BLI_space_transform_invert_normal(const SpaceTransform *data, float no[3])
+{
+ mul_mat3_m4_v3(((SpaceTransform *)data)->target2local, no);
+ normalize_v3(no);
+}
diff --git a/source/blender/blenlib/intern/math_rotation.c b/source/blender/blenlib/intern/math_rotation.c
index dce2e9d54e3..141f9201689 100644
--- a/source/blender/blenlib/intern/math_rotation.c
+++ b/source/blender/blenlib/intern/math_rotation.c
@@ -139,7 +139,7 @@ float dot_qtqt(const float q1[4], const float q2[4])
void invert_qt(float q[4])
{
- float f = dot_qtqt(q, q);
+ const float f = dot_qtqt(q, q);
if (f == 0.0f)
return;
@@ -380,9 +380,8 @@ void mat3_to_quat_is_ok(float q[4], float wmat[3][3])
float normalize_qt(float q[4])
{
- float len;
+ const float len = sqrtf(dot_qtqt(q, q));
- len = sqrtf(dot_qtqt(q, q));
if (len != 0.0f) {
mul_qt_fl(q, 1.0f / len);
}
@@ -520,7 +519,7 @@ float angle_qtqt(const float q1[4], const float q2[4])
void vec_to_quat(float q[4], const float vec[3], short axis, const short upflag)
{
- const float eps = 0.0001f;
+ const float eps = 1e-4f;
float nor[3], tvec[3];
float angle, si, co, len;
@@ -669,7 +668,7 @@ void QuatInterpolW(float *result, float quat1[4], float quat2[4], float t)
*/
void interp_dot_slerp(const float t, const float cosom, float r_w[2])
{
- const float eps = 0.0001f;
+ const float eps = 1e-4f;
BLI_assert(IN_RANGE_INCL(cosom, -1.0001f, 1.0001f));
@@ -783,9 +782,8 @@ void tri_to_quat_ex(float quat[4], const float v1[3], const float v2[3], const f
float tri_to_quat(float quat[4], const float v1[3], const float v2[3], const float v3[3])
{
float vec[3];
- float len;
+ const float len = normal_tri_v3(vec, v1, v2, v3);
- len = normal_tri_v3(vec, v1, v2, v3);
tri_to_quat_ex(quat, v1, v2, v3, vec);
return len;
}
@@ -1606,7 +1604,7 @@ void mat4_to_dquat(DualQuat *dq, float basemat[4][4], float mat[4][4])
mul_m4_m4m4(S, baseRinv, baseRS);
/* set scaling part */
- mul_serie_m4(dq->scale, basemat, S, baseinv, NULL, NULL, NULL, NULL, NULL);
+ mul_m4_series(dq->scale, basemat, S, baseinv);
dq->scale_weight = 1.0f;
}
else {
@@ -1658,7 +1656,7 @@ void add_weighted_dq_dq(DualQuat *dqsum, const DualQuat *dq, float weight)
/* make sure we interpolate quats in the right direction */
if (dot_qtqt(dq->quat, dqsum->quat) < 0) {
- flipped = 1;
+ flipped = true;
weight = -weight;
}
@@ -1689,7 +1687,7 @@ void add_weighted_dq_dq(DualQuat *dqsum, const DualQuat *dq, float weight)
void normalize_dq(DualQuat *dq, float totweight)
{
- float scale = 1.0f / totweight;
+ const float scale = 1.0f / totweight;
mul_qt_fl(dq->quat, scale);
mul_qt_fl(dq->trans, scale);
diff --git a/source/blender/blenlib/intern/math_vector.c b/source/blender/blenlib/intern/math_vector.c
index 15b88fe0c7f..6b37b0d5d32 100644
--- a/source/blender/blenlib/intern/math_vector.c
+++ b/source/blender/blenlib/intern/math_vector.c
@@ -35,7 +35,7 @@
void interp_v2_v2v2(float target[2], const float a[2], const float b[2], const float t)
{
- float s = 1.0f - t;
+ const float s = 1.0f - t;
target[0] = s * a[0] + t * b[0];
target[1] = s * a[1] + t * b[1];
@@ -51,7 +51,7 @@ void interp_v2_v2v2v2(float p[2], const float v1[2], const float v2[2], const fl
void interp_v3_v3v3(float target[3], const float a[3], const float b[3], const float t)
{
- float s = 1.0f - t;
+ const float s = 1.0f - t;
target[0] = s * a[0] + t * b[0];
target[1] = s * a[1] + t * b[1];
@@ -60,7 +60,7 @@ void interp_v3_v3v3(float target[3], const float a[3], const float b[3], const f
void interp_v4_v4v4(float target[4], const float a[4], const float b[4], const float t)
{
- float s = 1.0f - t;
+ const float s = 1.0f - t;
target[0] = s * a[0] + t * b[0];
target[1] = s * a[1] + t * b[1];
@@ -119,8 +119,7 @@ bool interp_v2_v2v2_slerp(float target[2], const float a[2], const float b[2], c
}
/**
- * Same as #interp_v3_v3v3_slerp buy uses fallback values
- * for opposite vectors.
+ * Same as #interp_v3_v3v3_slerp but uses fallback values for opposite vectors.
*/
void interp_v3_v3v3_slerp_safe(float target[3], const float a[3], const float b[3], const float t)
{
@@ -208,7 +207,7 @@ void interp_v3_v3v3v3_uv(float p[3], const float v1[3], const float v2[3], const
void interp_v3_v3v3_uchar(char unsigned target[3], const unsigned char a[3], const unsigned char b[3], const float t)
{
- float s = 1.0f - t;
+ const float s = 1.0f - t;
target[0] = (char)floorf(s * a[0] + t * b[0]);
target[1] = (char)floorf(s * a[1] + t * b[1]);
@@ -221,7 +220,7 @@ void interp_v3_v3v3_char(char target[3], const char a[3], const char b[3], const
void interp_v4_v4v4_uchar(char unsigned target[4], const unsigned char a[4], const unsigned char b[4], const float t)
{
- float s = 1.0f - t;
+ const float s = 1.0f - t;
target[0] = (char)floorf(s * a[0] + t * b[0]);
target[1] = (char)floorf(s * a[1] + t * b[1]);
@@ -550,8 +549,7 @@ void angle_poly_v3(float *angles, const float *verts[3], int len)
/* Project v1 on v2 */
void project_v2_v2v2(float c[2], const float v1[2], const float v2[2])
{
- float mul;
- mul = dot_v2v2(v1, v2) / dot_v2v2(v2, v2);
+ const float mul = dot_v2v2(v1, v2) / dot_v2v2(v2, v2);
c[0] = mul * v2[0];
c[1] = mul * v2[1];
@@ -560,8 +558,7 @@ void project_v2_v2v2(float c[2], const float v1[2], const float v2[2])
/* Project v1 on v2 */
void project_v3_v3v3(float c[3], const float v1[3], const float v2[3])
{
- float mul;
- mul = dot_v3v3(v1, v2) / dot_v3v3(v2, v2);
+ const float mul = dot_v3v3(v1, v2) / dot_v3v3(v2, v2);
c[0] = mul * v2[0];
c[1] = mul * v2[1];
@@ -837,7 +834,7 @@ double len_squared_vn(const float *array, const int size)
float normalize_vn_vn(float *array_tar, const float *array_src, const int size)
{
- double d = len_squared_vn(array_src, size);
+ const double d = len_squared_vn(array_src, size);
float d_sqrt;
if (d > 1.0e-35) {
d_sqrt = (float)sqrt(d);
diff --git a/source/blender/blenlib/intern/math_vector_inline.c b/source/blender/blenlib/intern/math_vector_inline.c
index 135050f4a3f..0a990e0d63d 100644
--- a/source/blender/blenlib/intern/math_vector_inline.c
+++ b/source/blender/blenlib/intern/math_vector_inline.c
@@ -850,17 +850,17 @@ MINLINE void normal_float_to_short_v3(short out[3], const float in[3])
MINLINE bool is_zero_v2(const float v[2])
{
- return (v[0] == 0 && v[1] == 0);
+ return (v[0] == 0.0f && v[1] == 0.0f);
}
MINLINE bool is_zero_v3(const float v[3])
{
- return (v[0] == 0 && v[1] == 0 && v[2] == 0);
+ return (v[0] == 0.0f && v[1] == 0.0f && v[2] == 0.0f);
}
MINLINE bool is_zero_v4(const float v[4])
{
- return (v[0] == 0 && v[1] == 0 && v[2] == 0 && v[3] == 0);
+ return (v[0] == 0.0f && v[1] == 0.0f && v[2] == 0.0f && v[3] == 0.0f);
}
MINLINE bool is_finite_v2(const float v[2])
@@ -880,7 +880,7 @@ MINLINE bool is_finite_v4(const float v[4])
MINLINE bool is_one_v3(const float v[3])
{
- return (v[0] == 1 && v[1] == 1 && v[2] == 1);
+ return (v[0] == 1.0f && v[1] == 1.0f && v[2] == 1.0f);
}
diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c
index 0b89ec1f0d0..a7fa443cfc4 100644
--- a/source/blender/blenlib/intern/path_util.c
+++ b/source/blender/blenlib/intern/path_util.c
@@ -1175,7 +1175,13 @@ static bool get_path_local(char *targetpath, const char *folder_name, const char
}
/* try EXECUTABLE_DIR/2.5x/folder_name - new default directory for local blender installed files */
+#ifdef __APPLE__
+ static char osx_resourses[FILE_MAX]; /* due new codesign situation in OSX > 10.9.5 we must move the blender_version dir with contents to Resources */
+ sprintf(osx_resourses, "%s../Resources", bprogdir);
+ return test_path(targetpath, osx_resourses, blender_version_decimal(ver), relfolder);
+#else
return test_path(targetpath, bprogdir, blender_version_decimal(ver), relfolder);
+#endif
}
/**
@@ -1415,7 +1421,7 @@ const char *BLI_get_folder_create(int folder_id, const char *subfolder)
const char *path;
/* only for user folders */
- if (!ELEM4(folder_id, BLENDER_USER_DATAFILES, BLENDER_USER_CONFIG, BLENDER_USER_SCRIPTS, BLENDER_USER_AUTOSAVE))
+ if (!ELEM(folder_id, BLENDER_USER_DATAFILES, BLENDER_USER_CONFIG, BLENDER_USER_SCRIPTS, BLENDER_USER_AUTOSAVE))
return NULL;
path = BLI_get_folder(folder_id, subfolder);
@@ -1515,21 +1521,6 @@ void BLI_setenv_if_new(const char *env, const char *val)
BLI_setenv(env, val);
}
-
-/**
- * Changes to the path separators to the native ones for this OS.
- */
-void BLI_clean(char *path)
-{
-#ifdef WIN32
- if (path && BLI_strnlen(path, 3) > 2) {
- BLI_char_switch(path + 2, '/', '\\');
- }
-#else
- BLI_char_switch(path + BLI_path_unc_prefix_len(path), '\\', '/');
-#endif
-}
-
/**
* Change every \a from in \a string into \a to. The
* result will be in \a string
@@ -1681,7 +1672,7 @@ void BLI_make_file_string(const char *relabase, char *string, const char *dir, c
strcat(string, file);
/* Push all slashes to the system preferred direction */
- BLI_clean(string);
+ BLI_path_native_slash(string);
}
static bool testextensie_ex(const char *str, const size_t str_len,
@@ -1783,7 +1774,7 @@ bool BLI_replace_extension(char *path, size_t maxlen, const char *ext)
ssize_t a;
for (a = path_len - 1; a >= 0; a--) {
- if (ELEM3(path[a], '.', '/', '\\')) {
+ if (ELEM(path[a], '.', '/', '\\')) {
break;
}
}
@@ -2146,6 +2137,20 @@ void BLI_del_slash(char *string)
}
/**
+ * Changes to the path separators to the native ones for this OS.
+ */
+void BLI_path_native_slash(char *path)
+{
+#ifdef WIN32
+ if (path && BLI_strnlen(path, 3) > 2) {
+ BLI_char_switch(path + 2, '/', '\\');
+ }
+#else
+ BLI_char_switch(path + BLI_path_unc_prefix_len(path), '\\', '/');
+#endif
+}
+
+/**
* Tries appending each of the semicolon-separated extensions in the PATHEXT
* environment variable (Windows-only) onto *name in turn until such a file is found.
* Returns success/failure.
diff --git a/source/blender/blenlib/intern/polyfill2d.c b/source/blender/blenlib/intern/polyfill2d.c
index 71cda92842a..dd829e5d80a 100644
--- a/source/blender/blenlib/intern/polyfill2d.c
+++ b/source/blender/blenlib/intern/polyfill2d.c
@@ -387,7 +387,7 @@ static bool kdtree2d_isect_tri_recursive(
(span_tri_v2_sign(tri_coords[1], tri_coords[2], co) != CONCAVE) &&
(span_tri_v2_sign(tri_coords[2], tri_coords[0], co) != CONCAVE))
{
- if (!ELEM3(node->index, tri_index[0], tri_index[1], tri_index[2])) {
+ if (!ELEM(node->index, tri_index[0], tri_index[1], tri_index[2])) {
return true;
}
}
diff --git a/source/blender/blenlib/intern/rand.c b/source/blender/blenlib/intern/rand.c
index 410f98897ce..3dff0b31091 100644
--- a/source/blender/blenlib/intern/rand.c
+++ b/source/blender/blenlib/intern/rand.c
@@ -95,15 +95,20 @@ void BLI_rng_srandom(RNG *rng, unsigned int seed)
BLI_rng_seed(rng, seed + hash[seed & 255]);
}
-int BLI_rng_get_int(RNG *rng)
+BLI_INLINE void rng_step(RNG *rng)
{
rng->X = (MULTIPLIER * rng->X + ADDEND) & MASK;
+}
+
+int BLI_rng_get_int(RNG *rng)
+{
+ rng_step(rng);
return (int) (rng->X >> 17);
}
unsigned int BLI_rng_get_uint(RNG *rng)
{
- rng->X = (MULTIPLIER * rng->X + ADDEND) & MASK;
+ rng_step(rng);
return (unsigned int) (rng->X >> 17);
}
@@ -167,10 +172,9 @@ void BLI_rng_shuffle_array(RNG *rng, void *data, unsigned int elem_size_i, unsig
void BLI_rng_skip(RNG *rng, int n)
{
- int i;
-
- for (i = 0; i < n; i++)
- BLI_rng_get_int(rng);
+ while (n--) {
+ rng_step(rng);
+ }
}
/***/
diff --git a/source/blender/blenlib/intern/scanfill.c b/source/blender/blenlib/intern/scanfill.c
index 05e4984d9a3..3d3dfeef302 100644
--- a/source/blender/blenlib/intern/scanfill.c
+++ b/source/blender/blenlib/intern/scanfill.c
@@ -865,6 +865,9 @@ unsigned int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const
/* Newell's Method */
/* Similar code used elsewhere, but this checks for double ups
* which historically this function supports so better not change */
+
+ /* warning: this only gives stable direction with single polygons,
+ * ideally we'd calcualte connectivity and calculate each polys normal, see T41047 */
const float *v_prev;
zero_v3(n);
diff --git a/source/blender/blenlib/intern/storage.c b/source/blender/blenlib/intern/storage.c
index 453b0cc939f..f3ecc799e1e 100644
--- a/source/blender/blenlib/intern/storage.c
+++ b/source/blender/blenlib/intern/storage.c
@@ -515,7 +515,7 @@ int BLI_stat(const char *path, BLI_stat_t *buffer)
int BLI_wstat(const wchar_t *path, BLI_stat_t *buffer)
{
-#if (defined(_MSC_VER) && (_MSC_VER >= 1500)) || defined(__MINGW64__)
+#if defined(_MSC_VER) || defined(__MINGW64__)
return _wstat64(path, buffer);
#elif defined(__MINGW32__)
return _wstati64(path, buffer);
diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c
index aa705aaf63e..eeafc1a9e8f 100644
--- a/source/blender/blenlib/intern/string.c
+++ b/source/blender/blenlib/intern/string.c
@@ -648,7 +648,7 @@ int BLI_str_rstrip_float_zero(char *str, const char pad)
* \param str_array_len The length of the array, or -1 for a NULL-terminated array.
* \return The index of str in str_array or -1.
*/
-int BLI_str_index_in_array_n(const char *str, const char **str_array, const int str_array_len)
+int BLI_str_index_in_array_n(const char *__restrict str, const char **__restrict str_array, const int str_array_len)
{
int index;
const char **str_iter = str_array;
@@ -668,7 +668,7 @@ int BLI_str_index_in_array_n(const char *str, const char **str_array, const int
* \param str_array Array of strings, (must be NULL-terminated).
* \return The index of str in str_array or -1.
*/
-int BLI_str_index_in_array(const char *str, const char **str_array)
+int BLI_str_index_in_array(const char *__restrict str, const char **__restrict str_array)
{
int index;
const char **str_iter = str_array;
diff --git a/source/blender/blenloader/BLO_readfile.h b/source/blender/blenloader/BLO_readfile.h
index 4fb983c119b..4b7b9cecb17 100644
--- a/source/blender/blenloader/BLO_readfile.h
+++ b/source/blender/blenloader/BLO_readfile.h
@@ -275,7 +275,8 @@ void BLO_main_expander(void (*expand_doit_func)(void *, struct Main *, void *));
*/
void BLO_expand_main(void *fdhandle, struct Main *mainvar);
-/* Update defaults in startup.blend, without having to save and embed it */
+/* Update defaults in startup.blend & userprefs.blend, without having to save and embed it */
+void BLO_update_defaults_userpref_blend(void);
void BLO_update_defaults_startup_blend(struct Main *mainvar);
#ifdef __cplusplus
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index eb10aae8adb..7a21c190966 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -434,8 +434,7 @@ void blo_join_main(ListBase *mainlist)
while ((tojoin = mainl->next)) {
add_main_to_main(mainl, tojoin);
BLI_remlink(mainlist, tojoin);
- MEM_freeN(tojoin->eval_ctx);
- MEM_freeN(tojoin);
+ BKE_main_free(tojoin);
}
}
@@ -1824,6 +1823,7 @@ static void lib_link_brush(FileData *fd, Main *main)
brush->mtex.tex = newlibadr_us(fd, brush->id.lib, brush->mtex.tex);
brush->mask_mtex.tex = newlibadr_us(fd, brush->id.lib, brush->mask_mtex.tex);
brush->clone.image = newlibadr_us(fd, brush->id.lib, brush->clone.image);
+ brush->paint_curve = newlibadr_us(fd, brush->id.lib, brush->paint_curve);
}
}
}
@@ -1834,6 +1834,8 @@ static void direct_link_brush(FileData *fd, Brush *brush)
/* fallof curve */
brush->curve = newdataadr(fd, brush->curve);
+ brush->gradient = newdataadr(fd, brush->gradient);
+
if (brush->curve)
direct_link_curvemapping(fd, brush->curve);
else
@@ -1843,6 +1845,43 @@ static void direct_link_brush(FileData *fd, Brush *brush)
brush->icon_imbuf = NULL;
}
+/* ************ READ Palette *************** */
+static void lib_link_palette(FileData *UNUSED(fd), Main *main)
+{
+ Palette *palette;
+
+ /* only link ID pointers */
+ for (palette = main->palettes.first; palette; palette = palette->id.next) {
+ if (palette->id.flag & LIB_NEED_LINK) {
+ palette->id.flag -= LIB_NEED_LINK;
+ }
+ }
+}
+
+static void direct_link_palette(FileData *fd, Palette *palette)
+{
+ /* palette itself has been read */
+ link_list(fd, &palette->colors);
+}
+
+static void lib_link_paint_curve(FileData *UNUSED(fd), Main *main)
+{
+ PaintCurve *pc;
+
+ /* only link ID pointers */
+ for (pc = main->paintcurves.first; pc; pc = pc->id.next) {
+ if (pc->id.flag & LIB_NEED_LINK) {
+ pc->id.flag -= LIB_NEED_LINK;
+ }
+ }
+}
+
+static void direct_link_paint_curve(FileData *fd, PaintCurve *pc)
+{
+ pc->points = newdataadr(fd, pc->points);
+}
+
+
static void direct_link_script(FileData *UNUSED(fd), Script *script)
{
script->id.us = 1;
@@ -2664,9 +2703,9 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree)
}
}
else if (ntree->type==NTREE_COMPOSIT) {
- if (ELEM4(node->type, CMP_NODE_TIME, CMP_NODE_CURVE_VEC, CMP_NODE_CURVE_RGB, CMP_NODE_HUECORRECT))
+ if (ELEM(node->type, CMP_NODE_TIME, CMP_NODE_CURVE_VEC, CMP_NODE_CURVE_RGB, CMP_NODE_HUECORRECT))
direct_link_curvemapping(fd, node->storage);
- else if (ELEM3(node->type, CMP_NODE_IMAGE, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER))
+ else if (ELEM(node->type, CMP_NODE_IMAGE, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER))
((ImageUser *)node->storage)->ok = 1;
}
else if ( ntree->type==NTREE_TEXTURE) {
@@ -3564,7 +3603,8 @@ static void direct_link_material(FileData *fd, Material *ma)
for (a = 0; a < MAX_MTEX; a++) {
ma->mtex[a] = newdataadr(fd, ma->mtex[a]);
}
-
+ ma->texpaintslot = NULL;
+
ma->ramp_col = newdataadr(fd, ma->ramp_col);
ma->ramp_spec = newdataadr(fd, ma->ramp_spec);
@@ -5107,6 +5147,7 @@ static void link_paint(FileData *fd, Scene *sce, Paint *p)
{
if (p) {
p->brush = newlibadr_us(fd, sce->id.lib, p->brush);
+ p->palette = newlibadr_us(fd, sce->id.lib, p->palette);
p->paint_cursor = NULL;
}
}
@@ -5155,6 +5196,10 @@ static void lib_link_scene(FileData *fd, Main *main)
sce->toolsettings->sculpt->gravity_object =
newlibadr_us(fd, sce->id.lib, sce->toolsettings->sculpt->gravity_object);
+ if (sce->toolsettings->imapaint.stencil)
+ sce->toolsettings->imapaint.stencil =
+ newlibadr_us(fd, sce->id.lib, sce->toolsettings->imapaint.stencil);
+
sce->toolsettings->skgen_template = newlibadr(fd, sce->id.lib, sce->toolsettings->skgen_template);
for (base = sce->base.first; base; base = next) {
@@ -5403,7 +5448,7 @@ static void direct_link_scene(FileData *fd, Scene *sce)
if (seq->strip && seq->strip->done==0) {
seq->strip->done = true;
- if (ELEM4(seq->type, SEQ_TYPE_IMAGE, SEQ_TYPE_MOVIE, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SOUND_HD)) {
+ if (ELEM(seq->type, SEQ_TYPE_IMAGE, SEQ_TYPE_MOVIE, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SOUND_HD)) {
seq->strip->stripdata = newdataadr(fd, seq->strip->stripdata);
}
else {
@@ -7186,6 +7231,8 @@ static const char *dataname(short id_code)
case ID_NT: return "Data from NT";
case ID_BR: return "Data from BR";
case ID_PA: return "Data from PA";
+ case ID_PAL: return "Data from PAL";
+ case ID_PC: return "Data from PCRV";
case ID_GD: return "Data from GD";
case ID_WM: return "Data from WM";
case ID_MC: return "Data from MC";
@@ -7371,6 +7418,12 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, int flag, ID
case ID_LS:
direct_link_linestyle(fd, (FreestyleLineStyle *)id);
break;
+ case ID_PAL:
+ direct_link_palette(fd, (Palette *)id);
+ break;
+ case ID_PC:
+ direct_link_paint_curve(fd, (PaintCurve *)id);
+ break;
}
oldnewmap_free_unused(fd->datamap);
@@ -7559,6 +7612,8 @@ static void lib_link_all(FileData *fd, Main *main)
lib_link_vfont(fd, main);
lib_link_nodetree(fd, main); /* has to be done after scene/materials, this will verify group nodes */
lib_link_brush(fd, main);
+ lib_link_palette(fd, main);
+ lib_link_paint_curve(fd, main);
lib_link_particlesettings(fd, main);
lib_link_movieclip(fd, main);
lib_link_mask(fd, main);
@@ -8098,6 +8153,7 @@ static void expand_brush(FileData *fd, Main *mainvar, Brush *brush)
expand_doit(fd, mainvar, brush->mtex.tex);
expand_doit(fd, mainvar, brush->mask_mtex.tex);
expand_doit(fd, mainvar, brush->clone.image);
+ expand_doit(fd, mainvar, brush->paint_curve);
}
static void expand_material(FileData *fd, Main *mainvar, Material *ma)
diff --git a/source/blender/blenloader/intern/versioning_260.c b/source/blender/blenloader/intern/versioning_260.c
index 3890e07bb65..7c6b6ec7249 100644
--- a/source/blender/blenloader/intern/versioning_260.c
+++ b/source/blender/blenloader/intern/versioning_260.c
@@ -2454,9 +2454,9 @@ void blo_do_versions_260(FileData *fd, Library *UNUSED(lib), Main *main)
if (sl->spacetype == SPACE_OUTLINER) {
SpaceOops *so = (SpaceOops *)sl;
- if (!ELEM11(so->outlinevis, SO_ALL_SCENES, SO_CUR_SCENE, SO_VISIBLE, SO_SELECTED, SO_ACTIVE,
- SO_SAME_TYPE, SO_GROUPS, SO_LIBRARIES, SO_SEQUENCE, SO_DATABLOCKS,
- SO_USERDEF))
+ if (!ELEM(so->outlinevis, SO_ALL_SCENES, SO_CUR_SCENE, SO_VISIBLE, SO_SELECTED, SO_ACTIVE,
+ SO_SAME_TYPE, SO_GROUPS, SO_LIBRARIES, SO_SEQUENCE, SO_DATABLOCKS,
+ SO_USERDEF))
{
so->outlinevis = SO_ALL_SCENES;
}
diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c
index 12603ba71ef..01ca8d2d51d 100644
--- a/source/blender/blenloader/intern/versioning_270.c
+++ b/source/blender/blenloader/intern/versioning_270.c
@@ -34,6 +34,7 @@
/* allow readfile to use deprecated functionality */
#define DNA_DEPRECATED_ALLOW
+#include "DNA_brush_types.h"
#include "DNA_constraint_types.h"
#include "DNA_sdna_types.h"
#include "DNA_space_types.h"
@@ -320,6 +321,13 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
mat->line_col[3] = mat->alpha;
}
}
+
+ if (!DNA_struct_elem_find(fd->filesdna, "RenderData", "int", "preview_start_resolution")) {
+ Scene *scene;
+ for (scene = main->scene.first; scene; scene = scene->id.next) {
+ scene->r.preview_start_resolution = 64;
+ }
+ }
}
if (!MAIN_VERSION_ATLEAST(main, 271, 2)) {
@@ -345,6 +353,14 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
}
}
+ if (!MAIN_VERSION_ATLEAST(main, 271, 3)) {
+ Brush *br;
+
+ for (br = main->brush.first; br; br = br->id.next) {
+ br->fill_threshold = 0.2f;
+ }
+ }
+
if (!DNA_struct_elem_find(fd->filesdna, "RenderData", "int", "preview_start_resolution")) {
Scene *scene;
for (scene = main->scene.first; scene; scene = scene->id.next) {
diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c
index fdedd3f4edd..02f9c1fde17 100644
--- a/source/blender/blenloader/intern/versioning_defaults.c
+++ b/source/blender/blenloader/intern/versioning_defaults.c
@@ -28,6 +28,7 @@
#include "BLI_utildefines.h"
#include "BLI_math.h"
+#include "DNA_brush_types.h"
#include "DNA_freestyle_types.h"
#include "DNA_linestyle_types.h"
#include "DNA_scene_types.h"
@@ -36,14 +37,34 @@
#include "DNA_userdef_types.h"
#include "DNA_mesh_types.h"
#include "DNA_material_types.h"
+#include "DNA_object_types.h"
+#include "BKE_brush.h"
+#include "BKE_library.h"
#include "BKE_main.h"
#include "BLO_readfile.h"
-/* Update defaults in startup.blend, without having to save and embed the file.
+
+/**
+ * Override values in in-memory startup.blend, avoids resaving for small changes.
+ */
+void BLO_update_defaults_userpref_blend(void)
+{
+ /* defaults from T37518 */
+
+ U.uiflag |= USER_ZBUF_CURSOR;
+ U.uiflag |= USER_QUIT_PROMPT;
+ U.uiflag |= USER_CONTINUOUS_MOUSE;
+
+ U.versions = 1;
+ U.savetime = 2;
+}
+
+/**
+ * Update defaults in startup.blend, without having to save and embed the file.
* This function can be emptied each time the startup.blend is updated. */
-void BLO_update_defaults_startup_blend(Main *main)
+void BLO_update_defaults_startup_blend(Main *bmain)
{
Scene *scene;
SceneRenderLayer *srl;
@@ -51,7 +72,7 @@ void BLO_update_defaults_startup_blend(Main *main)
Mesh *me;
Material *mat;
- for (scene = main->scene.first; scene; scene = scene->id.next) {
+ for (scene = bmain->scene.first; scene; scene = scene->id.next) {
scene->r.im_format.planes = R_IMF_PLANES_RGBA;
scene->r.im_format.compress = 15;
@@ -59,9 +80,20 @@ void BLO_update_defaults_startup_blend(Main *main)
srl->freestyleConfig.sphere_radius = 0.1f;
srl->pass_alpha_threshold = 0.5f;
}
+
+ if (scene->toolsettings) {
+ ToolSettings *ts = scene->toolsettings;
+
+ if (ts->sculpt) {
+ Sculpt *sculpt = ts->sculpt;
+ sculpt->paint.symmetry_flags |= PAINT_SYMM_X;
+ sculpt->flags |= SCULPT_DYNTOPO_COLLAPSE;
+ sculpt->detail_size = 12;
+ }
+ }
}
- for (linestyle = main->linestyle.first; linestyle; linestyle = linestyle->id.next) {
+ for (linestyle = bmain->linestyle.first; linestyle; linestyle = linestyle->id.next) {
linestyle->flag = LS_SAME_OBJECT | LS_NO_SORTING | LS_TEXTURE;
linestyle->sort_key = LS_SORT_KEY_DISTANCE_FROM_CAMERA;
linestyle->integration_type = LS_INTEGRATION_MEAN;
@@ -71,7 +103,7 @@ void BLO_update_defaults_startup_blend(Main *main)
{
bScreen *screen;
- for (screen = main->screen.first; screen; screen = screen->id.next) {
+ for (screen = bmain->screen.first; screen; screen = screen->id.next) {
ScrArea *area;
for (area = screen->areabase.first; area; area = area->next) {
SpaceLink *space_link;
@@ -85,13 +117,27 @@ void BLO_update_defaults_startup_blend(Main *main)
}
}
- for (me = main->mesh.first; me; me = me->id.next) {
+ for (me = bmain->mesh.first; me; me = me->id.next) {
me->smoothresh = DEG2RADF(180.0f);
+ me->flag &= ~ME_TWOSIDED;
}
- for (mat = main->mat.first; mat; mat = mat->id.next) {
+ for (mat = bmain->mat.first; mat; mat = mat->id.next) {
mat->line_col[0] = mat->line_col[1] = mat->line_col[2] = 0.0f;
mat->line_col[3] = 1.0f;
}
+
+ {
+ Brush *br;
+ br = BKE_brush_add(bmain, "Fill");
+ br->imagepaint_tool = PAINT_TOOL_FILL;
+ br->ob_mode = OB_MODE_TEXTURE_PAINT;
+
+ br = (Brush *)BKE_libblock_find_name_ex(bmain, ID_BR, "Mask");
+ if (br) {
+ br->imagepaint_tool = PAINT_TOOL_MASK;
+ br->ob_mode |= OB_MODE_TEXTURE_PAINT;
+ }
+ }
}
diff --git a/source/blender/blenloader/intern/versioning_legacy.c b/source/blender/blenloader/intern/versioning_legacy.c
index 572c6d0a02d..557cc147f19 100644
--- a/source/blender/blenloader/intern/versioning_legacy.c
+++ b/source/blender/blenloader/intern/versioning_legacy.c
@@ -473,7 +473,7 @@ static void do_version_ntree_242_2(bNodeTree *ntree)
if (ntree->type == NTREE_COMPOSIT) {
for (node = ntree->nodes.first; node; node = node->next) {
- if (ELEM3(node->type, CMP_NODE_IMAGE, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
+ if (ELEM(node->type, CMP_NODE_IMAGE, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
/* only image had storage */
if (node->storage) {
NodeImageAnim *nia = node->storage;
@@ -2232,7 +2232,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
}
if (sce->r.mode & R_PANORAMA) {
- /* all these checks to ensure saved files with svn version keep working... */
+ /* all these checks to ensure saved files between released versions keep working... */
if (sce->r.xsch < sce->r.ysch) {
Object *obc = blo_do_versions_newlibadr(fd, lib, sce->camera);
if (obc && obc->type == OB_CAMERA) {
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index de10e6fcfbf..82670d2d2b4 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -769,7 +769,7 @@ static void write_nodetree(WriteData *wd, bNodeTree *ntree)
writedata(wd, DATA, strlen(nss->bytecode)+1, nss->bytecode);
writestruct(wd, DATA, node->typeinfo->storagename, 1, node->storage);
}
- else if (ntree->type==NTREE_COMPOSIT && ELEM4(node->type, CMP_NODE_TIME, CMP_NODE_CURVE_VEC, CMP_NODE_CURVE_RGB, CMP_NODE_HUECORRECT))
+ else if (ntree->type==NTREE_COMPOSIT && ELEM(node->type, CMP_NODE_TIME, CMP_NODE_CURVE_VEC, CMP_NODE_CURVE_RGB, CMP_NODE_HUECORRECT))
write_curvemapping(wd, node->storage);
else if (ntree->type==NTREE_TEXTURE && (node->type==TEX_NODE_CURVE_RGB || node->type==TEX_NODE_CURVE_TIME) )
write_curvemapping(wd, node->storage);
@@ -2363,6 +2363,9 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
case SEQ_TYPE_TRANSFORM:
writestruct(wd, DATA, "TransformVars", 1, seq->effectdata);
break;
+ case SEQ_TYPE_GAUSSIAN_BLUR:
+ writestruct(wd, DATA, "GaussianBlurVars", 1, seq->effectdata);
+ break;
}
}
@@ -3028,6 +3031,38 @@ static void write_brushes(WriteData *wd, ListBase *idbase)
if (brush->curve)
write_curvemapping(wd, brush->curve);
+ if (brush->curve)
+ writestruct(wd, DATA, "ColorBand", 1, brush->gradient);
+ }
+ }
+}
+
+static void write_palettes(WriteData *wd, ListBase *idbase)
+{
+ Palette *palette;
+
+ for (palette = idbase->first; palette; palette = palette->id.next) {
+ if (palette->id.us > 0 || wd->current) {
+ PaletteColor *color;
+ writestruct(wd, ID_PAL, "Palette", 1, palette);
+ if (palette->id.properties) IDP_WriteProperty(palette->id.properties, wd);
+
+ for (color = palette->colors.first; color; color= color->next)
+ writestruct(wd, DATA, "PaletteColor", 1, color);
+ }
+ }
+}
+
+static void write_paintcurves(WriteData *wd, ListBase *idbase)
+{
+ PaintCurve *pc;
+
+ for (pc = idbase->first; pc; pc = pc->id.next) {
+ if (pc->id.us > 0 || wd->current) {
+ writestruct(wd, ID_PC, "PaintCurve", 1, pc);
+
+ writestruct(wd, DATA, "PaintCurvePoint", pc->tot_points, pc->points);
+ if (pc->id.properties) IDP_WriteProperty(pc->id.properties, wd);
}
}
}
@@ -3503,6 +3538,8 @@ static int write_file_handle(Main *mainvar, int handle, MemFile *compare, MemFil
write_particlesettings(wd, &mainvar->particle);
write_nodetrees(wd, &mainvar->nodetree);
write_brushes (wd, &mainvar->brush);
+ write_palettes (wd, &mainvar->palettes);
+ write_paintcurves (wd, &mainvar->paintcurves);
write_scripts (wd, &mainvar->script);
write_gpencils (wd, &mainvar->gpencil);
write_linestyles(wd, &mainvar->linestyle);
diff --git a/source/blender/bmesh/bmesh_class.h b/source/blender/bmesh/bmesh_class.h
index 01745396cd1..39359b97a4e 100644
--- a/source/blender/bmesh/bmesh_class.h
+++ b/source/blender/bmesh/bmesh_class.h
@@ -285,8 +285,8 @@ extern void bpy_bm_generic_invalidate(struct BPy_BMGeneric *self);
typedef bool (*BMElemFilterFunc)(BMElem *, void *user_data);
/* defines */
-#define BM_ELEM_CD_SET_INT(ele, offset, f) \
- { assert(offset != -1); *((int *)((char *)(ele)->head.data + (offset))) = (f); } (void)0
+#define BM_ELEM_CD_SET_INT(ele, offset, f) { CHECK_TYPE_NONCONST(ele); \
+ assert(offset != -1); *((int *)((char *)(ele)->head.data + (offset))) = (f); } (void)0
#define BM_ELEM_CD_GET_INT(ele, offset) \
(assert(offset != -1), *((int *)((char *)(ele)->head.data + (offset))))
@@ -294,8 +294,8 @@ typedef bool (*BMElemFilterFunc)(BMElem *, void *user_data);
#define BM_ELEM_CD_GET_VOID_P(ele, offset) \
(assert(offset != -1), (void *)((char *)(ele)->head.data + (offset)))
-#define BM_ELEM_CD_SET_FLOAT(ele, offset, f) \
- { assert(offset != -1); *((float *)((char *)(ele)->head.data + (offset))) = (f); } (void)0
+#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
#define BM_ELEM_CD_GET_FLOAT(ele, offset) \
(assert(offset != -1), *((float *)((char *)(ele)->head.data + (offset))))
diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c
index 18575b42d94..6f886ed5b37 100644
--- a/source/blender/bmesh/intern/bmesh_core.c
+++ b/source/blender/bmesh/intern/bmesh_core.c
@@ -1732,8 +1732,7 @@ BMEdge *bmesh_jekv(BMesh *bm, BMEdge *e_kill, BMVert *v_kill,
l_kill = l_kill->radial_next;
}
for (i = 0; i < radlen; i++) {
- bm->totloop--;
- BLI_mempool_free(bm->lpool, loops[i]);
+ bm_kill_only_loop(bm, loops[i]);
}
}
#ifndef NDEBUG
diff --git a/source/blender/bmesh/intern/bmesh_edgeloop.c b/source/blender/bmesh/intern/bmesh_edgeloop.c
index f01e1197bb7..e83a1d5b00a 100644
--- a/source/blender/bmesh/intern/bmesh_edgeloop.c
+++ b/source/blender/bmesh/intern/bmesh_edgeloop.c
@@ -682,12 +682,12 @@ void BM_edgeloop_expand(BMesh *UNUSED(bm), BMEdgeLoopStore *el_store, int el_sto
LinkData *node_curr_init = node_curr;
LinkData *node_curr_copy;
int i = 0;
- LISTBASE_CIRCULAR_FORWARD_BEGIN (&el_store->verts, node_curr, node_curr_init) {
+ BLI_LISTBASE_CIRCULAR_FORWARD_BEGIN (&el_store->verts, node_curr, node_curr_init) {
if (i++ < step) {
break;
}
}
- LISTBASE_CIRCULAR_FORWARD_END (&el_store->verts, node_curr, node_curr_init);
+ BLI_LISTBASE_CIRCULAR_FORWARD_END (&el_store->verts, node_curr, node_curr_init);
node_curr_copy = MEM_dupallocN(node_curr);
BLI_insertlinkafter(&el_store->verts, node_curr, node_curr_copy);
diff --git a/source/blender/bmesh/intern/bmesh_iterators_inline.h b/source/blender/bmesh/intern/bmesh_iterators_inline.h
index 6a0eb0e0a30..b9733d4702f 100644
--- a/source/blender/bmesh/intern/bmesh_iterators_inline.h
+++ b/source/blender/bmesh/intern/bmesh_iterators_inline.h
@@ -80,60 +80,70 @@ BLI_INLINE bool BM_iter_init(BMIter *iter, BMesh *bm, const char itype, void *da
break;
case BM_EDGES_OF_VERT:
BLI_assert(data != NULL);
+ BLI_assert(((BMElem *)data)->head.htype == BM_VERT);
iter->begin = (BMIter__begin_cb)bmiter__edge_of_vert_begin;
iter->step = (BMIter__step_cb)bmiter__edge_of_vert_step;
iter->data.edge_of_vert.vdata = (BMVert *)data;
break;
case BM_FACES_OF_VERT:
BLI_assert(data != NULL);
+ BLI_assert(((BMElem *)data)->head.htype == BM_VERT);
iter->begin = (BMIter__begin_cb)bmiter__face_of_vert_begin;
iter->step = (BMIter__step_cb)bmiter__face_of_vert_step;
iter->data.face_of_vert.vdata = (BMVert *)data;
break;
case BM_LOOPS_OF_VERT:
BLI_assert(data != NULL);
+ BLI_assert(((BMElem *)data)->head.htype == BM_VERT);
iter->begin = (BMIter__begin_cb)bmiter__loop_of_vert_begin;
iter->step = (BMIter__step_cb)bmiter__loop_of_vert_step;
iter->data.loop_of_vert.vdata = (BMVert *)data;
break;
case BM_VERTS_OF_EDGE:
BLI_assert(data != NULL);
+ BLI_assert(((BMElem *)data)->head.htype == BM_EDGE);
iter->begin = (BMIter__begin_cb)bmiter__vert_of_edge_begin;
iter->step = (BMIter__step_cb)bmiter__vert_of_edge_step;
iter->data.vert_of_edge.edata = (BMEdge *)data;
break;
case BM_FACES_OF_EDGE:
BLI_assert(data != NULL);
+ BLI_assert(((BMElem *)data)->head.htype == BM_EDGE);
iter->begin = (BMIter__begin_cb)bmiter__face_of_edge_begin;
iter->step = (BMIter__step_cb)bmiter__face_of_edge_step;
iter->data.face_of_edge.edata = (BMEdge *)data;
break;
case BM_VERTS_OF_FACE:
BLI_assert(data != NULL);
+ BLI_assert(((BMElem *)data)->head.htype == BM_FACE);
iter->begin = (BMIter__begin_cb)bmiter__vert_of_face_begin;
iter->step = (BMIter__step_cb)bmiter__vert_of_face_step;
iter->data.vert_of_face.pdata = (BMFace *)data;
break;
case BM_EDGES_OF_FACE:
BLI_assert(data != NULL);
+ BLI_assert(((BMElem *)data)->head.htype == BM_FACE);
iter->begin = (BMIter__begin_cb)bmiter__edge_of_face_begin;
iter->step = (BMIter__step_cb)bmiter__edge_of_face_step;
iter->data.edge_of_face.pdata = (BMFace *)data;
break;
case BM_LOOPS_OF_FACE:
BLI_assert(data != NULL);
+ BLI_assert(((BMElem *)data)->head.htype == BM_FACE);
iter->begin = (BMIter__begin_cb)bmiter__loop_of_face_begin;
iter->step = (BMIter__step_cb)bmiter__loop_of_face_step;
iter->data.loop_of_face.pdata = (BMFace *)data;
break;
case BM_LOOPS_OF_LOOP:
BLI_assert(data != NULL);
+ BLI_assert(((BMElem *)data)->head.htype == BM_LOOP);
iter->begin = (BMIter__begin_cb)bmiter__loop_of_loop_begin;
iter->step = (BMIter__step_cb)bmiter__loop_of_loop_step;
iter->data.loop_of_loop.ldata = (BMLoop *)data;
break;
case BM_LOOPS_OF_EDGE:
BLI_assert(data != NULL);
+ BLI_assert(((BMElem *)data)->head.htype == BM_EDGE);
iter->begin = (BMIter__begin_cb)bmiter__loop_of_edge_begin;
iter->step = (BMIter__step_cb)bmiter__loop_of_edge_step;
iter->data.loop_of_edge.edata = (BMEdge *)data;
diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c
index a9e6dad7fd0..26a224c7c71 100644
--- a/source/blender/bmesh/intern/bmesh_mesh.c
+++ b/source/blender/bmesh/intern/bmesh_mesh.c
@@ -802,7 +802,7 @@ void BM_mesh_elem_index_ensure(BMesh *bm, const char htype)
}
/* skip if we only need to operate on one element */
-#pragma omp parallel sections if ((!ELEM5(htype_needed, BM_VERT, BM_EDGE, BM_FACE, BM_LOOP, BM_FACE | BM_LOOP)) && \
+#pragma omp parallel sections if ((!ELEM(htype_needed, BM_VERT, BM_EDGE, BM_FACE, BM_LOOP, BM_FACE | BM_LOOP)) && \
(bm->totvert + bm->totedge + bm->totface >= BM_OMP_LIMIT))
{
#pragma omp section
@@ -1056,7 +1056,7 @@ void BM_mesh_elem_table_ensure(BMesh *bm, const char htype)
}
/* skip if we only need to operate on one element */
-#pragma omp parallel sections if ((!ELEM3(htype_needed, BM_VERT, BM_EDGE, BM_FACE)) && \
+#pragma omp parallel sections if ((!ELEM(htype_needed, BM_VERT, BM_EDGE, BM_FACE)) && \
(bm->totvert + bm->totedge + bm->totface >= BM_OMP_LIMIT))
{
#pragma omp section
@@ -1181,7 +1181,11 @@ int BM_mesh_elem_count(BMesh *bm, const char htype)
*
* WARNING: Be careful if you keep pointers to affected BM elements, or arrays, when using this func!
*/
-void BM_mesh_remap(BMesh *bm, unsigned int *vert_idx, unsigned int *edge_idx, unsigned int *face_idx)
+void BM_mesh_remap(
+ BMesh *bm,
+ const unsigned int *vert_idx,
+ const unsigned int *edge_idx,
+ const unsigned int *face_idx)
{
/* Mapping old to new pointers. */
GHash *vptr_map = NULL, *eptr_map = NULL, *fptr_map = NULL;
@@ -1194,18 +1198,23 @@ void BM_mesh_remap(BMesh *bm, unsigned int *vert_idx, unsigned int *edge_idx, un
if (!(vert_idx || edge_idx || face_idx))
return;
+ BM_mesh_elem_table_ensure(
+ bm,
+ (vert_idx ? BM_VERT : 0) |
+ (edge_idx ? BM_EDGE : 0) |
+ (face_idx ? BM_FACE : 0));
+
/* Remap Verts */
if (vert_idx) {
BMVert **verts_pool, *verts_copy, **vep;
int i, totvert = bm->totvert;
- unsigned int *new_idx = NULL;
+ const unsigned int *new_idx;
/* Init the old-to-new vert pointers mapping */
vptr_map = BLI_ghash_ptr_new_ex("BM_mesh_remap vert pointers mapping", bm->totvert);
/* Make a copy of all vertices. */
- verts_pool = MEM_callocN(sizeof(BMVert *) * totvert, "BM_mesh_remap verts pool");
- BM_iter_as_array(bm, BM_VERTS_OF_MESH, NULL, (void **)verts_pool, totvert);
+ verts_pool = bm->vtable;
verts_copy = MEM_mallocN(sizeof(BMVert) * totvert, "BM_mesh_remap verts copy");
for (i = totvert, ve = verts_copy + totvert - 1, vep = verts_pool + totvert - 1; i--; ve--, vep--) {
*ve = **vep;
@@ -1223,8 +1232,8 @@ void BM_mesh_remap(BMesh *bm, unsigned int *vert_idx, unsigned int *edge_idx, un
BLI_ghash_insert(vptr_map, (void *)*vep, (void *)new_vep);
}
bm->elem_index_dirty |= BM_VERT;
+ bm->elem_table_dirty |= BM_VERT;
- MEM_freeN(verts_pool);
MEM_freeN(verts_copy);
}
@@ -1232,14 +1241,13 @@ void BM_mesh_remap(BMesh *bm, unsigned int *vert_idx, unsigned int *edge_idx, un
if (edge_idx) {
BMEdge **edges_pool, *edges_copy, **edp;
int i, totedge = bm->totedge;
- unsigned int *new_idx = NULL;
+ const unsigned int *new_idx;
/* Init the old-to-new vert pointers mapping */
eptr_map = BLI_ghash_ptr_new_ex("BM_mesh_remap edge pointers mapping", bm->totedge);
/* Make a copy of all vertices. */
- edges_pool = MEM_callocN(sizeof(BMEdge *) * totedge, "BM_mesh_remap edges pool");
- BM_iter_as_array(bm, BM_EDGES_OF_MESH, NULL, (void **)edges_pool, totedge);
+ edges_pool = bm->etable;
edges_copy = MEM_mallocN(sizeof(BMEdge) * totedge, "BM_mesh_remap edges copy");
for (i = totedge, ed = edges_copy + totedge - 1, edp = edges_pool + totedge - 1; i--; ed--, edp--) {
*ed = **edp;
@@ -1256,8 +1264,8 @@ void BM_mesh_remap(BMesh *bm, unsigned int *vert_idx, unsigned int *edge_idx, un
/* printf("mapping edge from %d to %d (%p/%p to %p)\n", i, *new_idx, *edp, edges_pool[i], new_edp);*/
}
bm->elem_index_dirty |= BM_EDGE;
+ bm->elem_table_dirty |= BM_EDGE;
- MEM_freeN(edges_pool);
MEM_freeN(edges_copy);
}
@@ -1265,14 +1273,13 @@ void BM_mesh_remap(BMesh *bm, unsigned int *vert_idx, unsigned int *edge_idx, un
if (face_idx) {
BMFace **faces_pool, *faces_copy, **fap;
int i, totface = bm->totface;
- unsigned int *new_idx = NULL;
+ const unsigned int *new_idx;
/* Init the old-to-new vert pointers mapping */
fptr_map = BLI_ghash_ptr_new_ex("BM_mesh_remap face pointers mapping", bm->totface);
/* Make a copy of all vertices. */
- faces_pool = MEM_callocN(sizeof(BMFace *) * totface, "BM_mesh_remap faces pool");
- BM_iter_as_array(bm, BM_FACES_OF_MESH, NULL, (void **)faces_pool, totface);
+ faces_pool = bm->ftable;
faces_copy = MEM_mallocN(sizeof(BMFace) * totface, "BM_mesh_remap faces copy");
for (i = totface, fa = faces_copy + totface - 1, fap = faces_pool + totface - 1; i--; fa--, fap--) {
*fa = **fap;
@@ -1289,8 +1296,8 @@ void BM_mesh_remap(BMesh *bm, unsigned int *vert_idx, unsigned int *edge_idx, un
}
bm->elem_index_dirty |= BM_FACE | BM_LOOP;
+ bm->elem_table_dirty |= BM_FACE;
- MEM_freeN(faces_pool);
MEM_freeN(faces_copy);
}
diff --git a/source/blender/bmesh/intern/bmesh_mesh.h b/source/blender/bmesh/intern/bmesh_mesh.h
index 3923c2515a3..da181df4eed 100644
--- a/source/blender/bmesh/intern/bmesh_mesh.h
+++ b/source/blender/bmesh/intern/bmesh_mesh.h
@@ -69,7 +69,11 @@ BMFace *BM_face_at_index_find(BMesh *bm, const int index);
int BM_mesh_elem_count(BMesh *bm, const char htype);
-void BM_mesh_remap(BMesh *bm, unsigned int *vert_idx, unsigned int *edge_idx, unsigned int *face_idx);
+void BM_mesh_remap(
+ BMesh *bm,
+ const unsigned int *vert_idx,
+ const unsigned int *edge_idx,
+ const unsigned int *face_idx);
typedef struct BMAllocTemplate {
int totvert, totedge, totloop, totface;
diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c
index b9da7618df8..7dc46cf0678 100644
--- a/source/blender/bmesh/intern/bmesh_opdefines.c
+++ b/source/blender/bmesh/intern/bmesh_opdefines.c
@@ -956,6 +956,7 @@ static BMOpDefine bmo_dissolve_verts_def = {
/* slots_in */
{{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}},
{"use_face_split", BMO_OP_SLOT_BOOL},
+ {"use_boundary_tear", BMO_OP_SLOT_BOOL},
{{'\0'}},
},
{{{'\0'}}}, /* no output */
diff --git a/source/blender/bmesh/intern/bmesh_walkers.c b/source/blender/bmesh/intern/bmesh_walkers.c
index 8f74e98e762..6a5efbe70ac 100644
--- a/source/blender/bmesh/intern/bmesh_walkers.c
+++ b/source/blender/bmesh/intern/bmesh_walkers.c
@@ -47,7 +47,7 @@
*
* basic design pattern: the walker step function goes through it's
* list of possible choices for recursion, and recurses (by pushing a new state)
- * using the first non-visited one. this choise is the flagged as visited using
+ * using the first non-visited one. This choice is the flagged as visited using
* the ghash. each step may push multiple new states onto the worklist at once.
*
* - Walkers use tool flags, not header flags.
diff --git a/source/blender/bmesh/operators/bmo_bridge.c b/source/blender/bmesh/operators/bmo_bridge.c
index 9e9cd0d66e2..e4417477e76 100644
--- a/source/blender/bmesh/operators/bmo_bridge.c
+++ b/source/blender/bmesh/operators/bmo_bridge.c
@@ -119,7 +119,7 @@ static void bm_bridge_best_rotation(struct BMEdgeLoopStore *el_store_a, struct B
}
if (el_b_best) {
- BLI_rotatelist_first(lb_b, el_b_best);
+ BLI_listbase_rotate_first(lb_b, el_b_best);
}
}
@@ -272,7 +272,7 @@ static void bridge_loop_pair(BMesh *bm,
const int len_b = BM_edgeloop_length_get(el_store_b);
ListBase *lb_b = BM_edgeloop_verts_get(el_store_b);
LinkData *el_b = BLI_rfindlink(lb_b, mod_i(twist_offset, len_b));
- BLI_rotatelist_first(lb_b, el_b);
+ BLI_listbase_rotate_first(lb_b, el_b);
}
}
diff --git a/source/blender/bmesh/operators/bmo_connect_pair.c b/source/blender/bmesh/operators/bmo_connect_pair.c
index b497ab2f693..426e20939ca 100644
--- a/source/blender/bmesh/operators/bmo_connect_pair.c
+++ b/source/blender/bmesh/operators/bmo_connect_pair.c
@@ -134,7 +134,7 @@ static void state_calc_co_pair(const PathContext *pc,
static bool state_link_find(PathLinkState *state, BMElem *ele)
{
PathLink *link = state->link_last;
- BLI_assert(ELEM3(ele->head.htype, BM_VERT, BM_EDGE, BM_FACE));
+ BLI_assert(ELEM(ele->head.htype, BM_VERT, BM_EDGE, BM_FACE));
if (link) {
do {
if (link->ele == ele) {
diff --git a/source/blender/bmesh/operators/bmo_dissolve.c b/source/blender/bmesh/operators/bmo_dissolve.c
index 209ca30ddc3..877cd16d9d2 100644
--- a/source/blender/bmesh/operators/bmo_dissolve.c
+++ b/source/blender/bmesh/operators/bmo_dissolve.c
@@ -51,6 +51,7 @@
#define VERT_MARK_PAIR 4
#define VERT_TAG 2
#define VERT_ISGC 8
+#define VERT_MARK_TEAR 16
@@ -85,7 +86,7 @@ static bool UNUSED_FUNCTION(check_hole_in_region) (BMesh *bm, BMFace *f)
return true;
}
-static void bm_face_split(BMesh *bm, const short oflag)
+static void bm_face_split(BMesh *bm, const short oflag, bool use_edge_delete)
{
BMIter iter;
BMVert *v;
@@ -104,6 +105,12 @@ static void bm_face_split(BMesh *bm, const short oflag)
}
}
}
+ /* remove surrounding edges & faces */
+ if (use_edge_delete) {
+ while (v->e) {
+ BM_edge_kill(bm, v->e);
+ }
+ }
}
}
}
@@ -268,7 +275,7 @@ void bmo_dissolve_edges_exec(BMesh *bm, BMOperator *op)
}
}
- bm_face_split(bm, VERT_TAG);
+ bm_face_split(bm, VERT_TAG, false);
}
if (use_verts) {
@@ -345,13 +352,29 @@ void bmo_dissolve_verts_exec(BMesh *bm, BMOperator *op)
BMFace *act_face = bm->act_face;
const bool use_face_split = BMO_slot_bool_get(op->slots_in, "use_face_split");
+ const bool use_boundary_tear = BMO_slot_bool_get(op->slots_in, "use_boundary_tear");
BMO_ITER (v, &oiter, op->slots_in, "verts", BM_VERT) {
BMO_elem_flag_enable(bm, v, VERT_MARK | VERT_ISGC);
}
if (use_face_split) {
- bm_face_split(bm, VERT_MARK);
+ bm_face_split(bm, VERT_MARK, false);
+ }
+
+ if (use_boundary_tear) {
+ BMO_ITER (v, &oiter, op->slots_in, "verts", BM_VERT) {
+ if (!BM_vert_is_edge_pair(v)) {
+ BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
+ if (BM_edge_is_boundary(e)) {
+ BMO_elem_flag_enable(bm, v, VERT_MARK_TEAR);
+ break;
+ }
+ }
+ }
+ }
+
+ bm_face_split(bm, VERT_MARK_TEAR, true);
}
BMO_ITER (v, &oiter, op->slots_in, "verts", BM_VERT) {
diff --git a/source/blender/bmesh/operators/bmo_subdivide_edgering.c b/source/blender/bmesh/operators/bmo_subdivide_edgering.c
index e13a9df4474..8bb4722ea07 100644
--- a/source/blender/bmesh/operators/bmo_subdivide_edgering.c
+++ b/source/blender/bmesh/operators/bmo_subdivide_edgering.c
@@ -920,13 +920,13 @@ static void bm_edgering_pair_order(BMesh *bm,
}
BLI_assert(node != NULL);
- BLI_rotatelist_first(lb_b, node);
+ BLI_listbase_rotate_first(lb_b, node);
/* now check we are winding the same way */
if (bm_edgering_pair_order_is_flipped(bm, el_store_a, el_store_b)) {
BM_edgeloop_flip(bm, el_store_b);
/* re-ensure the first node */
- BLI_rotatelist_first(lb_b, node);
+ BLI_listbase_rotate_first(lb_b, node);
}
/* sanity checks that we are aligned & winding now */
diff --git a/source/blender/bmesh/operators/bmo_utils.c b/source/blender/bmesh/operators/bmo_utils.c
index 600386893dd..d2d1c0854de 100644
--- a/source/blender/bmesh/operators/bmo_utils.c
+++ b/source/blender/bmesh/operators/bmo_utils.c
@@ -63,7 +63,7 @@ void bmo_transform_exec(BMesh *UNUSED(bm), BMOperator *op)
if (!is_zero_m4(mat_space)) {
invert_m4_m4(imat_space, mat_space);
- mul_serie_m4(mat, imat_space, mat, mat_space, NULL, NULL, NULL, NULL, NULL);
+ mul_m4_series(mat, imat_space, mat, mat_space);
}
BMO_ITER (v, &iter, op->slots_in, "verts", BM_VERT) {
diff --git a/source/blender/bmesh/tools/bmesh_beautify.c b/source/blender/bmesh/tools/bmesh_beautify.c
index 90d26a775d3..6639e767e77 100644
--- a/source/blender/bmesh/tools/bmesh_beautify.c
+++ b/source/blender/bmesh/tools/bmesh_beautify.c
@@ -67,6 +67,7 @@ static unsigned int erot_gsetutil_hash(const void *ptr)
return BLI_ghashutil_inthash_v4(&e_state->v1);
}
#endif
+#if 0
static int erot_gsetutil_cmp(const void *a, const void *b)
{
const EdRotState *e_state_a = (const EdRotState *)a;
@@ -81,10 +82,10 @@ static int erot_gsetutil_cmp(const void *a, const void *b)
else if (e_state_a->f2 > e_state_b->f2) return 1;
else return 0;
}
-
+#endif
static GSet *erot_gset_new(void)
{
- return BLI_gset_new(BLI_ghashutil_inthash_v4_p, erot_gsetutil_cmp, __func__);
+ return BLI_gset_new(BLI_ghashutil_inthash_v4_p, BLI_ghashutil_inthash_v4_cmp, __func__);
}
/* ensure v0 is smaller */
@@ -142,10 +143,10 @@ static float bm_edge_calc_rotate_beauty__area(
float axis_mat[3][3];
// printf("%p %p %p %p - %p %p\n", v1, v2, v3, v4, e->l->f, e->l->radial_next->f);
- BLI_assert((ELEM3(v1, v2, v3, v4) == false) &&
- (ELEM3(v2, v1, v3, v4) == false) &&
- (ELEM3(v3, v1, v2, v4) == false) &&
- (ELEM3(v4, v1, v2, v3) == false));
+ BLI_assert((ELEM(v1, v2, v3, v4) == false) &&
+ (ELEM(v2, v1, v3, v4) == false) &&
+ (ELEM(v3, v1, v2, v4) == false) &&
+ (ELEM(v4, v1, v2, v3) == false));
is_zero_a = (normal_tri_v3(no_a, v2, v3, v4) <= FLT_EPSILON);
is_zero_b = (normal_tri_v3(no_b, v2, v4, v1) <= FLT_EPSILON);
diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c
index bd7378f30e9..aedc551b5a6 100644
--- a/source/blender/bmesh/tools/bmesh_bevel.c
+++ b/source/blender/bmesh/tools/bmesh_bevel.c
@@ -1631,7 +1631,7 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
* corresponding ones that changed on the other end.
* The graph is dynamic in the sense that having an offset that
* doesn't meet the user spec can be added as the search proceeds.
- * We want this search to be deterministic (not dependendent
+ * We want this search to be deterministic (not dependent
* on order of processing through hash table), so as to avoid
* flicker to to different decisions made if search is different
* while dragging the offset number in the UI. So look for the
@@ -3387,7 +3387,7 @@ static void bevel_build_edge_polygons(BMesh *bm, BevelParams *bp, BMEdge *bme)
VMesh *vm1, *vm2;
EdgeHalf *e1, *e2;
BMEdge *bme1, *bme2;
- BMFace *f1, *f2, *f, *newf;
+ BMFace *f1, *f2, *f;
int k, nseg, i1, i2, odd, mid;
int mat_nr = bp->mat_nr;
@@ -3428,7 +3428,7 @@ static void bevel_build_edge_polygons(BMesh *bm, BevelParams *bp, BMEdge *bme)
vm2 = bv2->vmesh;
if (nseg == 1) {
- newf = bev_create_quad_straddle(bm, bmv1, bmv2, bmv3, bmv4, f1, f2, mat_nr, e1->is_seam);
+ bev_create_quad_straddle(bm, bmv1, bmv2, bmv3, bmv4, f1, f2, mat_nr, e1->is_seam);
}
else {
bmv1i = bmv1;
diff --git a/source/blender/bmesh/tools/bmesh_decimate_collapse.c b/source/blender/bmesh/tools/bmesh_decimate_collapse.c
index 4b6209fc4eb..ef1783cc693 100644
--- a/source/blender/bmesh/tools/bmesh_decimate_collapse.c
+++ b/source/blender/bmesh/tools/bmesh_decimate_collapse.c
@@ -414,10 +414,10 @@ static void bm_decim_triangulate_end(BMesh *bm)
BM_vert_in_edge(e, l_b->next->v) ? l_b->prev->v : l_b->next->v,
};
- BLI_assert(ELEM3(vquad[0], vquad[1], vquad[2], vquad[3]) == false);
- BLI_assert(ELEM3(vquad[1], vquad[0], vquad[2], vquad[3]) == false);
- BLI_assert(ELEM3(vquad[2], vquad[1], vquad[0], vquad[3]) == false);
- BLI_assert(ELEM3(vquad[3], vquad[1], vquad[2], vquad[0]) == false);
+ BLI_assert(ELEM(vquad[0], vquad[1], vquad[2], vquad[3]) == false);
+ BLI_assert(ELEM(vquad[1], vquad[0], vquad[2], vquad[3]) == false);
+ BLI_assert(ELEM(vquad[2], vquad[1], vquad[0], vquad[3]) == false);
+ BLI_assert(ELEM(vquad[3], vquad[1], vquad[2], vquad[0]) == false);
if (is_quad_convex_v3(vquad[0]->co, vquad[1]->co, vquad[2]->co, vquad[3]->co)) {
/* highly unlikely to fail, but prevents possible double-ups */
diff --git a/source/blender/bmesh/tools/bmesh_edgenet.c b/source/blender/bmesh/tools/bmesh_edgenet.c
index a08aa6184b5..1328b81b746 100644
--- a/source/blender/bmesh/tools/bmesh_edgenet.c
+++ b/source/blender/bmesh/tools/bmesh_edgenet.c
@@ -393,8 +393,8 @@ static LinkNode *bm_edgenet_path_calc_best(
if (path == NULL) {
return NULL;
}
- else if (path_cost <= 1) {
- /* any face that takes 1-2 iterations to find we consider valid */
+ else if (path_cost < 1) {
+ /* any face that takes 1 iteration to find we consider valid */
return path;
}
else {
@@ -465,7 +465,6 @@ void BM_mesh_edgenet(BMesh *bm,
if (use_edge_tag == false) {
BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- BM_elem_flag_enable(e, BM_ELEM_TAG);
BM_elem_flag_set(e, BM_ELEM_TAG, bm_edge_step_ok(e));
}
}
diff --git a/source/blender/collada/AnimationImporter.cpp b/source/blender/collada/AnimationImporter.cpp
index d27795b0ab2..6e2d337a32e 100644
--- a/source/blender/collada/AnimationImporter.cpp
+++ b/source/blender/collada/AnimationImporter.cpp
@@ -804,7 +804,7 @@ void AnimationImporter::apply_matrix_curves(Object *ob, std::vector<FCurve *>& a
// evaluate_joint_world_transform_at_frame(temp, NULL, node, fra);
// calc special matrix
- mul_serie_m4(mat, irest, temp, irest_dae, rest, NULL, NULL, NULL, NULL);
+ mul_m4_series(mat, irest, temp, irest_dae, rest);
}
else {
copy_m4_m4(mat, matfra);
@@ -1210,7 +1210,7 @@ void AnimationImporter::add_bone_animation_sampled(Object *ob, std::vector<FCurv
// evaluate_joint_world_transform_at_frame(temp, NULL, node, fra);
// calc special matrix
- mul_serie_m4(mat, irest, temp, irest_dae, rest, NULL, NULL, NULL, NULL);
+ mul_m4_series(mat, irest, temp, irest_dae, rest);
float rot[4], loc[3], scale[3];
@@ -1545,7 +1545,7 @@ Object *AnimationImporter::translate_animation_OLD(COLLADAFW::Node *node,
// evaluate_joint_world_transform_at_frame(temp, NULL, node, fra);
// calc special matrix
- mul_serie_m4(mat, irest, temp, irest_dae, rest, NULL, NULL, NULL, NULL);
+ mul_m4_series(mat, irest, temp, irest_dae, rest);
}
else {
copy_m4_m4(mat, matfra);
diff --git a/source/blender/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp
index bbbbbf211c6..97d300e77f5 100644
--- a/source/blender/collada/DocumentImporter.cpp
+++ b/source/blender/collada/DocumentImporter.cpp
@@ -805,10 +805,14 @@ void DocumentImporter::write_profile_COMMON(COLLADAFW::EffectCommon *ef, Materia
// DIFFUSE
// color
if (ef->getDiffuse().isColor()) {
+ /* too high intensity can create artefacts (fireflies)
+ So here we take care that intensity is set to 0.8 wherever possible
+ */
col = ef->getDiffuse().getColor();
- ma->r = col.getRed();
- ma->g = col.getGreen();
- ma->b = col.getBlue();
+ ma->ref = max_ffff(col.getRed(), col.getGreen(), col.getBlue(), 0.8);
+ ma->r = col.getRed() / ma->ref;
+ ma->g = col.getGreen() / ma->ref;
+ ma->b = col.getBlue() / ma->ref;
}
// texture
else if (ef->getDiffuse().isTexture()) {
diff --git a/source/blender/collada/TransformWriter.cpp b/source/blender/collada/TransformWriter.cpp
index c3665a33ca4..595787b44ac 100644
--- a/source/blender/collada/TransformWriter.cpp
+++ b/source/blender/collada/TransformWriter.cpp
@@ -77,7 +77,7 @@ void TransformWriter::add_node_transform_ob(COLLADASW::Node& node, Object *ob, B
BKE_object_to_mat4(ob, C);
copy_v3_v3(ob->size, scale);
- mul_serie_m4(tmat, ob->parent->obmat, ob->parentinv, C, NULL, NULL, NULL, NULL, NULL);
+ mul_m4_series(tmat, ob->parent->obmat, ob->parentinv, C);
// calculate local mat
diff --git a/source/blender/compositor/CMakeLists.txt b/source/blender/compositor/CMakeLists.txt
index a19433436f1..4bcdd4d9e34 100644
--- a/source/blender/compositor/CMakeLists.txt
+++ b/source/blender/compositor/CMakeLists.txt
@@ -39,7 +39,7 @@ set(INC
../nodes/intern
../render/extern/include
../render/intern/include
- ../../../intern/opencl
+ ../../../extern/clew/include
../../../intern/guardedalloc
)
@@ -175,6 +175,11 @@ set(SRC
nodes/COM_GlareNode.cpp
nodes/COM_GlareNode.h
+ nodes/COM_SunBeamsNode.cpp
+ nodes/COM_SunBeamsNode.h
+ operations/COM_SunBeamsOperation.cpp
+ operations/COM_SunBeamsOperation.h
+
nodes/COM_CornerPinNode.cpp
nodes/COM_CornerPinNode.h
nodes/COM_PlaneTrackDeformNode.cpp
@@ -535,4 +540,6 @@ list(APPEND INC
data_to_c(${CMAKE_CURRENT_SOURCE_DIR}/operations/COM_OpenCLKernels.cl
${CMAKE_CURRENT_BINARY_DIR}/operations/COM_OpenCLKernels.cl.h SRC)
+add_definitions(-DCL_USE_DEPRECATED_OPENCL_1_1_APIS)
+
blender_add_lib(bf_compositor "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/compositor/COM_compositor.h b/source/blender/compositor/COM_compositor.h
index 2cf2c690d3e..9b22444cf7f 100644
--- a/source/blender/compositor/COM_compositor.h
+++ b/source/blender/compositor/COM_compositor.h
@@ -208,7 +208,7 @@ extern "C" {
*
* @see ExecutionGroup.execute Execute a complete ExecutionGroup. Halts until finished or breaked by user
* @see ExecutionGroup.scheduleChunkWhenPossible Tries to schedule a single chunk,
- * checks if all input data is available. Can trigger dependant chunks to be calculated
+ * checks if all input data is available. Can trigger dependent chunks to be calculated
* @see ExecutionGroup.scheduleAreaWhenPossible Tries to schedule an area. This can be multiple chunks
* (is called from [@ref ExecutionGroup.scheduleChunkWhenPossible])
* @see ExecutionGroup.scheduleChunk Schedule a chunk on the WorkScheduler
diff --git a/source/blender/compositor/SConscript b/source/blender/compositor/SConscript
index 073b100e156..eab40873f64 100644
--- a/source/blender/compositor/SConscript
+++ b/source/blender/compositor/SConscript
@@ -26,7 +26,7 @@
# ***** END GPL LICENSE BLOCK *****
Import ('env')
-defs = ['GLEW_STATIC']
+defs = ['GLEW_STATIC', 'CL_USE_DEPRECATED_OPENCL_1_1_APIS']
sources_intern = env.Glob('intern/*.cpp')
sources_nodes = env.Glob('nodes/*.cpp')
@@ -37,7 +37,7 @@ incs = [
'intern',
'nodes',
'operations',
- '#/intern/opencl',
+ '#/extern/clew/include',
'../blenkernel',
'../blenlib',
'../imbuf',
diff --git a/source/blender/compositor/intern/COM_Converter.cpp b/source/blender/compositor/intern/COM_Converter.cpp
index 9251e161839..99f66bcb5b4 100644
--- a/source/blender/compositor/intern/COM_Converter.cpp
+++ b/source/blender/compositor/intern/COM_Converter.cpp
@@ -99,6 +99,7 @@ extern "C" {
#include "COM_SetValueOperation.h"
#include "COM_SplitViewerNode.h"
#include "COM_Stabilize2dNode.h"
+#include "COM_SunBeamsNode.h"
#include "COM_SwitchNode.h"
#include "COM_TextureNode.h"
#include "COM_TimeNode.h"
@@ -394,6 +395,9 @@ Node *Converter::convert(bNode *b_node)
case CMP_NODE_CORNERPIN:
node = new CornerPinNode(b_node);
break;
+ case CMP_NODE_SUNBEAMS:
+ node = new SunBeamsNode(b_node);
+ break;
}
return node;
}
diff --git a/source/blender/compositor/intern/COM_NodeOperation.h b/source/blender/compositor/intern/COM_NodeOperation.h
index b2b8f03c476..d9c16615fb6 100644
--- a/source/blender/compositor/intern/COM_NodeOperation.h
+++ b/source/blender/compositor/intern/COM_NodeOperation.h
@@ -38,7 +38,7 @@ extern "C" {
#include "COM_MemoryProxy.h"
#include "COM_SocketReader.h"
-#include "OCL_opencl.h"
+#include "clew.h"
using std::list;
using std::min;
diff --git a/source/blender/compositor/intern/COM_OpenCLDevice.cpp b/source/blender/compositor/intern/COM_OpenCLDevice.cpp
index 2cfc10cff29..c5b663d2aef 100644
--- a/source/blender/compositor/intern/COM_OpenCLDevice.cpp
+++ b/source/blender/compositor/intern/COM_OpenCLDevice.cpp
@@ -103,7 +103,7 @@ void OpenCLDevice::COM_clAttachMemoryBufferOffsetToKernelParameter(cl_kernel ker
if (offsetIndex != -1) {
cl_int error;
rcti *rect = memoryBuffer->getRect();
- cl_int2 offset = {rect->xmin, rect->ymin};
+ cl_int2 offset = {{rect->xmin, rect->ymin}};
error = clSetKernelArg(kernel, offsetIndex, sizeof(cl_int2), &offset);
if (error != CL_SUCCESS) { printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); }
@@ -114,7 +114,7 @@ void OpenCLDevice::COM_clAttachSizeToKernelParameter(cl_kernel kernel, int offse
{
if (offsetIndex != -1) {
cl_int error;
- cl_int2 offset = {(cl_int)operation->getWidth(), (cl_int)operation->getHeight()};
+ cl_int2 offset = {{(cl_int)operation->getWidth(), (cl_int)operation->getHeight()}};
error = clSetKernelArg(kernel, offsetIndex, sizeof(cl_int2), &offset);
if (error != CL_SUCCESS) { printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); }
@@ -154,7 +154,7 @@ void OpenCLDevice::COM_clEnqueueRange(cl_kernel kernel, MemoryBuffer *outputMemo
bool breaked = false;
for (offsety = 0; offsety < height && (!breaked); offsety += localSize) {
- offset[1] = offsety;
+ offset.y = offsety;
if (offsety + localSize < height) {
size[1] = localSize;
}
@@ -169,7 +169,7 @@ void OpenCLDevice::COM_clEnqueueRange(cl_kernel kernel, MemoryBuffer *outputMemo
else {
size[0] = width - offsetx;
}
- offset[0] = offsetx;
+ offset.x = offsetx;
error = clSetKernelArg(kernel, offsetIndex, sizeof(cl_int2), &offset);
if (error != CL_SUCCESS) { printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); }
diff --git a/source/blender/compositor/intern/COM_OpenCLDevice.h b/source/blender/compositor/intern/COM_OpenCLDevice.h
index 50cc6f25f70..94df2f2b44c 100644
--- a/source/blender/compositor/intern/COM_OpenCLDevice.h
+++ b/source/blender/compositor/intern/COM_OpenCLDevice.h
@@ -26,7 +26,7 @@ class OpenCLDevice;
#define _COM_OpenCLDevice_h
#include "COM_Device.h"
-#include "OCL_opencl.h"
+#include "clew.h"
#include "COM_WorkScheduler.h"
#include "COM_ReadBufferOperation.h"
diff --git a/source/blender/compositor/intern/COM_WorkScheduler.cpp b/source/blender/compositor/intern/COM_WorkScheduler.cpp
index d60f9cb7f10..e1016731c7f 100644
--- a/source/blender/compositor/intern/COM_WorkScheduler.cpp
+++ b/source/blender/compositor/intern/COM_WorkScheduler.cpp
@@ -28,7 +28,7 @@
#include "COM_CPUDevice.h"
#include "COM_OpenCLDevice.h"
#include "COM_OpenCLKernels.cl.h"
-#include "OCL_opencl.h"
+#include "clew.h"
#include "COM_WriteBufferOperation.h"
#include "MEM_guardedalloc.h"
@@ -274,7 +274,7 @@ bool WorkScheduler::hasGPUDevices()
#endif
}
-static void clContextError(const char *errinfo, const void *private_info, size_t cb, void *user_data)
+static void CL_CALLBACK clContextError(const char *errinfo, const void *private_info, size_t cb, void *user_data)
{
printf("OPENCL error: %s\n", errinfo);
}
@@ -326,7 +326,7 @@ void WorkScheduler::initialize(bool use_opencl, int num_cpu_threads)
g_context = NULL;
g_program = NULL;
- if (!OCL_init()) /* this will check for errors and skip if already initialized */
+ if (clewInit() != CLEW_SUCCESS) /* this will check for errors and skip if already initialized */
return;
if (clCreateContextFromType) {
diff --git a/source/blender/compositor/intern/COM_compositor.cpp b/source/blender/compositor/intern/COM_compositor.cpp
index 99655c67a3f..ec9ef6c7e68 100644
--- a/source/blender/compositor/intern/COM_compositor.cpp
+++ b/source/blender/compositor/intern/COM_compositor.cpp
@@ -32,7 +32,7 @@ extern "C" {
#include "COM_compositor.h"
#include "COM_ExecutionSystem.h"
#include "COM_WorkScheduler.h"
-#include "OCL_opencl.h"
+#include "clew.h"
#include "COM_MovieDistortionOperation.h"
static ThreadMutex s_compositorMutex;
diff --git a/source/blender/compositor/nodes/COM_SunBeamsNode.cpp b/source/blender/compositor/nodes/COM_SunBeamsNode.cpp
new file mode 100644
index 00000000000..ed14acabf36
--- /dev/null
+++ b/source/blender/compositor/nodes/COM_SunBeamsNode.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2014, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor:
+ * Lukas Toenne
+ */
+
+#include "COM_SunBeamsNode.h"
+#include "COM_SunBeamsOperation.h"
+
+SunBeamsNode::SunBeamsNode(bNode *editorNode) : Node(editorNode)
+{
+ /* pass */
+}
+
+void SunBeamsNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
+{
+ NodeInput *inputSocket = this->getInputSocket(0);
+ NodeOutput *outputSocket = this->getOutputSocket(0);
+ NodeSunBeams *data = (NodeSunBeams *)getbNode()->storage;
+
+ SunBeamsOperation *operation = new SunBeamsOperation();
+ operation->setData(*data);
+ converter.addOperation(operation);
+
+ converter.mapInputSocket(inputSocket, operation->getInputSocket(0));
+ converter.mapOutputSocket(outputSocket, operation->getOutputSocket(0));
+}
diff --git a/source/blender/compositor/nodes/COM_SunBeamsNode.h b/source/blender/compositor/nodes/COM_SunBeamsNode.h
new file mode 100644
index 00000000000..4024eb276bc
--- /dev/null
+++ b/source/blender/compositor/nodes/COM_SunBeamsNode.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2014, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor:
+ * Lukas Toenne
+ */
+
+#ifndef _COM_SunBeamsNode_h_
+#define _COM_SunBeamsNode_h_
+
+#include "COM_Node.h"
+
+/**
+ * @brief SunBeamsNode
+ * @ingroup Node
+ */
+class SunBeamsNode : public Node {
+public:
+ SunBeamsNode(bNode *editorNode);
+ void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
+};
+
+#endif
diff --git a/source/blender/compositor/operations/COM_DirectionalBlurOperation.cpp b/source/blender/compositor/operations/COM_DirectionalBlurOperation.cpp
index 0cea2a7183f..67f52934b13 100644
--- a/source/blender/compositor/operations/COM_DirectionalBlurOperation.cpp
+++ b/source/blender/compositor/operations/COM_DirectionalBlurOperation.cpp
@@ -109,8 +109,8 @@ void DirectionalBlurOperation::executeOpenCL(OpenCLDevice *device,
cl_kernel directionalBlurKernel = device->COM_clCreateKernel("directionalBlurKernel", NULL);
cl_int iterations = pow(2.0f, this->m_data->iter);
- cl_float2 ltxy = {this->m_tx, this->m_ty};
- cl_float2 centerpix = {this->m_center_x_pix, this->m_center_y_pix};
+ cl_float2 ltxy = {{this->m_tx, this->m_ty}};
+ cl_float2 centerpix = {{this->m_center_x_pix, this->m_center_y_pix}};
cl_float lsc = this->m_sc;
cl_float lrot = this->m_rot;
diff --git a/source/blender/compositor/operations/COM_MathBaseOperation.cpp b/source/blender/compositor/operations/COM_MathBaseOperation.cpp
index cbc60b5091d..32a1e77b9a7 100644
--- a/source/blender/compositor/operations/COM_MathBaseOperation.cpp
+++ b/source/blender/compositor/operations/COM_MathBaseOperation.cpp
@@ -335,12 +335,11 @@ void MathModuloOperation::executePixelSampled(float output[4], float x, float y,
void MathAbsoluteOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
{
- float inputValue1[4];
+ float inputValue1[4];
- this->m_inputValue1Operation->readSampled(inputValue1, x, y, sampler);
+ this->m_inputValue1Operation->readSampled(inputValue1, x, y, sampler);
- output[0] = fabs(inputValue1[0]);
+ output[0] = fabs(inputValue1[0]);
- clampIfNeeded(output);
+ clampIfNeeded(output);
}
-
diff --git a/source/blender/compositor/operations/COM_MathBaseOperation.h b/source/blender/compositor/operations/COM_MathBaseOperation.h
index 05d2bb054d3..32cd19f1fb9 100644
--- a/source/blender/compositor/operations/COM_MathBaseOperation.h
+++ b/source/blender/compositor/operations/COM_MathBaseOperation.h
@@ -165,8 +165,8 @@ public:
class MathAbsoluteOperation : public MathBaseOperation {
public:
- MathAbsoluteOperation() : MathBaseOperation() {}
- void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+ MathAbsoluteOperation() : MathBaseOperation() {}
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
};
#endif
diff --git a/source/blender/compositor/operations/COM_SunBeamsOperation.cpp b/source/blender/compositor/operations/COM_SunBeamsOperation.cpp
new file mode 100644
index 00000000000..97f9f7b5eea
--- /dev/null
+++ b/source/blender/compositor/operations/COM_SunBeamsOperation.cpp
@@ -0,0 +1,303 @@
+/*
+ * Copyright 2014, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor:
+ * Lukas Toenne
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "COM_SunBeamsOperation.h"
+
+SunBeamsOperation::SunBeamsOperation() : NodeOperation()
+{
+ this->addInputSocket(COM_DT_COLOR);
+ this->addOutputSocket(COM_DT_COLOR);
+ this->setResolutionInputSocketIndex(0);
+
+ this->setComplex(true);
+}
+
+void SunBeamsOperation::initExecution()
+{
+ /* convert to pixels */
+ this->m_source_px[0] = this->m_data.source[0] * this->getWidth();
+ this->m_source_px[1] = this->m_data.source[1] * this->getHeight();
+ this->m_ray_length_px = this->m_data.ray_length * max(this->getWidth(), this->getHeight());
+}
+
+/**
+ * Defines a line accumulator for a specific sector,
+ * given by the four matrix entries that rotate from buffer space into the sector
+ *
+ * (x,y) is used to designate buffer space coordinates
+ * (u,v) is used to designate sector space coordinates
+ *
+ * For a target point (x,y) the sector should be chosen such that
+ * ``u >= v >= 0``
+ * This removes the need to handle all sorts of special cases.
+ */
+template <int fxx, int fxy, int fyx, int fyy>
+struct BufferLineAccumulator {
+
+ /* utility functions implementing the matrix transform to/from sector space */
+
+ static inline void buffer_to_sector(int x, int y, int &u, int &v)
+ {
+ u = x * fxx + y * fyx;
+ v = x * fxy + y * fyy;
+ }
+
+ static inline void buffer_to_sector(float x, float y, float &u, float &v)
+ {
+ u = x * fxx + y * fyx;
+ v = x * fxy + y * fyy;
+ }
+
+ static inline void sector_to_buffer(int u, int v, int &x, int &y)
+ {
+ x = u * fxx + v * fxy;
+ y = u * fyx + v * fyy;
+ }
+
+ static inline void sector_to_buffer(float u, float v, float &x, float &y)
+ {
+ x = u * fxx + v * fxy;
+ y = u * fyx + v * fyy;
+ }
+
+ /**
+ * Set up the initial buffer pointer and calculate necessary variables for looping.
+ *
+ * Note that sector space is centered around the "source" point while the loop starts
+ * at dist_min from the target pt. This way the loop can be canceled as soon as it runs
+ * out of the buffer rect, because no pixels further along the line can contribute.
+ *
+ * \param x, y Start location in the buffer
+ * \param num Total steps in the loop
+ * \param v, dv Vertical offset in sector space, for line offset perpendicular to the loop axis
+ */
+ static float *init_buffer_iterator(MemoryBuffer *input, const float source[2], const float pt_ofs[2],
+ float dist_min, float dist_max,
+ int &x, int &y, int &num, float &v, float &dv)
+ {
+ float pu, pv;
+ buffer_to_sector(pt_ofs[0], pt_ofs[1], pu, pv);
+
+ /* line angle */
+ float tan_phi = pv / pu;
+ float cos_phi = 1.0f / sqrtf(tan_phi * tan_phi + 1.0f);
+
+ float umin = pu - cos_phi * dist_min;
+ float umax = pu - cos_phi * dist_max;
+ v = umin * tan_phi;
+ dv = tan_phi;
+
+ sector_to_buffer(umin, v, x, y);
+ x += source[0];
+ y += source[1];
+
+ num = (int)ceilf(umin) - max_ii((int)floorf(umax), 1);
+
+ float *iter = input->getBuffer() + COM_NUMBER_OF_CHANNELS * (x + input->getWidth() * y);
+ return iter;
+ }
+
+ /**
+ * Perform the actual accumulation along a ray segment from source to pt.
+ * Only pixels withing dist_min..dist_max contribute.
+ *
+ * The loop runs backwards(!) over the primary sector space axis u, i.e. increasing distance to pt.
+ * After each step it decrements v by dv < 1, adding a buffer shift when necessary.
+ */
+ static void eval(MemoryBuffer *input, float output[4], const float pt_ofs[2], const float source[2],
+ float dist_min, float dist_max)
+ {
+ rcti rect = *input->getRect();
+ int buffer_width = input->getWidth();
+ int x, y, num;
+ float v, dv;
+
+ /* initialise the iteration variables */
+ float *buffer = init_buffer_iterator(input, source, pt_ofs, dist_min, dist_max, x, y, num, v, dv);
+
+ float falloff_factor = num > 1 ? 1.0f / (float)(num - 1) : 0.0f;
+
+ int tot = 0;
+
+ /* v_local keeps track of when to decrement v (see below) */
+ float v_local = v - floorf(v);
+
+ for (int i = 0; i < num; i++) {
+ /* range check, abort when running beyond the image border */
+ if (x < rect.xmin || x >= rect.xmax || y < rect.ymin || y >= rect.ymax)
+ break;
+
+ float f = 1.0f - (float)i * falloff_factor;
+ madd_v4_v4fl(output, buffer, buffer[3] * f * f);
+ /* TODO implement proper filtering here, see
+ * http://en.wikipedia.org/wiki/Lanczos_resampling
+ * http://en.wikipedia.org/wiki/Sinc_function
+ *
+ * using lanczos with x = distance from the line segment,
+ * normalized to a == 0.5f, could give a good result
+ *
+ * for now just count samples and divide equally at the end ...
+ */
+ tot++;
+
+ /* decrement u */
+ x -= fxx;
+ y -= fyx;
+ buffer -= (fxx + fyx * buffer_width) * COM_NUMBER_OF_CHANNELS;
+
+ /* decrement v (in steps of dv < 1) */
+ v_local -= dv;
+ if (v_local < 0.0f) {
+ v_local += 1.0f;
+
+ x -= fxy;
+ y -= fyy;
+ buffer -= (fxy + fyy * buffer_width) * COM_NUMBER_OF_CHANNELS;
+ }
+ }
+
+ /* normalize */
+ if (num > 0) {
+ mul_v4_fl(output, 1.0f / (float)num);
+ }
+ }
+};
+
+/**
+ * Dispatch function which selects an appropriate accumulator based on the sector of the target point,
+ * relative to the source.
+ *
+ * The BufferLineAccumulator defines the actual loop over the buffer, with an efficient inner loop
+ * due to using compile time constants instead of a local matrix variable defining the sector space.
+ */
+static void accumulate_line(MemoryBuffer *input, float output[4], const float co[2], const float source[2],
+ float dist_min, float dist_max)
+{
+ /* coordinates relative to source */
+ float pt_ofs[2] = {co[0] - source[0], co[1] - source[1]};
+
+ /* The source sectors are defined like so:
+ *
+ * \ 3 | 2 /
+ * \ | /
+ * 4 \ | / 1
+ * \|/
+ * -----------
+ * /|\
+ * 5 / | \ 8
+ * / | \
+ * / 6 | 7 \
+ *
+ * The template arguments encode the transformation into "sector space",
+ * by means of rotation/mirroring matrix elements.
+ */
+
+ if (fabsf(pt_ofs[1]) > fabsf(pt_ofs[0])) {
+ if (pt_ofs[0] > 0.0f) {
+ if (pt_ofs[1] > 0.0f) {
+ /* 2 */
+ BufferLineAccumulator<0, 1, 1, 0>::eval(input, output, pt_ofs, source, dist_min, dist_max);
+ }
+ else {
+ /* 7 */
+ BufferLineAccumulator<0, 1, -1, 0>::eval(input, output, pt_ofs, source, dist_min, dist_max);
+ }
+ }
+ else {
+ if (pt_ofs[1] > 0.0f) {
+ /* 3 */
+ BufferLineAccumulator<0, -1, 1, 0>::eval(input, output, pt_ofs, source, dist_min, dist_max);
+ }
+ else {
+ /* 6 */
+ BufferLineAccumulator<0, -1, -1, 0>::eval(input, output, pt_ofs, source, dist_min, dist_max);
+ }
+ }
+ }
+ else {
+ if (pt_ofs[0] > 0.0f) {
+ if (pt_ofs[1] > 0.0f) {
+ /* 1 */
+ BufferLineAccumulator< 1, 0, 0, 1>::eval(input, output, pt_ofs, source, dist_min, dist_max);
+ }
+ else {
+ /* 8 */
+ BufferLineAccumulator< 1, 0, 0, -1>::eval(input, output, pt_ofs, source, dist_min, dist_max);
+ }
+ }
+ else {
+ if (pt_ofs[1] > 0.0f) {
+ /* 4 */
+ BufferLineAccumulator<-1, 0, 0, 1>::eval(input, output, pt_ofs, source, dist_min, dist_max);
+ }
+ else {
+ /* 5 */
+ BufferLineAccumulator<-1, 0, 0, -1>::eval(input, output, pt_ofs, source, dist_min, dist_max);
+ }
+ }
+ }
+}
+
+void *SunBeamsOperation::initializeTileData(rcti *rect)
+{
+ void *buffer = getInputOperation(0)->initializeTileData(NULL);
+ return buffer;
+}
+
+void SunBeamsOperation::executePixel(float output[4], int x, int y, void *data)
+{
+ const float co[2] = {(float)x, (float)y};
+
+ accumulate_line((MemoryBuffer *)data, output, co, this->m_source_px, 0.0f, this->m_ray_length_px);
+}
+
+static void calc_ray_shift(rcti *rect, float x, float y, const float source[2], float ray_length)
+{
+ float co[2] = {x, y};
+ float dir[2], dist;
+
+ /* move (x,y) vector toward the source by ray_length distance */
+ sub_v2_v2v2(dir, co, source);
+ dist = normalize_v2(dir);
+ mul_v2_fl(dir, min_ff(dist, ray_length));
+ sub_v2_v2(co, dir);
+
+ int ico[2] = {(int)co[0], (int)co[1]};
+ BLI_rcti_do_minmax_v(rect, ico);
+}
+
+bool SunBeamsOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output)
+{
+ /* Enlarges the rect by moving each corner toward the source.
+ * This is the maximum distance that pixels can influence each other
+ * and gives a rect that contains all possible accumulated pixels.
+ */
+ rcti rect = *input;
+ calc_ray_shift(&rect, input->xmin, input->ymin, this->m_source_px, this->m_ray_length_px);
+ calc_ray_shift(&rect, input->xmin, input->ymax, this->m_source_px, this->m_ray_length_px);
+ calc_ray_shift(&rect, input->xmax, input->ymin, this->m_source_px, this->m_ray_length_px);
+ calc_ray_shift(&rect, input->xmax, input->ymax, this->m_source_px, this->m_ray_length_px);
+
+ return NodeOperation::determineDependingAreaOfInterest(&rect, readOperation, output);
+}
+
diff --git a/source/blender/compositor/operations/COM_SunBeamsOperation.h b/source/blender/compositor/operations/COM_SunBeamsOperation.h
new file mode 100644
index 00000000000..ef80a31fe40
--- /dev/null
+++ b/source/blender/compositor/operations/COM_SunBeamsOperation.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2014, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor:
+ * Lukas Toenne
+ */
+
+#ifndef _COM_SunBeamsOperation_h
+#define _COM_SunBeamsOperation_h
+
+#include "COM_NodeOperation.h"
+
+class SunBeamsOperation : public NodeOperation {
+public:
+ SunBeamsOperation();
+
+ void executePixel(float output[4], int x, int y, void *data);
+
+ void initExecution();
+
+ void *initializeTileData(rcti *rect);
+
+ bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output);
+
+ void setData(const NodeSunBeams &data) { m_data = data; }
+
+private:
+ NodeSunBeams m_data;
+
+ float m_source_px[2];
+ float m_ray_length_px;
+};
+
+#endif
diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c
index 3530857266d..7d8e278f0cf 100644
--- a/source/blender/editors/animation/anim_channels_defines.c
+++ b/source/blender/editors/animation/anim_channels_defines.c
@@ -3846,7 +3846,7 @@ void ANIM_channel_draw_widgets(bContext *C, bAnimContext *ac, bAnimListElem *ale
short offset;
/* sanity checks - don't draw anything */
- if (ELEM3(NULL, acf, ale, block))
+ if (ELEM(NULL, acf, ale, block))
return;
/* get initial offset */
diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c
index 9997cc07c19..b6ab0407711 100644
--- a/source/blender/editors/animation/anim_channels_edit.c
+++ b/source/blender/editors/animation/anim_channels_edit.c
@@ -605,7 +605,7 @@ static int animedit_poll_channels_active(bContext *C)
if (ELEM(NULL, sa, CTX_wm_region(C)))
return 0;
/* animation editor test */
- if (ELEM3(sa->spacetype, SPACE_ACTION, SPACE_IPO, SPACE_NLA) == 0)
+ if (ELEM(sa->spacetype, SPACE_ACTION, SPACE_IPO, SPACE_NLA) == 0)
return 0;
return 1;
@@ -622,7 +622,7 @@ static int animedit_poll_channels_nla_tweakmode_off(bContext *C)
if (ELEM(NULL, sa, CTX_wm_region(C)))
return 0;
/* animation editor test */
- if (ELEM3(sa->spacetype, SPACE_ACTION, SPACE_IPO, SPACE_NLA) == 0)
+ if (ELEM(sa->spacetype, SPACE_ACTION, SPACE_IPO, SPACE_NLA) == 0)
return 0;
/* NLA TweakMode test */
@@ -901,10 +901,10 @@ static void rearrange_animchannels_filter_visible(ListBase *anim_data_visible, b
{
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale, *ale_next;
- int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
+ int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
/* get all visible channels */
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+ ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* now, only keep the ones that are of the types we are interested in */
for (ale = anim_data.first; ale; ale = ale_next) {
@@ -2257,7 +2257,7 @@ static int animchannels_find_poll(bContext *C)
return 0;
/* animation editor with dopesheet */
- return ELEM3(sa->spacetype, SPACE_ACTION, SPACE_IPO, SPACE_NLA);
+ return ELEM(sa->spacetype, SPACE_ACTION, SPACE_IPO, SPACE_NLA);
}
/* find_invoke() - Get initial channels */
@@ -2802,7 +2802,7 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index,
/* deselect all other channels */
ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, false, ACHANNEL_SETFLAG_CLEAR);
- if (pchan) ED_pose_deselectall(ob, 0);
+ if (pchan) ED_pose_de_selectall(ob, SEL_DESELECT, false);
/* only select channels in group and group itself */
for (fcu = agrp->channels.first; fcu && fcu->grp == agrp; fcu = fcu->next)
@@ -2812,7 +2812,7 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index,
else {
/* select group by itself */
ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, false, ACHANNEL_SETFLAG_CLEAR);
- if (pchan) ED_pose_deselectall(ob, 0);
+ if (pchan) ED_pose_de_selectall(ob, SEL_DESELECT, false);
agrp->flag |= AGRP_SELECTED;
}
diff --git a/source/blender/editors/animation/anim_deps.c b/source/blender/editors/animation/anim_deps.c
index 640349199be..f3b47b168e9 100644
--- a/source/blender/editors/animation/anim_deps.c
+++ b/source/blender/editors/animation/anim_deps.c
@@ -193,7 +193,7 @@ static void animchan_sync_fcurve(bAnimContext *ac, bAnimListElem *ale, FCurve **
/* major priority is selection status, so refer to the checks done in anim_filter.c
* skip_fcurve_selected_data() for reference about what's going on here...
*/
- if (ELEM3(NULL, fcu, fcu->rna_path, owner_id))
+ if (ELEM(NULL, fcu, fcu->rna_path, owner_id))
return;
if (GS(owner_id->name) == ID_OB) {
diff --git a/source/blender/editors/animation/anim_ipo_utils.c b/source/blender/editors/animation/anim_ipo_utils.c
index d3e6d8f474f..57df6d32f03 100644
--- a/source/blender/editors/animation/anim_ipo_utils.c
+++ b/source/blender/editors/animation/anim_ipo_utils.c
@@ -63,7 +63,7 @@ int getname_anim_fcurve(char *name, ID *id, FCurve *fcu)
/* sanity checks */
if (name == NULL)
return icon;
- else if (ELEM3(NULL, id, fcu, fcu->rna_path)) {
+ else if (ELEM(NULL, id, fcu, fcu->rna_path)) {
if (fcu == NULL)
strcpy(name, IFACE_("<invalid>"));
else if (fcu->rna_path == NULL)
diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c
index e519fc8bfef..a133bc49a69 100644
--- a/source/blender/editors/animation/anim_markers.c
+++ b/source/blender/editors/animation/anim_markers.c
@@ -204,7 +204,7 @@ void ED_markers_get_minmax(ListBase *markers, short sel, float *first, float *la
/* sanity check */
//printf("markers = %p - %p, %p\n", markers, markers->first, markers->last);
- if (ELEM3(NULL, markers, markers->first, markers->last)) {
+ if (ELEM(NULL, markers, markers->first, markers->last)) {
*first = 0.0f;
*last = 0.0f;
return;
@@ -1012,14 +1012,14 @@ static void select_timeline_marker_frame(ListBase *markers, int frame, bool exte
}
}
- LISTBASE_CIRCULAR_FORWARD_BEGIN (markers, marker, marker_first) {
+ BLI_LISTBASE_CIRCULAR_FORWARD_BEGIN (markers, marker, marker_first) {
/* this way a not-extend select will allways give 1 selected marker */
if (marker->frame == frame) {
marker->flag ^= SELECT;
break;
}
}
- LISTBASE_CIRCULAR_FORWARD_END (markers, marker, marker_first);
+ BLI_LISTBASE_CIRCULAR_FORWARD_END (markers, marker, marker_first);
}
static int ed_marker_select(bContext *C, const wmEvent *event, bool extend, bool camera)
diff --git a/source/blender/editors/animation/anim_ops.c b/source/blender/editors/animation/anim_ops.c
index 88429aa3867..620bd52e527 100644
--- a/source/blender/editors/animation/anim_ops.c
+++ b/source/blender/editors/animation/anim_ops.c
@@ -72,7 +72,7 @@ static int change_frame_poll(bContext *C)
* this shouldn't show up in 3D editor (or others without 2D timeline view) via search
*/
if (sa) {
- if (ELEM5(sa->spacetype, SPACE_TIME, SPACE_ACTION, SPACE_NLA, SPACE_SEQ, SPACE_CLIP)) {
+ if (ELEM(sa->spacetype, SPACE_TIME, SPACE_ACTION, SPACE_NLA, SPACE_SEQ, SPACE_CLIP)) {
return true;
}
else if (sa->spacetype == SPACE_IPO) {
diff --git a/source/blender/editors/animation/keyframes_edit.c b/source/blender/editors/animation/keyframes_edit.c
index ee5039488bd..83593faff22 100644
--- a/source/blender/editors/animation/keyframes_edit.c
+++ b/source/blender/editors/animation/keyframes_edit.c
@@ -670,8 +670,8 @@ static short snap_bezier_horizontal(KeyframeEditData *UNUSED(ked), BezTriple *be
if (bezt->f2 & SELECT) {
bezt->vec[0][1] = bezt->vec[2][1] = bezt->vec[1][1];
- if (ELEM3(bezt->h1, HD_AUTO, HD_AUTO_ANIM, HD_VECT)) bezt->h1 = HD_ALIGN;
- if (ELEM3(bezt->h2, HD_AUTO, HD_AUTO_ANIM, HD_VECT)) bezt->h2 = HD_ALIGN;
+ if (ELEM(bezt->h1, HD_AUTO, HD_AUTO_ANIM, HD_VECT)) bezt->h1 = HD_ALIGN;
+ if (ELEM(bezt->h2, HD_AUTO, HD_AUTO_ANIM, HD_VECT)) bezt->h2 = HD_ALIGN;
}
return 0;
}
@@ -810,9 +810,9 @@ KeyframeEditFunc ANIM_editkeyframes_mirror(short type)
*/
#define ENSURE_HANDLES_MATCH(bezt) \
if (bezt->h1 != bezt->h2) { \
- if (ELEM3(bezt->h1, HD_ALIGN, HD_AUTO, HD_AUTO_ANIM)) \
+ if (ELEM(bezt->h1, HD_ALIGN, HD_AUTO, HD_AUTO_ANIM)) \
bezt->h1 = HD_FREE; \
- if (ELEM3(bezt->h2, HD_ALIGN, HD_AUTO, HD_AUTO_ANIM)) \
+ if (ELEM(bezt->h2, HD_ALIGN, HD_AUTO, HD_AUTO_ANIM)) \
bezt->h2 = HD_FREE; \
} (void)0
diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c
index 878c9193b23..a68751e9294 100644
--- a/source/blender/editors/animation/keyframing.c
+++ b/source/blender/editors/animation/keyframing.c
@@ -652,7 +652,7 @@ static bool visualkey_can_use(PointerRNA *ptr, PropertyRNA *prop)
const char *identifier = NULL;
/* validate data */
- if (ELEM3(NULL, ptr, ptr->data, prop))
+ if (ELEM(NULL, ptr, ptr->data, prop))
return 0;
/* get first constraint and determine type of keyframe constraints to check for
@@ -1042,7 +1042,7 @@ short insert_keyframe(ReportList *reports, ID *id, bAction *act, const char grou
/* for Loc/Rot/Scale and also Color F-Curves, the color of the F-Curve in the Graph Editor,
* is determined by the array index for the F-Curve
*/
- if (ELEM5(RNA_property_subtype(prop), PROP_TRANSLATION, PROP_XYZ, PROP_EULER, PROP_COLOR, PROP_COORDS)) {
+ if (ELEM(RNA_property_subtype(prop), PROP_TRANSLATION, PROP_XYZ, PROP_EULER, PROP_COLOR, PROP_COORDS)) {
fcu->color_mode = FCURVE_COLOR_AUTO_RGB;
}
}
diff --git a/source/blender/editors/armature/CMakeLists.txt b/source/blender/editors/armature/CMakeLists.txt
index ca2dc1b66e2..9aa17f1e503 100644
--- a/source/blender/editors/armature/CMakeLists.txt
+++ b/source/blender/editors/armature/CMakeLists.txt
@@ -26,6 +26,7 @@ set(INC
../../makesdna
../../makesrna
../../windowmanager
+ ../../gpu
../../../../intern/guardedalloc
)
diff --git a/source/blender/editors/armature/SConscript b/source/blender/editors/armature/SConscript
index b3c1ea2dbe9..c68045c9398 100644
--- a/source/blender/editors/armature/SConscript
+++ b/source/blender/editors/armature/SConscript
@@ -39,6 +39,7 @@ incs = [
'../../blenlib',
'../../makesdna',
'../../makesrna',
+ '../../gpu',
'../../windowmanager',
]
incs = ' '.join(incs)
diff --git a/source/blender/editors/armature/armature_edit.c b/source/blender/editors/armature/armature_edit.c
index f71cfd52175..1e4d9bac246 100644
--- a/source/blender/editors/armature/armature_edit.c
+++ b/source/blender/editors/armature/armature_edit.c
@@ -1343,7 +1343,9 @@ static int armature_reveal_exec(bContext *C, wmOperator *UNUSED(op))
for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
if (arm->layer & ebone->layer) {
if (ebone->flag & BONE_HIDDEN_A) {
- ebone->flag |= (BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
+ if (!(ebone->flag & BONE_UNSELECTABLE)) {
+ ebone->flag |= (BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
+ }
ebone->flag &= ~BONE_HIDDEN_A;
}
}
diff --git a/source/blender/editors/armature/armature_select.c b/source/blender/editors/armature/armature_select.c
index 9c3c93e4850..12d13b05ee1 100644
--- a/source/blender/editors/armature/armature_select.c
+++ b/source/blender/editors/armature/armature_select.c
@@ -160,7 +160,7 @@ void *get_nearest_bone(bContext *C, short findunsel, int x, int y)
rect.ymin = rect.ymax = y;
glInitNames();
- hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect);
+ hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect, true);
if (hits > 0)
return get_bone_from_selectbuffer(vc.scene, vc.scene->basact, buffer, hits, findunsel);
@@ -295,13 +295,13 @@ static EditBone *get_nearest_editbonepoint(ViewContext *vc, const int mval[2],
rect.ymin = mval[1] - 5;
rect.ymax = mval[1] + 5;
- hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect);
+ hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect, true);
if (hits == 0) {
rect.xmin = mval[0] - 12;
rect.xmax = mval[0] + 12;
rect.ymin = mval[1] - 12;
rect.ymax = mval[1] + 12;
- hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect);
+ hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect, true);
}
/* See if there are any selected bones in this group */
if (hits > 0) {
diff --git a/source/blender/editors/armature/armature_skinning.c b/source/blender/editors/armature/armature_skinning.c
index e898e600e9b..57ae03ccebe 100644
--- a/source/blender/editors/armature/armature_skinning.c
+++ b/source/blender/editors/armature/armature_skinning.c
@@ -200,10 +200,22 @@ static void envelope_bone_weighting(Object *ob, Mesh *mesh, float (*verts)[3], i
float distance;
int i, iflip, j;
bool use_topology = (mesh->editflag & ME_EDIT_MIRROR_TOPO) != 0;
+ bool use_mask = false;
+
+ if ((ob->mode & OB_MODE_WEIGHT_PAINT) &&
+ (mesh->editflag & (ME_EDIT_PAINT_FACE_SEL | ME_EDIT_PAINT_VERT_SEL)))
+ {
+ use_mask = true;
+ }
/* for each vertex in the mesh */
for (i = 0; i < mesh->totvert; i++) {
- iflip = (dgroupflip) ? mesh_get_x_mirror_vert(ob, i, use_topology) : 0;
+
+ if (use_mask && !(mesh->mvert[i].flag & SELECT)) {
+ continue;
+ }
+
+ iflip = (dgroupflip) ? mesh_get_x_mirror_vert(ob, i, use_topology) : -1;
/* for each skinnable bone */
for (j = 0; j < numbones; ++j) {
@@ -224,7 +236,7 @@ static void envelope_bone_weighting(Object *ob, Mesh *mesh, float (*verts)[3], i
ED_vgroup_vert_remove(ob, dgroup, i);
/* do same for mirror */
- if (dgroupflip && dgroupflip[j] && iflip >= 0) {
+ if (dgroupflip && dgroupflip[j] && iflip != -1) {
if (distance != 0.0f)
ED_vgroup_vert_add(ob, dgroupflip[j], iflip, distance,
WEIGHT_REPLACE);
diff --git a/source/blender/editors/armature/editarmature_sketch.c b/source/blender/editors/armature/editarmature_sketch.c
index 475ffd23617..ba105325b97 100644
--- a/source/blender/editors/armature/editarmature_sketch.c
+++ b/source/blender/editors/armature/editarmature_sketch.c
@@ -53,6 +53,8 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "GPU_select.h"
+
typedef int (*GestureDetectFct)(bContext *, SK_Gesture *, SK_Sketch *);
typedef void (*GestureApplyFct)(bContext *, SK_Gesture *, SK_Sketch *);
@@ -493,7 +495,7 @@ static void sk_drawStroke(SK_Stroke *stk, int id, float color[3], int start, int
gluQuadricNormals(quad, GLU_SMOOTH);
if (id != -1) {
- glLoadName(id);
+ GPU_select_load_id(id);
for (i = 0; i < stk->nb_points; i++) {
glPushMatrix();
@@ -1969,7 +1971,7 @@ static int sk_selectStroke(bContext *C, SK_Sketch *sketch, const int mval[2], in
rect.ymin = mval[1] - 5;
rect.ymax = mval[1] + 5;
- hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect);
+ hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect, true);
if (hits > 0) {
int besthitresult = -1;
@@ -2032,7 +2034,7 @@ static void sk_drawSketch(Scene *scene, View3D *UNUSED(v3d), SK_Sketch *sketch,
sk_drawStroke(stk, id, NULL, -1, -1);
}
- glLoadName(-1);
+ GPU_select_load_id(-1);
}
else {
float selected_rgb[3] = {1, 0, 0};
diff --git a/source/blender/editors/armature/meshlaplacian.c b/source/blender/editors/armature/meshlaplacian.c
index 56e7bde0081..49650fcadbf 100644
--- a/source/blender/editors/armature/meshlaplacian.c
+++ b/source/blender/editors/armature/meshlaplacian.c
@@ -635,8 +635,8 @@ void heat_bone_weighting(Object *ob, Mesh *me, float (*verts)[3], int numsource,
bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
MVert *mvert = me->mvert;
- bool use_vert_sel = false;
- bool use_face_sel = false;
+ bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
+ bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
*err_str = NULL;
@@ -652,9 +652,8 @@ void heat_bone_weighting(Object *ob, Mesh *me, float (*verts)[3], int numsource,
return;
/* count triangles and create mask */
- if (ob->mode == OB_MODE_WEIGHT_PAINT &&
- ((use_face_sel = ((me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0)) ||
- (use_vert_sel = ((me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0))))
+ if (ob->mode & OB_MODE_WEIGHT_PAINT &&
+ (use_face_sel || use_vert_sel))
{
mask = MEM_callocN(sizeof(int) * me->totvert, "heat_bone_weighting mask");
diff --git a/source/blender/editors/armature/pose_edit.c b/source/blender/editors/armature/pose_edit.c
index 890bf6649b9..da68108285f 100644
--- a/source/blender/editors/armature/pose_edit.c
+++ b/source/blender/editors/armature/pose_edit.c
@@ -1074,7 +1074,9 @@ static int show_pose_bone_cb(Object *ob, Bone *bone, void *UNUSED(ptr))
if (arm->layer & bone->layer) {
if (bone->flag & BONE_HIDDEN_P) {
bone->flag &= ~BONE_HIDDEN_P;
- bone->flag |= BONE_SELECTED;
+ if (!(bone->flag & BONE_UNSELECTABLE)) {
+ bone->flag |= BONE_SELECTED;
+ }
}
}
diff --git a/source/blender/editors/armature/pose_lib.c b/source/blender/editors/armature/pose_lib.c
index 6762ffc17b2..0609fcc29e8 100644
--- a/source/blender/editors/armature/pose_lib.c
+++ b/source/blender/editors/armature/pose_lib.c
@@ -307,7 +307,7 @@ static int poselib_sanitize_exec(bContext *C, wmOperator *op)
/* check if any pose matches this */
/* TODO: don't go looking through the list like this every time... */
for (marker = act->markers.first; marker; marker = marker->next) {
- if (IS_EQ(marker->frame, (double)ak->cfra)) {
+ if (IS_EQ((double)marker->frame, (double)ak->cfra)) {
marker->flag = -1;
break;
}
@@ -1417,7 +1417,7 @@ static void poselib_preview_init_data(bContext *C, wmOperator *op)
pld->marker = (pld->act) ? BLI_findlink(&pld->act->markers, pose_index) : NULL;
/* check if valid poselib */
- if (ELEM3(NULL, pld->ob, pld->pose, pld->arm)) {
+ if (ELEM(NULL, pld->ob, pld->pose, pld->arm)) {
BKE_report(op->reports, RPT_ERROR, "Pose lib is only for armatures in pose mode");
pld->state = PL_PREVIEW_ERROR;
return;
diff --git a/source/blender/editors/armature/pose_select.c b/source/blender/editors/armature/pose_select.c
index aa741ef9aaf..76284ba44de 100644
--- a/source/blender/editors/armature/pose_select.c
+++ b/source/blender/editors/armature/pose_select.c
@@ -69,6 +69,29 @@
/* ***************** Pose Select Utilities ********************* */
+/* Note: SEL_TOGGLE is assumed to have already been handled! */
+static void pose_do_bone_select(bPoseChannel *pchan, const int select_mode)
+{
+ /* select pchan only if selectable, but deselect works always */
+ switch (select_mode) {
+ case SEL_SELECT:
+ if (!(pchan->bone->flag & BONE_UNSELECTABLE))
+ pchan->bone->flag |= BONE_SELECTED;
+ break;
+ case SEL_DESELECT:
+ pchan->bone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ break;
+ case SEL_INVERT:
+ if (pchan->bone->flag & BONE_SELECTED) {
+ pchan->bone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ }
+ else if (!(pchan->bone->flag & BONE_UNSELECTABLE)) {
+ pchan->bone->flag |= BONE_SELECTED;
+ }
+ break;
+ }
+}
+
/* Utility method for changing the selection status of a bone */
void ED_pose_bone_select(Object *ob, bPoseChannel *pchan, bool select)
{
@@ -76,7 +99,7 @@ void ED_pose_bone_select(Object *ob, bPoseChannel *pchan, bool select)
/* sanity checks */
// XXX: actually, we can probably still get away with no object - at most we have no updates
- if (ELEM4(NULL, ob, ob->pose, pchan, pchan->bone))
+ if (ELEM(NULL, ob, ob->pose, pchan, pchan->bone))
return;
arm = ob->data;
@@ -139,7 +162,7 @@ int ED_do_pose_selectbuffer(Scene *scene, Base *base, unsigned int *buffer, shor
}
if (!extend && !deselect && !toggle) {
- ED_pose_deselectall(ob, 0);
+ ED_pose_de_selectall(ob, SEL_DESELECT, true);
nearBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
arm->act_bone = nearBone;
}
@@ -191,16 +214,12 @@ int ED_do_pose_selectbuffer(Scene *scene, Base *base, unsigned int *buffer, shor
return nearBone != NULL;
}
-/* test==0: deselect all
- * test==1: swap select (apply to all the opposite of current situation)
- * test==2: only clear active tag
- * test==3: swap select (no test / inverse selection status of all independently)
- */
-void ED_pose_deselectall(Object *ob, int test)
+/* 'select_mode' is usual SEL_SELECT/SEL_DESELECT/SEL_TOGGLE/SEL_INVERT.
+ * When true, 'ignore_visibility' makes this func also affect invisible bones (hidden or on hidden layers). */
+void ED_pose_de_selectall(Object *ob, int select_mode, const bool ignore_visibility)
{
bArmature *arm = ob->data;
bPoseChannel *pchan;
- int selectmode = 0;
/* we call this from outliner too */
if (ob->pose == NULL) {
@@ -208,31 +227,23 @@ void ED_pose_deselectall(Object *ob, int test)
}
/* Determine if we're selecting or deselecting */
- if (test == 1) {
+ if (select_mode == SEL_TOGGLE) {
+ select_mode = SEL_SELECT;
for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- if (PBONE_VISIBLE(arm, pchan->bone)) {
- if (pchan->bone->flag & BONE_SELECTED)
+ if (ignore_visibility || PBONE_VISIBLE(arm, pchan->bone)) {
+ if (pchan->bone->flag & BONE_SELECTED) {
+ select_mode = SEL_DESELECT;
break;
+ }
}
}
-
- if (pchan == NULL)
- selectmode = 1;
}
- else if (test == 2)
- selectmode = 2;
- /* Set the flags accordingly */
+ /* Set the flags accordingly */
for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
/* ignore the pchan if it isn't visible or if its selection cannot be changed */
- if ((pchan->bone->layer & arm->layer) && !(pchan->bone->flag & (BONE_HIDDEN_P | BONE_UNSELECTABLE))) {
- if (test == 3) {
- pchan->bone->flag ^= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- }
- else {
- if (selectmode == 0) pchan->bone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- else if (selectmode == 1) pchan->bone->flag |= BONE_SELECTED;
- }
+ if (ignore_visibility || PBONE_VISIBLE(arm, pchan->bone)) {
+ pose_do_bone_select(pchan, select_mode);
}
}
}
@@ -353,24 +364,7 @@ static int pose_de_select_all_exec(bContext *C, wmOperator *op)
/* Set the flags */
CTX_DATA_BEGIN(C, bPoseChannel *, pchan, visible_pose_bones)
{
- /* select pchan only if selectable, but deselect works always */
- switch (action) {
- case SEL_SELECT:
- if ((pchan->bone->flag & BONE_UNSELECTABLE) == 0)
- pchan->bone->flag |= BONE_SELECTED;
- break;
- case SEL_DESELECT:
- pchan->bone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- break;
- case SEL_INVERT:
- if (pchan->bone->flag & BONE_SELECTED) {
- pchan->bone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
- }
- else if ((pchan->bone->flag & BONE_UNSELECTABLE) == 0) {
- pchan->bone->flag |= BONE_SELECTED;
- }
- break;
- }
+ pose_do_bone_select(pchan, action);
}
CTX_DATA_END;
@@ -644,7 +638,7 @@ static bool pose_select_same_group(bContext *C, Object *ob, bool extend)
bool changed = false, tagged = false;
/* sanity checks */
- if (ELEM3(NULL, ob, pose, arm))
+ if (ELEM(NULL, ob, pose, arm))
return 0;
/* count the number of groups */
@@ -701,7 +695,7 @@ static bool pose_select_same_layer(bContext *C, Object *ob, bool extend)
bool changed = false;
int layers = 0;
- if (ELEM3(NULL, ob, pose, arm))
+ if (ELEM(NULL, ob, pose, arm))
return 0;
/* figure out what bones are selected */
@@ -761,7 +755,7 @@ static bool pose_select_same_keyingset(bContext *C, ReportList *reports, Object
return false;
}
- if (ELEM3(NULL, ob, pose, arm))
+ if (ELEM(NULL, ob, pose, arm))
return false;
/* if not extending selection, deselect all selected first */
diff --git a/source/blender/editors/armature/pose_slide.c b/source/blender/editors/armature/pose_slide.c
index 375cbb0fe2b..5f9f24d23a4 100644
--- a/source/blender/editors/armature/pose_slide.c
+++ b/source/blender/editors/armature/pose_slide.c
@@ -134,7 +134,7 @@ static int pose_slide_init(bContext *C, wmOperator *op, short mode)
pso->nextFrame = RNA_int_get(op->ptr, "next_frame");
/* check the settings from the context */
- if (ELEM4(NULL, pso->ob, pso->arm, pso->ob->adt, pso->ob->adt->action))
+ if (ELEM(NULL, pso->ob, pso->arm, pso->ob->adt, pso->ob->adt->action))
return 0;
else
act = pso->ob->adt->action;
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
index 11c8b11e31d..b0371b8dd6c 100644
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@ -7019,7 +7019,7 @@ static int match_texture_space_poll(bContext *C)
{
Object *object = CTX_data_active_object(C);
- return object && ELEM3(object->type, OB_CURVE, OB_SURF, OB_FONT);
+ return object && ELEM(object->type, OB_CURVE, OB_SURF, OB_FONT);
}
static int match_texture_space_exec(bContext *C, wmOperator *UNUSED(op))
diff --git a/source/blender/editors/datafiles/CMakeLists.txt b/source/blender/editors/datafiles/CMakeLists.txt
index 3fc6e2e6f0d..2a84ca7f297 100644
--- a/source/blender/editors/datafiles/CMakeLists.txt
+++ b/source/blender/editors/datafiles/CMakeLists.txt
@@ -93,6 +93,8 @@ if(WITH_BLENDER)
data_to_c_simple(../../../../release/datafiles/brushicons/soften.png SRC)
data_to_c_simple(../../../../release/datafiles/brushicons/subtract.png SRC)
data_to_c_simple(../../../../release/datafiles/brushicons/texdraw.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/texfill.png SRC)
+ data_to_c_simple(../../../../release/datafiles/brushicons/texmask.png SRC)
data_to_c_simple(../../../../release/datafiles/brushicons/thumb.png SRC)
data_to_c_simple(../../../../release/datafiles/brushicons/twist.png SRC)
data_to_c_simple(../../../../release/datafiles/brushicons/vertexdraw.png SRC)
diff --git a/source/blender/editors/datafiles/SConscript b/source/blender/editors/datafiles/SConscript
index 47819d0e33c..6bc8f21e384 100644
--- a/source/blender/editors/datafiles/SConscript
+++ b/source/blender/editors/datafiles/SConscript
@@ -77,6 +77,8 @@ sources.extend((
os.path.join(env['DATA_SOURCES'], "soften.png.c"),
os.path.join(env['DATA_SOURCES'], "subtract.png.c"),
os.path.join(env['DATA_SOURCES'], "texdraw.png.c"),
+ os.path.join(env['DATA_SOURCES'], "texfill.png.c"),
+ os.path.join(env['DATA_SOURCES'], "texmask.png.c"),
os.path.join(env['DATA_SOURCES'], "thumb.png.c"),
os.path.join(env['DATA_SOURCES'], "twist.png.c"),
os.path.join(env['DATA_SOURCES'], "vertexdraw.png.c"),
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index b725f5c773a..6e17be04623 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -1412,7 +1412,7 @@ static void gp_layer_to_curve(bContext *C, ReportList *reports, bGPdata *gpd, bG
rctf subrect, *subrect_ptr = NULL;
/* error checking */
- if (ELEM3(NULL, gpd, gpl, gpf))
+ if (ELEM(NULL, gpd, gpl, gpf))
return;
/* only convert if there are any strokes on this layer's frame to convert */
diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c
index 4910396ac6f..afecdd91599 100644
--- a/source/blender/editors/gpencil/gpencil_paint.c
+++ b/source/blender/editors/gpencil/gpencil_paint.c
@@ -1861,7 +1861,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* we don't pass on key events, GP is used with key-modifiers - prevents Dkey to insert drivers */
if (ISKEYBOARD(event->type)) {
- if (ELEM4(event->type, LEFTARROWKEY, DOWNARROWKEY, RIGHTARROWKEY, UPARROWKEY)) {
+ if (ELEM(event->type, LEFTARROWKEY, DOWNARROWKEY, RIGHTARROWKEY, UPARROWKEY)) {
/* allow some keys - for frame changing: [#33412] */
}
else {
@@ -1874,7 +1874,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* exit painting mode (and/or end current stroke)
* NOTE: cannot do RIGHTMOUSE (as is standard for canceling) as that would break polyline [#32647]
*/
- if (ELEM4(event->type, RETKEY, PADENTER, ESCKEY, SPACEKEY)) {
+ if (ELEM(event->type, RETKEY, PADENTER, ESCKEY, SPACEKEY)) {
/* exit() ends the current stroke before cleaning up */
/* printf("\t\tGP - end of paint op + end of stroke\n"); */
p->status = GP_STATUS_DONE;
@@ -1949,7 +1949,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
/* eraser size */
else if ((p->paintmode == GP_PAINTMODE_ERASER) &&
- ELEM4(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE, PADPLUSKEY, PADMINUS))
+ ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE, PADPLUSKEY, PADMINUS))
{
/* just resize the brush (local version)
* TODO: fix the hardcoded size jumps (set to make a visible difference) and hardcoded keys
diff --git a/source/blender/editors/include/BIF_gl.h b/source/blender/editors/include/BIF_gl.h
index 477a7c0ce17..9fa603966b6 100644
--- a/source/blender/editors/include/BIF_gl.h
+++ b/source/blender/editors/include/BIF_gl.h
@@ -58,8 +58,24 @@
* */
void cpack(unsigned int x);
-#define glMultMatrixf(x) glMultMatrixf( (float *)(x))
-#define glLoadMatrixf(x) glLoadMatrixf( (float *)(x))
+
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
+# define glMultMatrixf(x) \
+ glMultMatrixf(_Generic((x), \
+ float *: (float *)(x), \
+ float (*)[4]: (float *)(x), \
+ const float *: (float *)(x), \
+ const float (*)[4]: (float *)(x)) \
+)
+# define glLoadMatrixf(x) \
+ glLoadMatrixf(_Generic((x), \
+ float *: (float *)(x), \
+ float (*)[4]: (float *)(x)) \
+)
+#else
+# define glMultMatrixf(x) glMultMatrixf((float *)(x))
+# define glLoadMatrixf(x) glLoadMatrixf((float *)(x))
+#endif
#define GLA_PIXEL_OFS 0.375f
diff --git a/source/blender/editors/include/ED_armature.h b/source/blender/editors/include/ED_armature.h
index 7579f6cba65..f6a1b493fac 100644
--- a/source/blender/editors/include/ED_armature.h
+++ b/source/blender/editors/include/ED_armature.h
@@ -174,7 +174,7 @@ void ED_armature_ebone_selectflag_disable(EditBone *ebone, int flag);
/* poseobject.c */
void ED_armature_exit_posemode(struct bContext *C, struct Base *base);
void ED_armature_enter_posemode(struct bContext *C, struct Base *base);
-void ED_pose_deselectall(struct Object *ob, int test);
+void ED_pose_de_selectall(struct Object *ob, int select_mode, const bool ignore_visibility);
void ED_pose_bone_select(struct Object *ob, struct bPoseChannel *pchan, bool select);
void ED_pose_recalculate_paths(struct Scene *scene, struct Object *ob);
struct Object *ED_pose_object_from_context(struct bContext *C);
diff --git a/source/blender/editors/include/ED_datafiles.h b/source/blender/editors/include/ED_datafiles.h
index 9022a1481aa..661ab58b98c 100644
--- a/source/blender/editors/include/ED_datafiles.h
+++ b/source/blender/editors/include/ED_datafiles.h
@@ -150,6 +150,12 @@ extern char datatoc_subtract_png[];
extern int datatoc_texdraw_png_size;
extern char datatoc_texdraw_png[];
+extern int datatoc_texfill_png_size;
+extern char datatoc_texfill_png[];
+
+extern int datatoc_texmask_png_size;
+extern char datatoc_texmask_png[];
+
extern int datatoc_thumb_png_size;
extern char datatoc_thumb_png[];
diff --git a/source/blender/editors/include/ED_image.h b/source/blender/editors/include/ED_image.h
index b15a83809f5..db13c628ade 100644
--- a/source/blender/editors/include/ED_image.h
+++ b/source/blender/editors/include/ED_image.h
@@ -69,8 +69,11 @@ void ED_image_point_pos__reverse(struct SpaceImage *sima, struct ARegion *ar, co
bool ED_space_image_show_render(struct SpaceImage *sima);
bool ED_space_image_show_paint(struct SpaceImage *sima);
bool ED_space_image_show_uvedit(struct SpaceImage *sima, struct Object *obedit);
+bool ED_space_image_show_texpaint(struct SpaceImage *sima, struct Object *ob);
bool ED_space_image_show_uvshadow(struct SpaceImage *sima, struct Object *obedit);
+bool ED_space_image_paint_curve(const struct bContext *C);
+
bool ED_space_image_check_show_maskedit(struct Scene *scene, struct SpaceImage *sima);
int ED_space_image_maskedit_poll(struct bContext *C);
int ED_space_image_maskedit_mask_poll(struct bContext *C);
diff --git a/source/blender/editors/include/ED_paint.h b/source/blender/editors/include/ED_paint.h
index d7e84d8f50d..decd79fcc7b 100644
--- a/source/blender/editors/include/ED_paint.h
+++ b/source/blender/editors/include/ED_paint.h
@@ -28,9 +28,11 @@
struct bContext;
struct RegionView3D;
struct wmKeyConfig;
+struct wmOperator;
/* paint_ops.c */
void ED_operatortypes_paint(void);
+void ED_operatormacros_paint(void);
void ED_keymap_paint(struct wmKeyConfig *keyconf);
/* paint_undo.c */
@@ -41,6 +43,7 @@ enum {
typedef void (*UndoRestoreCb)(struct bContext *C, struct ListBase *lb);
typedef void (*UndoFreeCb)(struct ListBase *lb);
+typedef bool (*UndoCleanupCb)(struct bContext *C, struct ListBase *lb);
int ED_undo_paint_step(struct bContext *C, int type, int step, const char *name);
void ED_undo_paint_step_num(struct bContext *C, int type, int num);
@@ -48,7 +51,7 @@ const char *ED_undo_paint_get_name(struct bContext *C, int type, int nr, int *ac
void ED_undo_paint_free(void);
int ED_undo_paint_valid(int type, const char *name);
bool ED_undo_paint_empty(int type);
-void ED_undo_paint_push_begin(int type, const char *name, UndoRestoreCb restore, UndoFreeCb free);
+void ED_undo_paint_push_begin(int type, const char *name, UndoRestoreCb restore, UndoFreeCb free, UndoCleanupCb cleanup);
void ED_undo_paint_push_end(int type);
/* paint_image.c */
@@ -57,5 +60,6 @@ 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_bucket_fill(struct bContext *C, float color[3], struct wmOperator *op);
#endif /* __ED_PAINT_H__ */
diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h
index 41ff9b88da9..daa6864b5aa 100644
--- a/source/blender/editors/include/ED_transform.h
+++ b/source/blender/editors/include/ED_transform.h
@@ -98,6 +98,7 @@ enum TfmMode {
#define CTX_NDOF (1 << 5)
#define CTX_MOVIECLIP (1 << 6)
#define CTX_MASK (1 << 7)
+#define CTX_PAINT_CURVE (1 << 8)
/* Standalone call to get the transformation center corresponding to the current situation
* returns 1 if successful, 0 otherwise (usually means there's no selection)
diff --git a/source/blender/editors/include/ED_uvedit.h b/source/blender/editors/include/ED_uvedit.h
index 04eb829979f..4b82fa40c6a 100644
--- a/source/blender/editors/include/ED_uvedit.h
+++ b/source/blender/editors/include/ED_uvedit.h
@@ -54,7 +54,7 @@ void ED_uvedit_assign_image(struct Main *bmain, struct Scene *scene, struct Obje
bool ED_uvedit_minmax(struct Scene *scene, struct Image *ima, struct Object *obedit, float min[2], float max[2]);
bool ED_object_get_active_image(struct Object *ob, int mat_nr,
- struct Image **r_ima, struct ImageUser **r_iuser, struct bNode **r_node);
+ struct Image **r_ima, struct ImageUser **r_iuser, struct bNode **r_node, struct bNodeTree **r_ntree);
void ED_object_assign_active_image(struct Main *bmain, struct Object *ob, int mat_nr, struct Image *ima);
bool ED_uvedit_test(struct Object *obedit);
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index 76839747076..dceede7a540 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -56,6 +56,7 @@ struct bContext;
struct bPoseChannel;
struct bScreen;
struct bglMats;
+struct rctf;
struct rcti;
struct wmOperator;
struct wmOperatorType;
@@ -84,6 +85,7 @@ typedef struct ViewDepths {
float *ED_view3d_cursor3d_get(struct Scene *scene, struct View3D *v3d);
void ED_view3d_cursor3d_position(struct bContext *C, float fp[3], const int mval[2]);
+void ED_view3d_cursor3d_update(struct bContext *C, const int mval[2]);
struct Camera *ED_view3d_camera_data_get(struct View3D *v3d, struct RegionView3D *rv3d);
@@ -269,7 +271,7 @@ bool ED_view3d_autodist_depth_seg(struct ARegion *ar, const int mval_sta[2], con
/* select */
#define MAXPICKBUF 10000
-short view3d_opengl_select(struct ViewContext *vc, unsigned int *buffer, unsigned int bufsize, const rcti *input);
+short view3d_opengl_select(struct ViewContext *vc, unsigned int *buffer, unsigned int bufsize, const struct rcti *input, bool do_nearest);
/* view3d_select.c */
float ED_view3d_select_dist_px(void);
@@ -364,6 +366,6 @@ void ED_view3d_operator_properties_viewmat_get(struct wmOperator *op, int *winx,
#endif
/* render */
-void ED_view3d_shade_update(struct Main *bmain, struct View3D *v3d, struct ScrArea *sa);
+void ED_view3d_shade_update(struct Main *bmain, struct Scene *scene, struct View3D *v3d, struct ScrArea *sa);
#endif /* __ED_VIEW3D_H__ */
diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h
index 904c14f0573..f1b544f269b 100644
--- a/source/blender/editors/include/UI_icons.h
+++ b/source/blender/editors/include/UI_icons.h
@@ -978,6 +978,8 @@ DEF_ICON(BRUSH_SNAKE_HOOK)
DEF_ICON(BRUSH_SOFTEN)
DEF_ICON(BRUSH_SUBTRACT)
DEF_ICON(BRUSH_TEXDRAW)
+DEF_ICON(BRUSH_TEXFILL)
+DEF_ICON(BRUSH_TEXMASK)
DEF_ICON(BRUSH_THUMB)
DEF_ICON(BRUSH_ROTATE)
DEF_ICON(BRUSH_VERTEXDRAW)
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 1565583b574..d7b4f753810 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -75,6 +75,9 @@ struct ImBuf;
struct bNodeTree;
struct bNode;
struct bNodeSocket;
+struct wmDropBox;
+struct wmDrag;
+struct wmEvent;
typedef struct uiBut uiBut;
typedef struct uiBlock uiBlock;
@@ -175,6 +178,7 @@ enum {
UI_BUT_DRAG_MULTI = (1 << 25), /* edit this button as well as the active button (not just dragging) */
UI_BUT_SCA_LINK_GREY = (1 << 26), /* used to flag if sca links shoud be grey out */
UI_BUT_HAS_SEP_CHAR = (1 << 27), /* but->str contains UI_SEP_CHAR, used for key shortcuts */
+ UI_OPTION_TOOLTIPS = (1 << 28), /* force show tooltips when holding option/alt if U's USER_TOOLTIPS is off */
};
#define UI_PANEL_WIDTH 340
@@ -288,6 +292,9 @@ typedef enum {
#define UI_GRAD_V_ALT 9
#define UI_GRAD_L_ALT 10
+#define UI_PALETTE_COLOR 20
+#define UI_PALETTE_COLOR_ACTIVE 1
+
/* Drawing
*
* Functions to draw various shapes, taking theme settings into account.
@@ -437,6 +444,7 @@ void uiButSetDragValue(uiBut *but);
void uiButSetDragImage(uiBut *but, const char *path, int icon, struct ImBuf *ima, float scale);
bool UI_but_active_drop_name(struct bContext *C);
+bool UI_but_active_drop_color(struct bContext *C);
void uiButSetFlag(uiBut *but, int flag);
void uiButClearFlag(uiBut *but, int flag);
@@ -708,7 +716,6 @@ void UI_remove_popup_handlers_all(struct bContext *C, struct ListBase *handlers)
void UI_init(void);
void UI_init_userdef(void);
-void UI_init_userdef_factory(void);
void UI_reinit_font(void);
void UI_exit(void);
@@ -847,6 +854,7 @@ void uiTemplateVectorscope(uiLayout *layout, struct PointerRNA *ptr, const char
void uiTemplateCurveMapping(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int type,
int levels, int brush, int neg_slope);
void uiTemplateColorPicker(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int value_slider, int lock, int lock_luminosity, int cubic);
+void uiTemplatePalette(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int color);
void uiTemplateLayers(uiLayout *layout, struct PointerRNA *ptr, const char *propname,
PointerRNA *used_ptr, const char *used_propname, int active_layer);
void uiTemplateGameStates(uiLayout *layout, struct PointerRNA *ptr, const char *propname,
@@ -916,7 +924,14 @@ void uiItemMenuEnumO(uiLayout *layout, struct bContext *C, const char *opname, c
void uiItemMenuEnumR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *name, int icon);
/* UI Operators */
+typedef struct uiDragColorHandle {
+ float color[3];
+ bool gamma_corrected;
+} uiDragColorHandle;
+
void UI_buttons_operatortypes(void);
+void UI_drop_color_copy(struct wmDrag *drag, struct wmDropBox *drop);
+int UI_drop_color_poll(struct bContext *C, struct wmDrag *drag, const struct wmEvent *event);
/* Helpers for Operators */
uiBut *uiContextActiveButton(const struct bContext *C);
diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h
index 2e78940a813..da365355e95 100644
--- a/source/blender/editors/include/UI_resources.h
+++ b/source/blender/editors/include/UI_resources.h
@@ -237,6 +237,9 @@ enum {
TH_STITCH_PREVIEW_UNSTITCHABLE,
TH_STITCH_PREVIEW_ACTIVE,
+ TH_PAINT_CURVE_HANDLE,
+ TH_PAINT_CURVE_PIVOT,
+
TH_UV_SHADOW,
TH_UV_OTHERS,
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index c857150782e..0a45ffc4c13 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -830,7 +830,7 @@ static void ui_menu_block_set_keyaccels(uiBlock *block)
* fun first pass on all buttons so first word chars always get first priority */
for (but = block->buttons.first; but; but = but->next) {
- if (!ELEM5(but->type, BUT, BUTM, MENU, BLOCK, PULLDOWN) || (but->flag & UI_HIDDEN)) {
+ if (!ELEM(but->type, BUT, BUTM, MENU, BLOCK, PULLDOWN) || (but->flag & UI_HIDDEN)) {
/* pass */
}
else if (but->menu_key == '\0') {
@@ -1320,7 +1320,7 @@ int ui_is_but_push_ex(uiBut *but, double *value)
int is_push = 0;
if (but->bit) {
- const bool state = ELEM3(but->type, TOGN, ICONTOGN, OPTIONN) ? false : true;
+ const bool state = ELEM(but->type, TOGN, ICONTOGN, OPTIONN) ? false : true;
int lvalue;
UI_GET_BUT_VALUE_INIT(but, *value);
lvalue = (int)*value;
@@ -1630,7 +1630,7 @@ bool ui_is_but_float(const uiBut *but)
bool ui_is_but_bool(const uiBut *but)
{
- if (ELEM4(but->type, TOG, TOGN, ICONTOG, ICONTOGN))
+ if (ELEM(but->type, TOG, TOGN, ICONTOG, ICONTOGN))
return true;
if (but->rnaprop && RNA_property_type(but->rnaprop) == PROP_BOOLEAN)
@@ -1843,7 +1843,7 @@ void ui_set_but_val(uiBut *but, double value)
int ui_get_but_string_max_length(uiBut *but)
{
- if (ELEM3(but->type, TEX, SEARCH_MENU, SEARCH_MENU_UNLINK))
+ if (ELEM(but->type, TEX, SEARCH_MENU, SEARCH_MENU_UNLINK))
return but->hardmax;
else
return UI_MAX_DRAW_STR;
@@ -1958,7 +1958,7 @@ static float ui_get_but_step_unit(uiBut *but, float step_default)
*/
void ui_get_but_string_ex(uiBut *but, char *str, const size_t maxlen, const int float_precision)
{
- if (but->rnaprop && ELEM3(but->type, TEX, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
+ if (but->rnaprop && ELEM(but->type, TEX, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
PropertyType type;
const char *buf = NULL;
int buf_len;
@@ -2095,7 +2095,7 @@ bool ui_set_but_string_eval_num(bContext *C, uiBut *but, const char *str, double
bool ui_set_but_string(bContext *C, uiBut *but, const char *str)
{
- if (but->rnaprop && ELEM3(but->type, TEX, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
+ if (but->rnaprop && ELEM(but->type, TEX, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
if (RNA_property_editable(&but->rnapoin, but->rnaprop)) {
PropertyType type;
@@ -2747,7 +2747,7 @@ void uiBlockEndAlign(uiBlock *block)
bool ui_but_can_align(uiBut *but)
{
- return !ELEM5(but->type, LABEL, OPTION, OPTIONN, SEPR, SEPRLINE);
+ return !ELEM(but->type, LABEL, OPTION, OPTIONN, SEPR, SEPRLINE);
}
static void ui_block_do_align_but(uiBut *first, short nr)
@@ -3029,7 +3029,7 @@ static uiBut *ui_def_but(uiBlock *block, int type, int retval, const char *str,
}
if ((block->flag & UI_BLOCK_LOOP) ||
- ELEM8(but->type, MENU, TEX, LABEL, BLOCK, BUTM, SEARCH_MENU, PROGRESSBAR, SEARCH_MENU_UNLINK))
+ ELEM(but->type, MENU, TEX, LABEL, BLOCK, BUTM, SEARCH_MENU, PROGRESSBAR, SEARCH_MENU_UNLINK))
{
but->drawflag |= (UI_BUT_TEXT_LEFT | UI_BUT_ICON_LEFT);
}
@@ -3048,7 +3048,7 @@ static uiBut *ui_def_but(uiBlock *block, int type, int retval, const char *str,
}
/* keep track of UI_interface.h */
- if (ELEM11(but->type, BLOCK, BUT, LABEL, PULLDOWN, ROUNDBOX, LISTBOX, BUTM, SCROLL, SEPR, SEPRLINE, GRIP)) {}
+ if (ELEM(but->type, BLOCK, BUT, LABEL, PULLDOWN, ROUNDBOX, LISTBOX, BUTM, SCROLL, SEPR, SEPRLINE, GRIP)) {}
else if (but->type >= SEARCH_MENU) {}
else but->flag |= UI_BUT_UNDO;
@@ -3213,12 +3213,12 @@ static uiBut *ui_def_but_rna(uiBlock *block, int type, int retval, const char *s
int icon = 0;
uiMenuCreateFunc func = NULL;
- if (ELEM3(type, COLOR, HSVCIRCLE, HSVCUBE)) {
+ if (ELEM(type, COLOR, HSVCIRCLE, HSVCUBE)) {
BLI_assert(index == -1);
}
/* use rna values if parameters are not specified */
- if ((proptype == PROP_ENUM) && ELEM3(type, MENU, ROW, LISTROW)) {
+ if ((proptype == PROP_ENUM) && ELEM(type, MENU, ROW, LISTROW)) {
/* MENU is handled a little differently here */
EnumPropertyItem *item;
int value;
@@ -3811,9 +3811,6 @@ void uiBlockFlipOrder(uiBlock *block)
but->rect.ymax = centy - (but->rect.ymax - centy);
SWAP(float, but->rect.ymin, but->rect.ymax);
}
-
- /* also flip order in block itself, for example for arrowkey */
- BLI_listbase_reverse(&block->buttons);
}
@@ -4339,7 +4336,7 @@ void uiButGetStrInfo(bContext *C, uiBut *but, ...)
}
tmp = BLI_strdup(_tmp);
}
- else if (ELEM3(type, BUT_GET_RNAENUM_IDENTIFIER, BUT_GET_RNAENUM_LABEL, BUT_GET_RNAENUM_TIP)) {
+ else if (ELEM(type, BUT_GET_RNAENUM_IDENTIFIER, BUT_GET_RNAENUM_LABEL, BUT_GET_RNAENUM_TIP)) {
PointerRNA *ptr = NULL;
PropertyRNA *prop = NULL;
int value = 0;
@@ -4429,11 +4426,6 @@ void UI_init_userdef(void)
uiStyleInit();
}
-void UI_init_userdef_factory(void)
-{
- init_userdef_factory();
-}
-
void UI_reinit_font(void)
{
uiStyleInit();
diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c
index f821aab8c4d..15b8494cb34 100644
--- a/source/blender/editors/interface/interface_draw.c
+++ b/source/blender/editors/interface/interface_draw.c
@@ -695,11 +695,11 @@ void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol),
}
/* RGB / YCC (3 channels) */
- else if (ELEM4(scopes->wavefrm_mode,
- SCOPES_WAVEFRM_RGB,
- SCOPES_WAVEFRM_YCC_601,
- SCOPES_WAVEFRM_YCC_709,
- SCOPES_WAVEFRM_YCC_JPEG))
+ else if (ELEM(scopes->wavefrm_mode,
+ SCOPES_WAVEFRM_RGB,
+ SCOPES_WAVEFRM_YCC_601,
+ SCOPES_WAVEFRM_YCC_709,
+ SCOPES_WAVEFRM_YCC_JPEG))
{
int rgb = (scopes->wavefrm_mode == SCOPES_WAVEFRM_RGB);
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index d37660a0611..68148d30136 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -38,6 +38,7 @@
#include "MEM_guardedalloc.h"
+#include "DNA_brush_types.h"
#include "DNA_sensor_types.h"
#include "DNA_controller_types.h"
#include "DNA_actuator_types.h"
@@ -60,6 +61,7 @@
#include "PIL_time.h"
#include "BKE_blender.h"
+#include "BKE_brush.h"
#include "BKE_colortools.h"
#include "BKE_context.h"
#include "BKE_idprop.h"
@@ -383,16 +385,16 @@ void ui_pan_to_scroll(const wmEvent *event, int *type, int *val)
}
}
-static bool ui_but_editable(uiBut *but)
+bool ui_but_is_editable(const uiBut *but)
{
- return ELEM6(but->type, LABEL, SEPR, SEPRLINE, ROUNDBOX, LISTBOX, PROGRESSBAR);
+ return !ELEM(but->type, LABEL, SEPR, SEPRLINE, ROUNDBOX, LISTBOX, PROGRESSBAR);
}
static uiBut *ui_but_prev(uiBut *but)
{
while (but->prev) {
but = but->prev;
- if (!ui_but_editable(but)) return but;
+ if (ui_but_is_editable(but)) return but;
}
return NULL;
}
@@ -401,7 +403,7 @@ static uiBut *ui_but_next(uiBut *but)
{
while (but->next) {
but = but->next;
- if (!ui_but_editable(but)) return but;
+ if (ui_but_is_editable(but)) return but;
}
return NULL;
}
@@ -412,7 +414,7 @@ static uiBut *ui_but_first(uiBlock *block)
but = block->buttons.first;
while (but) {
- if (!ui_but_editable(but)) return but;
+ if (ui_but_is_editable(but)) return but;
but = but->next;
}
return NULL;
@@ -424,7 +426,7 @@ static uiBut *ui_but_last(uiBlock *block)
but = block->buttons.last;
while (but) {
- if (!ui_but_editable(but)) return but;
+ if (ui_but_is_editable(but)) return but;
but = but->prev;
}
return NULL;
@@ -433,7 +435,7 @@ static uiBut *ui_but_last(uiBlock *block)
static bool ui_is_a_warp_but(uiBut *but)
{
if (U.uiflag & USER_CONTINUOUS_MOUSE) {
- if (ELEM6(but->type, NUM, NUMSLI, HSVCIRCLE, TRACKPREVIEW, HSVCUBE, BUT_CURVE)) {
+ if (ELEM(but->type, NUM, NUMSLI, HSVCIRCLE, TRACKPREVIEW, HSVCUBE, BUT_CURVE)) {
return true;
}
}
@@ -463,7 +465,7 @@ bool ui_is_but_utf8(const uiBut *but)
{
if (but->rnaprop) {
const int subtype = RNA_property_subtype(but->rnaprop);
- return !(ELEM4(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME, PROP_BYTESTRING));
+ return !(ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME, PROP_BYTESTRING));
}
else {
return !(but->flag & UI_BUT_NO_UTF8);
@@ -717,7 +719,7 @@ static void ui_apply_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data)
if (value == 0.0) push = 1;
else push = 0;
- if (ELEM3(but->type, TOGN, ICONTOGN, OPTIONN)) push = !push;
+ if (ELEM(but->type, TOGN, ICONTOGN, OPTIONN)) push = !push;
ui_set_but_val(but, (double)push);
if (but->type == ICONTOG || but->type == ICONTOGN) ui_check_but(but);
}
@@ -1189,7 +1191,7 @@ static bool ui_but_mouse_inside_icon(uiBut *but, ARegion *ar, const wmEvent *eve
BLI_rcti_rctf_copy(&rect, &but->rect);
- if (but->imb) {
+ if (but->imb || but->type == COLOR) {
/* use button size itself */
}
else if (but->drawflag & UI_BUT_ICON_LEFT) {
@@ -1242,10 +1244,42 @@ static bool ui_but_start_drag(bContext *C, uiBut *but, uiHandleButtonData *data,
}
else
#endif
- {
+ if (but->type == COLOR) {
+ bool valid = false;
+ uiDragColorHandle *drag_info = MEM_callocN(sizeof(*drag_info), __func__);
+
+ /* TODO support more button pointer types */
+ if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) {
+ RNA_property_float_get_array(&but->rnapoin, but->rnaprop, drag_info->color);
+ drag_info->gamma_corrected = true;
+ valid = true;
+ }
+ else if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR) {
+ RNA_property_float_get_array(&but->rnapoin, but->rnaprop, drag_info->color);
+ drag_info->gamma_corrected = false;
+ valid = true;
+ }
+ else if (but->pointype == UI_BUT_POIN_FLOAT) {
+ copy_v3_v3(drag_info->color, (float *)but->poin);
+ valid = true;
+ }
+ else if (but->pointype == UI_BUT_POIN_CHAR) {
+ rgb_uchar_to_float(drag_info->color, (unsigned char *)but->poin);
+ valid = true;
+ }
+
+ if (valid) {
+ WM_event_start_drag(C, ICON_COLOR, WM_DRAG_COLOR, drag_info, 0.0, WM_DRAG_FREE_DATA);
+ }
+ else {
+ MEM_freeN(drag_info);
+ return false;
+ }
+ }
+ else {
wmDrag *drag;
- drag = WM_event_start_drag(C, but->icon, but->dragtype, but->dragpoin, ui_get_but_val(but));
+ drag = WM_event_start_drag(C, but->icon, but->dragtype, but->dragpoin, ui_get_but_val(but), WM_DRAG_NOP);
if (but->imb)
WM_event_drag_image(drag, but->imb, but->imb_scale, BLI_rctf_size_x(&but->rect), BLI_rctf_size_y(&but->rect));
}
@@ -1655,7 +1689,7 @@ static void ui_but_drop(bContext *C, const wmEvent *event, uiBut *but, uiHandleB
for (wmd = drags->first; wmd; wmd = wmd->next) {
if (wmd->type == WM_DRAG_ID) {
/* align these types with UI_but_active_drop_name */
- if (ELEM3(but->type, TEX, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
+ if (ELEM(but->type, TEX, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
ID *id = (ID *)wmd->poin;
button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
@@ -1802,7 +1836,7 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data,
}
/* text/string and ID data */
- else if (ELEM3(but->type, TEX, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
+ else if (ELEM(but->type, TEX, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
uiHandleButtonData *active_data = but->active;
if (but->poin == NULL && but->rnapoin.data == NULL) {
@@ -2009,7 +2043,7 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, con
BLI_strncpy(origstr, but->editstr, data->maxlen);
- if (ELEM3(but->type, TEX, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
+ if (ELEM(but->type, TEX, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
if (but->flag & UI_HAS_ICON) {
startx += UI_DPI_ICON_SIZE / aspect;
}
@@ -2461,11 +2495,11 @@ static void ui_textedit_next_but(uiBlock *block, uiBut *actbut, uiHandleButtonDa
uiBut *but;
/* label and roundbox can overlap real buttons (backdrops...) */
- if (ELEM5(actbut->type, LABEL, SEPR, SEPRLINE, ROUNDBOX, LISTBOX))
+ if (ELEM(actbut->type, LABEL, SEPR, SEPRLINE, ROUNDBOX, LISTBOX))
return;
for (but = actbut->next; but; but = but->next) {
- if (ELEM5(but->type, TEX, NUM, NUMSLI, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
+ if (ELEM(but->type, TEX, NUM, NUMSLI, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
if (!(but->flag & UI_BUT_DISABLED)) {
data->postbut = but;
data->posttype = BUTTON_ACTIVATE_TEXT_EDITING;
@@ -2474,7 +2508,7 @@ static void ui_textedit_next_but(uiBlock *block, uiBut *actbut, uiHandleButtonDa
}
}
for (but = block->buttons.first; but != actbut; but = but->next) {
- if (ELEM5(but->type, TEX, NUM, NUMSLI, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
+ if (ELEM(but->type, TEX, NUM, NUMSLI, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
if (!(but->flag & UI_BUT_DISABLED)) {
data->postbut = but;
data->posttype = BUTTON_ACTIVATE_TEXT_EDITING;
@@ -2489,11 +2523,11 @@ static void ui_textedit_prev_but(uiBlock *block, uiBut *actbut, uiHandleButtonDa
uiBut *but;
/* label and roundbox can overlap real buttons (backdrops...) */
- if (ELEM5(actbut->type, LABEL, SEPR, SEPRLINE, ROUNDBOX, LISTBOX))
+ if (ELEM(actbut->type, LABEL, SEPR, SEPRLINE, ROUNDBOX, LISTBOX))
return;
for (but = actbut->prev; but; but = but->prev) {
- if (ELEM5(but->type, TEX, NUM, NUMSLI, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
+ if (ELEM(but->type, TEX, NUM, NUMSLI, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
if (!(but->flag & UI_BUT_DISABLED)) {
data->postbut = but;
data->posttype = BUTTON_ACTIVATE_TEXT_EDITING;
@@ -2502,7 +2536,7 @@ static void ui_textedit_prev_but(uiBlock *block, uiBut *actbut, uiHandleButtonDa
}
}
for (but = block->buttons.last; but != actbut; but = but->prev) {
- if (ELEM5(but->type, TEX, NUM, NUMSLI, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
+ if (ELEM(but->type, TEX, NUM, NUMSLI, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
if (!(but->flag & UI_BUT_DISABLED)) {
data->postbut = but;
data->posttype = BUTTON_ACTIVATE_TEXT_EDITING;
@@ -2803,7 +2837,7 @@ static void ui_numedit_begin(uiBut *but, uiHandleButtonData *data)
data->coba = (ColorBand *)but->poin;
but->editcoba = data->coba;
}
- else if (ELEM4(but->type, BUT_NORMAL, HSVCUBE, HSVCIRCLE, COLOR)) {
+ else if (ELEM(but->type, BUT_NORMAL, HSVCUBE, HSVCIRCLE, COLOR)) {
ui_get_but_vectorf(but, data->origvec);
copy_v3_v3(data->vec, data->origvec);
but->editvec = data->vec;
@@ -2990,7 +3024,7 @@ static int ui_do_but_BUT(bContext *C, uiBut *but, uiHandleButtonData *data, cons
static int ui_do_but_HOTKEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
if (data->state == BUTTON_STATE_HIGHLIGHT) {
- if (ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
+ if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
but->drawstr[0] = 0;
but->modifier_key = 0;
button_activate_state(C, but, BUTTON_STATE_WAIT_KEY_EVENT);
@@ -3053,7 +3087,7 @@ static int ui_do_but_HOTKEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data
static int ui_do_but_KEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
if (data->state == BUTTON_STATE_HIGHLIGHT) {
- if (ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
+ if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
button_activate_state(C, but, BUTTON_STATE_WAIT_KEY_EVENT);
return WM_UI_HANDLER_BREAK;
}
@@ -3078,7 +3112,7 @@ static int ui_do_but_KEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data, c
static int ui_do_but_TEX(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
if (data->state == BUTTON_STATE_HIGHLIGHT) {
- if (ELEM4(event->type, LEFTMOUSE, EVT_BUT_OPEN, PADENTER, RETKEY) && event->val == KM_PRESS) {
+ if (ELEM(event->type, LEFTMOUSE, EVT_BUT_OPEN, PADENTER, RETKEY) && event->val == KM_PRESS) {
if (ELEM(event->type, PADENTER, RETKEY) && (!ui_is_but_utf8(but))) {
/* pass - allow filesel, enter to execute */
}
@@ -3106,7 +3140,7 @@ 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)
{
/* unlink icon is on right */
- if (ELEM4(event->type, LEFTMOUSE, EVT_BUT_OPEN, PADENTER, RETKEY) && event->val == KM_PRESS &&
+ if (ELEM(event->type, LEFTMOUSE, EVT_BUT_OPEN, PADENTER, RETKEY) && event->val == KM_PRESS &&
ui_is_but_search_unlink_visible(but))
{
ARegion *ar = data->region;
@@ -3156,7 +3190,7 @@ static int ui_do_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data, cons
}
#endif
if (data->state == BUTTON_STATE_HIGHLIGHT) {
- if (ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
+ if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
#if 0 /* UNUSED */
data->togdual = event->ctrl;
data->togonly = !event->shift;
@@ -3194,7 +3228,7 @@ static int ui_do_but_EXIT(bContext *C, uiBut *but, uiHandleButtonData *data, con
}
#endif
- if (ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
+ if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
int ret = WM_UI_HANDLER_BREAK;
/* XXX (a bit ugly) Special case handling for filebrowser drag button */
if (but->dragpoin && but->imb && ui_but_mouse_inside_icon(but, data->region, event)) {
@@ -3243,7 +3277,7 @@ static float ui_numedit_apply_snapf(uiBut *but, float tempf, float softmin, floa
if (bUnit_IsValid(unit->system, unit_type)) {
fac = (float)bUnit_BaseScalar(unit->system, unit_type);
- if (ELEM3(unit_type, B_UNIT_LENGTH, B_UNIT_AREA, B_UNIT_VOLUME)) {
+ if (ELEM(unit_type, B_UNIT_LENGTH, B_UNIT_AREA, B_UNIT_VOLUME)) {
fac /= unit->scale_length;
}
}
@@ -3478,7 +3512,7 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
click = 1;
}
else if (event->val == KM_PRESS) {
- if (ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->ctrl) {
+ if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->ctrl) {
button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
retval = WM_UI_HANDLER_BREAK;
}
@@ -3767,7 +3801,7 @@ static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
click = 2;
}
else if (event->val == KM_PRESS) {
- if (ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->ctrl) {
+ if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->ctrl) {
button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
retval = WM_UI_HANDLER_BREAK;
}
@@ -4024,7 +4058,7 @@ static int ui_do_but_LISTROW(bContext *C, uiBut *but, uiHandleButtonData *data,
/* hack to pass on ctrl+click and double click to overlapping text
* editing field for editing list item names
*/
- if ((ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS && event->ctrl) ||
+ if ((ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS && event->ctrl) ||
(event->type == LEFTMOUSE && event->val == KM_DBL_CLICK))
{
uiBut *labelbut = ui_but_list_row_text_activate(C, but, data, event, BUTTON_ACTIVATE_TEXT_EDITING);
@@ -4053,7 +4087,7 @@ static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, co
}
}
#ifdef USE_DRAG_TOGGLE
- if (event->type == LEFTMOUSE && ui_is_but_drag_toggle(but)) {
+ if (event->type == LEFTMOUSE && event->val == KM_PRESS && (ui_is_but_drag_toggle(but))) {
button_activate_state(C, but, BUTTON_STATE_WAIT_DRAG);
data->dragstartx = event->x;
data->dragstarty = event->y;
@@ -4061,7 +4095,7 @@ static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, co
}
#endif
/* regular open menu */
- if (ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
+ if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
button_activate_state(C, but, BUTTON_STATE_MENU_OPEN);
return WM_UI_HANDLER_BREAK;
}
@@ -4206,11 +4240,29 @@ static bool ui_numedit_but_NORMAL(uiBut *but, uiHandleButtonData *data,
static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
if (data->state == BUTTON_STATE_HIGHLIGHT) {
- if (ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
+ /* first handle click on icondrag type button */
+ if (event->type == LEFTMOUSE && but->dragpoin && event->val == KM_PRESS) {
+ if (ui_but_mouse_inside_icon(but, data->region, event)) {
+ button_activate_state(C, but, BUTTON_STATE_WAIT_DRAG);
+ data->dragstartx = event->x;
+ data->dragstarty = event->y;
+ return WM_UI_HANDLER_BREAK;
+ }
+ }
+#ifdef USE_DRAG_TOGGLE
+ if (event->type == LEFTMOUSE && event->val == KM_PRESS) {
+ button_activate_state(C, but, BUTTON_STATE_WAIT_DRAG);
+ data->dragstartx = event->x;
+ data->dragstarty = event->y;
+ return WM_UI_HANDLER_BREAK;
+ }
+#endif
+ /* regular open menu */
+ if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
button_activate_state(C, but, BUTTON_STATE_MENU_OPEN);
return WM_UI_HANDLER_BREAK;
}
- else if (ELEM3(event->type, MOUSEPAN, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->alt) {
+ else if (ELEM(event->type, MOUSEPAN, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->alt) {
float *hsv = ui_block_hsv_get(but->block);
float col[3];
@@ -4233,6 +4285,81 @@ static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, co
ui_apply_button(C, but->block, but, data, true);
return WM_UI_HANDLER_BREAK;
}
+ else if ((int)(but->a1) == UI_PALETTE_COLOR &&
+ event->type == DELKEY && event->val == KM_PRESS)
+ {
+ Scene *scene = CTX_data_scene(C);
+ Paint *paint = BKE_paint_get_active(scene);
+ Palette *palette = BKE_paint_palette(paint);
+ PaletteColor *color = but->rnapoin.data;
+
+ BKE_palette_color_remove(palette, color);
+
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ return WM_UI_HANDLER_BREAK;
+ }
+ }
+ else if (data->state == BUTTON_STATE_WAIT_DRAG) {
+
+ /* this function also ends state */
+ if (ui_but_start_drag(C, but, data, event)) {
+ return WM_UI_HANDLER_BREAK;
+ }
+
+ /* outside icon quit, not needed if drag activated */
+ if (0 == ui_but_mouse_inside_icon(but, data->region, event)) {
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ data->cancel = true;
+ return WM_UI_HANDLER_BREAK;
+ }
+
+ if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
+ if ((int)(but->a1) == UI_PALETTE_COLOR) {
+ Palette *palette = but->rnapoin.id.data;
+ PaletteColor *color = but->rnapoin.data;
+ palette->active_color = BLI_findindex(&palette->colors, color);
+
+ if (!event->ctrl) {
+ float color[3];
+ Scene *scene = CTX_data_scene(C);
+ Paint *paint = BKE_paint_get_active(scene);
+ Brush *brush = BKE_paint_brush(paint);
+
+ if (brush->flag & BRUSH_USE_GRADIENT) {
+ float *target = &brush->gradient->data[brush->gradient->cur].r;
+
+ if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) {
+ RNA_property_float_get_array(&but->rnapoin, but->rnaprop, target);
+ ui_block_to_scene_linear_v3(but->block, target);
+ }
+ else if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR) {
+ RNA_property_float_get_array(&but->rnapoin, but->rnaprop, target);
+ }
+ }
+ else {
+ if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) {
+ RNA_property_float_get_array(&but->rnapoin, but->rnaprop, color);
+ BKE_brush_color_set(scene, brush, color);
+ }
+ else if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR) {
+ RNA_property_float_get_array(&but->rnapoin, but->rnaprop, color);
+ ui_block_to_display_space_v3(but->block, color);
+ BKE_brush_color_set(scene, brush, color);
+ }
+ }
+
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ else {
+ button_activate_state(C, but, BUTTON_STATE_MENU_OPEN);
+ }
+ }
+ else {
+ button_activate_state(C, but, BUTTON_STATE_MENU_OPEN);
+ }
+ return WM_UI_HANDLER_BREAK;
+ }
+
}
return WM_UI_HANDLER_CONTINUE;
@@ -4412,7 +4539,7 @@ static bool ui_numedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data,
}
if (snap != SNAP_OFF) {
- if (ELEM3((int)but->a1, UI_GRAD_HV, UI_GRAD_HS, UI_GRAD_H)) {
+ if (ELEM((int)but->a1, UI_GRAD_HV, UI_GRAD_HS, UI_GRAD_H)) {
ui_color_snap_hue(snap, &hsv[0]);
}
}
@@ -4489,7 +4616,7 @@ static void ui_ndofedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data,
}
if (snap != SNAP_OFF) {
- if (ELEM3((int)but->a1, UI_GRAD_HV, UI_GRAD_HS, UI_GRAD_H)) {
+ if (ELEM((int)but->a1, UI_GRAD_HV, UI_GRAD_HS, UI_GRAD_H)) {
ui_color_snap_hue(snap, &hsv[0]);
}
}
@@ -6012,7 +6139,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
}
/* handle drivers */
else if ((event->type == DKEY) &&
- !ELEM3(KM_MOD_FIRST, event->ctrl, event->oskey, event->shift) &&
+ !ELEM(KM_MOD_FIRST, event->ctrl, event->oskey, event->shift) &&
(event->val == KM_PRESS))
{
if (event->alt)
@@ -6026,7 +6153,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
}
/* handle keyingsets */
else if ((event->type == KKEY) &&
- !ELEM3(KM_MOD_FIRST, event->ctrl, event->oskey, event->shift) &&
+ !ELEM(KM_MOD_FIRST, event->ctrl, event->oskey, event->shift) &&
(event->val == KM_PRESS))
{
if (event->alt)
@@ -6250,7 +6377,7 @@ static bool ui_but_contains_pt(uiBut *but, float mx, float my)
return BLI_rctf_isect_pt(&but->rect, mx, my);
}
-static uiBut *ui_but_find_activated(ARegion *ar)
+uiBut *ui_but_find_activated(ARegion *ar)
{
uiBlock *block;
uiBut *but;
@@ -6298,13 +6425,27 @@ bool UI_but_active_drop_name(bContext *C)
uiBut *but = ui_but_find_activated(ar);
if (but) {
- if (ELEM3(but->type, TEX, SEARCH_MENU, SEARCH_MENU_UNLINK))
+ if (ELEM(but->type, TEX, SEARCH_MENU, SEARCH_MENU_UNLINK))
return 1;
}
return 0;
}
+bool UI_but_active_drop_color(bContext *C)
+{
+ ARegion *ar = CTX_wm_region(C);
+
+ if (ar) {
+ uiBut *but = ui_but_find_activated(ar);
+
+ if (but && but->type == COLOR)
+ return true;
+ }
+
+ return false;
+}
+
static void ui_blocks_set_tooltips(ARegion *ar, const bool enable)
{
uiBlock *block;
@@ -6378,7 +6519,7 @@ static bool ui_is_but_interactive(const uiBut *but, const bool labeledit)
/* note, LABEL is included for highlights, this allows drags */
if ((but->type == LABEL) && but->dragpoin == NULL)
return false;
- if (ELEM4(but->type, ROUNDBOX, SEPR, SEPRLINE, LISTBOX))
+ if (ELEM(but->type, ROUNDBOX, SEPR, SEPRLINE, LISTBOX))
return false;
if (but->flag & UI_HIDDEN)
return false;
@@ -6471,9 +6612,13 @@ static uiBut *ui_list_find_mouse_over(ARegion *ar, int x, int y)
static bool button_modal_state(uiHandleButtonState state)
{
- return ELEM6(state, BUTTON_STATE_WAIT_RELEASE, BUTTON_STATE_WAIT_KEY_EVENT,
- BUTTON_STATE_NUM_EDITING, BUTTON_STATE_TEXT_EDITING,
- BUTTON_STATE_TEXT_SELECTING, BUTTON_STATE_MENU_OPEN);
+ return ELEM(state,
+ BUTTON_STATE_WAIT_RELEASE,
+ BUTTON_STATE_WAIT_KEY_EVENT,
+ BUTTON_STATE_NUM_EDITING,
+ BUTTON_STATE_TEXT_EDITING,
+ BUTTON_STATE_TEXT_SELECTING,
+ BUTTON_STATE_MENU_OPEN);
}
static void button_timers_tooltip_remove(bContext *C, uiBut *but)
@@ -6511,7 +6656,7 @@ static void button_tooltip_timer_reset(bContext *C, uiBut *but)
data->tooltiptimer = NULL;
}
- if (U.flag & USER_TOOLTIPS)
+ if ((U.flag & USER_TOOLTIPS) || (but->flag & UI_OPTION_TOOLTIPS))
if (!but->block->tooltipdisabled)
if (!wm->drags.first)
data->tooltiptimer = WM_event_add_timer(data->wm, data->window, TIMER, BUTTON_TOOLTIP_DELAY);
@@ -6664,7 +6809,7 @@ static void button_activate_init(bContext *C, ARegion *ar, uiBut *but, uiButtonA
copy_v2_fl(data->ungrab_mval, FLT_MAX);
#endif
- if (ELEM3(but->type, BUT_CURVE, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
+ if (ELEM(but->type, BUT_CURVE, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
/* XXX curve is temp */
}
else {
@@ -7023,6 +7168,11 @@ static int ui_handle_button_over(bContext *C, const wmEvent *event, ARegion *ar)
if (event->type == MOUSEMOVE) {
but = ui_but_find_mouse_over(ar, event);
if (but) {
+ if (event->alt)
+ /* display tooltips if holding alt on mouseover when tooltips are off in prefs */
+ but->flag |= UI_OPTION_TOOLTIPS;
+ else
+ but->flag &= ~UI_OPTION_TOOLTIPS;
button_activate_init(C, ar, but, BUTTON_ACTIVATE_OVER);
}
}
@@ -7054,6 +7204,17 @@ void ui_button_activate_do(bContext *C, ARegion *ar, uiBut *but)
ui_do_button(C, but->block, but, &event);
}
+/**
+ * Simulate moving the mouse over a button (or navigating to it with arrow keys).
+ *
+ * exported so menus can start with a highlighted button,
+ * even if the mouse isnt over it
+ */
+void ui_button_activate_over(bContext *C, ARegion *ar, uiBut *but)
+{
+ button_activate_init(C, ar, but, BUTTON_ACTIVATE_OVER);
+}
+
void ui_button_execute_begin(struct bContext *UNUSED(C), struct ARegion *ar, uiBut *but, void **active_back)
{
/* note: ideally we would not have to change 'but->active' however
@@ -7116,12 +7277,20 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but)
retval = WM_UI_HANDLER_CONTINUE;
break;
case MOUSEMOVE:
- /* verify if we are still over the button, if not exit */
- if (!ui_mouse_inside_button(ar, but, event->x, event->y)) {
- data->cancel = true;
- button_activate_state(C, but, BUTTON_STATE_EXIT);
+ {
+ uiBut *but_other = ui_but_find_mouse_over(ar, event);
+ bool exit = false;
+
+ if (!ui_block_is_menu(block) &&
+ !ui_mouse_inside_button(ar, but, event->x, event->y))
+ {
+ exit = true;
+ }
+ else if (but_other && ui_but_is_editable(but_other) && (but_other != but)) {
+ exit = true;
}
- else if (ui_but_find_mouse_over(ar, event) != but) {
+
+ if (exit) {
data->cancel = true;
button_activate_state(C, but, BUTTON_STATE_EXIT);
}
@@ -7132,6 +7301,7 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but)
}
break;
+ }
case TIMER:
{
/* handle tooltip timer */
@@ -7715,6 +7885,22 @@ static int ui_handle_menu_button(bContext *C, const wmEvent *event, uiPopupBlock
int retval;
if (but) {
+ /* Its possible there is an active menu item NOT under the mouse,
+ * in this case ignore mouse clicks outside the button (but Enter etc is accepted) */
+ if (event->val == KM_RELEASE) {
+ /* pass, needed so we can exit active menu-items when click-dragging out of them */
+ }
+ else if (!ui_mouse_inside_region(but->active->region, event->x, event->y)) {
+ /* pass, needed to click-exit outside of non-flaoting menus */
+ }
+ else if ((event->type != MOUSEMOVE) && ISMOUSE(event->type)) {
+ if (!ui_mouse_inside_button(but->active->region, but, event->x, event->y)) {
+ but = NULL;
+ }
+ }
+ }
+
+ if (but) {
ScrArea *ctx_area = CTX_wm_area(C);
ARegion *ctx_region = CTX_wm_region(C);
@@ -7764,6 +7950,7 @@ static int ui_handle_menu_event(
if (menu->is_grab) {
if (event->type == LEFTMOUSE) {
menu->is_grab = false;
+ retval = WM_UI_HANDLER_BREAK;
}
else {
if (event->type == MOUSEMOVE) {
@@ -7968,7 +8155,7 @@ static int ui_handle_menu_event(
for (but = block->buttons.first; but; but = but->next) {
bool doit = false;
- if (!ELEM3(but->type, LABEL, SEPR, SEPRLINE))
+ if (!ELEM(but->type, LABEL, SEPR, SEPRLINE))
count++;
/* exception for rna layer buts */
@@ -8079,7 +8266,7 @@ static int ui_handle_menu_event(
if (inside == 0) {
uiSafetyRct *saferct = block->saferct.first;
- if (ELEM3(event->type, LEFTMOUSE, MIDDLEMOUSE, RIGHTMOUSE) &&
+ if (ELEM(event->type, LEFTMOUSE, MIDDLEMOUSE, RIGHTMOUSE) &&
ELEM(event->val, KM_PRESS, KM_DBL_CLICK))
{
if ((is_parent_menu == false) && (U.uiflag & USER_MENUOPENAUTO) == 0) {
@@ -8121,9 +8308,14 @@ static int ui_handle_menu_event(
else if ((event->type == LEFTMOUSE) && (event->val == KM_PRESS) &&
(inside && is_floating && inside_title))
{
- if (!ui_but_find_activated(ar)) {
+ if (!but || !ui_mouse_inside_button(ar, but, event->x, event->y)) {
+ if (but) {
+ button_timers_tooltip_remove(C, but);
+ }
+
menu->is_grab = true;
copy_v2_v2_int(menu->grab_xy_prev, &event->x);
+ retval = WM_UI_HANDLER_BREAK;
}
}
#endif
@@ -8458,15 +8650,15 @@ static int ui_handler_popup(bContext *C, const wmEvent *event, void *userdata)
/* free if done, does not free handle itself */
if (menu->menuretval) {
+ wmWindow *win = CTX_wm_window(C);
/* copy values, we have to free first (closes region) */
uiPopupBlockHandle temp = *menu;
ui_popup_block_free(C, menu);
- UI_remove_popup_handlers(&CTX_wm_window(C)->modalhandlers, menu);
+ UI_remove_popup_handlers(&win->modalhandlers, menu);
#ifdef USE_DRAG_TOGGLE
{
- wmWindow *win = CTX_wm_window(C);
WM_event_free_ui_handler_all(C, &win->modalhandlers,
ui_handler_region_drag_toggle, ui_handler_region_drag_toggle_remove);
}
diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index 546b2b85af5..51dd9166e46 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -508,6 +508,8 @@ static void init_brush_icons(void)
INIT_BRUSH_ICON(ICON_BRUSH_SOFTEN, soften);
INIT_BRUSH_ICON(ICON_BRUSH_SUBTRACT, subtract);
INIT_BRUSH_ICON(ICON_BRUSH_TEXDRAW, texdraw);
+ INIT_BRUSH_ICON(ICON_BRUSH_TEXFILL, texfill);
+ INIT_BRUSH_ICON(ICON_BRUSH_TEXMASK, texmask);
INIT_BRUSH_ICON(ICON_BRUSH_THUMB, thumb);
INIT_BRUSH_ICON(ICON_BRUSH_ROTATE, twist);
INIT_BRUSH_ICON(ICON_BRUSH_VERTEXDRAW, vertexdraw);
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index cd3b6390184..7d03aaea6b3 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -186,6 +186,7 @@ struct uiBut {
* (type == LABEL), Use (a1 == 1.0f) to use a2 as a blending factor (wow, this is imaginative!).
* (type == SCROLL) Use as scroll size.
* (type == SEARCH_MENU) Use as number or rows.
+ * (type == COLOR) Use as indication of color palette
*/
float a1;
@@ -193,6 +194,7 @@ struct uiBut {
* (type == NUM), Use to store RNA 'precision' value, for dragging and click-step.
* (type == LABEL), If (a1 == 1.0f) use a2 as a blending factor.
* (type == SEARCH_MENU) Use as number or columns.
+ * (type == COLOR) Use as indication of active palette color
*/
float a2;
@@ -550,12 +552,16 @@ void ui_draw_but_NODESOCKET(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol
PointerRNA *ui_handle_afterfunc_add_operator(struct wmOperatorType *ot, int opcontext, bool create_props);
extern void ui_pan_to_scroll(const struct wmEvent *event, int *type, int *val);
extern void ui_button_activate_do(struct bContext *C, struct ARegion *ar, uiBut *but);
+extern void ui_button_activate_over(struct bContext *C, struct ARegion *ar, uiBut *but);
extern void ui_button_execute_begin(struct bContext *C, struct ARegion *ar, uiBut *but, void **active_back);
extern void ui_button_execute_end(struct bContext *C, struct ARegion *ar, uiBut *but, void *active_back);
extern void ui_button_active_free(const struct bContext *C, uiBut *but);
extern bool ui_button_is_active(struct ARegion *ar) ATTR_WARN_UNUSED_RESULT;
extern int ui_button_open_menu_direction(uiBut *but);
extern void ui_button_text_password_hide(char password_str[UI_MAX_DRAW_STR], uiBut *but, const bool restore);
+extern uiBut *ui_but_find_activated(struct ARegion *ar);
+bool ui_but_is_editable(const uiBut *but);
+
void ui_button_clipboard_free(void);
void ui_panel_menu(struct bContext *C, ARegion *ar, Panel *pa);
uiBut *ui_but_find_old(uiBlock *block_old, const uiBut *but_new);
@@ -589,7 +595,6 @@ int ui_id_icon_get(struct bContext *C, struct ID *id, const bool big);
/* resources.c */
void init_userdef_do_versions(void);
-void init_userdef_factory(void);
void ui_theme_init_default(void);
void ui_style_init_default(void);
void ui_resources_init(void);
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index 789c10d6693..645eb607031 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -1181,7 +1181,7 @@ void uiItemFullR(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index
if (flag & UI_ITEM_R_ICON_ONLY) {
/* pass */
}
- else if (ELEM4(type, PROP_INT, PROP_FLOAT, PROP_STRING, PROP_POINTER)) {
+ else if (ELEM(type, PROP_INT, PROP_FLOAT, PROP_STRING, PROP_POINTER)) {
name = ui_item_name_add_colon(name, namestr);
}
else if (type == PROP_BOOLEAN && is_array && index == RNA_NO_INDEX) {
@@ -1323,9 +1323,9 @@ void uiItemEnumR_string(uiLayout *layout, struct PointerRNA *ptr, const char *pr
for (a = 0; item[a].identifier; a++) {
if (item[a].value == ivalue) {
- const char *item_name = CTX_IFACE_(RNA_property_translation_context(prop), item[a].name);
+ const char *item_name = name ? name : CTX_IFACE_(RNA_property_translation_context(prop), item[a].name);
- uiItemFullR(layout, ptr, prop, RNA_ENUM_VALUE, ivalue, 0, item_name ? item_name : name, icon ? icon : item[a].icon);
+ uiItemFullR(layout, ptr, prop, RNA_ENUM_VALUE, ivalue, 0, item_name, icon ? icon : item[a].icon);
break;
}
}
@@ -1559,7 +1559,7 @@ void uiItemPointerR(uiLayout *layout, struct PointerRNA *ptr, const char *propna
}
type = RNA_property_type(prop);
- if (!ELEM3(type, PROP_POINTER, PROP_STRING, PROP_ENUM)) {
+ if (!ELEM(type, PROP_POINTER, PROP_STRING, PROP_ENUM)) {
RNA_warning("Property %s must be a pointer, string or enum", propname);
return;
}
diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c
index 877a993e0ac..458aca444cb 100644
--- a/source/blender/editors/interface/interface_ops.c
+++ b/source/blender/editors/interface/interface_ops.c
@@ -35,6 +35,7 @@
#include "DNA_text_types.h" /* for UI_OT_reports_to_text */
#include "BLI_blenlib.h"
+#include "BLI_math_color.h"
#include "BLF_api.h"
#include "BLF_translation.h"
@@ -44,6 +45,7 @@
#include "BKE_global.h"
#include "BKE_text.h" /* for UI_OT_reports_to_text */
#include "BKE_report.h"
+#include "BKE_paint.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -55,6 +57,8 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "ED_paint.h"
+
/* only for UI_OT_editsource */
#include "ED_screen.h"
#include "BKE_main.h"
@@ -258,28 +262,43 @@ static void UI_OT_unset_property_button(wmOperatorType *ot)
/* Copy To Selected Operator ------------------------ */
-static bool copy_to_selected_list(bContext *C, PointerRNA *ptr, ListBase *lb, bool *use_path)
+static bool copy_to_selected_list(
+ bContext *C, PointerRNA *ptr, PropertyRNA *prop,
+ ListBase *r_lb, bool *r_use_path_from_id, char **r_path)
{
- *use_path = false;
+ *r_use_path_from_id = false;
+ *r_path = NULL;
- if (RNA_struct_is_a(ptr->type, &RNA_EditBone))
- *lb = CTX_data_collection_get(C, "selected_editable_bones");
- else if (RNA_struct_is_a(ptr->type, &RNA_PoseBone))
- *lb = CTX_data_collection_get(C, "selected_pose_bones");
- else if (RNA_struct_is_a(ptr->type, &RNA_Sequence))
- *lb = CTX_data_collection_get(C, "selected_editable_sequences");
- else {
+ if (RNA_struct_is_a(ptr->type, &RNA_EditBone)) {
+ *r_lb = CTX_data_collection_get(C, "selected_editable_bones");
+ }
+ else if (RNA_struct_is_a(ptr->type, &RNA_PoseBone)) {
+ *r_lb = CTX_data_collection_get(C, "selected_pose_bones");
+ }
+ else if (RNA_struct_is_a(ptr->type, &RNA_Sequence)) {
+ *r_lb = CTX_data_collection_get(C, "selected_editable_sequences");
+ }
+ else if (ptr->id.data) {
ID *id = ptr->id.data;
- if (id && GS(id->name) == ID_OB) {
- *lb = CTX_data_collection_get(C, "selected_editable_objects");
- *use_path = true;
+ if (GS(id->name) == ID_OB) {
+ *r_lb = CTX_data_collection_get(C, "selected_editable_objects");
+ *r_use_path_from_id = true;
+ *r_path = RNA_path_from_ID_to_property(ptr, prop);
}
- else {
- return false;
+ else if (GS(id->name) == ID_SCE) {
+ /* Sequencer's ID is scene :/ */
+ /* Try to recursively find an RNA_Sequence ancestor, to handle situations like T41062... */
+ if ((*r_path = RNA_path_resolve_from_type_to_property(ptr, prop, &RNA_Sequence)) != NULL) {
+ *r_lb = CTX_data_collection_get(C, "selected_editable_sequences");
+ }
}
+ return (*r_path != NULL);
}
-
+ else {
+ return false;
+ }
+
return true;
}
@@ -303,47 +322,54 @@ static bool copy_to_selected_button(bContext *C, bool all, bool poll)
/* if there is a valid property that is editable... */
if (ptr.data && prop) {
char *path = NULL;
- bool use_path;
+ bool use_path_from_id;
CollectionPointerLink *link;
ListBase lb;
- if (!copy_to_selected_list(C, &ptr, &lb, &use_path))
+ if (!copy_to_selected_list(C, &ptr, prop, &lb, &use_path_from_id, &path))
return success;
- if (!use_path || (path = RNA_path_from_ID_to_property(&ptr, prop))) {
- for (link = lb.first; link; link = link->next) {
- if (link->ptr.data != ptr.data) {
- if (use_path) {
- lprop = NULL;
- RNA_id_pointer_create(link->ptr.id.data, &idptr);
- RNA_path_resolve_property(&idptr, path, &lptr, &lprop);
- }
- else {
- lptr = link->ptr;
- lprop = prop;
- }
+ for (link = lb.first; link; link = link->next) {
+ if (link->ptr.data != ptr.data) {
+ if (use_path_from_id) {
+ /* Path relative to ID. */
+ lprop = NULL;
+ RNA_id_pointer_create(link->ptr.id.data, &idptr);
+ RNA_path_resolve_property(&idptr, path, &lptr, &lprop);
+ }
+ else if (path) {
+ /* Path relative to elements from list. */
+ lprop = NULL;
+ RNA_path_resolve_property(&link->ptr, path, &lptr, &lprop);
+ }
+ else {
+ lptr = link->ptr;
+ lprop = prop;
+ }
+
+ if (lptr.data == ptr.data) {
+ /* lptr might not be the same as link->ptr! */
+ continue;
+ }
- if (lprop == prop) {
- if (RNA_property_editable(&lptr, lprop)) {
- if (poll) {
+ if (lprop == prop) {
+ if (RNA_property_editable(&lptr, lprop)) {
+ if (poll) {
+ success = true;
+ break;
+ }
+ else {
+ if (RNA_property_copy(&lptr, &ptr, prop, (all) ? -1 : index)) {
+ RNA_property_update(C, &lptr, prop);
success = true;
- break;
- }
- else {
- if (RNA_property_copy(&lptr, &ptr, prop, (all) ? -1 : index)) {
- RNA_property_update(C, &lptr, prop);
- success = true;
- }
}
}
}
}
}
-
- if (path)
- MEM_freeN(path);
}
+ MEM_SAFE_FREE(path);
BLI_freelistN(&lb);
}
@@ -810,6 +836,91 @@ static void UI_OT_reloadtranslation(wmOperatorType *ot)
ot->exec = reloadtranslation_exec;
}
+int UI_drop_color_poll(struct bContext *C, wmDrag *drag, const wmEvent *UNUSED(event))
+{
+ /* should only return true for regions that include buttons, for now
+ * return true always */
+ if (drag->type == WM_DRAG_COLOR) {
+ SpaceImage *sima = CTX_wm_space_image(C);
+ ARegion *ar = CTX_wm_region(C);
+
+ if (UI_but_active_drop_color(C))
+ return 1;
+
+ if (sima && (sima->mode == SI_MODE_PAINT) &&
+ sima->image && (ar && ar->regiontype == RGN_TYPE_WINDOW))
+ {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+void UI_drop_color_copy(wmDrag *drag, wmDropBox *drop)
+{
+ uiDragColorHandle *drag_info = (uiDragColorHandle *)drag->poin;
+
+ RNA_float_set_array(drop->ptr, "color", drag_info->color);
+ RNA_boolean_set(drop->ptr, "gamma", drag_info->gamma_corrected);
+}
+
+static int drop_color_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ ARegion *ar = CTX_wm_region(C);
+ uiBut *but = NULL;
+ float color[3];
+ bool gamma;
+
+ RNA_float_get_array(op->ptr, "color", color);
+ gamma = RNA_boolean_get(op->ptr, "gamma");
+
+ /* find button under mouse, check if it has RNA color property and
+ * if it does copy the data */
+ but = ui_but_find_activated(ar);
+
+ if (but && but->type == COLOR && but->rnaprop) {
+ if (RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) {
+ if (!gamma)
+ ui_block_to_display_space_v3(but->block, color);
+ RNA_property_float_set_array(&but->rnapoin, but->rnaprop, color);
+ RNA_property_update(C, &but->rnapoin, but->rnaprop);
+ }
+ else if (RNA_property_subtype(but->rnaprop) == PROP_COLOR) {
+ if (gamma)
+ ui_block_to_scene_linear_v3(but->block, color);
+ RNA_property_float_set_array(&but->rnapoin, but->rnaprop, color);
+ RNA_property_update(C, &but->rnapoin, but->rnaprop);
+ }
+ }
+ else {
+ if (gamma) {
+ srgb_to_linearrgb_v3_v3(color, color);
+ }
+
+ ED_imapaint_bucket_fill(C, color, op);
+ }
+
+ ED_region_tag_redraw(ar);
+
+ return OPERATOR_FINISHED;
+}
+
+
+static void UI_OT_drop_color(wmOperatorType *ot)
+{
+ ot->name = "Drop Color";
+ ot->idname = "UI_OT_drop_color";
+ ot->description = "Drop colors to buttons";
+
+ ot->invoke = drop_color_invoke;
+
+ RNA_def_float_color(ot->srna, "color", 3, NULL, 0.0, FLT_MAX, "Color", "Source color", 0.0, 1.0);
+ RNA_def_boolean(ot->srna, "gamma", 0, "Gamma Corrected", "The source color is gamma corrected ");
+}
+
+
+
/* ********************************************************* */
/* Registration */
@@ -821,7 +932,7 @@ void UI_buttons_operatortypes(void)
WM_operatortype_append(UI_OT_unset_property_button);
WM_operatortype_append(UI_OT_copy_to_selected_button);
WM_operatortype_append(UI_OT_reports_to_textblock); /* XXX: temp? */
-
+ WM_operatortype_append(UI_OT_drop_color);
#ifdef WITH_PYTHON
WM_operatortype_append(UI_OT_editsource);
WM_operatortype_append(UI_OT_edittranslation_init);
diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c
index 2ccb3740777..d0909e9413c 100644
--- a/source/blender/editors/interface/interface_panel.c
+++ b/source/blender/editors/interface/interface_panel.c
@@ -120,7 +120,7 @@ static int panel_aligned(ScrArea *sa, ARegion *ar)
return BUT_VERTICAL;
else if (sa->spacetype == SPACE_IMAGE && ar->regiontype == RGN_TYPE_PREVIEW)
return BUT_VERTICAL;
- else if (ELEM3(ar->regiontype, RGN_TYPE_UI, RGN_TYPE_TOOLS, RGN_TYPE_TOOL_PROPS))
+ else if (ELEM(ar->regiontype, RGN_TYPE_UI, RGN_TYPE_TOOLS, RGN_TYPE_TOOL_PROPS))
return BUT_VERTICAL;
return 0;
@@ -462,31 +462,41 @@ static void ui_draw_panel_scalewidget(const rcti *rect)
fdrawline(xmin + dx, ymin + 1, xmax, ymax - dy + 1);
glDisable(GL_BLEND);
}
-
static void ui_draw_panel_dragwidget(const rctf *rect)
{
- float xmin, xmax, dx;
- float ymin, ymax, dy;
-
- xmin = rect->xmin;
- xmax = rect->xmax;
- ymin = rect->ymin;
- ymax = rect->ymax;
-
- dx = (xmax - xmin) / 3.0f;
- dy = (ymax - ymin) / 3.0f;
-
- glEnable(GL_BLEND);
- glColor4ub(255, 255, 255, 50);
- fdrawline(xmin, ymax, xmax, ymin);
- fdrawline(xmin + dx, ymax, xmax, ymin + dy);
- fdrawline(xmin + 2 * dx, ymax, xmax, ymin + 2 * dy);
-
- glColor4ub(0, 0, 0, 50);
- fdrawline(xmin, ymax + 1, xmax, ymin + 1);
- fdrawline(xmin + dx, ymax + 1, xmax, ymin + dy + 1);
- fdrawline(xmin + 2 * dx, ymax + 1, xmax, ymin + 2 * dy + 1);
- glDisable(GL_BLEND);
+ unsigned char col_back[3], col_high[3], col_dark[3];
+ const int col_tint = 84;
+
+ const int px = (int)U.pixelsize;
+ const int px_zoom = max_ii(iroundf(BLI_rctf_size_y(rect) / 22.0f), 1);
+
+ const int box_margin = max_ii(iroundf((float)(px_zoom * 2.0f)), px);
+ const int box_size = max_ii(iroundf((BLI_rctf_size_y(rect) / 8.0f) - px), px);
+
+ const int x_min = rect->xmin;
+ const int y_min = rect->ymin;
+ const int y_ofs = max_ii(iroundf(BLI_rctf_size_y(rect) / 3.0f), px);
+ const int x_ofs = y_ofs;
+ int i_x, i_y;
+
+
+ UI_GetThemeColor3ubv(UI_GetThemeValue(TH_PANEL_SHOW_HEADER) ? TH_PANEL_HEADER : TH_PANEL_BACK, col_back);
+ UI_GetColorPtrShade3ubv(col_back, col_high, col_tint);
+ UI_GetColorPtrShade3ubv(col_back, col_dark, -col_tint);
+
+
+ /* draw multiple boxes */
+ for (i_x = 0; i_x < 4; i_x++) {
+ for (i_y = 0; i_y < 2; i_y++) {
+ const int x_co = (x_min + x_ofs) + (i_x * (box_size + box_margin));
+ const int y_co = (y_min + y_ofs) + (i_y * (box_size + box_margin));
+
+ glColor3ubv(col_dark);
+ glRectf(x_co - box_size, y_co - px_zoom, x_co, (y_co + box_size) - px_zoom);
+ glColor3ubv(col_high);
+ glRectf(x_co - box_size, y_co, x_co, y_co + box_size);
+ }
+ }
}
@@ -1131,7 +1141,7 @@ static void ui_handle_panel_header(const bContext *C, uiBlock *block, int mx, in
button = 1;
else if (event == AKEY)
button = 1;
- else if (ELEM3(event, 0, RETKEY, LEFTMOUSE) && shift) {
+ else if (ELEM(event, 0, RETKEY, LEFTMOUSE) && shift) {
block->panel->flag ^= PNL_PIN;
button = 2;
}
@@ -1716,7 +1726,7 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar)
/* XXX hardcoded key warning */
if ((inside || inside_header) && event->val == KM_PRESS) {
- if (event->type == AKEY && !ELEM4(KM_MOD_FIRST, event->ctrl, event->oskey, event->shift, event->alt)) {
+ if (event->type == AKEY && !ELEM(KM_MOD_FIRST, event->ctrl, event->oskey, event->shift, event->alt)) {
if (pa->flag & PNL_CLOSEDY) {
if ((block->rect.ymax <= my) && (block->rect.ymax + PNL_HEADER >= my))
diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c
index c32f0de937e..3629c72ce49 100644
--- a/source/blender/editors/interface/interface_regions.c
+++ b/source/blender/editors/interface/interface_regions.c
@@ -392,7 +392,7 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but)
data->totline++;
}
- if (ELEM3(but->type, TEX, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
+ if (ELEM(but->type, TEX, SEARCH_MENU, SEARCH_MENU_UNLINK)) {
/* better not show the value of a password */
if ((but->rnaprop && (RNA_property_subtype(but->rnaprop) == PROP_PASSWORD)) == 0) {
/* full string */
@@ -1872,7 +1872,7 @@ static void ui_update_block_buts_rgb(uiBlock *block, const float rgb[3], bool is
if (rgb_gamma[2] > 1.0f) rgb_gamma[2] = modf(rgb_gamma[2], &intpart);
rgb_float_to_uchar(rgb_gamma_uchar, rgb_gamma);
- BLI_snprintf(col, sizeof(col), "%02X%02X%02X", UNPACK3OP((unsigned int), rgb_gamma_uchar));
+ BLI_snprintf(col, sizeof(col), "%02X%02X%02X", UNPACK3_EX((unsigned int), rgb_gamma_uchar, ));
strcpy(bt->poin, col);
}
@@ -2160,7 +2160,7 @@ static void uiBlockPicker(uiBlock *block, float rgba[4], PointerRNA *ptr, Proper
}
rgb_float_to_uchar(rgb_gamma_uchar, rgb_gamma);
- BLI_snprintf(hexcol, sizeof(hexcol), "%02X%02X%02X", UNPACK3OP((unsigned int), rgb_gamma_uchar));
+ BLI_snprintf(hexcol, sizeof(hexcol), "%02X%02X%02X", UNPACK3_EX((unsigned int), rgb_gamma_uchar, ));
yco = -3.0f * UI_UNIT_Y;
bt = uiDefBut(block, TEX, 0, IFACE_("Hex: "), 0, yco, butwidth, UI_UNIT_Y, hexcol, 0, 8, 0, 0, TIP_("Hex triplet for color (#RRGGBB)"));
@@ -2408,6 +2408,7 @@ static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, voi
uiBlockSetFlag(block, UI_BLOCK_MOVEMOUSE_QUIT);
if (pup->popup) {
+ uiBut *but_activate = NULL;
uiBlockSetFlag(block, UI_BLOCK_LOOP | UI_BLOCK_REDRAW | UI_BLOCK_NUMSELECT);
uiBlockSetDirection(block, direction);
@@ -2421,6 +2422,10 @@ static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, voi
* block to be under the mouse */
offset[0] = -(bt->rect.xmin + 0.8f * BLI_rctf_size_x(&bt->rect));
offset[1] = -(bt->rect.ymin + 0.5f * UI_UNIT_Y);
+
+ if (ui_but_is_editable(bt)) {
+ but_activate = bt;
+ }
}
else {
/* position mouse at 0.8*width of the button and below the tile
@@ -2430,6 +2435,20 @@ static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, voi
offset[0] = min_ii(offset[0], -(bt->rect.xmin + 0.8f * BLI_rctf_size_x(&bt->rect)));
offset[1] = 2.1 * UI_UNIT_Y;
+
+ for (bt = block->buttons.first; bt; bt = bt->next) {
+ if (ui_but_is_editable(bt)) {
+ but_activate = bt;
+ break;
+ }
+ }
+ }
+
+ /* in rare cases this is needed since moving the popup
+ * to be within the window bounds may move it away from the mouse,
+ * This ensures we set an item to be active. */
+ if (but_activate) {
+ ui_button_activate_over(C, handle->region, but_activate);
}
block->minbounds = minwidth;
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 1c5d3ecfd2e..cb5f5331c2e 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -36,6 +36,7 @@
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
#include "DNA_object_force.h"
+#include "DNA_brush_types.h"
#include "BLI_utildefines.h"
#include "BLI_string.h"
@@ -60,6 +61,7 @@
#include "BKE_object.h"
#include "BKE_packedFile.h"
#include "BKE_particle.h"
+#include "BKE_paint.h"
#include "BKE_report.h"
#include "BKE_sca.h"
#include "BKE_screen.h"
@@ -349,6 +351,8 @@ static const char *template_id_browse_tip(StructRNA *type)
case ID_BR: return N_("Browse Brush to be linked");
case ID_PA: return N_("Browse Particle Settings to be linked");
case ID_GD: return N_("Browse Grease Pencil Data to be linked");
+ case ID_PAL: return N_("Browse Palette Data to be linked");
+ case ID_PC: return N_("Browse Paint Curve Data to be linked");
}
}
return N_("Browse ID data to be linked");
@@ -489,7 +493,7 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str
if (user_alert) uiButSetFlag(but, UI_BUT_REDALERT);
- if (id->lib == NULL && !(ELEM5(GS(id->name), ID_GR, ID_SCE, ID_SCR, ID_TXT, ID_OB))) {
+ if (id->lib == NULL && !(ELEM(GS(id->name), ID_GR, ID_SCE, ID_SCR, ID_TXT, ID_OB))) {
uiDefButR(block, TOG, 0, "F", 0, 0, UI_UNIT_X, UI_UNIT_Y, &idptr, "use_fake_user", -1, 0, 0, -1, -1, NULL);
}
}
@@ -808,7 +812,7 @@ static int modifier_can_delete(ModifierData *md)
static int modifier_is_simulation(ModifierData *md)
{
/* Physic Tab */
- if (ELEM7(md->type, eModifierType_Cloth, eModifierType_Collision, eModifierType_Fluidsim, eModifierType_Smoke,
+ if (ELEM(md->type, eModifierType_Cloth, eModifierType_Collision, eModifierType_Fluidsim, eModifierType_Smoke,
eModifierType_Softbody, eModifierType_Surface, eModifierType_DynamicPaint))
{
return 1;
@@ -906,9 +910,9 @@ static uiLayout *draw_modifier(uiLayout *layout, Scene *scene, Object *ob,
uiBlockSetEmboss(block, UI_EMBOSS);
}
} /* tessellation point for curve-typed objects */
- else if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
+ else if (ELEM(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
/* some modifiers could work with pre-tessellated curves only */
- if (ELEM3(md->type, eModifierType_Hook, eModifierType_Softbody, eModifierType_MeshDeform)) {
+ if (ELEM(md->type, eModifierType_Hook, eModifierType_Softbody, eModifierType_MeshDeform)) {
/* add disabled pre-tessellated button, so users could have
* message for this modifiers */
but = uiDefIconButBitI(block, TOG, eModifierMode_ApplyOnSpline, 0, ICON_SURFACE_DATA, 0, 0,
@@ -979,7 +983,7 @@ static uiLayout *draw_modifier(uiLayout *layout, Scene *scene, Object *ob,
uiBlockClearButLock(block);
uiBlockSetButLock(block, ob && ob->id.lib, ERROR_LIBDATA_MESSAGE);
- if (!ELEM5(md->type, eModifierType_Fluidsim, eModifierType_Softbody, eModifierType_ParticleSystem,
+ if (!ELEM(md->type, eModifierType_Fluidsim, eModifierType_Softbody, eModifierType_ParticleSystem,
eModifierType_Cloth, eModifierType_Smoke))
{
uiItemO(row, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Copy"), ICON_NONE,
@@ -1298,7 +1302,7 @@ void uiTemplatePreview(uiLayout *layout, bContext *C, ID *id, int show_buttons,
char _preview_id[UI_MAX_NAME_STR];
- if (id && !ELEM5(GS(id->name), ID_MA, ID_TE, ID_WO, ID_LA, ID_LS)) {
+ if (id && !ELEM(GS(id->name), ID_MA, ID_TE, ID_WO, ID_LA, ID_LS)) {
RNA_warning("Expected ID of type material, texture, lamp, world or line style");
return;
}
@@ -2363,6 +2367,61 @@ void uiTemplateColorPicker(uiLayout *layout, PointerRNA *ptr, const char *propna
}
}
+void uiTemplatePalette(uiLayout *layout, PointerRNA *ptr, const char *propname, int UNUSED(colors))
+{
+ PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
+ PointerRNA cptr;
+ Palette *palette;
+ PaletteColor *color;
+ uiBlock *block;
+ uiLayout *col;
+ int row_cols = 0, col_id = 0;
+ int cols_per_row = MAX2(uiLayoutGetWidth(layout) / UI_UNIT_X, 1);
+
+ if (!prop) {
+ RNA_warning("property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
+ return;
+ }
+
+ cptr = RNA_property_pointer_get(ptr, prop);
+ if (!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_Palette))
+ return;
+
+ block = uiLayoutGetBlock(layout);
+
+ palette = cptr.data;
+
+ /* first delete any pending colors */
+ BKE_palette_cleanup(palette);
+
+ color = palette->colors.first;
+
+ col = uiLayoutColumn(layout, true);
+ uiLayoutRow(col, true);
+ uiDefIconButO(block, BUT, "PALETTE_OT_color_add", WM_OP_INVOKE_DEFAULT, ICON_ZOOMIN, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL);
+ uiDefIconButO(block, BUT, "PALETTE_OT_color_delete", WM_OP_INVOKE_DEFAULT, ICON_ZOOMOUT, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL);
+
+ col = uiLayoutColumn(layout, true);
+ uiLayoutRow(col, true);
+
+ for (; color; color = color->next) {
+ PointerRNA ptr;
+
+ if (row_cols >= cols_per_row) {
+ uiLayoutRow(col, true);
+ row_cols = 0;
+ }
+
+ RNA_pointer_create(&palette->id, &RNA_PaletteColor, color, &ptr);
+ uiDefButR(block, COLOR, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, &ptr, "color", -1, 0.0, 1.0,
+ UI_PALETTE_COLOR, (col_id == palette->active_color) ? UI_PALETTE_COLOR_ACTIVE : 0.0, "");
+
+ row_cols++;
+ col_id++;
+ }
+}
+
+
/********************* Layer Buttons Template ************************/
static void handle_layer_buttons(bContext *C, void *arg1, void *arg2)
@@ -3543,7 +3602,7 @@ void uiTemplateColormanagedViewSettings(uiLayout *layout, bContext *UNUSED(C), P
col = uiLayoutColumn(layout, false);
row = uiLayoutRow(col, false);
- uiItemR(row, &view_transform_ptr, "view_transform", UI_ITEM_R_EXPAND, IFACE_("View"), ICON_NONE);
+ uiItemR(row, &view_transform_ptr, "view_transform", 0, IFACE_("View"), ICON_NONE);
col = uiLayoutColumn(layout, false);
uiItemR(col, &view_transform_ptr, "exposure", 0, NULL, ICON_NONE);
diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c
index 744ed7e5b72..008ea84b607 100644
--- a/source/blender/editors/interface/interface_utils.c
+++ b/source/blender/editors/interface/interface_utils.c
@@ -151,7 +151,7 @@ int uiDefAutoButsRNA(uiLayout *layout, PointerRNA *ptr,
const char *name;
int tot = 0;
- assert(ELEM3(label_align, '\0', 'H', 'V'));
+ assert(ELEM(label_align, '\0', 'H', 'V'));
RNA_STRUCT_BEGIN (ptr, prop)
{
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index 6ea0a55729d..23f185befb9 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -33,6 +33,7 @@
#include <string.h>
#include <assert.h>
+#include "DNA_brush_types.h"
#include "DNA_screen_types.h"
#include "DNA_userdef_types.h"
@@ -848,7 +849,7 @@ static void widget_draw_icon(const uiBut *but, BIFIconID icon, float alpha, cons
height = ICON_DEFAULT_HEIGHT / aspect;
/* calculate blend color */
- if (ELEM4(but->type, TOG, ROW, TOGN, LISTROW)) {
+ if (ELEM(but->type, TOG, ROW, TOGN, LISTROW)) {
if (but->flag & UI_SELECT) {}
else if (but->flag & UI_ACTIVE) {}
else alpha = 0.5f;
@@ -2825,6 +2826,17 @@ static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int stat
widgetbase_draw(&wtb, wcol);
+ if (but->a1 == UI_PALETTE_COLOR && but->a2 == UI_PALETTE_COLOR_ACTIVE) {
+ float width = rect->xmax - rect->xmin;
+ float height = rect->ymax - rect->ymin;
+
+ glColor4ubv((unsigned char *)wcol->outline);
+ glBegin(GL_TRIANGLES);
+ glVertex2f(rect->xmin + 0.1f * width, rect->ymin + 0.9f * height);
+ glVertex2f(rect->xmin + 0.1f * width, rect->ymin + 0.5f * height);
+ glVertex2f(rect->xmin + 0.5f * width, rect->ymin + 0.9f * height);
+ glEnd();
+ }
}
static void widget_normal(uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int UNUSED(roundboxalign))
diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c
index 372ced0a6fd..dbb0235f40f 100644
--- a/source/blender/editors/interface/resources.c
+++ b/source/blender/editors/interface/resources.c
@@ -36,11 +36,10 @@
#include "MEM_guardedalloc.h"
#include "DNA_curve_types.h"
-#include "DNA_userdef_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
+#include "DNA_userdef_types.h"
#include "DNA_windowmanager_types.h"
-#include "DNA_mesh_types.h" /* init_userdef_factory */
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
@@ -51,7 +50,6 @@
#include "BKE_main.h"
#include "BKE_texture.h"
-
#include "BIF_gl.h"
#include "UI_interface.h"
@@ -537,6 +535,13 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
cp = ts->preview_stitch_active;
break;
+ case TH_PAINT_CURVE_HANDLE:
+ cp = ts->paint_curve_handle;
+ break;
+ case TH_PAINT_CURVE_PIVOT:
+ cp = ts->paint_curve_pivot;
+ break;
+
case TH_UV_OTHERS:
cp = ts->uv_others;
break;
@@ -774,6 +779,8 @@ static void ui_theme_space_init_handles_color(ThemeSpace *theme_space)
rgba_char_args_set(theme_space->handle_sel_auto, 0xf0, 0xff, 0x40, 255);
rgba_char_args_set(theme_space->handle_sel_vect, 0x40, 0xc0, 0x30, 255);
rgba_char_args_set(theme_space->handle_sel_align, 0xf0, 0x90, 0xa0, 255);
+ rgba_char_args_set(theme_space->handle_vertex, 0x00, 0x00, 0x00, 0xff);
+ rgba_char_args_set(theme_space->handle_vertex_select, 0xff, 0xff, 0, 0xff);
rgba_char_args_set(theme_space->act_spline, 0xdb, 0x25, 0x12, 255);
}
@@ -871,6 +878,8 @@ void ui_theme_init_default(void)
rgba_char_args_set(btheme->tv3d.title, 0, 0, 0, 255);
rgba_char_args_set(btheme->tv3d.freestyle_edge_mark, 0x7f, 0xff, 0x7f, 255);
rgba_char_args_set(btheme->tv3d.freestyle_face_mark, 0x7f, 0xff, 0x7f, 51);
+ rgba_char_args_set_fl(btheme->tv3d.paint_curve_handle, 0.5f, 1.0f, 0.5f, 0.5f);
+ rgba_char_args_set_fl(btheme->tv3d.paint_curve_pivot, 1.0f, 0.5f, 0.5f, 0.5f);
btheme->tv3d.facedot_size = 4;
@@ -1129,8 +1138,6 @@ void ui_theme_init_default(void)
rgba_char_args_set(btheme->tclip.path_after, 0x00, 0x00, 0xff, 255);
rgba_char_args_set(btheme->tclip.grid, 0x5e, 0x5e, 0x5e, 255);
rgba_char_args_set(btheme->tclip.cframe, 0x60, 0xc0, 0x40, 255);
- rgba_char_args_set(btheme->tclip.handle_vertex, 0x00, 0x00, 0x00, 0xff);
- rgba_char_args_set(btheme->tclip.handle_vertex_select, 0xff, 0xff, 0, 0xff);
rgba_char_args_set(btheme->tclip.list, 0x66, 0x66, 0x66, 0xff);
rgba_char_args_set(btheme->tclip.strip, 0x0c, 0x0a, 0x0a, 0x80);
rgba_char_args_set(btheme->tclip.strip_select, 0xff, 0x8c, 0x00, 0xff);
@@ -2427,6 +2434,16 @@ void init_userdef_do_versions(void)
}
}
+ if (U.versionfile < 272 || (U.versionfile == 272 && U.subversionfile < 2)) {
+ bTheme *btheme;
+ for (btheme = U.themes.first; btheme; btheme = btheme->next) {
+ rgba_char_args_set_fl(btheme->tv3d.paint_curve_handle, 0.5f, 1.0f, 0.5f, 0.5f);
+ rgba_char_args_set_fl(btheme->tv3d.paint_curve_pivot, 1.0f, 0.5f, 0.5f, 0.5f);
+ rgba_char_args_set_fl(btheme->tima.paint_curve_handle, 0.5f, 1.0f, 0.5f, 0.5f);
+ rgba_char_args_set_fl(btheme->tima.paint_curve_pivot, 1.0f, 0.5f, 0.5f, 0.5f);
+ }
+ }
+
{
bTheme *btheme;
for (btheme = U.themes.first; btheme; btheme = btheme->next) {
@@ -2449,25 +2466,3 @@ void init_userdef_do_versions(void)
// XXX reset_autosave();
}
-
-/**
- * Override values in in-memory startup.blend, avoids resaving for small changes.
- */
-void init_userdef_factory(void)
-{
- /* defaults from T37518 */
-
- U.uiflag |= USER_ZBUF_CURSOR;
- U.uiflag |= USER_QUIT_PROMPT;
- U.uiflag |= USER_CONTINUOUS_MOUSE;
-
- U.versions = 1;
- U.savetime = 2;
-
- {
- Mesh *me;
- for (me = G.main->mesh.first; me; me = me->id.next) {
- me->flag &= ~ME_TWOSIDED;
- }
- }
-}
diff --git a/source/blender/editors/io/io_collada.c b/source/blender/editors/io/io_collada.c
index 4d2ea0e64f4..a4130540b1b 100644
--- a/source/blender/editors/io/io_collada.c
+++ b/source/blender/editors/io/io_collada.c
@@ -250,7 +250,7 @@ static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr)
row = uiLayoutRow(box, false);
split = uiLayoutSplit(row, 0.6f, UI_LAYOUT_ALIGN_RIGHT);
- uiItemL(split, IFACE_("Transformation Type"), ICON_NONE);
+ uiItemL(split, IFACE_("Transformation Type"), ICON_NONE);
uiItemR(split, imfptr, "export_transformation_type_selection", 0, "", ICON_NONE);
row = uiLayoutRow(box, false);
diff --git a/source/blender/editors/mesh/editmesh_knife_project.c b/source/blender/editors/mesh/editmesh_knife_project.c
index cc26d6079a9..553c1faa36a 100644
--- a/source/blender/editors/mesh/editmesh_knife_project.c
+++ b/source/blender/editors/mesh/editmesh_knife_project.c
@@ -65,7 +65,7 @@ static LinkNode *knifeproject_poly_from_object(ARegion *ar, Scene *scene, Object
dm = ob->derivedFinal ? ob->derivedFinal : mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
dm_needsFree = false;
}
- else if (ELEM3(ob->type, OB_FONT, OB_CURVE, OB_SURF)) {
+ else if (ELEM(ob->type, OB_FONT, OB_CURVE, OB_SURF)) {
dm = CDDM_from_curve(ob);
dm_needsFree = true;
}
diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c
index 23828098940..9cdfb43ae15 100644
--- a/source/blender/editors/mesh/editmesh_select.c
+++ b/source/blender/editors/mesh/editmesh_select.c
@@ -2807,6 +2807,13 @@ static int edbm_select_non_manifold_exec(bContext *C, wmOperator *op)
BMEdge *e;
BMIter iter;
+ const bool use_wire = RNA_boolean_get(op->ptr, "use_wire");
+ const bool use_boundary = RNA_boolean_get(op->ptr, "use_boundary");
+ const bool use_multi_face = RNA_boolean_get(op->ptr, "use_multi_face");
+ const bool use_non_contiguous = RNA_boolean_get(op->ptr, "use_non_contiguous");
+ const bool use_verts = RNA_boolean_get(op->ptr, "use_verts");
+
+
if (!RNA_boolean_get(op->ptr, "extend"))
EDBM_flag_disable_all(em, BM_ELEM_SELECT);
@@ -2819,15 +2826,30 @@ static int edbm_select_non_manifold_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
- if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN) && !BM_vert_is_manifold(v)) {
- BM_vert_select_set(em->bm, v, true);
+ if (use_verts) {
+ BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
+ if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
+ if (!BM_vert_is_manifold(v)) {
+ BM_vert_select_set(em->bm, v, true);
+ }
+ }
}
}
- BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
- if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN) && !BM_edge_is_manifold(e)) {
- BM_edge_select_set(em->bm, e, true);
+ if (use_wire || use_boundary || use_multi_face || use_non_contiguous) {
+ BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
+ if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
+ if ((use_wire && BM_edge_is_wire(e)) ||
+ (use_boundary && BM_edge_is_boundary(e)) ||
+ (use_non_contiguous && (BM_edge_is_manifold(e) && !BM_edge_is_contiguous(e))) ||
+ (use_multi_face && (BM_edge_face_count(e) > 2)))
+ {
+ /* check we never select perfect edge (in test above) */
+ BLI_assert(!(BM_edge_is_manifold(e) && BM_edge_is_contiguous(e)));
+
+ BM_edge_select_set(em->bm, e, true);
+ }
+ }
}
}
@@ -2854,6 +2876,18 @@ void MESH_OT_select_non_manifold(wmOperatorType *ot)
/* props */
RNA_def_boolean(ot->srna, "extend", true, "Extend", "Extend the selection");
+ /* edges */
+ RNA_def_boolean(ot->srna, "use_wire", true, "Wire",
+ "Wire edges");
+ RNA_def_boolean(ot->srna, "use_boundary", true, "Boundaries",
+ "Boundary edges");
+ RNA_def_boolean(ot->srna, "use_multi_face", true,
+ "Multiple Faces", "Edges shared by 3+ faces");
+ RNA_def_boolean(ot->srna, "use_non_contiguous", true, "Non Contiguous",
+ "Edges between faces pointing in alternate directions");
+ /* verts */
+ RNA_def_boolean(ot->srna, "use_verts", true, "Vertices",
+ "Vertices connecting multiple face regions");
}
static int edbm_select_random_exec(bContext *C, wmOperator *op)
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index 27145cc7649..ddf7650deaf 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -3052,7 +3052,7 @@ static int edbm_knife_cut_exec(bContext *C, wmOperator *op)
float (*screen_vert_coords)[2], (*sco)[2], (*mouse_path)[2];
/* edit-object needed for matrix, and ar->regiondata for projections to work */
- if (ELEM3(NULL, obedit, ar, ar->regiondata))
+ if (ELEM(NULL, obedit, ar, ar->regiondata))
return OPERATOR_CANCELLED;
if (bm->totvertsel < 2) {
@@ -3675,7 +3675,7 @@ static void edbm_fill_grid_prepare(BMesh *bm, int offset, int *r_span, bool span
}
/* set this vertex first */
- BLI_rotatelist_first(verts, v_act_link);
+ BLI_listbase_rotate_first(verts, v_act_link);
BM_edgeloop_edges_get(el_store, edges);
@@ -4107,6 +4107,11 @@ static void edbm_dissolve_prop__use_face_split(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "use_face_split", 0, "Face Split",
"Split off face corners to maintain surrounding geometry");
}
+static void edbm_dissolve_prop__use_boundary_tear(wmOperatorType *ot)
+{
+ RNA_def_boolean(ot->srna, "use_boundary_tear", 0, "Tear Boundary",
+ "Split off face corners instead of merging faces");
+}
static int edbm_dissolve_verts_exec(bContext *C, wmOperator *op)
{
@@ -4114,9 +4119,14 @@ static int edbm_dissolve_verts_exec(bContext *C, wmOperator *op)
BMEditMesh *em = BKE_editmesh_from_object(obedit);
const bool use_face_split = RNA_boolean_get(op->ptr, "use_face_split");
+ const bool use_boundary_tear = RNA_boolean_get(op->ptr, "use_boundary_tear");
- if (!EDBM_op_callf(em, op, "dissolve_verts verts=%hv use_face_split=%b", BM_ELEM_SELECT, use_face_split))
+ if (!EDBM_op_callf(em, op,
+ "dissolve_verts verts=%hv use_face_split=%b use_boundary_tear=%b",
+ BM_ELEM_SELECT, use_face_split, use_boundary_tear))
+ {
return OPERATOR_CANCELLED;
+ }
EDBM_update_generic(em, true, true);
@@ -4138,6 +4148,7 @@ void MESH_OT_dissolve_verts(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
edbm_dissolve_prop__use_face_split(ot);
+ edbm_dissolve_prop__use_boundary_tear(ot);
}
static int edbm_dissolve_edges_exec(bContext *C, wmOperator *op)
@@ -4249,6 +4260,7 @@ void MESH_OT_dissolve_mode(wmOperatorType *ot)
edbm_dissolve_prop__use_verts(ot);
edbm_dissolve_prop__use_face_split(ot);
+ edbm_dissolve_prop__use_boundary_tear(ot);
}
static int edbm_dissolve_limited_exec(bContext *C, wmOperator *op)
diff --git a/source/blender/editors/metaball/mball_edit.c b/source/blender/editors/metaball/mball_edit.c
index 36c7bb404da..feac7f6ece3 100644
--- a/source/blender/editors/metaball/mball_edit.c
+++ b/source/blender/editors/metaball/mball_edit.c
@@ -594,7 +594,7 @@ bool mouse_mball(bContext *C, const int mval[2], bool extend, bool deselect, boo
rect.ymin = mval[1] - 12;
rect.ymax = mval[1] + 12;
- hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect);
+ hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect, true);
/* does startelem exist? */
ml = mb->editelems->first;
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index 99dd8b75609..34b4ca2c0f1 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -1470,7 +1470,7 @@ static void convert_ensure_curve_cache(Main *bmain, Scene *scene, Object *ob)
/* Force creation. This is normally not needed but on operator
* redo we might end up with an object which isn't evaluated yet.
*/
- if (ELEM3(ob->type, OB_SURF, OB_CURVE, OB_FONT)) {
+ if (ELEM(ob->type, OB_SURF, OB_CURVE, OB_FONT)) {
BKE_displist_make_curveTypes(scene, ob, false);
}
else if (ob->type == OB_MBALL) {
@@ -2274,7 +2274,7 @@ static int join_poll(bContext *C)
if (!ob || ob->id.lib) return 0;
- if (ELEM4(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_ARMATURE))
+ if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_ARMATURE))
return ED_operator_screenactive(C);
else
return 0;
diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c
index 94574e81b81..2402ecb498d 100644
--- a/source/blender/editors/object/object_bake.c
+++ b/source/blender/editors/object/object_bake.c
@@ -770,7 +770,7 @@ static int objects_bake_render_modal(bContext *C, wmOperator *UNUSED(op), const
static bool is_multires_bake(Scene *scene)
{
- if (ELEM4(scene->r.bake_mode, RE_BAKE_NORMALS, RE_BAKE_DISPLACEMENT, RE_BAKE_DERIVATIVE, RE_BAKE_AO))
+ if (ELEM(scene->r.bake_mode, RE_BAKE_NORMALS, RE_BAKE_DISPLACEMENT, RE_BAKE_DERIVATIVE, RE_BAKE_AO))
return scene->r.bake_flag & R_BAKE_MULTIRES;
return 0;
diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c
index f57ab220471..e21f56538aa 100644
--- a/source/blender/editors/object/object_bake_api.c
+++ b/source/blender/editors/object/object_bake_api.c
@@ -51,6 +51,7 @@
#include "BKE_image.h"
#include "BKE_library.h"
#include "BKE_main.h"
+#include "BKE_node.h"
#include "BKE_report.h"
#include "BKE_modifier.h"
#include "BKE_mesh.h"
@@ -177,7 +178,7 @@ static bool write_internal_bake_pixels(
void *lock;
bool is_float;
char *mask_buffer = NULL;
- const int num_pixels = width * height;
+ const size_t num_pixels = (size_t)width * (size_t)height;
ibuf = BKE_image_acquire_ibuf(image, NULL, &lock);
@@ -310,7 +311,7 @@ static bool write_external_bake_pixels(
/* margins */
if (margin > 0) {
char *mask_buffer = NULL;
- const int num_pixels = width * height;
+ const size_t num_pixels = (size_t)width * (size_t)height;
mask_buffer = MEM_callocN(sizeof(char) * num_pixels, "Bake Mask");
RE_bake_mask_fill(pixel_array, num_pixels, mask_buffer);
@@ -335,14 +336,14 @@ static bool write_external_bake_pixels(
static bool is_noncolor_pass(ScenePassType pass_type)
{
- return ELEM7(pass_type,
- SCE_PASS_Z,
- SCE_PASS_NORMAL,
- SCE_PASS_VECTOR,
- SCE_PASS_INDEXOB,
- SCE_PASS_UV,
- SCE_PASS_RAYHITS,
- SCE_PASS_INDEXMA);
+ return ELEM(pass_type,
+ SCE_PASS_Z,
+ SCE_PASS_NORMAL,
+ SCE_PASS_VECTOR,
+ SCE_PASS_INDEXOB,
+ SCE_PASS_UV,
+ SCE_PASS_RAYHITS,
+ SCE_PASS_INDEXMA);
}
/* if all is good tag image and return true */
@@ -367,10 +368,22 @@ static bool bake_object_check(Object *ob, ReportList *reports)
}
for (i = 0; i < ob->totcol; i++) {
- ED_object_get_active_image(ob, i + 1, &image, NULL, NULL);
+ bNodeTree *ntree = NULL;
+ bNode *node = NULL;
+ ED_object_get_active_image(ob, i + 1, &image, NULL, &node, &ntree);
if (image) {
- ImBuf *ibuf = BKE_image_acquire_ibuf(image, NULL, &lock);
+ ImBuf *ibuf;
+
+ if (node) {
+ if (BKE_node_is_connected_to_output(ntree, node)) {
+ BKE_reportf(reports, RPT_ERROR,
+ "Circular dependency for image \"%s\" from object \"%s\"",
+ image->id.name + 2, ob->id.name + 2);
+ }
+ }
+
+ ibuf = BKE_image_acquire_ibuf(image, NULL, &lock);
if (ibuf) {
BKE_image_release_ibuf(image, ibuf, lock);
@@ -429,7 +442,7 @@ static bool bake_objects_check(Main *bmain, Object *ob, ListBase *selected_objec
if (ob_iter == ob)
continue;
- if (ELEM5(ob_iter->type, OB_MESH, OB_FONT, OB_CURVE, OB_SURF, OB_MBALL) == false) {
+ if (ELEM(ob_iter->type, OB_MESH, OB_FONT, OB_CURVE, OB_SURF, OB_MBALL) == false) {
BKE_reportf(reports, RPT_ERROR, "Object \"%s\" is not a mesh or can't be converted to a mesh (Curve, Text, Surface or Metaball)", ob_iter->id.name + 2);
return false;
}
@@ -477,7 +490,7 @@ static void build_image_lookup(Main *bmain, Object *ob, BakeImages *bake_images)
for (i = 0; i < tot_mat; i++) {
Image *image;
- ED_object_get_active_image(ob, i + 1, &image, NULL, NULL);
+ ED_object_get_active_image(ob, i + 1, &image, NULL, NULL, NULL);
if ((image->id.flag & LIB_DOIT)) {
for (j = 0; j < i; j++) {
@@ -501,10 +514,10 @@ static void build_image_lookup(Main *bmain, Object *ob, BakeImages *bake_images)
/*
* returns the total number of pixels
*/
-static int initialize_internal_images(BakeImages *bake_images, ReportList *reports)
+static size_t initialize_internal_images(BakeImages *bake_images, ReportList *reports)
{
int i;
- int tot_size = 0;
+ size_t tot_size = 0;
for (i = 0; i < bake_images->size; i++) {
ImBuf *ibuf;
@@ -518,7 +531,7 @@ static int initialize_internal_images(BakeImages *bake_images, ReportList *repor
bk_image->height = ibuf->y;
bk_image->offset = tot_size;
- tot_size += ibuf->x * ibuf->y;
+ tot_size += (size_t)ibuf->x * (size_t)ibuf->y;
}
else {
BKE_image_release_ibuf(bk_image->image, ibuf, lock);
@@ -563,7 +576,7 @@ static int bake(
BakeImages bake_images = {NULL};
- int num_pixels;
+ size_t num_pixels;
int tot_materials;
int i;
@@ -620,7 +633,7 @@ static int bake(
else {
/* when saving extenally always use the size specified in the UI */
- num_pixels = width * height * bake_images.size;
+ num_pixels = (size_t)width * (size_t)height * bake_images.size;
for (i = 0; i < bake_images.size; i++) {
bake_images.data[i].width = width;
@@ -1067,7 +1080,6 @@ static int bake_exec(bContext *C, wmOperator *op)
/* setup new render */
RE_test_break_cb(re, NULL, bake_break);
- RE_progress_cb(re, NULL, bake_progress_update);
if (!bake_objects_check(bkr.main, bkr.ob, &bkr.selected_objects, bkr.reports, bkr.is_selected_to_active))
return OPERATOR_CANCELLED;
diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c
index 85e4bbce8dc..92ed84b7f5e 100644
--- a/source/blender/editors/object/object_constraint.c
+++ b/source/blender/editors/object/object_constraint.c
@@ -485,7 +485,7 @@ static void test_constraints(Object *owner, bPoseChannel *pchan)
}
/* target checks for specific constraints */
- if (ELEM3(curcon->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO, CONSTRAINT_TYPE_SPLINEIK)) {
+ if (ELEM(curcon->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO, CONSTRAINT_TYPE_SPLINEIK)) {
if (ct->tar) {
if (ct->tar->type != OB_CURVE) {
ct->tar = NULL;
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index a6ab4bafcaf..2f499cbc4eb 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -139,7 +139,9 @@ static int object_hide_view_clear_exec(bContext *C, wmOperator *UNUSED(op))
/* XXX need a context loop to handle such cases */
for (base = FIRSTBASE; base; base = base->next) {
if ((base->lay & v3d->lay) && base->object->restrictflag & OB_RESTRICT_VIEW) {
- base->flag |= SELECT;
+ if (!(base->object->restrictflag & OB_RESTRICT_SELECT)) {
+ base->flag |= SELECT;
+ }
base->object->flag = base->flag;
base->object->restrictflag &= ~OB_RESTRICT_VIEW;
changed = true;
@@ -344,6 +346,11 @@ static bool ED_object_editmode_load_ex(Object *obedit, const bool freedata)
if (freedata) free_editMball(obedit);
}
+ /* Tag update so no access to freed data referenced from
+ * derived cache will happen.
+ */
+ DAG_id_tag_update((ID *)obedit->data, 0);
+
return true;
}
@@ -430,7 +437,7 @@ void ED_object_editmode_enter(bContext *C, int flag)
base = scene->basact;
}
- if (ELEM3(NULL, base, base->object, base->object->data)) return;
+ if (ELEM(NULL, base, base->object, base->object->data)) return;
ob = base->object;
@@ -559,7 +566,7 @@ static int editmode_toggle_poll(bContext *C)
if ((ob->restrictflag & OB_RESTRICT_VIEW) && !(ob->mode & OB_MODE_EDIT))
return 0;
- return (ELEM7(ob->type, OB_MESH, OB_ARMATURE, OB_FONT, OB_MBALL, OB_LATTICE, OB_SURF, OB_CURVE));
+ return OB_TYPE_SUPPORT_EDITMODE(ob->type);
}
void OBJECT_OT_editmode_toggle(wmOperatorType *ot)
@@ -730,7 +737,7 @@ static void copy_texture_space(Object *to, Object *ob)
texflag = ((Mesh *)ob->data)->texflag;
poin2 = ((Mesh *)ob->data)->loc;
}
- else if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
+ else if (ELEM(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
texflag = ((Curve *)ob->data)->texflag;
poin2 = ((Curve *)ob->data)->loc;
}
@@ -745,7 +752,7 @@ static void copy_texture_space(Object *to, Object *ob)
((Mesh *)to->data)->texflag = texflag;
poin1 = ((Mesh *)to->data)->loc;
}
- else if (ELEM3(to->type, OB_CURVE, OB_SURF, OB_FONT)) {
+ else if (ELEM(to->type, OB_CURVE, OB_SURF, OB_FONT)) {
((Curve *)to->data)->texflag = texflag;
poin1 = ((Curve *)to->data)->loc;
}
@@ -1082,7 +1089,7 @@ void ED_object_check_force_modifiers(Main *bmain, Scene *scene, Object *object)
/* add/remove modifier as needed */
if (!md) {
if (pd && (pd->shape == PFIELD_SHAPE_SURFACE) && ELEM(pd->forcefield, PFIELD_GUIDE, PFIELD_TEXTURE) == 0)
- if (ELEM4(object->type, OB_MESH, OB_SURF, OB_FONT, OB_CURVE))
+ if (ELEM(object->type, OB_MESH, OB_SURF, OB_FONT, OB_CURVE))
ED_object_modifier_add(NULL, bmain, scene, object, NULL, eModifierType_Surface);
}
else {
@@ -1423,7 +1430,7 @@ static void UNUSED_FUNCTION(image_aspect) (Scene *scene, View3D *v3d)
BKE_mesh_texspace_get(ob->data, NULL, NULL, size);
space = size[0] / size[1];
}
- else if (ELEM3(ob->type, OB_CURVE, OB_FONT, OB_SURF)) {
+ else if (ELEM(ob->type, OB_CURVE, OB_FONT, OB_SURF)) {
float size[3];
BKE_curve_texspace_get(ob->data, NULL, NULL, size);
space = size[0] / size[1];
@@ -1470,7 +1477,7 @@ static EnumPropertyItem *object_mode_set_itemsf(bContext *C, PointerRNA *UNUSED(
if ((input->value == OB_MODE_EDIT && OB_TYPE_SUPPORT_EDITMODE(ob->type)) ||
(input->value == OB_MODE_POSE && (ob->type == OB_ARMATURE)) ||
(input->value == OB_MODE_PARTICLE_EDIT && use_mode_particle_edit) ||
- (ELEM4(input->value, OB_MODE_SCULPT, OB_MODE_VERTEX_PAINT,
+ (ELEM(input->value, OB_MODE_SCULPT, OB_MODE_VERTEX_PAINT,
OB_MODE_WEIGHT_PAINT, OB_MODE_TEXTURE_PAINT) && (ob->type == OB_MESH)) ||
(input->value == OB_MODE_OBJECT))
{
diff --git a/source/blender/editors/object/object_group.c b/source/blender/editors/object/object_group.c
index 47b5f1605e7..20e2e22cdf8 100644
--- a/source/blender/editors/object/object_group.c
+++ b/source/blender/editors/object/object_group.c
@@ -563,3 +563,67 @@ void OBJECT_OT_group_remove(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+
+static int group_unlink_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Group *group = CTX_data_pointer_get_type(C, "group", &RNA_Group).data;
+
+ if (!group)
+ return OPERATOR_CANCELLED;
+
+ BKE_group_unlink(group);
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_group_unlink(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Unlink Group";
+ ot->idname = "OBJECT_OT_group_unlink";
+ ot->description = "Unlink the group from all objects";
+
+ /* api callbacks */
+ ot->exec = group_unlink_exec;
+ ot->poll = ED_operator_objectmode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+static int select_grouped_exec(bContext *C, wmOperator *UNUSED(op)) /* Select objects in the same group as the active */
+{
+ Group *group = CTX_data_pointer_get_type(C, "group", &RNA_Group).data;
+
+ if (!group)
+ return OPERATOR_CANCELLED;
+
+ CTX_DATA_BEGIN (C, Base *, base, visible_bases)
+ {
+ if (!(base->flag & SELECT) && BKE_group_object_exists(group, base->object)) {
+ ED_base_object_select(base, BA_SELECT);
+ }
+ }
+ CTX_DATA_END;
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_grouped_select(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select Grouped";
+ ot->idname = "OBJECT_OT_grouped_select";
+ ot->description = "Select all objects in group";
+
+ /* api callbacks */
+ ot->exec = select_grouped_exec;
+ ot->poll = ED_operator_objectmode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
diff --git a/source/blender/editors/object/object_hook.c b/source/blender/editors/object/object_hook.c
index afff367b939..9f9a647c9f1 100644
--- a/source/blender/editors/object/object_hook.c
+++ b/source/blender/editors/object/object_hook.c
@@ -528,8 +528,7 @@ static int add_hook_object(Main *bmain, Scene *scene, Object *obedit, Object *ob
invert_m4_m4(ob->imat, ob->obmat);
/* apparently this call goes from right to left... */
- mul_serie_m4(hmd->parentinv, pose_mat, ob->imat, obedit->obmat,
- NULL, NULL, NULL, NULL, NULL);
+ mul_m4_series(hmd->parentinv, pose_mat, ob->imat, obedit->obmat);
DAG_relations_tag_update(bmain);
diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h
index fd6b9a1bad0..b8824420018 100644
--- a/source/blender/editors/object/object_intern.h
+++ b/source/blender/editors/object/object_intern.h
@@ -251,6 +251,8 @@ void OBJECT_OT_shape_key_move(struct wmOperatorType *ot);
void OBJECT_OT_group_add(struct wmOperatorType *ot);
void OBJECT_OT_group_link(struct wmOperatorType *ot);
void OBJECT_OT_group_remove(struct wmOperatorType *ot);
+void OBJECT_OT_group_unlink(struct wmOperatorType *ot);
+void OBJECT_OT_grouped_select(struct wmOperatorType *ot);
/* object_bake.c */
void OBJECT_OT_bake_image(wmOperatorType *ot);
diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c
index 1249beb4517..b05840b5823 100644
--- a/source/blender/editors/object/object_modifier.c
+++ b/source/blender/editors/object/object_modifier.c
@@ -98,7 +98,7 @@ ModifierData *ED_object_modifier_add(ReportList *reports, Main *bmain, Scene *sc
ModifierTypeInfo *mti = modifierType_getInfo(type);
/* only geometry objects should be able to get modifiers [#25291] */
- if (!ELEM5(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE)) {
+ if (!ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE)) {
BKE_reportf(reports, RPT_WARNING, "Modifiers cannot be added to object '%s'", ob->id.name + 2);
return NULL;
}
@@ -1876,7 +1876,7 @@ static int meshdeform_bind_exec(bContext *C, wmOperator *op)
else if (ob->type == OB_MBALL) {
BKE_displist_make_mball(CTX_data_main(C)->eval_ctx, scene, ob);
}
- else if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
+ else if (ELEM(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
BKE_displist_make_curveTypes(scene, ob, 0);
}
diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c
index a8f07747d3a..45f981016dc 100644
--- a/source/blender/editors/object/object_ops.c
+++ b/source/blender/editors/object/object_ops.c
@@ -229,6 +229,8 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_group_add);
WM_operatortype_append(OBJECT_OT_group_link);
WM_operatortype_append(OBJECT_OT_group_remove);
+ WM_operatortype_append(OBJECT_OT_group_unlink);
+ WM_operatortype_append(OBJECT_OT_grouped_select);
WM_operatortype_append(OBJECT_OT_hook_add_selob);
WM_operatortype_append(OBJECT_OT_hook_add_newob);
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index 3059d84a085..f6d1df4e8d4 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -444,7 +444,7 @@ EnumPropertyItem prop_clear_parent_types[] = {
/* Helper for ED_object_parent_clear() - Remove deform-modifiers associated with parent */
static void object_remove_parent_deform_modifiers(Object *ob, const Object *par)
{
- if (ELEM3(par->type, OB_ARMATURE, OB_LATTICE, OB_CURVE)) {
+ if (ELEM(par->type, OB_ARMATURE, OB_LATTICE, OB_CURVE)) {
ModifierData *md, *mdn;
/* assume that we only need to remove the first instance of matching deform modifier here */
@@ -593,7 +593,7 @@ int ED_object_parent_set(ReportList *reports, Main *bmain, Scene *scene, Object
int partype, bool xmirror, bool keep_transform, const int vert_par[3])
{
bPoseChannel *pchan = NULL;
- int pararm = ELEM4(partype, PAR_ARMATURE, PAR_ARMATURE_NAME, PAR_ARMATURE_ENVELOPE, PAR_ARMATURE_AUTO);
+ int pararm = ELEM(partype, PAR_ARMATURE, PAR_ARMATURE_NAME, PAR_ARMATURE_ENVELOPE, PAR_ARMATURE_AUTO);
DAG_id_tag_update(&par->id, OB_RECALC_OB);
@@ -678,7 +678,7 @@ int ED_object_parent_set(ReportList *reports, Main *bmain, Scene *scene, Object
* assuming that the parent is selected too...
*/
// XXX currently this should only happen for meshes, curves, surfaces, and lattices - this stuff isn't available for metas yet
- if (ELEM5(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE)) {
+ if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE)) {
ModifierData *md;
switch (partype) {
@@ -1128,7 +1128,7 @@ static int object_track_clear_exec(bContext *C, wmOperator *op)
/* also remove all tracking constraints */
for (con = ob->constraints.last; con; con = pcon) {
pcon = con->prev;
- if (ELEM3(con->type, CONSTRAINT_TYPE_TRACKTO, CONSTRAINT_TYPE_LOCKTRACK, CONSTRAINT_TYPE_DAMPTRACK))
+ if (ELEM(con->type, CONSTRAINT_TYPE_TRACKTO, CONSTRAINT_TYPE_LOCKTRACK, CONSTRAINT_TYPE_DAMPTRACK))
BKE_constraint_remove(&ob->constraints, con);
}
@@ -1192,7 +1192,7 @@ static int track_set_exec(bContext *C, wmOperator *op)
DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
/* Lamp, Camera and Speaker track differently by default */
- if (ELEM3(ob->type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
+ if (ELEM(ob->type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
data->trackflag = TRACK_nZ;
}
}
@@ -1213,7 +1213,7 @@ static int track_set_exec(bContext *C, wmOperator *op)
DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
/* Lamp, Camera and Speaker track differently by default */
- if (ELEM3(ob->type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
+ if (ELEM(ob->type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
data->reserved1 = TRACK_nZ;
data->reserved2 = UP_Y;
}
@@ -1235,7 +1235,7 @@ static int track_set_exec(bContext *C, wmOperator *op)
DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
/* Lamp, Camera and Speaker track differently by default */
- if (ELEM3(ob->type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
+ if (ELEM(ob->type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
data->trackflag = TRACK_nZ;
data->lockflag = LOCK_Y;
}
diff --git a/source/blender/editors/object/object_shapekey.c b/source/blender/editors/object/object_shapekey.c
index be050917f5a..d741991ce7f 100644
--- a/source/blender/editors/object/object_shapekey.c
+++ b/source/blender/editors/object/object_shapekey.c
@@ -494,9 +494,9 @@ static int shape_key_move_poll(bContext *C)
Object *ob = ED_object_context(C);
ID *data = (ob) ? ob->data : NULL;
Key *key = BKE_key_from_object(ob);
- return (ob && !ob->id.lib && data && !data->lib && ob->mode != OB_MODE_EDIT && key && key->totkey);
-}
+ return (ob && !ob->id.lib && data && !data->lib && ob->mode != OB_MODE_EDIT && key && key->totkey > 1);
+}
static EnumPropertyItem slot_move[] = {
{ -2, "TOP", 0, "Top of the list", "" },
@@ -510,17 +510,15 @@ static int shape_key_move_exec(bContext *C, wmOperator *op)
{
Object *ob = ED_object_context(C);
- int type = RNA_enum_get(op->ptr, "type");
- int act_index = ob->shapenr - 1;
- int new_index = act_index;
Key *key = BKE_key_from_object(ob);
KeyBlock *kb = BKE_keyblock_from_object(ob);
+ const int type = RNA_enum_get(op->ptr, "type");
+ const int totkey = key->totkey;
+ const int act_index = ob->shapenr - 1;
+ int new_index;
- if (type >= -1 && type <= 1) {
- new_index = act_index + type;
- }
- else if (type == 2) {
- new_index = key->totkey - 1;
+ if (type == 2) {
+ new_index = totkey - 1;
}
else if (type == -2) {
if (act_index == 1 || act_index == 0)
@@ -528,6 +526,9 @@ static int shape_key_move_exec(bContext *C, wmOperator *op)
else
new_index = 1;
}
+ else {
+ new_index = (totkey + act_index + type) % totkey;
+ }
BKE_keyblock_move(ob, kb, new_index);
diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c
index 6e59f9f4aea..e2ebe583ecf 100644
--- a/source/blender/editors/object/object_transform.c
+++ b/source/blender/editors/object/object_transform.c
@@ -385,7 +385,7 @@ static int apply_objects_internal(bContext *C, ReportList *reports, bool apply_l
/* first check if we can execute */
CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
{
- if (ELEM6(ob->type, OB_MESH, OB_ARMATURE, OB_LATTICE, OB_MBALL, OB_CURVE, OB_SURF)) {
+ if (ELEM(ob->type, OB_MESH, OB_ARMATURE, OB_LATTICE, OB_MBALL, OB_CURVE, OB_SURF)) {
ID *obdata = ob->data;
if (ID_REAL_USERS(obdata) > 1) {
BKE_reportf(reports, RPT_ERROR,
@@ -784,7 +784,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
}
if (ctx_ob_act) {
- BLI_rotatelist_first(&ctx_data_list, (LinkData *)ctx_ob_act);
+ BLI_listbase_rotate_first(&ctx_data_list, (LinkData *)ctx_ob_act);
}
for (tob = bmain->object.first; tob; tob = tob->id.next) {
diff --git a/source/blender/editors/render/render_update.c b/source/blender/editors/render/render_update.c
index 94d8d78de1a..8a034fdd8b5 100644
--- a/source/blender/editors/render/render_update.c
+++ b/source/blender/editors/render/render_update.c
@@ -45,6 +45,7 @@
#include "BLI_utildefines.h"
#include "BKE_context.h"
+#include "BKE_depsgraph.h"
#include "BKE_DerivedMesh.h"
#include "BKE_icons.h"
#include "BKE_main.h"
@@ -165,6 +166,7 @@ void ED_render_engine_changed(Main *bmain)
bScreen *sc;
ScrArea *sa;
Scene *scene;
+ Material *ma;
for (sc = bmain->screen.first; sc; sc = sc->id.next)
for (sa = sc->areabase.first; sa; sa = sa->next)
@@ -174,6 +176,14 @@ void ED_render_engine_changed(Main *bmain)
for (scene = bmain->scene.first; scene; scene = scene->id.next)
ED_render_id_flush_update(bmain, &scene->id);
+
+ /* reset texture painting */
+ for (ma = bmain->mat.first; ma; ma = ma->id.next) {
+ if (ma->texpaintslot) {
+ BKE_texpaint_slots_clear(ma);
+ DAG_id_tag_update(&ma->id, 0);
+ }
+ }
}
/***************************** Updates ***********************************
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index d1375b1b8ab..11e7174ea98 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -931,11 +931,11 @@ static bool region_is_overlap(wmWindow *win, ScrArea *sa, ARegion *ar)
if (U.uiflag2 & USER_REGION_OVERLAP) {
if (WM_is_draw_triple(win)) {
if (ELEM(sa->spacetype, SPACE_VIEW3D, SPACE_SEQ)) {
- if (ELEM3(ar->regiontype, RGN_TYPE_TOOLS, RGN_TYPE_UI, RGN_TYPE_TOOL_PROPS))
+ if (ELEM(ar->regiontype, RGN_TYPE_TOOLS, RGN_TYPE_UI, RGN_TYPE_TOOL_PROPS))
return 1;
}
else if (sa->spacetype == SPACE_IMAGE) {
- if (ELEM4(ar->regiontype, RGN_TYPE_TOOLS, RGN_TYPE_UI, RGN_TYPE_TOOL_PROPS, RGN_TYPE_PREVIEW))
+ if (ELEM(ar->regiontype, RGN_TYPE_TOOLS, RGN_TYPE_UI, RGN_TYPE_TOOL_PROPS, RGN_TYPE_PREVIEW))
return 1;
}
}
diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c
index f76f76aacaa..5beab9fcc14 100644
--- a/source/blender/editors/screen/screen_edit.c
+++ b/source/blender/editors/screen/screen_edit.c
@@ -378,7 +378,7 @@ ScrArea *area_split(bScreen *sc, ScrArea *sa, char dir, float fac, int merge)
if (split == 0) return NULL;
/* note regarding (fac > 0.5f) checks below.
- * notmally it shouldn't matter which is used since the copy should match the original
+ * normally it shouldn't matter which is used since the copy should match the original
* however with viewport rendering and python console this isn't the case. - campbell */
if (dir == 'h') {
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index 2ddda19fb28..7c7574b3af3 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -201,7 +201,7 @@ int ED_operator_animview_active(bContext *C)
{
if (ED_operator_areaactive(C)) {
SpaceLink *sl = (SpaceLink *)CTX_wm_space_data(C);
- if (sl && (ELEM5(sl->spacetype, SPACE_SEQ, SPACE_ACTION, SPACE_NLA, SPACE_IPO, SPACE_TIME)))
+ if (sl && (ELEM(sl->spacetype, SPACE_SEQ, SPACE_ACTION, SPACE_NLA, SPACE_IPO, SPACE_TIME)))
return true;
}
@@ -3220,6 +3220,16 @@ static int match_region_with_redraws(int spacetype, int regiontype, int redraws)
}
}
+ else if (regiontype == RGN_TYPE_CHANNELS) {
+ switch (spacetype) {
+ case SPACE_IPO:
+ case SPACE_ACTION:
+ case SPACE_NLA:
+ if (redraws & TIME_ALL_ANIM_WIN)
+ return 1;
+ break;
+ }
+ }
else if (regiontype == RGN_TYPE_UI) {
if (spacetype == SPACE_CLIP) {
/* Track Preview button is on Properties Editor in SpaceClip,
@@ -4154,7 +4164,8 @@ void ED_keymap_screen(wmKeyConfig *keyconf)
/* dropbox for entire window */
lb = WM_dropboxmap_find("Window", 0, 0);
WM_dropbox_add(lb, "WM_OT_open_mainfile", open_file_drop_poll, open_file_drop_copy);
-
+ WM_dropbox_add(lb, "UI_OT_drop_color", UI_drop_color_poll, UI_drop_color_copy);
+
keymap_modal_set(keyconf);
}
diff --git a/source/blender/editors/sculpt_paint/CMakeLists.txt b/source/blender/editors/sculpt_paint/CMakeLists.txt
index 79ce4f879b7..18db57c9f21 100644
--- a/source/blender/editors/sculpt_paint/CMakeLists.txt
+++ b/source/blender/editors/sculpt_paint/CMakeLists.txt
@@ -40,6 +40,7 @@ set(INC_SYS
set(SRC
paint_cursor.c
+ paint_curve.c
paint_hide.c
paint_image.c
paint_image_2d.c
diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c
index b1e4696cd02..7b9ede38b39 100644
--- a/source/blender/editors/sculpt_paint/paint_cursor.c
+++ b/source/blender/editors/sculpt_paint/paint_cursor.c
@@ -44,6 +44,7 @@
#include "BKE_brush.h"
#include "BKE_context.h"
+#include "BKE_curve.h"
#include "BKE_image.h"
#include "BKE_node.h"
#include "BKE_paint.h"
@@ -58,6 +59,8 @@
#include "ED_view3d.h"
+#include "UI_resources.h"
+
#include "paint_intern.h"
/* still needed for sculpt_stroke_get_location, should be
* removed eventually (TODO) */
@@ -756,7 +759,7 @@ static void paint_draw_alpha_overlay(UnifiedPaintSettings *ups, Brush *brush,
ViewContext *vc, int x, int y, float zoom, PaintMode mode)
{
/* color means that primary brush texture is colured and secondary is used for alpha/mask control */
- bool col = ELEM3(mode, PAINT_TEXTURE_PROJECTIVE, PAINT_TEXTURE_2D, PAINT_VERTEX) ? true : false;
+ bool col = ELEM(mode, PAINT_TEXTURE_PROJECTIVE, PAINT_TEXTURE_2D, PAINT_VERTEX) ? true : false;
OverlayControlFlags flags = BKE_paint_get_overlay_flags();
/* save lots of GL state
* TODO: check on whether all of these are needed? */
@@ -791,6 +794,138 @@ static void paint_draw_alpha_overlay(UnifiedPaintSettings *ups, Brush *brush,
glPopAttrib();
}
+
+BLI_INLINE void draw_tri_point(float *co, float width, bool selected)
+{
+ float w = width / 2.0f;
+ if (selected)
+ UI_ThemeColor4(TH_VERTEX_SELECT);
+ else
+ UI_ThemeColor4(TH_PAINT_CURVE_PIVOT);
+
+ glLineWidth(3.0);
+
+ glBegin(GL_LINE_LOOP);
+ glVertex2f(co[0], co[1] + w);
+ glVertex2f(co[0] - w, co[1] - w);
+ glVertex2f(co[0] + w, co[1] - w);
+ glEnd();
+
+ glColor4f(1.0, 1.0, 1.0, 0.5);
+ glLineWidth(1.0);
+
+ glBegin(GL_LINE_LOOP);
+ glVertex2f(co[0], co[1] + w);
+ glVertex2f(co[0] - w, co[1] - w);
+ glVertex2f(co[0] + w, co[1] - w);
+ glEnd();
+}
+
+BLI_INLINE void draw_rect_point(float *co, float width, bool selected)
+{
+ float w = width / 2.0f;
+ if (selected)
+ UI_ThemeColor4(TH_VERTEX_SELECT);
+ else
+ UI_ThemeColor4(TH_PAINT_CURVE_HANDLE);
+ glLineWidth(3.0);
+
+ glBegin(GL_LINE_LOOP);
+ glVertex2f(co[0] + w, co[1] + w);
+ glVertex2f(co[0] - w, co[1] + w);
+ glVertex2f(co[0] - w, co[1] - w);
+ glVertex2f(co[0] + w, co[1] - w);
+ glEnd();
+
+ glColor4f(1.0, 1.0, 1.0, 0.5);
+ glLineWidth(1.0);
+
+ glBegin(GL_LINE_LOOP);
+ glVertex2f(co[0] + w, co[1] + w);
+ glVertex2f(co[0] - w, co[1] + w);
+ glVertex2f(co[0] - w, co[1] - w);
+ glVertex2f(co[0] + w, co[1] - w);
+ glEnd();
+}
+
+
+BLI_INLINE void draw_bezier_handle_lines(BezTriple *bez)
+{
+ short line1[] = {0, 1};
+ short line2[] = {1, 2};
+
+ glVertexPointer(2, GL_FLOAT, 3 * sizeof(float), bez->vec);
+ glColor4f(0.0, 0.0, 0.0, 0.5);
+ glLineWidth(3.0);
+ glDrawArrays(GL_LINE_STRIP, 0, 3);
+
+ glLineWidth(1.0);
+ if (bez->f1 || bez->f2)
+ UI_ThemeColor4(TH_VERTEX_SELECT);
+ else
+ glColor4f(1.0, 1.0, 1.0, 0.5);
+ glDrawElements(GL_LINES, 2, GL_UNSIGNED_SHORT, line1);
+ if (bez->f3 || bez->f2)
+ UI_ThemeColor4(TH_VERTEX_SELECT);
+ else
+ glColor4f(1.0, 1.0, 1.0, 0.5);
+ glDrawElements(GL_LINES, 2, GL_UNSIGNED_SHORT, line2);
+}
+
+static void paint_draw_curve_cursor(Brush *brush)
+{
+ if (brush->paint_curve && brush->paint_curve->points) {
+ int i;
+ PaintCurve *pc = brush->paint_curve;
+ PaintCurvePoint *cp = pc->points;
+
+ glEnable(GL_LINE_SMOOTH);
+ glEnable(GL_BLEND);
+ glEnableClientState(GL_VERTEX_ARRAY);
+
+ /* draw the bezier handles and the curve segment between the current and next point */
+ for (i = 0; i < pc->tot_points - 1; i++, cp++) {
+ int j;
+ PaintCurvePoint *cp_next = cp + 1;
+ float data[(PAINT_CURVE_NUM_SEGMENTS + 1) * 2];
+ /* use color coding to distinguish handles vs curve segments */
+ draw_bezier_handle_lines(&cp->bez);
+ draw_tri_point(&cp->bez.vec[1][0], 10.0, cp->bez.f2);
+ draw_rect_point(&cp->bez.vec[0][0], 8.0, cp->bez.f1 || cp->bez.f2);
+ draw_rect_point(&cp->bez.vec[2][0], 8.0, cp->bez.f3 || cp->bez.f2);
+
+ for (j = 0; j < 2; j++)
+ BKE_curve_forward_diff_bezier(
+ cp->bez.vec[1][j],
+ cp->bez.vec[2][j],
+ cp_next->bez.vec[0][j],
+ cp_next->bez.vec[1][j],
+ data + j, PAINT_CURVE_NUM_SEGMENTS, sizeof(float[2]));
+
+ glVertexPointer(2, GL_FLOAT, 0, data);
+ glLineWidth(3.0);
+ glColor4f(0.0, 0.0, 0.0, 0.5);
+ glDrawArrays(GL_LINE_STRIP, 0, PAINT_CURVE_NUM_SEGMENTS + 1);
+
+ glLineWidth(1.0);
+ glColor4f(0.9, 0.9, 1.0, 0.5);
+ glDrawArrays(GL_LINE_STRIP, 0, PAINT_CURVE_NUM_SEGMENTS + 1);
+ }
+
+ /* draw last line segment */
+ draw_bezier_handle_lines(&cp->bez);
+ draw_tri_point(&cp->bez.vec[1][0], 10.0, cp->bez.f2);
+ draw_rect_point(&cp->bez.vec[0][0], 8.0, cp->bez.f1 || cp->bez.f2);
+ draw_rect_point(&cp->bez.vec[2][0], 8.0, cp->bez.f3 || cp->bez.f2);
+
+ glLineWidth(1.0);
+
+ glDisable(GL_BLEND);
+ glDisable(GL_LINE_SMOOTH);
+ glDisableClientState(GL_VERTEX_ARRAY);
+ }
+}
+
/* Special actions taken when paint cursor goes over mesh */
/* TODO: sculpt only for now */
static void paint_cursor_on_hit(UnifiedPaintSettings *ups, Brush *brush, ViewContext *vc,
@@ -848,6 +983,12 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
zoomx = max_ff(zoomx, zoomy);
mode = BKE_paintmode_get_active_from_context(C);
+ /* skip everything and draw brush here */
+ if (brush->flag & BRUSH_CURVE) {
+ paint_draw_curve_cursor(brush);
+ return;
+ }
+
/* set various defaults */
translation[0] = x;
translation[1] = y;
@@ -857,8 +998,11 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
/* don't calculate rake angles while a stroke is active because the rake variables are global and
* we may get interference with the stroke itself. For line strokes, such interference is visible */
- if (!ups->stroke_active && (brush->flag & BRUSH_RAKE))
- paint_calculate_rake_rotation(ups, translation);
+ if (!ups->stroke_active) {
+ if (brush->flag & BRUSH_RAKE)
+ /* here, translation contains the mouse coordinates. */
+ paint_calculate_rake_rotation(ups, translation);
+ }
/* draw overlay */
paint_draw_alpha_overlay(ups, brush, &vc, x, y, zoomx, mode);
@@ -878,9 +1022,9 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
/* check if brush is subtracting, use different color then */
/* TODO: no way currently to know state of pen flip or
* invert key modifier without starting a stroke */
- if ((!(brush->flag & BRUSH_INVERTED) ^
+ if ((!(ups->draw_inverted) ^
!(brush->flag & BRUSH_DIR_IN)) &&
- ELEM5(brush->sculpt_tool, SCULPT_TOOL_DRAW,
+ ELEM(brush->sculpt_tool, SCULPT_TOOL_DRAW,
SCULPT_TOOL_INFLATE, SCULPT_TOOL_CLAY,
SCULPT_TOOL_PINCH, SCULPT_TOOL_CREASE))
{
@@ -890,12 +1034,12 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
/* only do if brush is over the mesh */
if (hit)
paint_cursor_on_hit(ups, brush, &vc, location);
+ }
- if (ups->draw_anchored) {
- final_radius = ups->anchored_size;
- translation[0] = ups->anchored_initial_mouse[0];
- translation[1] = ups->anchored_initial_mouse[1];
- }
+ if (ups->draw_anchored) {
+ final_radius = ups->anchored_size;
+ translation[0] = ups->anchored_initial_mouse[0];
+ translation[1] = ups->anchored_initial_mouse[1];
}
/* make lines pretty */
diff --git a/source/blender/editors/sculpt_paint/paint_curve.c b/source/blender/editors/sculpt_paint/paint_curve.c
new file mode 100644
index 00000000000..217c88c87ea
--- /dev/null
+++ b/source/blender/editors/sculpt_paint/paint_curve.c
@@ -0,0 +1,801 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/sculpt_paint/paint_curve.c
+ * \ingroup edsculpt
+ */
+
+#include <string.h>
+#include <limits.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_brush_types.h"
+#include "DNA_object_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_view3d_types.h"
+
+#include "BKE_context.h"
+#include "BKE_main.h"
+#include "BKE_paint.h"
+
+#include "BLI_math_vector.h"
+#include "BLI_string.h"
+
+#include "ED_paint.h"
+#include "ED_view3d.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "UI_view2d.h"
+
+#include "paint_intern.h"
+
+#define PAINT_CURVE_SELECT_THRESHOLD 40.0f
+#define PAINT_CURVE_POINT_SELECT(pcp, i) (*(&pcp->bez.f1 + i) = SELECT)
+
+
+int paint_curve_poll(bContext *C)
+{
+ Object *ob = CTX_data_active_object(C);
+ Paint *p;
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ SpaceImage *sima;
+
+ if (rv3d && !(ob && ((ob->mode & OB_MODE_ALL_PAINT) != 0)))
+ return false;
+
+ sima = CTX_wm_space_image(C);
+
+ if (sima && sima->mode != SI_MODE_PAINT)
+ return false;
+
+ p = BKE_paint_get_active_from_context(C);
+
+ if (p && p->brush && (p->brush->flag & BRUSH_CURVE)) {
+ return true;
+ }
+
+ return false;
+}
+
+/* Paint Curve Undo*/
+
+typedef struct UndoCurve {
+ struct UndoImageTile *next, *prev;
+
+ PaintCurvePoint *points; /* points of curve */
+ int tot_points;
+ int active_point;
+
+ char idname[MAX_ID_NAME]; /* name instead of pointer*/
+} UndoCurve;
+
+static void paintcurve_undo_restore(bContext *C, ListBase *lb)
+{
+ Paint *p = BKE_paint_get_active_from_context(C);
+ UndoCurve *uc;
+ PaintCurve *pc = NULL;
+
+ if (p->brush) {
+ pc = p->brush->paint_curve;
+ }
+
+ if (!pc)
+ return;
+
+ uc = (UndoCurve *)lb->first;
+
+ if (strncmp(uc->idname, pc->id.name, BLI_strnlen(uc->idname, sizeof(uc->idname))) == 0) {
+ SWAP(PaintCurvePoint *, pc->points, uc->points);
+ SWAP(int, pc->tot_points, uc->tot_points);
+ SWAP(int, pc->add_index, uc->active_point);
+ }
+}
+
+static void paintcurve_undo_delete(ListBase *lb)
+{
+ UndoCurve *uc;
+ uc = (UndoCurve *)lb->first;
+
+ if (uc->points)
+ MEM_freeN(uc->points);
+ uc->points = NULL;
+}
+
+
+static void paintcurve_undo_begin(bContext *C, wmOperator *op, PaintCurve *pc)
+{
+ PaintMode mode = BKE_paintmode_get_active_from_context(C);
+ ListBase *lb = NULL;
+ int undo_stack_id;
+ UndoCurve *uc;
+
+ switch (mode) {
+ case PAINT_TEXTURE_2D:
+ case PAINT_TEXTURE_PROJECTIVE:
+ undo_stack_id = UNDO_PAINT_IMAGE;
+ break;
+
+ case PAINT_SCULPT:
+ undo_stack_id = UNDO_PAINT_MESH;
+ break;
+
+ default:
+ /* do nothing, undo is handled by global */
+ return;
+ }
+
+
+ ED_undo_paint_push_begin(undo_stack_id, op->type->name,
+ paintcurve_undo_restore, paintcurve_undo_delete, NULL);
+ lb = undo_paint_push_get_list(undo_stack_id);
+
+ uc = MEM_callocN(sizeof(*uc), "Undo_curve");
+
+ lb->first = uc;
+
+ BLI_strncpy(uc->idname, pc->id.name, sizeof(uc->idname));
+ uc->tot_points = pc->tot_points;
+ uc->active_point = pc->add_index;
+ uc->points = MEM_dupallocN(pc->points);
+
+ undo_paint_push_count_alloc(undo_stack_id, sizeof(*uc) + sizeof(*pc->points) * pc->tot_points);
+
+ ED_undo_paint_push_end(undo_stack_id);
+}
+#define SEL_F1 (1 << 0)
+#define SEL_F2 (1 << 1)
+#define SEL_F3 (1 << 2)
+
+/* returns 0, 1, or 2 in point according to handle 1, pivot or handle 2 */
+static PaintCurvePoint *paintcurve_point_get_closest(PaintCurve *pc, const float pos[2], bool ignore_pivot, const float threshold, char *point)
+{
+ PaintCurvePoint *pcp, *closest = NULL;
+ int i;
+ float dist, closest_dist = FLT_MAX;
+
+ for (i = 0, pcp = pc->points; i < pc->tot_points; i++, pcp++) {
+ dist = len_manhattan_v2v2(pos, pcp->bez.vec[0]);
+ if (dist < threshold) {
+ if (dist < closest_dist) {
+ closest = pcp;
+ closest_dist = dist;
+ if (point)
+ *point = SEL_F1;
+ }
+ }
+ if (!ignore_pivot) {
+ dist = len_manhattan_v2v2(pos, pcp->bez.vec[1]);
+ if (dist < threshold) {
+ if (dist < closest_dist) {
+ closest = pcp;
+ closest_dist = dist;
+ if (point)
+ *point = SEL_F2;
+ }
+ }
+ }
+ dist = len_manhattan_v2v2(pos, pcp->bez.vec[2]);
+ if (dist < threshold) {
+ if (dist < closest_dist) {
+ closest = pcp;
+ closest_dist = dist;
+ if (point)
+ *point = SEL_F3;
+ }
+ }
+ }
+
+ return closest;
+}
+
+static int paintcurve_point_co_index(char sel)
+{
+ char i = 0;
+ while (sel != 1) {
+ sel >>= 1;
+ i++;
+ }
+ return i;
+}
+
+/******************* Operators *********************************/
+
+static int paintcurve_new_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Paint *p = BKE_paint_get_active_from_context(C);
+ Main *bmain = CTX_data_main(C);
+
+ if (p && p->brush) {
+ p->brush->paint_curve = BKE_paint_curve_add(bmain, "PaintCurve");
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void PAINTCURVE_OT_new(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add New Paint Curve";
+ ot->description = "Add new paint curve";
+ ot->idname = "PAINTCURVE_OT_new";
+
+ /* api callbacks */
+ ot->exec = paintcurve_new_exec;
+ ot->poll = paint_curve_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+static void paintcurve_point_add(bContext *C, wmOperator *op, const int loc[2])
+{
+ Paint *p = BKE_paint_get_active_from_context(C);
+ Brush *br = p->brush;
+ Main *bmain = CTX_data_main(C);
+ PaintCurve *pc;
+ PaintCurvePoint *pcp;
+ wmWindow *window = CTX_wm_window(C);
+ ARegion *ar = CTX_wm_region(C);
+ float vec[3] = {loc[0], loc[1], 0.0};
+ int add_index;
+ int i;
+
+ pc = br->paint_curve;
+ if (!pc) {
+ br->paint_curve = pc = BKE_paint_curve_add(bmain, "PaintCurve");
+ }
+
+ paintcurve_undo_begin(C, op, pc);
+
+ pcp = MEM_mallocN((pc->tot_points + 1) * sizeof(PaintCurvePoint), "PaintCurvePoint");
+ add_index = pc->add_index;
+
+ if (pc->points) {
+ if (add_index > 0)
+ memcpy(pcp, pc->points, add_index * sizeof(PaintCurvePoint));
+ if (add_index < pc->tot_points)
+ memcpy(pcp + add_index + 1, pc->points + add_index, (pc->tot_points - add_index) * sizeof(PaintCurvePoint));
+
+ MEM_freeN(pc->points);
+ }
+ pc->points = pcp;
+ pc->tot_points++;
+
+ /* initialize new point */
+ memset(&pcp[add_index], 0, sizeof(PaintCurvePoint));
+ copy_v3_v3(pcp[add_index].bez.vec[0], vec);
+ copy_v3_v3(pcp[add_index].bez.vec[1], vec);
+ copy_v3_v3(pcp[add_index].bez.vec[2], vec);
+
+ /* last step, clear selection from all bezier handles expect the next */
+ for (i = 0; i < pc->tot_points; i++) {
+ pcp[i].bez.f1 = pcp[i].bez.f2 = pcp[i].bez.f3 = 0;
+ }
+ pcp[add_index].bez.f3 = SELECT;
+ pcp[add_index].bez.h2 = HD_ALIGN;
+
+ pc->add_index = add_index + 1;
+
+ WM_paint_cursor_tag_redraw(window, ar);
+}
+
+
+static int paintcurve_add_point_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ int loc[2] = {event->mval[0], event->mval[1]};
+ paintcurve_point_add(C, op, loc);
+ RNA_int_set_array(op->ptr, "location", loc);
+ return OPERATOR_FINISHED;
+}
+
+static int paintcurve_add_point_exec(bContext *C, wmOperator *op)
+{
+ int loc[2];
+
+ if (RNA_struct_property_is_set(op->ptr, "location")) {
+ RNA_int_get_array(op->ptr, "location", loc);
+ paintcurve_point_add(C, op, loc);
+ return OPERATOR_FINISHED;
+ }
+
+ return OPERATOR_CANCELLED;
+}
+
+void PAINTCURVE_OT_add_point(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add New Paint Curve Point";
+ ot->description = "Add new paint curve point";
+ ot->idname = "PAINTCURVE_OT_add_point";
+
+ /* api callbacks */
+ ot->invoke = paintcurve_add_point_invoke;
+ ot->exec = paintcurve_add_point_exec;
+ ot->poll = paint_curve_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER;
+
+ /* properties */
+ RNA_def_int_vector(ot->srna, "location", 2, NULL, 0, SHRT_MAX,
+ "Location", "Location of vertex in area space", 0, SHRT_MAX);
+}
+
+static int paintcurve_delete_point_exec(bContext *C, wmOperator *op)
+{
+ Paint *p = BKE_paint_get_active_from_context(C);
+ Brush *br = p->brush;
+ PaintCurve *pc;
+ PaintCurvePoint *pcp;
+ wmWindow *window = CTX_wm_window(C);
+ ARegion *ar = CTX_wm_region(C);
+ int i;
+ int tot_del = 0;
+ pc = br->paint_curve;
+
+ if (!pc || pc->tot_points == 0) {
+ return OPERATOR_CANCELLED;
+ }
+
+ paintcurve_undo_begin(C, op, pc);
+
+#define DELETE_TAG 2
+
+ for (i = 0, pcp = pc->points; i < pc->tot_points; i++, pcp++) {
+ if ((pcp->bez.f1 & SELECT) || (pcp->bez.f2 & SELECT) || (pcp->bez.f3 & SELECT)) {
+ pcp->bez.f2 |= DELETE_TAG;
+ tot_del++;
+ }
+ }
+
+ if (tot_del > 0) {
+ int j = 0;
+ int new_tot = pc->tot_points - tot_del;
+ PaintCurvePoint *points_new = NULL;
+ if (new_tot > 0)
+ points_new = MEM_mallocN(new_tot * sizeof(PaintCurvePoint), "PaintCurvePoint");
+
+ for (i = 0, pcp = pc->points; i < pc->tot_points; i++, pcp++) {
+ if (!(pcp->bez.f2 & DELETE_TAG)) {
+ points_new[j] = pc->points[i];
+
+ if ((i + 1) == pc->add_index) {
+ pc->add_index = j + 1;
+ }
+ j++;
+ }
+ else if ((i + 1) == pc->add_index) {
+ /* prefer previous point */
+ pc->add_index = j;
+ }
+ }
+ MEM_freeN(pc->points);
+
+ pc->points = points_new;
+ pc->tot_points = new_tot;
+ }
+
+#undef DELETE_TAG
+
+ WM_paint_cursor_tag_redraw(window, ar);
+
+ return OPERATOR_FINISHED;
+}
+
+
+void PAINTCURVE_OT_delete_point(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add New Paint Curve Point";
+ ot->description = "Add new paint curve point";
+ ot->idname = "PAINTCURVE_OT_delete_point";
+
+ /* api callbacks */
+ ot->exec = paintcurve_delete_point_exec;
+ ot->poll = paint_curve_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+}
+
+
+static bool paintcurve_point_select(bContext *C, wmOperator *op, const int loc[2], bool toggle, bool extend)
+{
+ wmWindow *window = CTX_wm_window(C);
+ ARegion *ar = CTX_wm_region(C);
+ Paint *p = BKE_paint_get_active_from_context(C);
+ Brush *br = p->brush;
+ PaintCurve *pc;
+ PaintCurvePoint *pcp;
+ int i;
+ const float loc_fl[2] = {UNPACK2(loc)};
+
+ pc = br->paint_curve;
+
+ if (!pc)
+ return false;
+
+ paintcurve_undo_begin(C, op, pc);
+
+ pcp = pc->points;
+
+ if (toggle) {
+ char select = 0;
+ bool selected = false;
+
+ for (i = 0; i < pc->tot_points; i++) {
+ if (pcp[i].bez.f1 || pcp[i].bez.f2 || pcp[i].bez.f3) {
+ selected = true;
+ break;
+ }
+ }
+
+ if (!selected) {
+ select = SELECT;
+ }
+
+ for (i = 0; i < pc->tot_points; i++) {
+ pc->points[i].bez.f1 = pc->points[i].bez.f2 = pc->points[i].bez.f3 = select;
+ }
+ }
+ else {
+ PaintCurvePoint *pcp;
+ char selflag;
+
+ pcp = paintcurve_point_get_closest(pc, loc_fl, false, PAINT_CURVE_SELECT_THRESHOLD, &selflag);
+
+ if (pcp) {
+ pc->add_index = (pcp - pc->points) + 1;
+
+ if (selflag == SEL_F2) {
+ if (extend)
+ pcp->bez.f2 ^= SELECT;
+ else
+ pcp->bez.f2 |= SELECT;
+ }
+ else if (selflag == SEL_F1) {
+ if (extend)
+ pcp->bez.f1 ^= SELECT;
+ else
+ pcp->bez.f1 |= SELECT;
+ }
+ else if (selflag == SEL_F3) {
+ if (extend)
+ pcp->bez.f3 ^= SELECT;
+ else
+ pcp->bez.f3 |= SELECT;
+ }
+ }
+
+ /* clear selection for unselected points if not extending and if a point has been selected */
+ if (!extend && pcp) {
+ for (i = 0; i < pc->tot_points; i++) {
+ pc->points[i].bez.f1 = pc->points[i].bez.f2 = pc->points[i].bez.f3 = 0;
+
+ if ((pc->points + i) == pcp) {
+ char index = paintcurve_point_co_index(selflag);
+ PAINT_CURVE_POINT_SELECT(pcp, index);
+ }
+ }
+ }
+
+ if (!pcp)
+ return false;
+ }
+
+ WM_paint_cursor_tag_redraw(window, ar);
+
+ return true;
+}
+
+
+static int paintcurve_select_point_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ int loc[2] = {UNPACK2(event->mval)};
+ bool toggle = RNA_boolean_get(op->ptr, "toggle");
+ bool extend = RNA_boolean_get(op->ptr, "extend");
+ if (paintcurve_point_select(C, op, loc, toggle, extend)) {
+ RNA_int_set_array(op->ptr, "location", loc);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
+}
+
+static int paintcurve_select_point_exec(bContext *C, wmOperator *op)
+{
+ int loc[2];
+
+ if (RNA_struct_property_is_set(op->ptr, "location")) {
+ bool toggle = RNA_boolean_get(op->ptr, "toggle");
+ bool extend = RNA_boolean_get(op->ptr, "extend");
+ RNA_int_get_array(op->ptr, "location", loc);
+ if (paintcurve_point_select(C, op, loc, toggle, extend))
+ return OPERATOR_FINISHED;
+ }
+
+ return OPERATOR_CANCELLED;
+}
+
+void PAINTCURVE_OT_select(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Select Paint Curve Point";
+ ot->description = "Select a paint curve point";
+ ot->idname = "PAINTCURVE_OT_select";
+
+ /* api callbacks */
+ ot->invoke = paintcurve_select_point_invoke;
+ ot->exec = paintcurve_select_point_exec;
+ ot->poll = paint_curve_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER;
+
+ /* properties */
+ RNA_def_int_vector(ot->srna, "location", 2, NULL, 0, SHRT_MAX,
+ "Location", "Location of vertex in area space", 0, SHRT_MAX);
+ prop = RNA_def_boolean(ot->srna, "toggle", false, "Toggle", "(De)select all");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+}
+
+typedef struct PointSlideData {
+ PaintCurvePoint *pcp;
+ char select;
+ int initial_loc[2];
+ float point_initial_loc[3][2];
+ int event;
+ bool align;
+} PointSlideData;
+
+static int paintcurve_slide_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ Paint *p = BKE_paint_get_active_from_context(C);
+ const float loc_fl[2] = {UNPACK2(event->mval)};
+ char select;
+ int i;
+ bool do_select = RNA_boolean_get(op->ptr, "select");
+ bool align = RNA_boolean_get(op->ptr, "align");
+ Brush *br = p->brush;
+ PaintCurve *pc = br->paint_curve;
+ PaintCurvePoint *pcp;
+
+ if (!pc)
+ return OPERATOR_PASS_THROUGH;
+
+ if (do_select) {
+ pcp = paintcurve_point_get_closest(pc, loc_fl, align, PAINT_CURVE_SELECT_THRESHOLD, &select);
+ }
+ else {
+ pcp = NULL;
+ /* just find first selected point */
+ for (i = 0; i < pc->tot_points; i++) {
+ if (pc->points[i].bez.f1 || pc->points[i].bez.f2 || pc->points[i].bez.f3) {
+ pcp = &pc->points[i];
+ select = SEL_F3;
+ break;
+ }
+ }
+ }
+
+
+ if (pcp) {
+ ARegion *ar = CTX_wm_region(C);
+ wmWindow *window = CTX_wm_window(C);
+ PointSlideData *psd = MEM_mallocN(sizeof(PointSlideData), "PointSlideData");
+ copy_v2_v2_int(psd->initial_loc, event->mval);
+ psd->event = event->type;
+ psd->pcp = pcp;
+ psd->select = paintcurve_point_co_index(select);
+ for (i = 0; i < 3; i++) {
+ copy_v2_v2(psd->point_initial_loc[i], pcp->bez.vec[i]);
+ }
+ psd->align = align;
+ op->customdata = psd;
+
+ if (do_select)
+ paintcurve_undo_begin(C, op, pc);
+
+ /* first, clear all selection from points */
+ for (i = 0; i < pc->tot_points; i++)
+ pc->points[i].bez.f1 = pc->points[i].bez.f3 = pc->points[i].bez.f2 = 0;
+
+ /* only select the active point */
+ PAINT_CURVE_POINT_SELECT(pcp, psd->select);
+ pc->add_index = (pcp - pc->points) + 1;
+
+ WM_event_add_modal_handler(C, op);
+ WM_paint_cursor_tag_redraw(window, ar);
+ return OPERATOR_RUNNING_MODAL;
+ }
+
+ return OPERATOR_PASS_THROUGH;
+}
+
+static int paintcurve_slide_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ PointSlideData *psd = op->customdata;
+
+ if (event->type == psd->event && event->val == KM_RELEASE) {
+ MEM_freeN(psd);
+ return OPERATOR_FINISHED;
+ }
+
+ switch (event->type) {
+ case MOUSEMOVE:
+ {
+ ARegion *ar = CTX_wm_region(C);
+ wmWindow *window = CTX_wm_window(C);
+ float diff[2] = {event->mval[0] - psd->initial_loc[0],
+ event->mval[1] - psd->initial_loc[1]};
+ if (psd->select == 1) {
+ int i;
+ for (i = 0; i < 3; i++)
+ add_v2_v2v2(psd->pcp->bez.vec[i], diff, psd->point_initial_loc[i]);
+ }
+ else {
+ add_v2_v2(diff, psd->point_initial_loc[psd->select]);
+ copy_v2_v2(psd->pcp->bez.vec[psd->select], diff);
+
+ if (psd->align) {
+ char opposite = (psd->select == 0) ? 2 : 0;
+ sub_v2_v2v2(diff, psd->pcp->bez.vec[1], psd->pcp->bez.vec[psd->select]);
+ add_v2_v2v2(psd->pcp->bez.vec[opposite], psd->pcp->bez.vec[1], diff);
+ }
+ }
+ WM_paint_cursor_tag_redraw(window, ar);
+ break;
+ }
+ default:
+ break;
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+
+void PAINTCURVE_OT_slide(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Slide Paint Curve Point";
+ ot->description = "Select and slide paint curve point";
+ ot->idname = "PAINTCURVE_OT_slide";
+
+ /* api callbacks */
+ ot->invoke = paintcurve_slide_invoke;
+ ot->modal = paintcurve_slide_modal;
+ ot->poll = paint_curve_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "align", false, "Align Handles", "Aligns opposite point handle during transform");
+ RNA_def_boolean(ot->srna, "select", true, "Select", "Attempt to select a point handle before transform");
+}
+
+static int paintcurve_draw_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ PaintMode mode = BKE_paintmode_get_active_from_context(C);
+ const char *name;
+
+ switch (mode) {
+ case PAINT_TEXTURE_2D:
+ case PAINT_TEXTURE_PROJECTIVE:
+ name = "PAINT_OT_image_paint";
+ break;
+ case PAINT_WEIGHT:
+ name = "PAINT_OT_weight_paint";
+ break;
+ case PAINT_VERTEX:
+ name = "PAINT_OT_vertex_paint";
+ break;
+ case PAINT_SCULPT:
+ name = "SCULPT_OT_brush_stroke";
+ break;
+ default:
+ return OPERATOR_PASS_THROUGH;
+ }
+
+ return WM_operator_name_call(C, name, WM_OP_INVOKE_DEFAULT, NULL);
+}
+
+void PAINTCURVE_OT_draw(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Draw Curve";
+ ot->description = "Draw curve";
+ ot->idname = "PAINTCURVE_OT_draw";
+
+ /* api callbacks */
+ ot->exec = paintcurve_draw_exec;
+ ot->poll = paint_curve_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+}
+
+static int paintcurve_cursor_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ op->customdata = SET_INT_IN_POINTER(event->type);
+ WM_event_add_modal_handler(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int paintcurve_cursor_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ if (event->type == GET_INT_FROM_POINTER(op->customdata) && event->val == KM_RELEASE)
+ return OPERATOR_FINISHED;
+
+ if (event->type == MOUSEMOVE) {
+ PaintMode mode = BKE_paintmode_get_active_from_context(C);
+
+ switch (mode) {
+ case PAINT_TEXTURE_2D:
+ {
+ ARegion *ar = CTX_wm_region(C);
+ SpaceImage *sima = CTX_wm_space_image(C);
+ float location[2];
+
+ if (!sima)
+ return OPERATOR_CANCELLED;
+
+ UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &location[0], &location[1]);
+ copy_v2_v2(sima->cursor, location);
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_IMAGE, NULL);
+ break;
+ }
+ default:
+ ED_view3d_cursor3d_update(C, event->mval);
+ break;
+ }
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+void PAINTCURVE_OT_cursor(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Place Cursor";
+ ot->description = "Place cursor";
+ ot->idname = "PAINTCURVE_OT_cursor";
+
+ /* api callbacks */
+ ot->invoke = paintcurve_cursor_invoke;
+ ot->modal = paintcurve_cursor_modal;
+ ot->poll = paint_curve_poll;
+
+ /* flags */
+ ot->flag = 0;
+}
diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c
index 34232c51ff7..f1a2a8156d8 100644
--- a/source/blender/editors/sculpt_paint/paint_image.c
+++ b/source/blender/editors/sculpt_paint/paint_image.c
@@ -43,6 +43,7 @@
#include "BLI_math.h"
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
+#include "BLI_threads.h"
#include "PIL_time.h"
@@ -59,15 +60,21 @@
#include "BKE_brush.h"
#include "BKE_image.h"
#include "BKE_main.h"
+#include "BKE_material.h"
#include "BKE_mesh.h"
#include "BKE_node.h"
#include "BKE_paint.h"
+#include "BKE_report.h"
+#include "BKE_scene.h"
+#include "BKE_texture.h"
+#include "BKE_colortools.h"
#include "BKE_editmesh.h"
#include "UI_view2d.h"
#include "ED_image.h"
+#include "ED_mesh.h"
#include "ED_object.h"
#include "ED_paint.h"
#include "ED_screen.h"
@@ -82,6 +89,9 @@
#include "GPU_draw.h"
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
#include "IMB_colormanagement.h"
#include "paint_intern.h"
@@ -102,14 +112,27 @@ typedef struct UndoImageTile {
int x, y;
+ Image *ima;
short source, use_float;
char gen_type;
+ bool valid;
} UndoImageTile;
/* this is a static resource for non-globality,
* Maybe it should be exposed as part of the
* paint operation, but for now just give a public interface */
static ImagePaintPartialRedraw imapaintpartial = {0, 0, 0, 0, 0};
+static SpinLock undolock;
+
+void image_undo_init_locks(void)
+{
+ BLI_spin_init(&undolock);
+}
+
+void image_undo_end_locks(void)
+{
+ BLI_spin_end(&undolock);
+}
ImagePaintPartialRedraw *get_imapaintpartial(void)
{
@@ -122,26 +145,53 @@ void set_imapaintpartial(struct ImagePaintPartialRedraw *ippr)
}
/* UNDO */
+typedef enum {
+ COPY = 0,
+ RESTORE = 1,
+ RESTORE_COPY = 2
+} CopyMode;
-static void undo_copy_tile(UndoImageTile *tile, ImBuf *tmpibuf, ImBuf *ibuf, int restore)
+static void undo_copy_tile(UndoImageTile *tile, ImBuf *tmpibuf, ImBuf *ibuf, CopyMode mode)
{
- /* copy or swap contents of tile->rect and region in ibuf->rect */
- IMB_rectcpy(tmpibuf, ibuf, 0, 0, tile->x * IMAPAINT_TILE_SIZE,
- tile->y * IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE);
+ if (mode == COPY) {
+ /* copy or swap contents of tile->rect and region in ibuf->rect */
+ IMB_rectcpy(tmpibuf, ibuf, 0, 0, tile->x * IMAPAINT_TILE_SIZE,
+ tile->y * IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE);
- if (ibuf->rect_float) {
- SWAP(float *, tmpibuf->rect_float, tile->rect.fp);
+ if (ibuf->rect_float) {
+ SWAP(float *, tmpibuf->rect_float, tile->rect.fp);
+ }
+ else {
+ SWAP(unsigned int *, tmpibuf->rect, tile->rect.uint);
+ }
}
else {
- SWAP(unsigned int *, tmpibuf->rect, tile->rect.uint);
- }
-
- if (restore)
+ if (mode == RESTORE_COPY)
+ IMB_rectcpy(tmpibuf, ibuf, 0, 0, tile->x * IMAPAINT_TILE_SIZE,
+ tile->y * IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE);
+ /* swap to the tmpbuf for easy copying */
+ if (ibuf->rect_float) {
+ SWAP(float *, tmpibuf->rect_float, tile->rect.fp);
+ }
+ else {
+ SWAP(unsigned int *, tmpibuf->rect, tile->rect.uint);
+ }
+
IMB_rectcpy(ibuf, tmpibuf, tile->x * IMAPAINT_TILE_SIZE,
tile->y * IMAPAINT_TILE_SIZE, 0, 0, IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE);
+
+ if (mode == RESTORE) {
+ if (ibuf->rect_float) {
+ SWAP(float *, tmpibuf->rect_float, tile->rect.fp);
+ }
+ else {
+ SWAP(unsigned int *, tmpibuf->rect, tile->rect.uint);
+ }
+ }
+ }
}
-void *image_undo_find_tile(Image *ima, ImBuf *ibuf, int x_tile, int y_tile, unsigned short **mask)
+void *image_undo_find_tile(Image *ima, ImBuf *ibuf, int x_tile, int y_tile, unsigned short **mask, bool validate)
{
ListBase *lb = undo_paint_push_get_list(UNDO_PAINT_IMAGE);
UndoImageTile *tile;
@@ -160,6 +210,8 @@ void *image_undo_find_tile(Image *ima, ImBuf *ibuf, int x_tile, int y_tile, unsi
*mask = tile->mask;
}
+ if (validate)
+ tile->valid = true;
return tile->rect.pt;
}
@@ -170,7 +222,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)
+void *image_undo_push_tile(Image *ima, ImBuf *ibuf, ImBuf **tmpibuf, int x_tile, int y_tile, unsigned short **mask, bool **valid, bool proj)
{
ListBase *lb = undo_paint_push_get_list(UNDO_PAINT_IMAGE);
UndoImageTile *tile;
@@ -179,10 +231,14 @@ void *image_undo_push_tile(Image *ima, ImBuf *ibuf, ImBuf **tmpibuf, int x_tile,
void *data;
/* check if tile is already pushed */
- data = image_undo_find_tile(ima, ibuf, x_tile, y_tile, NULL);
- if (data)
- return data;
-
+
+ /* in projective painting we keep accounting of tiles, so if we need one pushed, just push! */
+ if (!proj) {
+ data = image_undo_find_tile(ima, ibuf, x_tile, y_tile, mask, true);
+ if (data)
+ return data;
+ }
+
if (*tmpibuf == NULL)
*tmpibuf = IMB_allocImBuf(IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, 32, IB_rectfloat | IB_rect);
@@ -191,6 +247,11 @@ void *image_undo_push_tile(Image *ima, ImBuf *ibuf, ImBuf **tmpibuf, int x_tile,
tile->x = x_tile;
tile->y = y_tile;
+ /* add mask explicitly here */
+ if (mask)
+ *mask = tile->mask = MEM_callocN(sizeof(unsigned short) * IMAPAINT_TILE_SIZE * IMAPAINT_TILE_SIZE,
+ "UndoImageTile.mask");
+
allocsize = IMAPAINT_TILE_SIZE * IMAPAINT_TILE_SIZE * 4;
allocsize *= (ibuf->rect_float) ? sizeof(float) : sizeof(char);
tile->rect.pt = MEM_mapallocN(allocsize, "UndeImageTile.rect");
@@ -200,12 +261,23 @@ void *image_undo_push_tile(Image *ima, ImBuf *ibuf, ImBuf **tmpibuf, int x_tile,
tile->gen_type = ima->gen_type;
tile->source = ima->source;
tile->use_float = use_float;
+ tile->valid = true;
+ tile->ima = ima;
- undo_copy_tile(tile, *tmpibuf, ibuf, 0);
- undo_paint_push_count_alloc(UNDO_PAINT_IMAGE, allocsize);
+ if (valid)
+ *valid = &tile->valid;
+
+ undo_copy_tile(tile, *tmpibuf, ibuf, COPY);
+
+ if (proj)
+ BLI_spin_lock(&undolock);
+ undo_paint_push_count_alloc(UNDO_PAINT_IMAGE, allocsize);
BLI_addtail(lb, tile);
-
+
+ if (proj)
+ BLI_spin_unlock(&undolock);
+
return tile->rect.pt;
}
@@ -222,6 +294,33 @@ void image_undo_remove_masks(void)
}
}
+static void image_undo_restore_runtime(ListBase *lb)
+{
+ ImBuf *ibuf, *tmpibuf;
+ UndoImageTile *tile;
+
+ tmpibuf = IMB_allocImBuf(IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, 32,
+ IB_rectfloat | IB_rect);
+
+ for (tile = lb->first; tile; tile = tile->next) {
+ Image *ima = tile->ima;
+ ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
+
+ undo_copy_tile(tile, tmpibuf, ibuf, RESTORE);
+
+ GPU_free_image(ima); /* force OpenGL reload (maybe partial update will operate better?) */
+ if (ibuf->rect_float)
+ ibuf->userflags |= IB_RECT_INVALID; /* force recreate of char rect */
+ if (ibuf->mipmap[0])
+ ibuf->userflags |= IB_MIPMAP_INVALID; /* force mipmap recreatiom */
+ ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
+
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ }
+
+ IMB_freeImBuf(tmpibuf);
+}
+
void ED_image_undo_restore(bContext *C, ListBase *lb)
{
Main *bmain = CTX_data_main(C);
@@ -273,7 +372,7 @@ void ED_image_undo_restore(bContext *C, ListBase *lb)
continue;
}
- undo_copy_tile(tile, tmpibuf, ibuf, 1);
+ undo_copy_tile(tile, tmpibuf, ibuf, RESTORE_COPY);
GPU_free_image(ima); /* force OpenGL reload */
if (ibuf->rect_float)
@@ -282,6 +381,8 @@ void ED_image_undo_restore(bContext *C, ListBase *lb)
ibuf->userflags |= IB_MIPMAP_INVALID; /* force mipmap recreatiom */
ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
+ DAG_id_tag_update(&ima->id, 0);
+
BKE_image_release_ibuf(ima, ibuf, NULL);
}
@@ -296,6 +397,42 @@ void ED_image_undo_free(ListBase *lb)
MEM_freeN(tile->rect.pt);
}
+static void image_undo_end(void)
+{
+ ListBase *lb = undo_paint_push_get_list(UNDO_PAINT_IMAGE);
+ UndoImageTile *tile;
+ int deallocsize = 0;
+ int allocsize = IMAPAINT_TILE_SIZE * IMAPAINT_TILE_SIZE * 4;
+
+ /* first dispose of invalid tiles (may happen due to drag dot for instance) */
+ for (tile = lb->first; tile;) {
+ if (!tile->valid) {
+ UndoImageTile *tmp_tile = tile->next;
+ deallocsize += allocsize * ((tile->use_float) ? sizeof(float) : sizeof(char));
+ MEM_freeN(tile->rect.pt);
+ BLI_freelinkN (lb, tile);
+ tile = tmp_tile;
+ }
+ else {
+ tile = tile->next;
+ }
+ }
+
+ /* don't forget to remove the size of deallocated tiles */
+ undo_paint_push_count_alloc(UNDO_PAINT_IMAGE, -deallocsize);
+
+ ED_undo_paint_push_end(UNDO_PAINT_IMAGE);
+}
+
+static void image_undo_invalidate(void)
+{
+ UndoImageTile *tile;
+ ListBase *lb = undo_paint_push_get_list(UNDO_PAINT_IMAGE);
+
+ for (tile = lb->first; tile; tile = tile->next)
+ tile->valid = false;
+}
+
/* Imagepaint Partial Redraw & Dirty Region */
void ED_imapaint_clear_partial_redraw(void)
@@ -344,7 +481,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);
+ image_undo_push_tile(ima, ibuf, &tmpibuf, tx, ty, NULL, NULL, false);
ibuf->userflags |= IB_BITMAPDIRTY;
@@ -373,6 +510,70 @@ void imapaint_image_update(SpaceImage *sima, Image *image, ImBuf *ibuf, short te
}
}
+/* paint blur kernels */
+BlurKernel *paint_new_blur_kernel(Brush *br)
+{
+ int i, j;
+ BlurKernel *kernel = MEM_mallocN(sizeof(BlurKernel), "blur kernel");
+ int pixel_len = br->blur_kernel_radius;
+ BlurKernelType type = br->blur_mode;
+
+ kernel->side = pixel_len * 2 + 1;
+ kernel->side_squared = kernel->side * kernel->side;
+ kernel->wdata = MEM_mallocN(sizeof(float) * kernel->side_squared, "blur kernel data");
+ kernel->pixel_len = pixel_len;
+
+ switch (type) {
+ case KERNEL_BOX:
+ for (i = 0; i < kernel->side_squared; i++)
+ kernel->wdata[i] = 1.0;
+ break;
+
+ case KERNEL_GAUSSIAN:
+ {
+ float standard_dev = pixel_len / 3.0; /* at standard deviation of 3.0 kernel is at about zero */
+ int i_term = pixel_len + 1;
+
+ /* make the necessary adjustment to the value for use in the normal distribution formula */
+ standard_dev = standard_dev * standard_dev * 2;
+
+ kernel->wdata[pixel_len + pixel_len * kernel->side] = 1.0;
+ /* fill in all four quadrants at once */
+ for (i = 0; i < i_term; i++) {
+ for (j = 0; j < pixel_len; j++) {
+ float idist = pixel_len - i;
+ float jdist = pixel_len - j;
+
+ float value = exp((idist * idist + jdist * jdist) / standard_dev);
+
+ kernel->wdata[i + j * kernel->side] =
+ kernel->wdata[(kernel->side - j - 1) + i * kernel->side] =
+ kernel->wdata[(kernel->side - i - 1) + (kernel->side - j - 1) * kernel->side] =
+ kernel->wdata[j + (kernel->side - i - 1) * kernel->side] =
+ value;
+ }
+ }
+
+ break;
+ }
+
+ default:
+ printf("unidentified kernel type, aborting\n");
+ MEM_freeN(kernel->wdata);
+ MEM_freeN(kernel);
+ return NULL;
+ break;
+ }
+
+ return kernel;
+}
+
+void paint_delete_blur_kernel(BlurKernel *kernel)
+{
+ if (kernel->wdata)
+ MEM_freeN(kernel->wdata);
+}
+
/************************ image paint poll ************************/
static Brush *image_paint_brush(bContext *C)
@@ -432,11 +633,57 @@ typedef struct PaintOperation {
void *custom_paint;
float prevmouse[2];
+ float startmouse[2];
double starttime;
+ void *cursor;
ViewContext vc;
} PaintOperation;
+bool paint_use_opacity_masking(Brush *brush)
+{
+ return (brush->flag & BRUSH_AIRBRUSH) ||
+ (brush->flag & BRUSH_DRAG_DOT) ||
+ (brush->flag & BRUSH_ANCHORED) ||
+ (brush->imagepaint_tool == PAINT_TOOL_SMEAR) ||
+ (brush->imagepaint_tool == PAINT_TOOL_SOFTEN) ||
+ (brush->imagepaint_tool == PAINT_TOOL_FILL) ||
+ (brush->flag & BRUSH_USE_GRADIENT) ||
+ (brush->mtex.tex && !ELEM(brush->mtex.brush_map_mode, MTEX_MAP_MODE_TILED, MTEX_MAP_MODE_STENCIL, MTEX_MAP_MODE_3D)) ?
+ false : true;
+}
+
+void paint_brush_color_get(struct Scene *scene, struct Brush *br, bool color_correction, bool invert, float distance,
+ float pressure, float color[3], struct ColorManagedDisplay *display)
+{
+ if (invert)
+ copy_v3_v3(color, BKE_brush_secondary_color_get(scene, br));
+ else {
+ if (br->flag & BRUSH_USE_GRADIENT) {
+ switch (br->gradient_stroke_mode) {
+ case BRUSH_GRADIENT_PRESSURE:
+ do_colorband(br->gradient, pressure, color);
+ break;
+ case BRUSH_GRADIENT_SPACING_REPEAT:
+ {
+ float coord = fmod(distance / br->gradient_spacing, 1.0);
+ do_colorband(br->gradient, coord, color);
+ break;
+ }
+ case BRUSH_GRADIENT_SPACING_CLAMP:
+ {
+ do_colorband(br->gradient, distance / br->gradient_spacing, color);
+ break;
+ }
+ }
+ }
+ else
+ copy_v3_v3(color, BKE_brush_color_get(scene, br));
+ }
+ if (color_correction)
+ IMB_colormanagement_display_to_scene_linear_v3(color, display);
+}
+
void paint_brush_init_tex(Brush *brush)
{
/* init mtex nodes */
@@ -462,26 +709,54 @@ void paint_brush_exit_tex(Brush *brush)
}
}
+static void gradient_draw_line(bContext *UNUSED(C), int x, int y, void *customdata)
+{
+ PaintOperation *pop = (PaintOperation *)customdata;
+
+ if (pop) {
+ glEnable(GL_LINE_SMOOTH);
+ glEnable(GL_BLEND);
+
+ glLineWidth(4.0);
+ glColor4ub(0, 0, 0, 255);
+ sdrawline(x, y, pop->startmouse[0], pop->startmouse[1]);
+ glLineWidth(2.0);
+ glColor4ub(255, 255, 255, 255);
+ sdrawline(x, y, pop->startmouse[0], pop->startmouse[1]);
+ glLineWidth(1.0);
+
+ glDisable(GL_BLEND);
+ glDisable(GL_LINE_SMOOTH);
+ }
+}
+
-static PaintOperation *texture_paint_init(bContext *C, wmOperator *op, float mouse[2])
+static PaintOperation *texture_paint_init(bContext *C, wmOperator *op, const float mouse[2])
{
Scene *scene = CTX_data_scene(C);
ToolSettings *settings = scene->toolsettings;
PaintOperation *pop = MEM_callocN(sizeof(PaintOperation), "PaintOperation"); /* caller frees */
+ Brush *brush = BKE_paint_brush(&settings->imapaint.paint);
int mode = RNA_enum_get(op->ptr, "mode");
view3d_set_viewcontext(C, &pop->vc);
- pop->prevmouse[0] = mouse[0];
- pop->prevmouse[1] = mouse[1];
+ copy_v2_v2(pop->prevmouse, mouse);
+ copy_v2_v2(pop->startmouse, mouse);
+
+ if ((brush->imagepaint_tool == PAINT_TOOL_FILL) && (brush->flag & BRUSH_USE_GRADIENT)) {
+ pop->cursor = WM_paint_cursor_activate(CTX_wm_manager(C), image_paint_poll, gradient_draw_line, pop);
+ }
/* initialize from context */
if (CTX_wm_region_view3d(C)) {
+ Object *ob = OBACT;
+ paint_proj_mesh_data_ensure(C, ob, op);
pop->mode = PAINT_MODE_3D_PROJECT;
- pop->custom_paint = paint_proj_new_stroke(C, OBACT, pop->prevmouse, mode);
+ pop->custom_paint = paint_proj_new_stroke(C, ob, mouse, mode);
}
else {
pop->mode = PAINT_MODE_2D;
- pop->custom_paint = paint_2d_new_stroke(C, op);
+ pop->custom_paint = paint_2d_new_stroke(C, op, mode);
}
if (!pop->custom_paint) {
@@ -491,52 +766,69 @@ static PaintOperation *texture_paint_init(bContext *C, wmOperator *op, float mou
settings->imapaint.flag |= IMAGEPAINT_DRAWING;
ED_undo_paint_push_begin(UNDO_PAINT_IMAGE, op->type->name,
- ED_image_undo_restore, ED_image_undo_free);
-
- {
- UnifiedPaintSettings *ups = &settings->unified_paint_settings;
- ups->stroke_active = true;
- }
+ ED_image_undo_restore, ED_image_undo_free, NULL);
return pop;
}
+/* restore painting image to previous state. Used for anchored and drag-dot style brushes*/
+static void paint_stroke_restore(void)
+{
+ ListBase *lb = undo_paint_push_get_list(UNDO_PAINT_IMAGE);
+ image_undo_restore_runtime(lb);
+ image_undo_invalidate();
+}
+
static void paint_stroke_update_step(bContext *C, struct PaintStroke *stroke, PointerRNA *itemptr)
{
PaintOperation *pop = paint_stroke_mode_data(stroke);
Scene *scene = CTX_data_scene(C);
- Brush *brush = BKE_paint_brush(&scene->toolsettings->imapaint.paint);
+ ToolSettings *toolsettings = CTX_data_tool_settings(C);
+ UnifiedPaintSettings *ups = &toolsettings->unified_paint_settings;
+ Brush *brush = BKE_paint_brush(&toolsettings->imapaint.paint);
+
+ float alphafac = (brush->flag & BRUSH_ACCUMULATE) ? ups->overlap_factor : 1.0f;
/* initial brush values. Maybe it should be considered moving these to stroke system */
- float startsize = (float)BKE_brush_size_get(scene, brush);
float startalpha = BKE_brush_alpha_get(scene, brush);
float mouse[2];
float pressure;
+ float size;
+ float distance = paint_stroke_distance_get(stroke);
int eraser;
RNA_float_get_array(itemptr, "mouse", mouse);
pressure = RNA_float_get(itemptr, "pressure");
eraser = RNA_boolean_get(itemptr, "pen_flip");
+ size = max_ff(1.0f, RNA_float_get(itemptr, "size"));
+
+ /* stroking with fill tool only acts on stroke end */
+ if (brush->imagepaint_tool == PAINT_TOOL_FILL) {
+ copy_v2_v2(pop->prevmouse, mouse);
+ return;
+ }
if (BKE_brush_use_alpha_pressure(scene, brush))
- BKE_brush_alpha_set(scene, brush, max_ff(0.0f, startalpha * pressure));
- if (BKE_brush_use_size_pressure(scene, brush))
- BKE_brush_size_set(scene, brush, (int)max_ff(1.0f, startsize * pressure));
+ BKE_brush_alpha_set(scene, brush, max_ff(0.0f, startalpha * pressure * alphafac));
+ else
+ BKE_brush_alpha_set(scene, brush, max_ff(0.0f, startalpha * alphafac));
+
+ if ((brush->flag & BRUSH_DRAG_DOT) || (brush->flag & BRUSH_ANCHORED)) {
+ paint_stroke_restore();
+ }
if (pop->mode == PAINT_MODE_3D_PROJECT) {
- paint_proj_stroke(C, pop->custom_paint, pop->prevmouse, mouse);
+ paint_proj_stroke(C, pop->custom_paint, pop->prevmouse, mouse, pressure, distance, size);
}
else {
- paint_2d_stroke(pop->custom_paint, pop->prevmouse, mouse, eraser);
+ paint_2d_stroke(pop->custom_paint, pop->prevmouse, mouse, eraser, pressure, distance, size);
}
- pop->prevmouse[0] = mouse[0];
- pop->prevmouse[1] = mouse[1];
+ copy_v2_v2(pop->prevmouse, mouse);
/* restore brush values */
BKE_brush_alpha_set(scene, brush, startalpha);
- BKE_brush_size_set(scene, brush, startsize);
}
static void paint_stroke_redraw(const bContext *C, struct PaintStroke *stroke, bool final)
@@ -554,11 +846,39 @@ static void paint_stroke_redraw(const bContext *C, struct PaintStroke *stroke, b
static void paint_stroke_done(const bContext *C, struct PaintStroke *stroke)
{
Scene *scene = CTX_data_scene(C);
- ToolSettings *settings = scene->toolsettings;
+ ToolSettings *toolsettings = scene->toolsettings;
PaintOperation *pop = paint_stroke_mode_data(stroke);
+ Brush *brush = BKE_paint_brush(&toolsettings->imapaint.paint);
- settings->imapaint.flag &= ~IMAGEPAINT_DRAWING;
+ toolsettings->imapaint.flag &= ~IMAGEPAINT_DRAWING;
+ if (brush->imagepaint_tool == PAINT_TOOL_FILL) {
+ if (brush->flag & BRUSH_USE_GRADIENT) {
+ if (pop->mode == PAINT_MODE_2D) {
+ paint_2d_gradient_fill(C, brush, pop->startmouse, pop->prevmouse, pop->custom_paint);
+ }
+ else {
+ paint_proj_stroke(C, pop->custom_paint, pop->startmouse, pop->prevmouse, 1.0, 0.0, BKE_brush_size_get(scene, brush));
+ /* two redraws, one for GPU update, one for notification */
+ paint_proj_redraw(C, pop->custom_paint, false);
+ paint_proj_redraw(C, pop->custom_paint, true);
+ }
+ }
+ else {
+ if (pop->mode == PAINT_MODE_2D) {
+ float color[3];
+
+ srgb_to_linearrgb_v3_v3(color, BKE_brush_color_get(scene, brush));
+ paint_2d_bucket_fill(C, color, brush, pop->prevmouse, pop->custom_paint);
+ }
+ else {
+ paint_proj_stroke(C, pop->custom_paint, pop->startmouse, pop->prevmouse, 1.0, 0.0, BKE_brush_size_get(scene, brush));
+ /* two redraws, one for GPU update, one for notification */
+ paint_proj_redraw(C, pop->custom_paint, false);
+ paint_proj_redraw(C, pop->custom_paint, true);
+ }
+ }
+ }
if (pop->mode == PAINT_MODE_3D_PROJECT) {
paint_proj_stroke_done(pop->custom_paint);
}
@@ -566,7 +886,11 @@ static void paint_stroke_done(const bContext *C, struct PaintStroke *stroke)
paint_2d_stroke_done(pop->custom_paint);
}
- ED_undo_paint_push_end(UNDO_PAINT_IMAGE);
+ if (pop->cursor) {
+ WM_paint_cursor_end(CTX_wm_manager(C), pop->cursor);
+ }
+
+ image_undo_end();
/* duplicate warning, see texpaint_init */
#if 0
@@ -576,43 +900,41 @@ static void paint_stroke_done(const bContext *C, struct PaintStroke *stroke)
BKE_reportf(op->reports, RPT_WARNING, "Packed MultiLayer files cannot be painted: %s", pop->s.warnpackedfile);
#endif
MEM_freeN(pop);
-
- {
- UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
- ups->stroke_active = false;
- }
-}
-
-static bool paint_stroke_test_start(bContext *UNUSED(C), wmOperator *UNUSED(op), const float UNUSED(mouse[2]))
-{
- return true;
}
-
-static int paint_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+static bool paint_stroke_test_start(bContext *C, wmOperator *op, const float mouse[2])
{
PaintOperation *pop;
- float mouse[2];
- int retval;
/* TODO Should avoid putting this here. Instead, last position should be requested
* from stroke system. */
- mouse[0] = event->mval[0];
- mouse[1] = event->mval[1];
if (!(pop = texture_paint_init(C, op, mouse))) {
- return OPERATOR_CANCELLED;
+ return false;
}
- op->customdata = paint_stroke_new(C, NULL, paint_stroke_test_start,
+ paint_stroke_set_mode_data(op->customdata, pop);
+
+ return true;
+}
+
+
+static int paint_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ int retval;
+
+ op->customdata = paint_stroke_new(C, op, NULL, paint_stroke_test_start,
paint_stroke_update_step,
paint_stroke_redraw,
paint_stroke_done, event->type);
- paint_stroke_set_mode_data(op->customdata, pop);
+
+ if ((retval = op->type->modal(C, op, event)) == OPERATOR_FINISHED) {
+ paint_stroke_data_free(op);
+ return OPERATOR_FINISHED;
+ }
/* add modal handler */
WM_event_add_modal_handler(C, op);
- retval = op->type->modal(C, op, event);
OPERATOR_RETVAL_CHECK(retval);
BLI_assert(retval == OPERATOR_RUNNING_MODAL);
@@ -637,12 +959,10 @@ static int paint_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- op->customdata = paint_stroke_new(C, NULL, paint_stroke_test_start,
+ op->customdata = paint_stroke_new(C, op, NULL, paint_stroke_test_start,
paint_stroke_update_step,
paint_stroke_redraw,
paint_stroke_done, 0);
- paint_stroke_set_mode_data(op->customdata, pop);
-
/* frees op->customdata */
paint_stroke_exec(C, op);
@@ -686,9 +1006,9 @@ int get_imapaint_zoom(bContext *C, float *zoomx, float *zoomy)
if (!rv3d) {
SpaceImage *sima = CTX_wm_space_image(C);
- ARegion *ar = CTX_wm_region(C);
if (sima->mode == SI_MODE_PAINT) {
+ ARegion *ar = CTX_wm_region(C);
ED_space_image_get_zoom(sima, ar, zoomx, zoomy);
return 1;
@@ -847,17 +1167,39 @@ void PAINT_OT_grab_clone(wmOperatorType *ot)
typedef struct {
bool show_cursor;
short event_type;
-} SampleColorData;
+ float initcolor[3];
+ bool sample_palette;
+} SampleColorData;
+
+
+static void sample_color_update_header(SampleColorData *data, bContext *C)
+{
+#define HEADER_LENGTH 150
+ char msg[HEADER_LENGTH];
+ ScrArea *sa = CTX_wm_area(C);
+
+ if (sa) {
+ BLI_snprintf(msg, HEADER_LENGTH,
+ "Sample color for %s",
+ !data->sample_palette ?
+ "Brush. Use Left Click to sample for palette instead" :
+ "Palette. Use Left Click to sample more colors");
+ ED_area_headerprint(sa, msg);
+ }
+
+#undef HEADER_LENGTH
+}
static int sample_color_exec(bContext *C, wmOperator *op)
{
Paint *paint = BKE_paint_get_active_from_context(C);
Brush *brush = BKE_paint_brush(paint);
+ PaintMode mode = BKE_paintmode_get_active_from_context(C);
ARegion *ar = CTX_wm_region(C);
wmWindow *win = CTX_wm_window(C);
bool show_cursor = ((paint->flags & PAINT_SHOW_BRUSH) != 0);
int location[2];
-
+ bool use_palette;
paint->flags &= ~PAINT_SHOW_BRUSH;
/* force redraw without cursor */
@@ -865,7 +1207,9 @@ static int sample_color_exec(bContext *C, wmOperator *op)
WM_redraw_windows(C);
RNA_int_get_array(op->ptr, "location", location);
- paint_sample_color(C, ar, location[0], location[1]);
+ use_palette = RNA_boolean_get(op->ptr, "palette");
+
+ paint_sample_color(C, ar, location[0], location[1], mode == PAINT_TEXTURE_PROJECTIVE, use_palette);
if (show_cursor) {
paint->flags |= PAINT_SHOW_BRUSH;
@@ -878,7 +1222,9 @@ static int sample_color_exec(bContext *C, wmOperator *op)
static int sample_color_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
+ Scene *scene = CTX_data_scene(C);
Paint *paint = BKE_paint_get_active_from_context(C);
+ PaintMode mode = BKE_paintmode_get_active_from_context(C);
Brush *brush = BKE_paint_brush(paint);
SampleColorData *data = MEM_mallocN(sizeof(SampleColorData), "sample color custom data");
ARegion *ar = CTX_wm_region(C);
@@ -886,18 +1232,24 @@ static int sample_color_invoke(bContext *C, wmOperator *op, const wmEvent *event
data->event_type = event->type;
data->show_cursor = ((paint->flags & PAINT_SHOW_BRUSH) != 0);
+ copy_v3_v3(data->initcolor, BKE_brush_color_get(scene, brush));
+ data->sample_palette = false;
op->customdata = data;
paint->flags &= ~PAINT_SHOW_BRUSH;
+ sample_color_update_header(data, C);
+
+ WM_event_add_modal_handler(C, op);
+
/* force redraw without cursor */
WM_paint_cursor_tag_redraw(win, ar);
WM_redraw_windows(C);
RNA_int_set_array(op->ptr, "location", event->mval);
- paint_sample_color(C, ar, event->mval[0], event->mval[1]);
+
+ paint_sample_color(C, ar, event->mval[0], event->mval[1], mode == PAINT_TEXTURE_PROJECTIVE, false);
WM_cursor_modal_set(win, BC_EYEDROPPER_CURSOR);
- WM_event_add_modal_handler(C, op);
WM_event_add_notifier(C, NC_BRUSH | NA_EDITED, brush);
return OPERATOR_RUNNING_MODAL;
@@ -905,17 +1257,27 @@ static int sample_color_invoke(bContext *C, wmOperator *op, const wmEvent *event
static int sample_color_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
+ Scene *scene = CTX_data_scene(C);
SampleColorData *data = op->customdata;
Paint *paint = BKE_paint_get_active_from_context(C);
Brush *brush = BKE_paint_brush(paint);
+ PaintMode mode = BKE_paintmode_get_active_from_context(C);
if ((event->type == data->event_type) && (event->val == KM_RELEASE)) {
+ ScrArea *sa = CTX_wm_area(C);
+
if (data->show_cursor) {
paint->flags |= PAINT_SHOW_BRUSH;
}
+ if (data->sample_palette) {
+ BKE_brush_color_set(scene, brush, data->initcolor);
+ RNA_boolean_set(op->ptr, "palette", true);
+ }
WM_cursor_modal_restore(CTX_wm_window(C));
MEM_freeN(data);
+ ED_area_headerprint(sa, NULL);
+
return OPERATOR_FINISHED;
}
@@ -924,10 +1286,22 @@ static int sample_color_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
ARegion *ar = CTX_wm_region(C);
RNA_int_set_array(op->ptr, "location", event->mval);
- paint_sample_color(C, ar, event->mval[0], event->mval[1]);
+ paint_sample_color(C, ar, event->mval[0], event->mval[1], mode == PAINT_TEXTURE_PROJECTIVE, false);
WM_event_add_notifier(C, NC_BRUSH | NA_EDITED, brush);
break;
}
+
+ case LEFTMOUSE:
+ if (event->val == KM_PRESS) {
+ ARegion *ar = CTX_wm_region(C);
+ RNA_int_set_array(op->ptr, "location", event->mval);
+ paint_sample_color(C, ar, event->mval[0], event->mval[1], mode == PAINT_TEXTURE_PROJECTIVE, true);
+ if (!data->sample_palette) {
+ data->sample_palette = true;
+ sample_color_update_header(data, C);
+ }
+ }
+ break;
}
return OPERATOR_RUNNING_MODAL;
@@ -956,6 +1330,7 @@ void PAINT_OT_sample_color(wmOperatorType *ot)
/* properties */
RNA_def_int_vector(ot->srna, "location", 2, NULL, 0, INT_MAX, "Location", "Cursor location in region coordinates", 0, 16384);
+ RNA_def_boolean(ot->srna, "palette", 0, "Palette", "Add color to palette");
}
/******************** texture paint toggle operator ********************/
@@ -973,13 +1348,78 @@ static int texture_paint_toggle_poll(bContext *C)
return 1;
}
+
+/* Make sure that active object has a material, and assign UVs and image layers if they do not exist */
+void paint_proj_mesh_data_ensure(bContext *C, Object *ob, wmOperator *op)
+{
+ Mesh *me;
+ int layernum;
+ bool add_material = false;
+ ImagePaintSettings *imapaint = &(CTX_data_tool_settings(C)->imapaint);
+ Brush *br = BKE_paint_brush(&imapaint->paint);
+
+ /* no material, add one */
+ if (ob->totcol == 0) {
+ add_material = true;
+ }
+ else {
+ /* there may be material slots but they may be empty, check */
+ bool has_material = false;
+ int i;
+
+ for (i = 1; i < ob->totcol + 1; i++) {
+ Material *ma = give_current_material(ob, i);
+ if (ma) {
+ has_material = true;
+ if (!ma->texpaintslot) {
+ proj_paint_add_slot(C, ma, NULL);
+ }
+ }
+ }
+
+ if (!has_material)
+ add_material = true;
+ }
+
+ if (add_material) {
+ Material *ma = BKE_material_add(CTX_data_main(C), "Material");
+ /* no material found, just assign to first slot */
+ assign_material(ob, ma, 1, BKE_MAT_ASSIGN_USERPREF);
+ proj_paint_add_slot(C, ma, NULL);
+ }
+
+ me = BKE_mesh_from_object(ob);
+ layernum = CustomData_number_of_layers(&me->pdata, CD_MTEXPOLY);
+
+ if (layernum == 0) {
+ BKE_reportf(op->reports, RPT_WARNING, "Object did not have UV map, manual unwrap recommended");
+
+ ED_mesh_uv_texture_add(me, "UVMap", true);
+ }
+
+ /* Make sure we have a stencil to paint on! */
+ if (br->imagepaint_tool == PAINT_TOOL_MASK) {
+ imapaint->flag |= IMAGEPAINT_PROJECT_LAYER_STENCIL;
+
+ if (imapaint->stencil == NULL) {
+ int width;
+ int height;
+ Main *bmain = CTX_data_main(C);
+ float color[4] = {0.0, 0.0, 0.0, 1.0};
+
+ width = 1024;
+ height = 1024;
+ imapaint->stencil = BKE_image_add_generated(bmain, width, height, "Stencil", 32, false, IMA_GENTYPE_BLANK, color);
+ }
+ }
+}
+
static int texture_paint_toggle_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
Object *ob = CTX_data_active_object(C);
const int mode_flag = OB_MODE_TEXTURE_PAINT;
const bool is_mode_set = (ob->mode & mode_flag) != 0;
- Mesh *me;
if (!is_mode_set) {
if (!ED_object_mode_compat_set(C, ob, mode_flag, op->reports)) {
@@ -987,8 +1427,6 @@ static int texture_paint_toggle_exec(bContext *C, wmOperator *op)
}
}
- me = BKE_mesh_from_object(ob);
-
if (ob->mode & mode_flag) {
ob->mode &= ~mode_flag;
@@ -999,11 +1437,36 @@ static int texture_paint_toggle_exec(bContext *C, wmOperator *op)
toggle_paint_cursor(C, 0);
}
else {
- ob->mode |= mode_flag;
+ bScreen *sc;
+ Main *bmain = CTX_data_main(C);
+ Material *ma;
+
+ bool use_nodes = BKE_scene_use_new_shading_nodes(scene);
+ /* This has to stay here to regenerate the texture paint
+ * cache in case we are loading a file */
+ BKE_texpaint_slots_refresh_object(ob, use_nodes);
+
+ paint_proj_mesh_data_ensure(C, ob, op);
+
+ /* set the current material active paint slot on image editor */
+ ma = give_current_material(ob, ob->actcol);
+
+ if (ma->tot_slots > 0) {
+ 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) {
+ if (sl->spacetype == SPACE_IMAGE) {
+ SpaceImage *sima = (SpaceImage *)sl;
+ ED_space_image_set(sima, scene, scene->obedit, ma->texpaintslot[ma->paint_active_slot].ima);
+ }
+ }
+ }
+ }
+ }
- if (me->mtface == NULL)
- me->mtface = CustomData_add_layer(&me->fdata, CD_MTFACE, CD_DEFAULT,
- NULL, me->totface);
+ ob->mode |= mode_flag;
BKE_paint_init(&scene->toolsettings->imapaint.paint, PAINT_CURSOR_TEXTURE_PAINT);
@@ -1035,6 +1498,60 @@ void PAINT_OT_texture_paint_toggle(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+
+static int brush_colors_flip_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings;
+ Brush *br = image_paint_brush(C);
+ if (ups->flag & UNIFIED_PAINT_COLOR) {
+ swap_v3_v3(ups->rgb, ups->secondary_rgb);
+ }
+ else if (br) {
+ swap_v3_v3(br->rgb, br->secondary_rgb);
+ }
+ WM_event_add_notifier(C, NC_BRUSH | NA_EDITED, br);
+
+ return OPERATOR_FINISHED;
+}
+
+static int brush_colors_flip_poll(bContext *C)
+{
+ if (image_paint_poll(C)) {
+ Brush *br = image_paint_brush(C);
+ if (br->imagepaint_tool == PAINT_TOOL_DRAW)
+ return 1;
+ }
+
+ return 0;
+}
+
+void PAINT_OT_brush_colors_flip(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Brush Colors Flip";
+ ot->idname = "PAINT_OT_brush_colors_flip";
+ ot->description = "Toggle foreground and background brush colors";
+
+ /* api callbacks */
+ ot->exec = brush_colors_flip_exec;
+ ot->poll = brush_colors_flip_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+
+void ED_imapaint_bucket_fill(struct bContext *C, float color[3], wmOperator *op)
+{
+ ED_undo_paint_push_begin(UNDO_PAINT_IMAGE, op->type->name,
+ ED_image_undo_restore, ED_image_undo_free, NULL);
+
+ paint_2d_bucket_fill(C, color, NULL, NULL, NULL);
+
+ ED_undo_paint_push_end(UNDO_PAINT_IMAGE);
+}
+
+
static int texture_paint_poll(bContext *C)
{
if (texture_paint_toggle_poll(C))
diff --git a/source/blender/editors/sculpt_paint/paint_image_2d.c b/source/blender/editors/sculpt_paint/paint_image_2d.c
index 4f67fc9cc87..1f66910eaa2 100644
--- a/source/blender/editors/sculpt_paint/paint_image_2d.c
+++ b/source/blender/editors/sculpt_paint/paint_image_2d.c
@@ -40,11 +40,18 @@
#include "BLI_math.h"
+#include "BLI_rect.h"
+#include "BLI_math_color_blend.h"
+#include "BLI_stack.h"
+#include "BLI_bitmap.h"
+
#include "BKE_context.h"
+#include "BKE_depsgraph.h"
#include "BKE_brush.h"
#include "BKE_image.h"
#include "BKE_paint.h"
#include "BKE_report.h"
+#include "BKE_texture.h"
#include "ED_paint.h"
#include "ED_screen.h"
@@ -69,24 +76,25 @@
/* Defines and Structs */
typedef struct BrushPainterCache {
- int size; /* size override, if 0 uses 2*BKE_brush_size_get(brush) */
-
bool use_float; /* need float imbuf? */
bool use_color_correction; /* use color correction for float */
- bool use_masking; /* use masking? */
+ bool invert;
bool is_texbrush;
bool is_maskbrush;
- int lastsize;
- float lastalpha;
- float lastjitter;
+ int lastdiameter;
float last_tex_rotation;
float last_mask_rotation;
+ float last_pressure;
ImBuf *ibuf;
ImBuf *texibuf;
- unsigned short *mask;
+ unsigned short *curve_mask;
+ unsigned short *tex_mask;
+ unsigned short *tex_mask_old;
+ unsigned int tex_mask_old_w;
+ unsigned int tex_mask_old_h;
} BrushPainterCache;
typedef struct BrushPainter {
@@ -136,43 +144,42 @@ typedef struct ImagePaintState {
int do_facesel;
bool need_redraw;
+
+ BlurKernel *blurkernel;
} ImagePaintState;
-static BrushPainter *brush_painter_2d_new(Scene *scene, Brush *brush)
+static BrushPainter *brush_painter_2d_new(Scene *scene, Brush *brush, bool invert)
{
BrushPainter *painter = MEM_callocN(sizeof(BrushPainter), "BrushPainter");
painter->brush = brush;
painter->scene = scene;
painter->firsttouch = 1;
- painter->cache.lastsize = -1; /* force ibuf create in refresh */
+ painter->cache.lastdiameter = -1; /* force ibuf create in refresh */
+ painter->cache.invert = invert;
return painter;
}
-static void brush_painter_2d_require_imbuf(BrushPainter *painter, bool use_float, bool use_color_correction, bool use_masking)
+static void brush_painter_2d_require_imbuf(BrushPainter *painter, bool use_float, bool use_color_correction)
{
Brush *brush = painter->brush;
if ((painter->cache.use_float != use_float)) {
if (painter->cache.ibuf) IMB_freeImBuf(painter->cache.ibuf);
- if (painter->cache.mask) MEM_freeN(painter->cache.mask);
+ if (painter->cache.curve_mask) MEM_freeN(painter->cache.curve_mask);
+ if (painter->cache.tex_mask) MEM_freeN(painter->cache.tex_mask);
+ if (painter->cache.tex_mask_old) MEM_freeN(painter->cache.tex_mask_old);
painter->cache.ibuf = NULL;
- painter->cache.mask = NULL;
- painter->cache.lastsize = -1; /* force ibuf create in refresh */
- }
-
- if (painter->cache.use_float != use_float) {
- if (painter->cache.texibuf) IMB_freeImBuf(painter->cache.texibuf);
- painter->cache.texibuf = NULL;
- painter->cache.lastsize = -1; /* force ibuf create in refresh */
+ painter->cache.curve_mask = NULL;
+ painter->cache.tex_mask = NULL;
+ painter->cache.lastdiameter = -1; /* force ibuf create in refresh */
}
painter->cache.use_float = use_float;
painter->cache.use_color_correction = use_float && use_color_correction;
- painter->cache.use_masking = use_masking;
painter->cache.is_texbrush = (brush->mtex.tex && brush->imagepaint_tool == PAINT_TOOL_DRAW) ? true : false;
painter->cache.is_maskbrush = (brush->mask_mtex.tex) ? true : false;
}
@@ -181,7 +188,9 @@ static void brush_painter_2d_free(BrushPainter *painter)
{
if (painter->cache.ibuf) IMB_freeImBuf(painter->cache.ibuf);
if (painter->cache.texibuf) IMB_freeImBuf(painter->cache.texibuf);
- if (painter->cache.mask) MEM_freeN(painter->cache.mask);
+ if (painter->cache.curve_mask) MEM_freeN(painter->cache.curve_mask);
+ if (painter->cache.tex_mask) MEM_freeN(painter->cache.tex_mask);
+ if (painter->cache.tex_mask_old) MEM_freeN(painter->cache.tex_mask_old);
MEM_freeN(painter);
}
@@ -192,41 +201,177 @@ static void brush_imbuf_tex_co(rctf *mapping, int x, int y, float texco[3])
texco[2] = 0.0f;
}
-/* create a mask with the falloff strength and optionally brush alpha */
-static unsigned short *brush_painter_mask_new(BrushPainter *painter, int size)
+/* create a mask with the mask texture */
+static unsigned short *brush_painter_mask_ibuf_new(BrushPainter *painter, int size)
{
Scene *scene = painter->scene;
Brush *brush = painter->brush;
- bool use_masking = painter->cache.use_masking;
-
- float alpha = (use_masking) ? 1.0f : BKE_brush_alpha_get(scene, brush);
- int radius = BKE_brush_size_get(scene, brush);
- int xoff = -size * 0.5f + 0.5f;
- int yoff = -size * 0.5f + 0.5f;
+ rctf mask_mapping = painter->mask_mapping;
+ struct ImagePool *pool = painter->pool;
+ float texco[3];
unsigned short *mask, *m;
- int x, y;
+ int x, y, thread = 0;
- mask = MEM_callocN(sizeof(unsigned short) * size * size, "brush_painter_mask");
+ mask = MEM_mallocN(sizeof(unsigned short) * size * size, "brush_painter_mask");
m = mask;
for (y = 0; y < size; y++) {
for (x = 0; x < size; x++, m++) {
+ float res;
+ brush_imbuf_tex_co(&mask_mapping, x, y, texco);
+ res = BKE_brush_sample_masktex(scene, brush, texco, thread, pool);
+ *m = (unsigned short)(65535.0f * res);
+ }
+ }
+
+ return mask;
+}
+
+/* update rectangular section of the brush image */
+static void brush_painter_mask_imbuf_update(
+ BrushPainter *painter, unsigned short *tex_mask_old,
+ int origx, int origy, int w, int h, int xt, int yt, int diameter)
+{
+ Scene *scene = painter->scene;
+ Brush *brush = painter->brush;
+ rctf tex_mapping = painter->mask_mapping;
+ struct ImagePool *pool = painter->pool;
+ unsigned short res;
+
+ bool use_texture_old = (tex_mask_old != NULL);
+
+ int x, y, thread = 0;
+
+ unsigned short *tex_mask = painter->cache.tex_mask;
+ unsigned short *tex_mask_cur = painter->cache.tex_mask_old;
+
+ /* fill pixels */
+ for (y = origy; y < h; y++) {
+ for (x = origx; x < w; x++) {
+ /* sample texture */
+ float texco[3];
+
+ /* handle byte pixel */
+ unsigned short *b = tex_mask + (y * diameter + x);
+ unsigned short *t = tex_mask_cur + (y * diameter + x);
+
+ if (!use_texture_old) {
+ brush_imbuf_tex_co(&tex_mapping, x, y, texco);
+ res = (unsigned short)(65535.0f * BKE_brush_sample_masktex(scene, brush, texco, thread, pool));
+ }
+
+ /* read from old texture buffer */
+ if (use_texture_old) {
+ res = *(tex_mask_old + ((y - origy + yt) * painter->cache.tex_mask_old_w + (x - origx + xt)));
+ }
+
+ /* write to new texture mask */
+ *t = res;
+ /* write to mask image buffer */
+ *b = res;
+ }
+ }
+}
+
+
+/**
+ * Update the brush mask image by trying to reuse the cached texture result.
+ * This can be considerably faster for brushes that change size due to pressure or
+ * textures that stick to the surface where only part of the pixels are new
+ */
+static void brush_painter_mask_imbuf_partial_update(BrushPainter *painter, const float pos[2], int diameter)
+{
+ BrushPainterCache *cache = &painter->cache;
+ unsigned short *tex_mask_old;
+ int destx, desty, srcx, srcy, w, h, x1, y1, x2, y2;
+
+ /* create brush image buffer if it didn't exist yet */
+ if (!cache->tex_mask)
+ cache->tex_mask = MEM_mallocN(sizeof(unsigned short) * diameter * diameter, "brush_painter_mask");
+
+ /* create new texture image buffer with coordinates relative to old */
+ tex_mask_old = cache->tex_mask_old;
+ cache->tex_mask_old = MEM_mallocN(sizeof(unsigned short) * diameter * diameter, "brush_painter_mask");
+
+ if (tex_mask_old) {
+ ImBuf maskibuf;
+ ImBuf maskibuf_old;
+ maskibuf.x = maskibuf.y = diameter;
+ maskibuf_old.x = cache->tex_mask_old_w;
+ maskibuf_old.y = cache->tex_mask_old_h;
+
+ srcx = srcy = 0;
+ w = cache->tex_mask_old_w;
+ h = cache->tex_mask_old_h;
+ destx = (int)painter->lastpaintpos[0] - (int)pos[0] + (diameter / 2 - w / 2);
+ desty = (int)painter->lastpaintpos[1] - (int)pos[1] + (diameter / 2 - h / 2);
+
+ /* hack, use temporary rects so that clipping works */
+ IMB_rectclip(&maskibuf, &maskibuf_old, &destx, &desty, &srcx, &srcy, &w, &h);
+ }
+ else {
+ srcx = srcy = 0;
+ destx = desty = 0;
+ w = h = 0;
+ }
+
+ x1 = min_ii(destx, diameter);
+ y1 = min_ii(desty, diameter);
+ x2 = min_ii(destx + w, diameter);
+ y2 = min_ii(desty + h, diameter);
+
+ /* blend existing texture in new position */
+ if ((x1 < x2) && (y1 < y2))
+ brush_painter_mask_imbuf_update(painter, tex_mask_old, x1, y1, x2, y2, srcx, srcy, diameter);
+
+ if (tex_mask_old)
+ MEM_freeN(tex_mask_old);
+
+ /* sample texture in new areas */
+ if ((0 < x1) && (0 < diameter))
+ brush_painter_mask_imbuf_update(painter, NULL, 0, 0, x1, diameter, 0, 0, diameter);
+ if ((x2 < diameter) && (0 < diameter))
+ brush_painter_mask_imbuf_update(painter, NULL, x2, 0, diameter, diameter, 0, 0, diameter);
+ if ((x1 < x2) && (0 < y1))
+ brush_painter_mask_imbuf_update(painter, NULL, x1, 0, x2, y1, 0, 0, diameter);
+ if ((x1 < x2) && (y2 < diameter))
+ brush_painter_mask_imbuf_update(painter, NULL, x1, y2, x2, diameter, 0, 0, diameter);
+
+ /* through with sampling, now update sizes */
+ cache->tex_mask_old_w = diameter;
+ cache->tex_mask_old_h = diameter;
+}
+
+/* create a mask with the falloff strength */
+static unsigned short *brush_painter_curve_mask_new(BrushPainter *painter, int diameter, float radius)
+{
+ Brush *brush = painter->brush;
+
+ int xoff = -diameter * 0.5f + 0.5f;
+ int yoff = -diameter * 0.5f + 0.5f;
+
+ unsigned short *mask, *m;
+ int x, y;
+
+ mask = MEM_mallocN(sizeof(unsigned short) * diameter * diameter, "brush_painter_mask");
+ m = mask;
+
+ for (y = 0; y < diameter; y++) {
+ for (x = 0; x < diameter; x++, m++) {
float xy[2] = {x + xoff, y + yoff};
float len = len_v2(xy);
- float strength = alpha;
-
- strength *= BKE_brush_curve_strength_clamp(brush, len, radius);
- *m = (unsigned short)(65535.0f * strength);
+ *m = (unsigned short)(65535.0f * BKE_brush_curve_strength_clamp(brush, len, radius));
}
}
return mask;
}
+
/* create imbuf with brush color */
-static ImBuf *brush_painter_imbuf_new(BrushPainter *painter, int size)
+static ImBuf *brush_painter_imbuf_new(BrushPainter *painter, int size, float pressure, float distance)
{
Scene *scene = painter->scene;
Brush *brush = painter->brush;
@@ -235,19 +380,11 @@ static ImBuf *brush_painter_imbuf_new(BrushPainter *painter, int size)
struct ColorManagedDisplay *display = IMB_colormanagement_display_get_named(display_device);
rctf tex_mapping = painter->tex_mapping;
- rctf mask_mapping = painter->mask_mapping;
struct ImagePool *pool = painter->pool;
- bool use_masking = painter->cache.use_masking;
bool use_color_correction = painter->cache.use_color_correction;
bool use_float = painter->cache.use_float;
bool is_texbrush = painter->cache.is_texbrush;
- bool is_maskbrush = painter->cache.is_maskbrush;
-
- float alpha = (use_masking) ? 1.0f : BKE_brush_alpha_get(scene, brush);
- int radius = BKE_brush_size_get(scene, brush);
- int xoff = -size * 0.5f + 0.5f;
- int yoff = -size * 0.5f + 0.5f;
int x, y, thread = 0;
float brush_rgb[3];
@@ -257,11 +394,7 @@ static ImBuf *brush_painter_imbuf_new(BrushPainter *painter, int size)
/* get brush color */
if (brush->imagepaint_tool == PAINT_TOOL_DRAW) {
- copy_v3_v3(brush_rgb, brush->rgb);
-
- if (use_color_correction) {
- IMB_colormanagement_display_to_scene_linear_v3(brush_rgb, display);
- }
+ paint_brush_color_get(scene, brush, use_color_correction, painter->cache.invert, distance, pressure, brush_rgb, display);
}
else {
brush_rgb[0] = 1.0f;
@@ -289,19 +422,6 @@ static ImBuf *brush_painter_imbuf_new(BrushPainter *painter, int size)
rgba[3] = 1.0f;
}
- if (is_maskbrush) {
- brush_imbuf_tex_co(&mask_mapping, x, y, texco);
- rgba[3] *= BKE_brush_sample_masktex(scene, brush, texco, thread, pool);
- }
-
- /* when not using masking, multiply in falloff and strength */
- if (!use_masking) {
- float xy[2] = {x + xoff, y + yoff};
- float len = len_v2(xy);
-
- rgba[3] *= alpha * BKE_brush_curve_strength_clamp(brush, len, radius);
- }
-
if (use_float) {
/* write to float pixel */
float *dstf = ibuf->rect_float + (y * size + x) * 4;
@@ -332,14 +452,11 @@ static void brush_painter_imbuf_update(BrushPainter *painter, ImBuf *oldtexibuf,
struct ColorManagedDisplay *display = IMB_colormanagement_display_get_named(display_device);
rctf tex_mapping = painter->tex_mapping;
- rctf mask_mapping = painter->mask_mapping;
struct ImagePool *pool = painter->pool;
- bool use_masking = painter->cache.use_masking;
bool use_color_correction = painter->cache.use_color_correction;
bool use_float = painter->cache.use_float;
bool is_texbrush = painter->cache.is_texbrush;
- bool is_maskbrush = painter->cache.is_maskbrush;
bool use_texture_old = (oldtexibuf != NULL);
int x, y, thread = 0;
@@ -347,15 +464,10 @@ static void brush_painter_imbuf_update(BrushPainter *painter, ImBuf *oldtexibuf,
ImBuf *ibuf = painter->cache.ibuf;
ImBuf *texibuf = painter->cache.texibuf;
- unsigned short *mask = painter->cache.mask;
/* get brush color */
if (brush->imagepaint_tool == PAINT_TOOL_DRAW) {
- copy_v3_v3(brush_rgb, brush->rgb);
-
- if (use_color_correction) {
- IMB_colormanagement_display_to_scene_linear_v3(brush_rgb, display);
- }
+ paint_brush_color_get(scene, brush, use_color_correction, painter->cache.invert, 0.0, 1.0, brush_rgb, display);
}
else {
brush_rgb[0] = 1.0f;
@@ -363,7 +475,7 @@ static void brush_painter_imbuf_update(BrushPainter *painter, ImBuf *oldtexibuf,
brush_rgb[2] = 1.0f;
}
- /* fill pixes */
+ /* fill pixels */
for (y = origy; y < h; y++) {
for (x = origx; x < w; x++) {
/* sample texture and multiply with brush color */
@@ -383,11 +495,6 @@ static void brush_painter_imbuf_update(BrushPainter *painter, ImBuf *oldtexibuf,
copy_v3_v3(rgba, brush_rgb);
rgba[3] = 1.0f;
}
-
- if (is_maskbrush) {
- brush_imbuf_tex_co(&mask_mapping, x, y, texco);
- rgba[3] *= BKE_brush_sample_masktex(scene, brush, texco, thread, pool);
- }
}
if (use_float) {
@@ -404,12 +511,6 @@ static void brush_painter_imbuf_update(BrushPainter *painter, ImBuf *oldtexibuf,
/* write to new texture buffer */
copy_v4_v4(tf, rgba);
- /* if not using masking, multiply in the mask now */
- if (!use_masking) {
- unsigned short *m = mask + (y * ibuf->x + x);
- rgba[3] *= *m * (1.0f / 65535.0f);
- }
-
/* output premultiplied float image, mf was already premultiplied */
mul_v3_v3fl(bf, rgba, rgba[3]);
bf[3] = rgba[3];
@@ -438,12 +539,6 @@ static void brush_painter_imbuf_update(BrushPainter *painter, ImBuf *oldtexibuf,
t[2] = crgba[2];
t[3] = crgba[3];
- /* if not using masking, multiply in the mask now */
- if (!use_masking) {
- unsigned short *m = mask + (y * ibuf->x + x);
- crgba[3] = (crgba[3] * (*m)) / 65535;
- }
-
/* write to brush image buffer */
b[0] = crgba[0];
b[1] = crgba[1];
@@ -457,14 +552,11 @@ static void brush_painter_imbuf_update(BrushPainter *painter, ImBuf *oldtexibuf,
/* update the brush image by trying to reuse the cached texture result. this
* can be considerably faster for brushes that change size due to pressure or
* textures that stick to the surface where only part of the pixels are new */
-static void brush_painter_imbuf_partial_update(BrushPainter *painter, const float pos[2])
+static void brush_painter_imbuf_partial_update(BrushPainter *painter, const float pos[2], int diameter)
{
- const Scene *scene = painter->scene;
- Brush *brush = painter->brush;
BrushPainterCache *cache = &painter->cache;
ImBuf *oldtexibuf, *ibuf;
int imbflag, destx, desty, srcx, srcy, w, h, x1, y1, x2, y2;
- int diameter = 2 * BKE_brush_size_get(scene, brush);
/* create brush image buffer if it didn't exist yet */
imbflag = (cache->use_float) ? IB_rectfloat : IB_rect;
@@ -478,10 +570,10 @@ static void brush_painter_imbuf_partial_update(BrushPainter *painter, const floa
if (oldtexibuf) {
srcx = srcy = 0;
- destx = (int)painter->lastpaintpos[0] - (int)pos[0];
- desty = (int)painter->lastpaintpos[1] - (int)pos[1];
w = oldtexibuf->x;
h = oldtexibuf->y;
+ destx = (int)painter->lastpaintpos[0] - (int)pos[0] + (diameter / 2 - w / 2);
+ desty = (int)painter->lastpaintpos[1] - (int)pos[1] + (diameter / 2 - h / 2);
IMB_rectclip(cache->texibuf, oldtexibuf, &destx, &desty, &srcx, &srcy, &w, &h);
}
@@ -514,7 +606,7 @@ static void brush_painter_imbuf_partial_update(BrushPainter *painter, const floa
brush_painter_imbuf_update(painter, NULL, x1, y2, x2, ibuf->y, 0, 0);
}
-static void brush_painter_2d_tex_mapping(ImagePaintState *s, int size, const float startpos[2], const float pos[2], const float mouse[2], int mapmode, rctf *mapping)
+static void brush_painter_2d_tex_mapping(ImagePaintState *s, int diameter, const float startpos[2], const float pos[2], const float mouse[2], int mapmode, rctf *mapping)
{
float invw = 1.0f / (float)s->canvas->x;
float invh = 1.0f / (float)s->canvas->y;
@@ -522,19 +614,19 @@ static void brush_painter_2d_tex_mapping(ImagePaintState *s, int size, const flo
int ipos[2];
/* find start coordinate of brush in canvas */
- ipos[0] = (int)floorf((pos[0] - size / 2) + 1.0f);
- ipos[1] = (int)floorf((pos[1] - size / 2) + 1.0f);
+ ipos[0] = (int)floorf((pos[0] - diameter / 2) + 1.0f);
+ ipos[1] = (int)floorf((pos[1] - diameter / 2) + 1.0f);
if (mapmode == MTEX_MAP_MODE_STENCIL) {
/* map from view coordinates of brush to region coordinates */
UI_view2d_view_to_region(s->v2d, ipos[0] * invw, ipos[1] * invh, &xmin, &ymin);
- UI_view2d_view_to_region(s->v2d, (ipos[0] + size) * invw, (ipos[1] + size) * invh, &xmax, &ymax);
+ UI_view2d_view_to_region(s->v2d, (ipos[0] + diameter) * invw, (ipos[1] + diameter) * invh, &xmax, &ymax);
/* output mapping from brush ibuf x/y to region coordinates */
mapping->xmin = xmin;
mapping->ymin = ymin;
- mapping->xmax = (xmax - xmin) / (float)size;
- mapping->ymax = (ymax - ymin) / (float)size;
+ mapping->xmax = (xmax - xmin) / (float)diameter;
+ mapping->ymax = (ymax - ymin) / (float)diameter;
}
else if (mapmode == MTEX_MAP_MODE_3D) {
/* 3D mapping, just mapping to canvas 0..1 */
@@ -545,104 +637,126 @@ static void brush_painter_2d_tex_mapping(ImagePaintState *s, int size, const flo
}
else if (ELEM(mapmode, MTEX_MAP_MODE_VIEW, MTEX_MAP_MODE_RANDOM)) {
/* view mapping */
- mapping->xmin = mouse[0] - size * 0.5f + 0.5f;
- mapping->ymin = mouse[1] - size * 0.5f + 0.5f;
+ mapping->xmin = mouse[0] - diameter * 0.5f + 0.5f;
+ mapping->ymin = mouse[1] - diameter * 0.5f + 0.5f;
mapping->xmax = 1.0f;
mapping->ymax = 1.0f;
}
else /* if (mapmode == MTEX_MAP_MODE_TILED) */ {
- mapping->xmin = -size * 0.5f + 0.5f + (int)pos[0] - (int)startpos[0];
- mapping->ymin = -size * 0.5f + 0.5f + (int)pos[1] - (int)startpos[1];
+ mapping->xmin = (int)(-diameter * 0.5) + (int)pos[0] - (int)startpos[0];
+ mapping->ymin = (int)(-diameter * 0.5) + (int)pos[1] - (int)startpos[1];
mapping->xmax = 1.0f;
mapping->ymax = 1.0f;
}
}
-static void brush_painter_2d_refresh_cache(ImagePaintState *s, BrushPainter *painter, const float pos[2], const float mouse[2])
+static void brush_painter_2d_refresh_cache(ImagePaintState *s, BrushPainter *painter, const float pos[2], const float mouse[2], float pressure, float distance, float size)
{
const Scene *scene = painter->scene;
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
Brush *brush = painter->brush;
BrushPainterCache *cache = &painter->cache;
- const int diameter = 2 * BKE_brush_size_get(scene, brush);
- const int size = (cache->size) ? cache->size : diameter;
- const float alpha = BKE_brush_alpha_get(scene, brush);
- const bool use_masking = painter->cache.use_masking;
+ const int diameter = 2 * size;
bool do_random = false;
bool do_partial_update = false;
- bool do_view = false;
+ bool update_color = (brush->flag & BRUSH_USE_GRADIENT) &&
+ ((ELEM(brush->gradient_stroke_mode,
+ BRUSH_GRADIENT_SPACING_REPEAT,
+ BRUSH_GRADIENT_SPACING_CLAMP)) ||
+ (cache->last_pressure != pressure));
float tex_rotation = -brush->mtex.rot;
float mask_rotation = -brush->mask_mtex.rot;
+ painter->pool = BKE_image_pool_new();
+
/* determine how can update based on textures used */
if (painter->cache.is_texbrush) {
if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_VIEW) {
- do_view = true;
tex_rotation += ups->brush_rotation;
}
else if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_RANDOM)
do_random = true;
- else
+ else if (!((brush->flag & BRUSH_ANCHORED) || update_color))
do_partial_update = true;
- brush_painter_2d_tex_mapping(s, size, painter->startpaintpos, pos, mouse,
+ brush_painter_2d_tex_mapping(s, diameter, painter->startpaintpos, pos, mouse,
brush->mtex.brush_map_mode, &painter->tex_mapping);
}
if (painter->cache.is_maskbrush) {
+ bool renew_maxmask = false;
+ bool do_partial_update_mask = false;
+ /* invalidate case for all mapping modes */
if (brush->mask_mtex.brush_map_mode == MTEX_MAP_MODE_VIEW) {
- do_view = true;
mask_rotation += ups->brush_rotation;
}
- else if (brush->mask_mtex.brush_map_mode == MTEX_MAP_MODE_RANDOM)
- do_random = true;
- else
- do_partial_update = true;
+ else if (brush->mask_mtex.brush_map_mode == MTEX_MAP_MODE_RANDOM) {
+ renew_maxmask = true;
+ }
+ else if (!(brush->flag & BRUSH_ANCHORED)) {
+ do_partial_update_mask = true;
+ renew_maxmask = true;
+ }
+ /* explicilty disable partial update even if it has been enabled above */
+ if (brush->mask_pressure) {
+ do_partial_update_mask = false;
+ renew_maxmask = true;
+ }
- brush_painter_2d_tex_mapping(s, size, painter->startpaintpos, pos, mouse,
- brush->mask_mtex.brush_map_mode, &painter->mask_mapping);
+ if ((diameter != cache->lastdiameter) ||
+ (mask_rotation != cache->last_mask_rotation) ||
+ renew_maxmask)
+ {
+ if (cache->tex_mask) {
+ MEM_freeN(cache->tex_mask);
+ cache->tex_mask = NULL;
+ }
+
+ brush_painter_2d_tex_mapping(s, diameter, painter->startpaintpos, pos, mouse,
+ brush->mask_mtex.brush_map_mode, &painter->mask_mapping);
+
+ if (do_partial_update_mask)
+ brush_painter_mask_imbuf_partial_update(painter, pos, diameter);
+ else
+ cache->tex_mask = brush_painter_mask_ibuf_new(painter, diameter);
+ cache->last_mask_rotation = mask_rotation;
+ }
}
- if (do_view || do_random)
- do_partial_update = false;
+ /* curve mask can only change if the size changes */
+ if (diameter != cache->lastdiameter) {
+ if (cache->curve_mask) {
+ MEM_freeN(cache->curve_mask);
+ cache->curve_mask = NULL;
+ }
- painter->pool = BKE_image_pool_new();
+ cache->curve_mask = brush_painter_curve_mask_new(painter, diameter, size);
+ }
/* detect if we need to recreate image brush buffer */
- if (diameter != cache->lastsize ||
- alpha != cache->lastalpha ||
- brush->jitter != cache->lastjitter ||
- tex_rotation != cache->last_tex_rotation ||
- mask_rotation != cache->last_mask_rotation ||
- do_random)
+ if ((diameter != cache->lastdiameter) ||
+ (tex_rotation != cache->last_tex_rotation) ||
+ do_random ||
+ update_color)
{
if (cache->ibuf) {
IMB_freeImBuf(cache->ibuf);
cache->ibuf = NULL;
}
- if (cache->mask) {
- MEM_freeN(cache->mask);
- cache->mask = NULL;
- }
if (do_partial_update) {
- /* do partial update of texture + recreate mask */
- cache->mask = brush_painter_mask_new(painter, size);
- brush_painter_imbuf_partial_update(painter, pos);
+ /* do partial update of texture */
+ brush_painter_imbuf_partial_update(painter, pos, diameter);
}
else {
- /* create brush and mask from scratch */
- if (use_masking)
- cache->mask = brush_painter_mask_new(painter, size);
- cache->ibuf = brush_painter_imbuf_new(painter, size);
+ /* create brush from scratch */
+ cache->ibuf = brush_painter_imbuf_new(painter, diameter, pressure, distance);
}
- cache->lastsize = diameter;
- cache->lastalpha = alpha;
- cache->lastjitter = brush->jitter;
+ cache->lastdiameter = diameter;
cache->last_tex_rotation = tex_rotation;
- cache->last_mask_rotation = mask_rotation;
+ cache->last_pressure = pressure;
}
else if (do_partial_update) {
/* do only partial update of texture */
@@ -650,7 +764,7 @@ static void brush_painter_2d_refresh_cache(ImagePaintState *s, BrushPainter *pai
int dy = (int)painter->lastpaintpos[1] - (int)pos[1];
if ((dx != 0) || (dy != 0)) {
- brush_painter_imbuf_partial_update(painter, pos);
+ brush_painter_imbuf_partial_update(painter, pos, diameter);
}
}
@@ -703,7 +817,7 @@ static void paint_2d_ibuf_rgb_set(ImBuf *ibuf, int x, int y, const bool is_torus
}
}
-static int paint_2d_ibuf_add_if(ImBuf *ibuf, unsigned int x, unsigned int y, float *outrgb, short torus)
+static float paint_2d_ibuf_add_if(ImBuf *ibuf, unsigned int x, unsigned int y, float *outrgb, short torus, float w)
{
float inrgb[4];
@@ -716,16 +830,23 @@ static int paint_2d_ibuf_add_if(ImBuf *ibuf, unsigned int x, unsigned int y, flo
paint_2d_ibuf_rgb_get(ibuf, x, y, 0, inrgb);
}
+ mul_v4_fl(inrgb, w);
add_v4_v4(outrgb, inrgb);
- return 1;
+ return w;
}
-static void paint_2d_lift_soften(ImBuf *ibuf, ImBuf *ibufb, int *pos, const bool is_torus)
+static void paint_2d_lift_soften(ImagePaintState *s, ImBuf *ibuf, ImBuf *ibufb, int *pos, const short is_torus)
{
- int x, y, count, xi, yi, xo, yo;
+ bool sharpen = (s->painter->cache.invert ^ ((s->brush->flag & BRUSH_DIR_IN) != 0));
+ float threshold = s->brush->sharp_threshold;
+ int x, y, xi, yi, xo, yo, xk, yk;
+ float count;
int out_off[2], in_off[2], dim[2];
+ int diff_pos[2];
float outrgb[4];
+ float rgba[4];
+ BlurKernel *kernel = s->blurkernel;
dim[0] = ibufb->x;
dim[1] = ibufb->y;
@@ -741,28 +862,52 @@ static void paint_2d_lift_soften(ImBuf *ibuf, ImBuf *ibufb, int *pos, const bool
return;
}
+ /* find offset inside mask buffers to sample them */
+ sub_v2_v2v2_int(diff_pos, out_off, in_off);
+
for (y = 0; y < dim[1]; y++) {
for (x = 0; x < dim[0]; x++) {
/* get input pixel */
xi = in_off[0] + x;
yi = in_off[1] + y;
- count = 1;
- paint_2d_ibuf_rgb_get(ibuf, xi, yi, is_torus, outrgb);
+ count = 0.0;
+ paint_2d_ibuf_rgb_get(ibuf, xi, yi, is_torus, rgba);
+ zero_v4(outrgb);
- count += paint_2d_ibuf_add_if(ibuf, xi - 1, yi - 1, outrgb, is_torus);
- count += paint_2d_ibuf_add_if(ibuf, xi - 1, yi, outrgb, is_torus);
- count += paint_2d_ibuf_add_if(ibuf, xi - 1, yi + 1, outrgb, is_torus);
+ for (yk = 0; yk < kernel->side; yk++) {
+ for (xk = 0; xk < kernel->side; xk++) {
+ count += paint_2d_ibuf_add_if(ibuf, xi + xk - kernel->pixel_len,
+ yi + yk - kernel->pixel_len, outrgb, is_torus,
+ kernel->wdata[xk + yk * kernel->side]);
+ }
+ }
- count += paint_2d_ibuf_add_if(ibuf, xi, yi - 1, outrgb, is_torus);
- count += paint_2d_ibuf_add_if(ibuf, xi, yi + 1, outrgb, is_torus);
+ if (count > 0.0f) {
+ mul_v4_fl(outrgb, 1.0f / (float)count);
- count += paint_2d_ibuf_add_if(ibuf, xi + 1, yi - 1, outrgb, is_torus);
- count += paint_2d_ibuf_add_if(ibuf, xi + 1, yi, outrgb, is_torus);
- count += paint_2d_ibuf_add_if(ibuf, xi + 1, yi + 1, outrgb, is_torus);
+ if (sharpen) {
+ /* subtract blurred image from normal image gives high pass filter */
+ sub_v3_v3v3(outrgb, rgba, outrgb);
- mul_v4_fl(outrgb, 1.0f / (float)count);
+ /* now rgba_ub contains the edge result, but this should be converted to luminance to avoid
+ * colored speckles appearing in final image, and also to check for threshold */
+ outrgb[0] = outrgb[1] = outrgb[2] = rgb_to_grayscale(outrgb);
+ if (fabsf(outrgb[0]) > threshold) {
+ float mask = BKE_brush_alpha_get(s->scene, s->brush);
+ float alpha = rgba[3];
+ rgba[3] = outrgb[3] = mask;
+ /* add to enhance edges */
+ blend_color_add_float(outrgb, rgba, outrgb);
+ outrgb[3] = alpha;
+ }
+ else
+ copy_v4_v4(outrgb, rgba);
+ }
+ }
+ else
+ copy_v4_v4(outrgb, rgba);
/* write into brush buffer */
xo = out_off[0] + x;
yo = out_off[1] + y;
@@ -830,10 +975,10 @@ static void paint_2d_lift_smear(ImBuf *ibuf, ImBuf *ibufb, int *pos)
tot = paint_2d_torus_split_region(region, ibufb, ibuf);
for (a = 0; a < tot; a++)
- IMB_rectblend(ibufb, ibufb, ibuf, NULL, NULL, 0, region[a].destx, region[a].desty,
+ IMB_rectblend(ibufb, ibufb, ibuf, NULL, NULL, NULL, 0, region[a].destx, region[a].desty,
region[a].destx, region[a].desty,
region[a].srcx, region[a].srcy,
- region[a].width, region[a].height, IMB_BLEND_COPY_RGB);
+ region[a].width, region[a].height, IMB_BLEND_COPY_RGB, false);
}
static ImBuf *paint_2d_lift_clone(ImBuf *ibuf, ImBuf *ibufb, int *pos)
@@ -844,10 +989,10 @@ static ImBuf *paint_2d_lift_clone(ImBuf *ibuf, ImBuf *ibufb, int *pos)
ImBuf *clonebuf = IMB_allocImBuf(w, h, ibufb->planes, ibufb->flags);
IMB_rectclip(clonebuf, ibuf, &destx, &desty, &srcx, &srcy, &w, &h);
- IMB_rectblend(clonebuf, clonebuf, ibufb, NULL, NULL, 0, destx, desty, destx, desty, destx, desty, w, h,
- IMB_BLEND_COPY_ALPHA);
- IMB_rectblend(clonebuf, clonebuf, ibuf, NULL, NULL, 0, destx, desty, destx, desty, srcx, srcy, w, h,
- IMB_BLEND_COPY_RGB);
+ IMB_rectblend(clonebuf, clonebuf, ibufb, NULL, NULL, NULL, 0, destx, desty, destx, desty, destx, desty, w, h,
+ IMB_BLEND_COPY_ALPHA, false);
+ IMB_rectblend(clonebuf, clonebuf, ibuf, NULL, NULL, NULL, 0, destx, desty, destx, desty, srcx, srcy, w, h,
+ IMB_BLEND_COPY_RGB, false);
return clonebuf;
}
@@ -858,17 +1003,16 @@ static void paint_2d_convert_brushco(ImBuf *ibufb, const float pos[2], int ipos[
ipos[1] = (int)floorf((pos[1] - ibufb->y / 2) + 1.0f);
}
-static int paint_2d_op(void *state, ImBuf *ibufb, unsigned short *maskb, const float lastpos[2], const float pos[2])
+static int paint_2d_op(void *state, ImBuf *ibufb, unsigned short *curveb, unsigned short *texmaskb, const float lastpos[2], const float pos[2])
{
ImagePaintState *s = ((ImagePaintState *)state);
- ImBuf *clonebuf = NULL, *frombuf, *tmpbuf = NULL;
+ ImBuf *clonebuf = NULL, *frombuf;
ImagePaintRegion region[4];
short torus = s->brush->flag & BRUSH_TORUS;
short blend = s->blend;
const float *offset = s->brush->clone.offset;
float liftpos[2];
- float brush_alpha = BKE_brush_alpha_get(s->scene, s->brush);
- unsigned short mask_max = (unsigned short)(brush_alpha * 65535.0f);
+ float mask_max = BKE_brush_alpha_get(s->scene, s->brush);
int bpos[2], blastpos[2], bliftpos[2];
int a, tot;
@@ -876,7 +1020,7 @@ static int paint_2d_op(void *state, ImBuf *ibufb, unsigned short *maskb, const f
/* lift from canvas */
if (s->tool == PAINT_TOOL_SOFTEN) {
- paint_2d_lift_soften(s->canvas, ibufb, bpos, torus);
+ paint_2d_lift_soften(s, s->canvas, ibufb, bpos, torus);
}
else if (s->tool == PAINT_TOOL_SMEAR) {
if (lastpos[0] == pos[0] && lastpos[1] == pos[1])
@@ -903,9 +1047,6 @@ static int paint_2d_op(void *state, ImBuf *ibufb, unsigned short *maskb, const f
paint_2d_set_region(region, bpos[0], bpos[1], 0, 0, frombuf->x, frombuf->y);
tot = 1;
}
-
- if (s->do_masking)
- tmpbuf = IMB_allocImBuf(IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, 32, 0);
/* blend into canvas */
for (a = 0; a < tot; a++) {
@@ -916,11 +1057,14 @@ static int paint_2d_op(void *state, ImBuf *ibufb, unsigned short *maskb, const f
if (s->do_masking) {
/* masking, find original pixels tiles from undo buffer to composite over */
int tilex, tiley, tilew, tileh, tx, ty;
+ ImBuf *tmpbuf;
imapaint_region_tiles(s->canvas, region[a].destx, region[a].desty,
region[a].width, region[a].height,
&tilex, &tiley, &tilew, &tileh);
-
+
+ tmpbuf = IMB_allocImBuf(IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, 32, 0);
+
for (ty = tiley; ty <= tileh; ty++) {
for (tx = tilex; tx <= tilew; tx++) {
/* retrieve original pixels + mask from undo buffer */
@@ -929,31 +1073,32 @@ static int paint_2d_op(void *state, ImBuf *ibufb, unsigned short *maskb, const f
int origy = region[a].desty - ty * IMAPAINT_TILE_SIZE;
if (s->canvas->rect_float)
- tmpbuf->rect_float = image_undo_find_tile(s->image, s->canvas, tx, ty, &mask);
+ tmpbuf->rect_float = image_undo_find_tile(s->image, s->canvas, tx, ty, &mask, false);
else
- tmpbuf->rect = image_undo_find_tile(s->image, s->canvas, tx, ty, &mask);
+ tmpbuf->rect = image_undo_find_tile(s->image, s->canvas, tx, ty, &mask, false);
IMB_rectblend(s->canvas, tmpbuf, frombuf, mask,
- maskb, mask_max,
+ curveb, texmaskb, mask_max,
region[a].destx, region[a].desty,
origx, origy,
region[a].srcx, region[a].srcy,
- region[a].width, region[a].height, blend);
+ region[a].width, region[a].height, blend, ((s->brush->flag & BRUSH_ACCUMULATE) != 0));
}
}
+
+ IMB_freeImBuf(tmpbuf);
}
else {
/* no masking, composite brush directly onto canvas */
- IMB_rectblend(s->canvas, s->canvas, frombuf, NULL, NULL, 0,
+ IMB_rectblend(s->canvas, s->canvas, frombuf, NULL, curveb, texmaskb, mask_max,
region[a].destx, region[a].desty,
region[a].destx, region[a].desty,
region[a].srcx, region[a].srcy,
- region[a].width, region[a].height, blend);
+ region[a].width, region[a].height, blend, false);
}
}
if (clonebuf) IMB_freeImBuf(clonebuf);
- if (tmpbuf) IMB_freeImBuf(tmpbuf);
return 1;
}
@@ -1003,10 +1148,7 @@ static int paint_2d_canvas_set(ImagePaintState *s, Image *ima)
}
/* set masking */
- s->do_masking = (s->brush->flag & BRUSH_AIRBRUSH ||
- (s->brush->imagepaint_tool == PAINT_TOOL_SMEAR) ||
- (s->brush->mtex.tex && !ELEM3(s->brush->mtex.brush_map_mode, MTEX_MAP_MODE_TILED, MTEX_MAP_MODE_STENCIL, MTEX_MAP_MODE_3D)))
- ? false : true;
+ s->do_masking = paint_use_opacity_masking(s->brush);
return 1;
}
@@ -1016,11 +1158,15 @@ static void paint_2d_canvas_free(ImagePaintState *s)
BKE_image_release_ibuf(s->image, s->canvas, NULL);
BKE_image_release_ibuf(s->brush->clone.image, s->clonecanvas, NULL);
- if (s->do_masking)
- image_undo_remove_masks();
+ if (s->blurkernel) {
+ paint_delete_blur_kernel(s->blurkernel);
+ MEM_freeN(s->blurkernel);
+ }
+
+ image_undo_remove_masks();
}
-void paint_2d_stroke(void *ps, const float prev_mval[2], const float mval[2], int eraser)
+void paint_2d_stroke(void *ps, const float prev_mval[2], const float mval[2], int eraser, float pressure, float distance, float size)
{
float newuv[2], olduv[2];
ImagePaintState *s = ps;
@@ -1063,17 +1209,17 @@ void paint_2d_stroke(void *ps, const float prev_mval[2], const float mval[2], in
/* OCIO_TODO: float buffers are now always linear, so always use color correction
* this should probably be changed when texture painting color space is supported
*/
- brush_painter_2d_require_imbuf(painter, (ibuf->rect_float != NULL), !is_data, s->do_masking);
+ brush_painter_2d_require_imbuf(painter, (ibuf->rect_float != NULL), !is_data);
- brush_painter_2d_refresh_cache(s, painter, newuv, mval);
+ brush_painter_2d_refresh_cache(s, painter, newuv, mval, pressure, distance, size);
- if (paint_2d_op(s, painter->cache.ibuf, painter->cache.mask, olduv, newuv))
+ if (paint_2d_op(s, painter->cache.ibuf, painter->cache.curve_mask, painter->cache.tex_mask, olduv, newuv))
s->need_redraw = true;
BKE_image_release_ibuf(s->image, ibuf, NULL);
}
-void *paint_2d_new_stroke(bContext *C, wmOperator *op)
+void *paint_2d_new_stroke(bContext *C, wmOperator *op, int mode)
{
Scene *scene = CTX_data_scene(C);
ToolSettings *settings = scene->toolsettings;
@@ -1102,10 +1248,14 @@ void *paint_2d_new_stroke(bContext *C, wmOperator *op)
return NULL;
}
+ if (brush->imagepaint_tool == PAINT_TOOL_SOFTEN) {
+ s->blurkernel = paint_new_blur_kernel(brush);
+ }
+
paint_brush_init_tex(s->brush);
/* create painter */
- s->painter = brush_painter_2d_new(scene, s->brush);
+ s->painter = brush_painter_2d_new(scene, s->brush, mode == BRUSH_STROKE_INVERT);
return s;
}
@@ -1134,6 +1284,7 @@ void paint_2d_redraw(const bContext *C, void *ps, bool final)
/* compositor listener deals with updating */
WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, s->image);
+ DAG_id_tag_update(&s->image->id, 0);
}
else {
if (!s->sima || !s->sima->lock)
@@ -1153,3 +1304,334 @@ void paint_2d_stroke_done(void *ps)
MEM_freeN(s);
}
+
+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;
+
+ if (x_px >= ibuf->x || x_px < 0 || y_px >= ibuf->y || y_px < 0)
+ return;
+
+ coordinate = y_px * ibuf->x + x_px;
+
+ if (!BLI_BITMAP_TEST(touched, coordinate)) {
+ float color_f[4];
+ unsigned char *color_b = (unsigned char *)(ibuf->rect + coordinate);
+ rgba_uchar_to_float(color_f, color_b);
+
+ if (compare_len_squared_v3v3(color_f, color, threshold_sq)) {
+ BLI_stack_push(stack, &coordinate);
+ }
+ BLI_BITMAP_SET(touched, coordinate, true);
+ }
+}
+
+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;
+
+ if (x_px >= ibuf->x || x_px < 0 || y_px >= ibuf->y || y_px < 0)
+ return;
+
+ coordinate = 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)) {
+ BLI_stack_push(stack, &coordinate);
+ }
+ BLI_BITMAP_SET(touched, coordinate, true);
+ }
+}
+
+/* this function expects linear space color values */
+void paint_2d_bucket_fill(
+ const bContext *C, const float color[3], Brush *br,
+ const float mouse_init[2],
+ void *ps)
+{
+ SpaceImage *sima = CTX_wm_space_image(C);
+ Image *ima = sima->image;
+
+ ImagePaintState *s = ps;
+
+ ImBuf *ibuf;
+ int x_px, y_px;
+ unsigned int color_b;
+ float color_f[4];
+ float strength = br ? br->alpha : 1.0f;
+
+ bool do_float;
+
+ if (!ima)
+ return;
+
+ ibuf = BKE_image_acquire_ibuf(ima, &sima->iuser, NULL);
+
+ if (!ibuf)
+ return;
+
+ do_float = (ibuf->rect_float != NULL);
+ /* first check if our image is float. If it is not we should correct the color to
+ * be in gamma space. strictly speaking this is not correct, but blender does not paint
+ * byte images in linear space */
+ if (!do_float) {
+ linearrgb_to_srgb_uchar3((unsigned char *)&color_b, color);
+ *(((char *)&color_b) + 3) = strength * 255;
+ }
+ else {
+ copy_v3_v3(color_f, color);
+ color_f[3] = strength;
+ }
+
+ 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);
+
+ 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);
+ }
+ }
+ }
+ 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);
+ }
+ }
+ }
+ }
+ else {
+ /* second case, start sweeping the neighboring pixels, looking for pixels whose
+ * value is within the brush fill threshold from the fill color */
+ BLI_Stack *stack;
+ BLI_bitmap *touched;
+ int coordinate;
+ int width = ibuf->x;
+ float image_init[2];
+ int minx = ibuf->x, miny = ibuf->y, maxx = 0, maxy = 0;
+ float pixel_color[4];
+ float threshold_sq = br->fill_threshold * br->fill_threshold;
+
+ UI_view2d_region_to_view(s->v2d, mouse_init[0], mouse_init[1], &image_init[0], &image_init[1]);
+
+ x_px = image_init[0] * ibuf->x;
+ y_px = image_init[1] * ibuf->y;
+
+ if (x_px >= ibuf->x || x_px < 0 || y_px > ibuf->y || y_px < 0) {
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ return;
+ }
+
+ /* change image invalidation method later */
+ ED_imapaint_dirty_region(ima, ibuf, 0, 0, ibuf->x, ibuf->y);
+
+ stack = BLI_stack_new(sizeof(int), __func__);
+ touched = BLI_BITMAP_NEW(ibuf->x * ibuf->y, "bucket_fill_bitmap");
+
+ coordinate = (y_px * ibuf->x + x_px);
+
+ if (do_float) {
+ copy_v4_v4(pixel_color, ibuf->rect_float + 4 * coordinate);
+ }
+ else {
+ int pixel_color_b = *(ibuf->rect + coordinate);
+ rgba_uchar_to_float(pixel_color, (unsigned char *)&pixel_color_b);
+ }
+
+ BLI_stack_push(stack, &coordinate);
+ BLI_BITMAP_SET(touched, coordinate, true);
+
+ if (do_float) {
+ while (!BLI_stack_is_empty(stack)) {
+ BLI_stack_pop(stack, &coordinate);
+
+ IMB_blend_color_float(ibuf->rect_float + 4 * (coordinate),
+ ibuf->rect_float + 4 * (coordinate),
+ color_f, br->blend);
+
+ /* reconstruct the coordinates here */
+ x_px = coordinate % width;
+ y_px = coordinate / width;
+
+ paint_2d_fill_add_pixel_float(x_px - 1, y_px - 1, ibuf, stack, touched, pixel_color, threshold_sq);
+ paint_2d_fill_add_pixel_float(x_px - 1, y_px, ibuf, stack, touched, pixel_color, threshold_sq);
+ paint_2d_fill_add_pixel_float(x_px - 1, y_px + 1, ibuf, stack, touched, pixel_color, threshold_sq);
+ paint_2d_fill_add_pixel_float(x_px, y_px + 1, ibuf, stack, touched, pixel_color, threshold_sq);
+ paint_2d_fill_add_pixel_float(x_px, y_px - 1, ibuf, stack, touched, pixel_color, threshold_sq);
+ paint_2d_fill_add_pixel_float(x_px + 1, y_px - 1, ibuf, stack, touched, pixel_color, threshold_sq);
+ paint_2d_fill_add_pixel_float(x_px + 1, y_px, ibuf, stack, touched, pixel_color, threshold_sq);
+ paint_2d_fill_add_pixel_float(x_px + 1, y_px + 1, ibuf, stack, touched, pixel_color, threshold_sq);
+
+ if (x_px > maxx)
+ maxx = x_px;
+ if (x_px < minx)
+ minx = x_px;
+ if (y_px > maxy)
+ maxy = y_px;
+ if (x_px > miny)
+ miny = y_px;
+ }
+ }
+ else {
+ while (!BLI_stack_is_empty(stack)) {
+ BLI_stack_pop(stack, &coordinate);
+
+ IMB_blend_color_byte((unsigned char *)(ibuf->rect + coordinate),
+ (unsigned char *)(ibuf->rect + coordinate),
+ (unsigned char *)&color_b, br->blend);
+
+ /* reconstruct the coordinates here */
+ x_px = coordinate % width;
+ y_px = coordinate / width;
+
+ paint_2d_fill_add_pixel_byte(x_px - 1, y_px - 1, ibuf, stack, touched, pixel_color, threshold_sq);
+ paint_2d_fill_add_pixel_byte(x_px - 1, y_px, ibuf, stack, touched, pixel_color, threshold_sq);
+ paint_2d_fill_add_pixel_byte(x_px - 1, y_px + 1, ibuf, stack, touched, pixel_color, threshold_sq);
+ paint_2d_fill_add_pixel_byte(x_px, y_px + 1, ibuf, stack, touched, pixel_color, threshold_sq);
+ paint_2d_fill_add_pixel_byte(x_px, y_px - 1, ibuf, stack, touched, pixel_color, threshold_sq);
+ paint_2d_fill_add_pixel_byte(x_px + 1, y_px - 1, ibuf, stack, touched, pixel_color, threshold_sq);
+ paint_2d_fill_add_pixel_byte(x_px + 1, y_px, ibuf, stack, touched, pixel_color, threshold_sq);
+ paint_2d_fill_add_pixel_byte(x_px + 1, y_px + 1, ibuf, stack, touched, pixel_color, threshold_sq);
+
+ if (x_px > maxx)
+ maxx = x_px;
+ if (x_px < minx)
+ minx = x_px;
+ if (y_px > maxy)
+ maxy = y_px;
+ if (x_px > miny)
+ miny = y_px;
+ }
+ }
+
+ MEM_freeN(touched);
+ BLI_stack_free(stack);
+ }
+
+ imapaint_image_update(sima, ima, ibuf, false);
+ ED_imapaint_clear_partial_redraw();
+
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+
+ WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima);
+}
+
+void paint_2d_gradient_fill(
+ const bContext *C, Brush *br,
+ const float mouse_init[2], const float mouse_final[2],
+ void *ps)
+{
+ SpaceImage *sima = CTX_wm_space_image(C);
+ Image *ima = sima->image;
+ ImagePaintState *s = ps;
+
+ ImBuf *ibuf;
+ int x_px, y_px;
+ unsigned int color_b;
+ float color_f[4];
+ float image_init[2], image_final[2];
+ float tangent[2];
+ float line_len_sq_inv, line_len;
+
+ bool do_float;
+
+ if (!ima)
+ return;
+
+ ibuf = BKE_image_acquire_ibuf(ima, &sima->iuser, NULL);
+
+ if (!ibuf)
+ return;
+
+ UI_view2d_region_to_view(s->v2d, mouse_final[0], mouse_final[1], &image_final[0], &image_final[1]);
+ UI_view2d_region_to_view(s->v2d, mouse_init[0], mouse_init[1], &image_init[0], &image_init[1]);
+
+ image_final[0] *= ibuf->x;
+ image_final[1] *= ibuf->y;
+
+ image_init[0] *= ibuf->x;
+ image_init[1] *= ibuf->y;
+
+ /* some math to get needed gradient variables */
+ sub_v2_v2v2(tangent, image_final, image_init);
+ line_len = len_squared_v2(tangent);
+ line_len_sq_inv = 1.0f / line_len;
+ line_len = sqrt(line_len);
+
+ 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);
+
+ if (do_float) {
+ for (x_px = 0; x_px < ibuf->x; x_px++) {
+ for (y_px = 0; y_px < ibuf->y; y_px++) {
+ float f;
+ float p[2] = {x_px - image_init[0], y_px - image_init[1]};
+
+ switch (br->gradient_fill_mode) {
+ case BRUSH_GRADIENT_LINEAR:
+ {
+ f = dot_v2v2(p, tangent) * line_len_sq_inv;
+ break;
+ }
+ case BRUSH_GRADIENT_RADIAL:
+ {
+ f = len_v2(p) / line_len;
+ break;
+ }
+ }
+ do_colorband(br->gradient, f, color_f);
+ /* 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),
+ color_f, br->blend);
+ }
+ }
+ }
+ else {
+ for (x_px = 0; x_px < ibuf->x; x_px++) {
+ for (y_px = 0; y_px < ibuf->y; y_px++) {
+ float f;
+ float p[2] = {x_px - image_init[0], y_px - image_init[1]};
+
+ switch (br->gradient_fill_mode) {
+ case BRUSH_GRADIENT_LINEAR:
+ {
+ f = dot_v2v2(p, tangent) * line_len_sq_inv;
+ break;
+ }
+ case BRUSH_GRADIENT_RADIAL:
+ {
+ f = len_v2(p) / line_len;
+ break;
+ }
+ }
+
+ do_colorband(br->gradient, 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),
+ (unsigned char *)&color_b, br->blend);
+ }
+ }
+ }
+
+ imapaint_image_update(sima, ima, ibuf, false);
+ ED_imapaint_clear_partial_redraw();
+
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+
+ WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima);
+}
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c
index 399b5044a05..e10c97ea9f0 100644
--- a/source/blender/editors/sculpt_paint/paint_image_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_image_proj.c
@@ -48,30 +48,39 @@
#include "BLI_threads.h"
#include "BLI_utildefines.h"
+#include "BLF_translation.h"
+
#include "PIL_time.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
#include "DNA_brush_types.h"
+#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_node_types.h"
#include "DNA_object_types.h"
#include "BKE_camera.h"
+#include "BKE_colortools.h"
#include "BKE_context.h"
+#include "BKE_depsgraph.h"
#include "BKE_DerivedMesh.h"
#include "BKE_idprop.h"
#include "BKE_brush.h"
#include "BKE_image.h"
#include "BKE_library.h"
#include "BKE_main.h"
+#include "BKE_material.h"
+#include "BKE_mesh.h"
#include "BKE_mesh_mapping.h"
#include "BKE_paint.h"
#include "BKE_report.h"
#include "BKE_scene.h"
+#include "BKE_texture.h"
#include "UI_view2d.h"
+#include "UI_interface.h"
#include "ED_paint.h"
#include "ED_screen.h"
@@ -141,6 +150,7 @@ BLI_INLINE unsigned char f_to_char(const float val)
#define PROJ_SRC_VIEW 1
#define PROJ_SRC_IMAGE_CAM 2
#define PROJ_SRC_IMAGE_VIEW 3
+#define PROJ_SRC_VIEW_FILL 4
#define PROJ_VIEW_DATA_ID "view_data"
#define PROJ_VIEW_DATA_SIZE (4 * 4 + 4 * 4 + 3) /* viewmat + winmat + clipsta + clipend + is_ortho */
@@ -162,6 +172,9 @@ BLI_INLINE unsigned char f_to_char(const float val)
/* vert flags */
#define PROJ_VERT_CULL 1
+/* to avoid locking in tile initialization */
+#define TILE_PENDING SET_INT_IN_POINTER(-1)
+
/* This is mainly a convenience struct used so we can keep an array of images we use
* Thir imbufs, etc, in 1 array, When using threads this array is copied for each thread
* because 'partRedrawRect' and 'touch' values would not be thread safe */
@@ -169,7 +182,10 @@ typedef struct ProjPaintImage {
Image *ima;
ImBuf *ibuf;
ImagePaintPartialRedraw *partRedrawRect;
- void **undoRect; /* only used to build undo tiles after painting */
+ volatile void **undoRect; /* only used to build undo tiles during painting */
+ 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;
} ProjPaintImage;
@@ -181,9 +197,14 @@ typedef struct ProjPaintState {
Scene *scene;
int source; /* PROJ_SRC_**** */
+ /* the paint color. It can change depending of inverted mode or not */
+ float paint_color[3];
+ float paint_color_linear[3];
+
Brush *brush;
short tool, blend, mode;
int orig_brush_size;
+ float brush_size;
Object *ob;
/* end similarities with ImagePaintState */
@@ -194,10 +215,13 @@ typedef struct ProjPaintState {
MVert *dm_mvert;
MFace *dm_mface;
- MTFace *dm_mtface;
- MTFace *dm_mtface_clone; /* other UV map, use for cloning between layers */
+ MTFace **dm_mtface;
+ MTFace **dm_mtface_clone; /* other UV map, use for cloning between layers */
MTFace *dm_mtface_stencil;
+ Image *stencil_ima;
+ float stencil_value;
+
/* projection painting only */
MemArena *arena_mt[BLENDER_MAX_THREADS]; /* for multithreading, the first item is sometimes used for non threaded cases too */
LinkNode **bucketRect; /* screen sized 2D array, each pixel has a linked list of ProjPixel's */
@@ -231,6 +255,7 @@ typedef struct ProjPaintState {
bool do_layer_clone;
bool do_layer_stencil;
bool do_layer_stencil_inv;
+ bool do_stencil_brush;
bool do_occlude; /* Use raytraced occlusion? - ortherwise will paint right through to the back*/
bool do_backfacecull; /* ignore faces with normals pointing away, skips a lot of raycasts if your normals are correctly flipped */
@@ -245,7 +270,6 @@ typedef struct ProjPaintState {
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 */
- bool is_maskbrush_tiled; /* mask brush is applied after masking */
#ifndef PROJ_DEBUG_NOSEAMBLEED
float seam_bleed_px;
#endif
@@ -269,6 +293,10 @@ typedef struct ProjPaintState {
/* redraw */
bool need_redraw;
+
+ BlurKernel *blurkernel;
+
+ SpinLock *tile_lock;
} ProjPaintState;
typedef union pixelPointer {
@@ -290,14 +318,16 @@ typedef struct ProjPixel {
* 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;
+ 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;
- PixelStore origColor;
+ PixelPointer origColor;
PixelStore newColor;
PixelPointer pixel;
@@ -310,33 +340,44 @@ typedef struct ProjPixelClone {
PixelStore clonepx;
} ProjPixelClone;
-/* blur, store surrounding colors */
-#define PROJ_PIXEL_SOFTEN_TOT 4
-/* blur picking offset (in screenspace) */
-#define PROJ_PIXEL_SOFTEN_OFS_PX 1.0f
+/* undo tile pushing */
+typedef struct {
+ SpinLock *lock;
+ bool masked;
+ unsigned short tile_width;
+ ImBuf **tmpibuf;
+ ProjPaintImage *pjima;
+} TileInfo;
-static const float proj_pixel_soften_v2[PROJ_PIXEL_SOFTEN_TOT][2] = {
- {-PROJ_PIXEL_SOFTEN_OFS_PX, 0.0f},
- { 0.0f, -PROJ_PIXEL_SOFTEN_OFS_PX},
- { 0.0f, PROJ_PIXEL_SOFTEN_OFS_PX},
- { PROJ_PIXEL_SOFTEN_OFS_PX, 0.0f},
-};
/* Finish projection painting structs */
-static Image *project_paint_face_image(const ProjPaintState *ps, MTFace *dm_mtface, int face_index)
+static TexPaintSlot *project_paint_face_paint_slot(const ProjPaintState *ps, int face_index)
{
- Image *ima;
+ MFace *mf = ps->dm_mface + face_index;
+ Material *ma = ps->dm->mat[mf->mat_nr];
+ return ma->texpaintslot + ma->paint_active_slot;
+}
- if (ps->do_new_shading_nodes) { /* cached BKE_scene_use_new_shading_nodes result */
- MFace *mf = ps->dm_mface + face_index;
- ED_object_get_active_image(ps->ob, mf->mat_nr + 1, &ima, NULL, NULL);
+static Image *project_paint_face_paint_image(const ProjPaintState *ps, int face_index)
+{
+ if (ps->do_stencil_brush) {
+ return ps->stencil_ima;
}
else {
- ima = dm_mtface[face_index].tpage;
+ MFace *mf = ps->dm_mface + face_index;
+ Material *ma = ps->dm->mat[mf->mat_nr];
+ TexPaintSlot *slot = ma->texpaintslot + ma->paint_active_slot;
+ return slot ? slot->ima : NULL;
}
+}
+
- return ima;
+static TexPaintSlot *project_paint_face_clone_slot(const ProjPaintState *ps, int face_index)
+{
+ MFace *mf = ps->dm_mface + face_index;
+ Material *ma = ps->dm->mat[mf->mat_nr];
+ return &ma->texpaintslot[ma->paint_clone_slot];
}
/* fast projection bucket array lookup, use the safe version for bound checking */
@@ -477,8 +518,8 @@ static int project_paint_PickFace(const ProjPaintState *ps, const float pt[2], f
static void uvco_to_wrapped_pxco(const float uv[2], int ibuf_x, int ibuf_y, float *x, float *y)
{
/* use */
- *x = (float)fmodf(uv[0], 1.0f);
- *y = (float)fmodf(uv[1], 1.0f);
+ *x = fmodf(uv[0], 1.0f);
+ *y = fmodf(uv[1], 1.0f);
if (*x < 0.0f) *x += 1.0f;
if (*y < 0.0f) *y += 1.0f;
@@ -505,7 +546,7 @@ static bool project_paint_PickColor(const ProjPaintState *ps, const float pt[2],
if (face_index == -1)
return 0;
- tf = ps->dm_mtface + face_index;
+ tf = *(ps->dm_mtface + face_index);
if (side == 0) {
interp_v2_v2v2v2(uv, tf->uv[0], tf->uv[1], tf->uv[2], w);
@@ -514,8 +555,9 @@ static bool project_paint_PickColor(const ProjPaintState *ps, const float pt[2],
interp_v2_v2v2v2(uv, tf->uv[0], tf->uv[2], tf->uv[3], w);
}
- ima = project_paint_face_image(ps, ps->dm_mtface, face_index);
+ ima = project_paint_face_paint_image(ps, face_index);
ibuf = BKE_image_get_first_ibuf(ima); /* we must have got the imbuf before getting here */
+ if (!ibuf) return 0;
if (interp) {
float x, y;
@@ -762,11 +804,11 @@ static int line_isect_x(const float p1[2], const float p2[2], const float x_leve
static bool cmp_uv(const float vec2a[2], const float vec2b[2])
{
/* if the UV's are not between 0.0 and 1.0 */
- float xa = (float)fmodf(vec2a[0], 1.0f);
- float ya = (float)fmodf(vec2a[1], 1.0f);
+ float xa = fmodf(vec2a[0], 1.0f);
+ float ya = fmodf(vec2a[1], 1.0f);
- float xb = (float)fmodf(vec2b[0], 1.0f);
- float yb = (float)fmodf(vec2b[1], 1.0f);
+ float xb = fmodf(vec2b[0], 1.0f);
+ float yb = fmodf(vec2b[1], 1.0f);
if (xa < 0.0f) xa += 1.0f;
if (ya < 0.0f) ya += 1.0f;
@@ -843,7 +885,7 @@ static bool pixel_bounds_array(float (*uv)[2], rcti *bounds_px, const int ibuf_x
static void project_face_winding_init(const ProjPaintState *ps, const int face_index)
{
/* detect the winding of faces in uv space */
- MTFace *tf = ps->dm_mtface + face_index;
+ MTFace *tf = ps->dm_mtface[face_index];
float winding = cross_tri_v2(tf->uv[0], tf->uv[1], tf->uv[2]);
if (ps->dm_mface[face_index].v4)
@@ -868,7 +910,7 @@ static bool check_seam(const ProjPaintState *ps,
MFace *mf;
MTFace *tf;
const MFace *orig_mf = ps->dm_mface + orig_face;
- const MTFace *orig_tf = ps->dm_mtface + orig_face;
+ const MTFace *orig_tf = ps->dm_mtface[orig_face];
/* vert indices from face vert order indices */
i1 = (*(&orig_mf->v1 + orig_i1_fidx));
@@ -890,13 +932,13 @@ static bool check_seam(const ProjPaintState *ps,
/* Only need to check if 'i2_fidx' is valid because we know i1_fidx is the same vert on both faces */
if (i2_fidx != -1) {
- Image *tpage = project_paint_face_image(ps, ps->dm_mtface, face_index);
- Image *orig_tpage = project_paint_face_image(ps, ps->dm_mtface, orig_face);
+ Image *tpage = project_paint_face_paint_image(ps, face_index);
+ Image *orig_tpage = project_paint_face_paint_image(ps, orig_face);
BLI_assert(i1_fidx != -1);
/* This IS an adjacent face!, now lets check if the UVs are ok */
- tf = ps->dm_mtface + face_index;
+ tf = ps->dm_mtface[face_index];
/* set up the other face */
*other_face = face_index;
@@ -909,7 +951,7 @@ static bool check_seam(const ProjPaintState *ps,
/* first test if they have the same image */
if ((orig_tpage == tpage) &&
cmp_uv(orig_tf->uv[orig_i1_fidx], tf->uv[i1_fidx]) &&
- cmp_uv(orig_tf->uv[orig_i2_fidx], tf->uv[i2_fidx]) )
+ cmp_uv(orig_tf->uv[orig_i2_fidx], tf->uv[i2_fidx]))
{
/* if faces don't have the same winding in uv space,
* they are on the same side so edge is boundary */
@@ -1168,7 +1210,7 @@ static float project_paint_uvpixel_mask(
if (ps->do_layer_stencil) {
/* another UV maps image is masking this one's */
ImBuf *ibuf_other;
- Image *other_tpage = project_paint_face_image(ps, ps->dm_mtface_stencil, face_index);
+ Image *other_tpage = ps->stencil_ima;
const MTFace *tf_other = ps->dm_mtface_stencil + face_index;
if (other_tpage && (ibuf_other = BKE_image_acquire_ibuf(other_tpage, NULL, NULL))) {
@@ -1296,24 +1338,70 @@ static int project_paint_pixel_sizeof(const short tool)
}
}
+static int project_paint_undo_subtiles(const TileInfo *tinf, int tx, int ty)
+{
+ ProjPaintImage *pjIma = tinf->pjima;
+ int tile_index = tx + ty * tinf->tile_width;
+ bool generate_tile = false;
+
+ /* double check lock to avoid locking */
+ if (UNLIKELY(!pjIma->undoRect[tile_index])) {
+ if (tinf->lock)
+ BLI_spin_lock(tinf->lock);
+ if (LIKELY(!pjIma->undoRect[tile_index])) {
+ pjIma->undoRect[tile_index] = TILE_PENDING;
+ generate_tile = true;
+ }
+ if (tinf->lock)
+ BLI_spin_unlock(tinf->lock);
+ }
+
+
+ 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);
+ }
+ else {
+ undorect = image_undo_push_tile(pjIma->ima, pjIma->ibuf, tinf->tmpibuf, tx, ty, NULL, &pjIma->valid[tile_index], true);
+ }
+
+ pjIma->ibuf->userflags |= IB_BITMAPDIRTY;
+ /* tile ready, publish */
+ if (tinf->lock)
+ BLI_spin_lock(tinf->lock);
+ pjIma->undoRect[tile_index] = undorect;
+ if (tinf->lock)
+ BLI_spin_unlock(tinf->lock);
+
+ }
+
+ return tile_index;
+}
/* run this function when we know a bucket's, face's pixel can be initialized,
* return the ProjPixel which is added to 'ps->bucketRect[bucket_index]' */
static ProjPixel *project_paint_uvpixel_init(
const ProjPaintState *ps,
MemArena *arena,
- const ImBuf *ibuf,
+ const TileInfo *tinf,
int x_px, int y_px,
const float mask,
const int face_index,
- const int image_index,
const float pixelScreenCo[4],
const float world_spaceCo[3],
const int side,
const float w[3])
{
ProjPixel *projPixel;
-
+ int x_tile, y_tile;
+ int x_round, y_round;
+ int tile_offset;
+ /* volatile is important here to ensure pending check is not optimized away by compiler*/
+ volatile int tile_index;
+
+ ProjPaintImage *projima = tinf->pjima;
+ ImBuf *ibuf = projima->ibuf;
/* wrap pixel location */
x_px = mod_i(x_px, ibuf->x);
@@ -1321,19 +1409,36 @@ static ProjPixel *project_paint_uvpixel_init(
BLI_assert(ps->pixel_sizeof == project_paint_pixel_sizeof(ps->tool));
projPixel = (ProjPixel *)BLI_memarena_alloc(arena, ps->pixel_sizeof);
+
+ /* calculate the undo tile offset of the pixel, used to store the original
+ * pixel color and accumulated mask if any */
+ x_tile = x_px >> IMAPAINT_TILE_BITS;
+ y_tile = y_px >> IMAPAINT_TILE_BITS;
+
+ x_round = x_tile * IMAPAINT_TILE_SIZE;
+ y_round = y_tile * IMAPAINT_TILE_SIZE;
//memset(projPixel, 0, size);
+ tile_offset = (x_px - x_round) + (y_px - y_round) * IMAPAINT_TILE_SIZE;
+ tile_index = project_paint_undo_subtiles(tinf, x_tile, y_tile);
+
+ /* other thread may be initializing the tile so wait here */
+ while (projima->undoRect[tile_index] == TILE_PENDING)
+ ;
+
+ BLI_assert(tile_index < (IMAPAINT_TILE_NUMBER(ibuf->x) * IMAPAINT_TILE_NUMBER(ibuf->y)));
+ BLI_assert(tile_offset < (IMAPAINT_TILE_SIZE * IMAPAINT_TILE_SIZE));
+
+ projPixel->valid = projima->valid[tile_index];
+
if (ibuf->rect_float) {
projPixel->pixel.f_pt = ibuf->rect_float + ((x_px + y_px * ibuf->x) * 4);
- projPixel->origColor.f[0] = projPixel->pixel.f_pt[0];
- projPixel->origColor.f[1] = projPixel->pixel.f_pt[1];
- projPixel->origColor.f[2] = projPixel->pixel.f_pt[2];
- projPixel->origColor.f[3] = projPixel->pixel.f_pt[3];
+ projPixel->origColor.f_pt = (float *)projima->undoRect[tile_index] + 4 * tile_offset;
zero_v4(projPixel->newColor.f);
}
else {
- projPixel->pixel.ch_pt = ((unsigned char *)ibuf->rect + ((x_px + y_px * ibuf->x) * 4));
- projPixel->origColor.uint = *projPixel->pixel.uint_pt;
+ projPixel->pixel.ch_pt = (unsigned char *)(ibuf->rect + (x_px + y_px * ibuf->x));
+ projPixel->origColor.uint_pt = (unsigned int *)projima->undoRect[tile_index] + tile_offset;
projPixel->newColor.uint = 0;
}
@@ -1348,7 +1453,10 @@ static ProjPixel *project_paint_uvpixel_init(
projPixel->y_px = y_px;
projPixel->mask = (unsigned short)(mask * 65535);
- projPixel->mask_accum = 0;
+ if (ps->do_masking)
+ projPixel->mask_accum = projima->maskRect[tile_index] + tile_offset;
+ else
+ projPixel->mask_accum = NULL;
/* which bounding box cell are we in?, needed for undo */
projPixel->bb_cell_index = ((int)(((float)x_px / (float)ibuf->x) * PROJ_BOUNDBOX_DIV)) +
@@ -1358,8 +1466,8 @@ static ProjPixel *project_paint_uvpixel_init(
if (ps->tool == PAINT_TOOL_CLONE) {
if (ps->dm_mtface_clone) {
ImBuf *ibuf_other;
- Image *other_tpage = project_paint_face_image(ps, ps->dm_mtface_clone, face_index);
- const MTFace *tf_other = ps->dm_mtface_clone + face_index;
+ Image *other_tpage = project_paint_face_clone_slot(ps, face_index)->ima;
+ const MTFace *tf_other = ps->dm_mtface_clone[face_index];
if (other_tpage && (ibuf_other = BKE_image_acquire_ibuf(other_tpage, NULL, NULL))) {
/* BKE_image_acquire_ibuf - TODO - this may be slow */
@@ -1423,7 +1531,8 @@ static ProjPixel *project_paint_uvpixel_init(
if (ibuf->rect_float) projPixel->pixel.f_pt[0] = 0;
else projPixel->pixel.ch_pt[0] = 0;
#endif
- projPixel->image_index = image_index;
+ /* pointer arithmetics */
+ projPixel->image_index = projima - ps->projImages;
return projPixel;
}
@@ -2131,15 +2240,24 @@ static bool IsectPoly2Df_twoside(const float pt[2], float uv[][2], const int tot
/* One of the most important function for projection painting, since it selects the pixels to be added into each bucket.
* initialize pixels from this face where it intersects with the bucket_index, optionally initialize pixels for removing seams */
-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, rctf *bucket_bounds, const ImBuf *ibuf, const short clamp_u, const short clamp_v)
+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, rctf *bucket_bounds, ImBuf *ibuf, ImBuf **tmpibuf, const short clamp_u, const short clamp_v)
{
/* Projection vars, to get the 3D locations into screen space */
MemArena *arena = ps->arena_mt[thread_index];
LinkNode **bucketPixelNodes = ps->bucketRect + bucket_index;
LinkNode *bucketFaceNodes = ps->bucketFaces[bucket_index];
+ bool threaded = (ps->thread_tot > 1);
+
+ TileInfo tinf = {
+ ps->tile_lock,
+ ps->do_masking,
+ IMAPAINT_TILE_NUMBER(ibuf->x),
+ tmpibuf,
+ ps->projImages + image_index
+ };
const MFace *mf = ps->dm_mface + face_index;
- const MTFace *tf = ps->dm_mtface + face_index;
+ const MTFace *tf = ps->dm_mtface[face_index];
/* UV/pixel seeking data */
int x; /* Image X-Pixel */
@@ -2183,8 +2301,8 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i
/* Use tf_uv_pxoffset instead of tf->uv so we can offset the UV half a pixel
* this is done so we can avoid offsetting all the pixels by 0.5 which causes
* problems when wrapping negative coords */
- xhalfpx = (0.5f + (PROJ_GEOM_TOLERANCE * (1.0f / 3.0f))) / ibuf_xf;
- yhalfpx = (0.5f + (PROJ_GEOM_TOLERANCE * (1.0f / 4.0f))) / ibuf_yf;
+ xhalfpx = (0.5f + (PROJ_PIXEL_TOLERANCE * (1.0f / 3.0f))) / ibuf_xf;
+ yhalfpx = (0.5f + (PROJ_PIXEL_TOLERANCE * (1.0f / 4.0f))) / ibuf_yf;
/* Note about (PROJ_GEOM_TOLERANCE/x) above...
* Needed to add this offset since UV coords are often quads aligned to pixels.
@@ -2258,6 +2376,10 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i
CLAMP(bounds_px.ymax, 0, ibuf->y);
}
+ /*
+ project_paint_undo_tiles_init(&bounds_px, ps->projImages + image_index, tmpibuf,
+ tile_width, threaded, ps->do_masking);
+ */
/* clip face and */
has_isect = 0;
@@ -2300,8 +2422,8 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i
if (mask > 0.0f) {
BLI_linklist_prepend_arena(
bucketPixelNodes,
- project_paint_uvpixel_init(ps, arena, ibuf, x, y, mask, face_index,
- image_index, pixelScreenCo, wco, side, w),
+ project_paint_uvpixel_init(ps, arena, &tinf, x, y, mask, face_index,
+ pixelScreenCo, wco, side, w),
arena
);
}
@@ -2333,7 +2455,7 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i
if (ps->seam_bleed_px > 0.0f) {
int face_seam_flag;
- if (ps->thread_tot > 1)
+ if (threaded)
BLI_lock_thread(LOCK_CUSTOM1); /* Other threads could be modifying these vars */
face_seam_flag = ps->faceSeamFlags[face_index];
@@ -2351,7 +2473,7 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i
if ((face_seam_flag & (PROJ_FACE_SEAM1 | PROJ_FACE_SEAM2 | PROJ_FACE_SEAM3 | PROJ_FACE_SEAM4)) == 0) {
- if (ps->thread_tot > 1)
+ if (threaded)
BLI_unlock_thread(LOCK_CUSTOM1); /* Other threads could be modifying these vars */
}
@@ -2376,7 +2498,7 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i
uv_image_outset(tf_uv_pxoffset, outset_uv, ps->seam_bleed_px, ibuf->x, ibuf->y, mf->v4 != 0);
/* ps->faceSeamUVs cant be modified when threading, now this is done we can unlock */
- if (ps->thread_tot > 1)
+ if (threaded)
BLI_unlock_thread(LOCK_CUSTOM1); /* Other threads could be modifying these vars */
vCoSS[0] = ps->screenCoords[mf->v1];
@@ -2520,7 +2642,8 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i
if (mask > 0.0f) {
BLI_linklist_prepend_arena(
bucketPixelNodes,
- project_paint_uvpixel_init(ps, arena, ibuf, x, y, mask, face_index, image_index, pixelScreenCo, wco, side, w),
+ project_paint_uvpixel_init(ps, arena, &tinf, x, y, mask, face_index,
+ pixelScreenCo, wco, side, w),
arena
);
}
@@ -2589,6 +2712,7 @@ static void project_bucket_init(const ProjPaintState *ps, const int thread_index
ImBuf *ibuf = NULL;
Image *tpage_last = NULL, *tpage;
Image *ima = NULL;
+ ImBuf *tmpibuf = NULL;
if (ps->image_tot == 1) {
/* Simple loop, no context switching */
@@ -2596,7 +2720,7 @@ 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, 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, ima->tpageflag & IMA_CLAMP_V);
}
}
else {
@@ -2606,7 +2730,7 @@ static void project_bucket_init(const ProjPaintState *ps, const int thread_index
face_index = GET_INT_FROM_POINTER(node->link);
/* Image context switching */
- tpage = project_paint_face_image(ps, ps->dm_mtface, face_index);
+ tpage = project_paint_face_paint_image(ps, face_index);
if (tpage_last != tpage) {
tpage_last = tpage;
@@ -2620,10 +2744,13 @@ 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, 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, ima->tpageflag & IMA_CLAMP_V);
}
}
+ if (tmpibuf)
+ IMB_freeImBuf(tmpibuf);
+
ps->bucketFlags[bucket_index] |= PROJ_BUCKET_INIT;
}
@@ -2771,11 +2898,17 @@ static void project_paint_begin(ProjPaintState *ps)
ProjPaintImage *projIma;
Image *tpage_last = NULL, *tpage;
+ TexPaintSlot *slot_last = NULL, *slot = NULL;
+ TexPaintSlot *slot_last_clone = NULL, *slot_clone;
/* Face vars */
MPoly *mpoly_orig;
MFace *mf;
- MTFace *tf;
+ MTFace **tf;
+ MTFace *tf_base;
+
+ MTFace **tf_clone;
+ MTFace *tf_clone_base;
int a, i; /* generic looping vars */
int image_index = -1, face_index;
@@ -2830,13 +2963,15 @@ static void project_paint_begin(ProjPaintState *ps)
return;
}
- ps->dm_mvert = ps->dm->getVertArray(ps->dm);
- ps->dm_mface = ps->dm->getTessFaceArray(ps->dm);
- ps->dm_mtface = ps->dm->getTessFaceDataArray(ps->dm, CD_MTFACE);
+ DM_update_materials(ps->dm, ps->ob);
ps->dm_totvert = ps->dm->getNumVerts(ps->dm);
ps->dm_totface = ps->dm->getNumTessFaces(ps->dm);
+ ps->dm_mvert = ps->dm->getVertArray(ps->dm);
+ ps->dm_mface = ps->dm->getTessFaceArray(ps->dm);
+ ps->dm_mtface = MEM_mallocN(ps->dm_totface * sizeof(MTFace *), "proj_paint_mtfaces");
+
if (ps->do_face_sel) {
index_mf_to_mpoly = ps->dm->getTessFaceDataArray(ps->dm, CD_ORIGINDEX);
index_mp_to_orig = ps->dm->getPolyDataArray(ps->dm, CD_ORIGINDEX);
@@ -2852,32 +2987,23 @@ static void project_paint_begin(ProjPaintState *ps)
}
/* use clone mtface? */
-
-
- /* Note, use the original mesh for getting the clone and mask layer index
- * this avoids re-generating the derived mesh just to get the new index */
if (ps->do_layer_clone) {
- //int layer_num = CustomData_get_clone_layer(&ps->dm->faceData, CD_MTFACE);
- int layer_num = CustomData_get_clone_layer(&((Mesh *)ps->ob->data)->pdata, CD_MTEXPOLY);
- if (layer_num != -1)
- ps->dm_mtface_clone = CustomData_get_layer_n(&ps->dm->faceData, CD_MTFACE, layer_num);
-
- if (ps->dm_mtface_clone == NULL || ps->dm_mtface_clone == ps->dm_mtface) {
- ps->do_layer_clone = false;
- ps->dm_mtface_clone = NULL;
- }
+ ps->dm_mtface_clone = MEM_mallocN(ps->dm_totface * sizeof(MTFace *), "proj_paint_mtfaces");
}
- if (ps->do_layer_stencil) {
+ if (ps->do_layer_stencil || ps->do_stencil_brush) {
//int layer_num = CustomData_get_stencil_layer(&ps->dm->faceData, CD_MTFACE);
int layer_num = CustomData_get_stencil_layer(&((Mesh *)ps->ob->data)->pdata, CD_MTEXPOLY);
if (layer_num != -1)
ps->dm_mtface_stencil = CustomData_get_layer_n(&ps->dm->faceData, CD_MTFACE, layer_num);
- if (ps->dm_mtface_stencil == NULL || ps->dm_mtface_stencil == ps->dm_mtface) {
- ps->do_layer_stencil = false;
- ps->dm_mtface_stencil = NULL;
+ if (ps->dm_mtface_stencil == NULL) {
+ /* get active instead */
+ ps->dm_mtface_stencil = CustomData_get_layer(&ps->dm->faceData, CD_MTFACE);
}
+
+ if (ps->do_stencil_brush)
+ tf_base = ps->dm_mtface_stencil;
}
/* when using subsurf or multires, mface arrays are thrown away, we need to keep a copy */
@@ -3092,6 +3218,13 @@ static void project_paint_begin(ProjPaintState *ps)
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);
+ }
+
+ 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");
}
@@ -3153,7 +3286,48 @@ static void project_paint_begin(ProjPaintState *ps)
is_face_sel = true;
}
- if (is_face_sel && (tpage = project_paint_face_image(ps, ps->dm_mtface, face_index))) {
+ if (!ps->do_stencil_brush) {
+ slot = project_paint_face_paint_slot(ps, face_index);
+ /* all faces should have a valid slot, reassert here */
+ if (slot == NULL) {
+ tf_base = CustomData_get_layer(&ps->dm->faceData, CD_MTFACE);
+ }
+ else {
+ if (slot != slot_last) {
+ if (!slot->uvname || !(tf_base = CustomData_get_layer_named(&ps->dm->faceData, CD_MTFACE, slot->uvname)))
+ tf_base = CustomData_get_layer(&ps->dm->faceData, CD_MTFACE);
+ slot_last = slot;
+ }
+
+ /* don't allow using the same inage for painting and stencilling */
+ if (slot->ima == ps->stencil_ima)
+ continue;
+ }
+ }
+
+ *tf = tf_base + face_index;
+
+ if (ps->do_layer_clone) {
+ slot_clone = project_paint_face_clone_slot(ps, face_index);
+ /* all faces should have a valid slot, reassert here */
+ if (ELEM(slot_clone, NULL, slot))
+ continue;
+
+ tf_clone = ps->dm_mtface_clone + face_index;
+
+ if (slot_clone != slot_last_clone) {
+ if (!slot->uvname || !(tf_clone_base = CustomData_get_layer_named(&ps->dm->faceData, CD_MTFACE, slot_clone->uvname)))
+ tf_clone_base = CustomData_get_layer(&ps->dm->faceData, CD_MTFACE);
+ slot_last_clone = slot_clone;
+ }
+
+ *tf_clone = tf_clone_base + face_index;
+ }
+
+ /* tfbase here should be non-null! */
+ BLI_assert (tf_base != NULL);
+
+ if (is_face_sel && ((slot && (tpage = slot->ima)) || (tpage = project_paint_face_paint_image(ps, face_index)))) {
const float *v1coSS, *v2coSS, *v3coSS, *v4coSS = NULL;
v1coSS = ps->screenCoords[mf->v1];
@@ -3251,10 +3425,19 @@ static void project_paint_begin(ProjPaintState *ps)
projIma = ps->projImages = (ProjPaintImage *)BLI_memarena_alloc(arena, sizeof(ProjPaintImage) * ps->image_tot);
for (node = image_LinkList, i = 0; node; node = node->next, i++, projIma++) {
+ int size;
projIma->ima = node->link;
projIma->touch = 0;
projIma->ibuf = BKE_image_acquire_ibuf(projIma->ima, NULL, NULL);
- projIma->partRedrawRect = BLI_memarena_calloc(arena, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
+ size = sizeof(void **) * IMAPAINT_TILE_NUMBER(projIma->ibuf->x) * IMAPAINT_TILE_NUMBER(projIma->ibuf->y);
+ projIma->partRedrawRect = BLI_memarena_alloc(arena, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
+ memset(projIma->partRedrawRect, 0, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
+ projIma->undoRect = (volatile void **) BLI_memarena_alloc(arena, size);
+ memset(projIma->undoRect, 0, size);
+ projIma->maskRect = (unsigned short **) BLI_memarena_alloc(arena, size);
+ memset(projIma->maskRect, 0, size);
+ projIma->valid = (bool **) BLI_memarena_alloc(arena, size);
+ memset(projIma->valid, 0, size);
}
/* we have built the array, discard the linked list */
@@ -3281,95 +3464,12 @@ static void project_paint_end(ProjPaintState *ps)
int a;
ProjPaintImage *projIma;
- /* build undo data from original pixel colors */
- if (U.uiflag & USER_GLOBALUNDO) {
- ProjPixel *projPixel;
- ImBuf *tmpibuf = NULL, *tmpibuf_float = NULL;
- LinkNode *pixel_node;
- void *tilerect;
- MemArena *arena = ps->arena_mt[0]; /* threaded arena re-used for non threaded case */
-
- int bucket_tot = (ps->buckets_x * ps->buckets_y); /* we could get an X/Y but easier to loop through all possible buckets */
- int bucket_index;
- int tile_index;
- int x_round, y_round;
- int x_tile, y_tile;
- int is_float = -1;
-
- /* context */
- ProjPaintImage *last_projIma;
- int last_image_index = -1;
- int last_tile_width = 0;
-
- for (a = 0, last_projIma = ps->projImages; a < ps->image_tot; a++, last_projIma++) {
- int size = sizeof(void **) * IMAPAINT_TILE_NUMBER(last_projIma->ibuf->x) * IMAPAINT_TILE_NUMBER(last_projIma->ibuf->y);
- last_projIma->undoRect = (void **) BLI_memarena_calloc(arena, size);
- last_projIma->ibuf->userflags |= IB_BITMAPDIRTY;
- }
-
- for (bucket_index = 0; bucket_index < bucket_tot; bucket_index++) {
- /* loop through all pixels */
- for (pixel_node = ps->bucketRect[bucket_index]; pixel_node; pixel_node = pixel_node->next) {
-
- /* ok we have a pixel, was it modified? */
- projPixel = (ProjPixel *)pixel_node->link;
-
- if (last_image_index != projPixel->image_index) {
- /* set the context */
- last_image_index = projPixel->image_index;
- last_projIma = ps->projImages + last_image_index;
- last_tile_width = IMAPAINT_TILE_NUMBER(last_projIma->ibuf->x);
- is_float = last_projIma->ibuf->rect_float ? 1 : 0;
- }
-
-
- if ((is_float == 0 && projPixel->origColor.uint != *projPixel->pixel.uint_pt) ||
- (is_float == 1 &&
- (projPixel->origColor.f[0] != projPixel->pixel.f_pt[0] ||
- projPixel->origColor.f[1] != projPixel->pixel.f_pt[1] ||
- projPixel->origColor.f[2] != projPixel->pixel.f_pt[2] ||
- projPixel->origColor.f[3] != projPixel->pixel.f_pt[3]))
- )
- {
-
- x_tile = projPixel->x_px >> IMAPAINT_TILE_BITS;
- y_tile = projPixel->y_px >> IMAPAINT_TILE_BITS;
-
- x_round = x_tile * IMAPAINT_TILE_SIZE;
- y_round = y_tile * IMAPAINT_TILE_SIZE;
-
- tile_index = x_tile + y_tile * last_tile_width;
-
- if (last_projIma->undoRect[tile_index] == NULL) {
- /* add the undo tile from the modified image, then write the original colors back into it */
- tilerect = last_projIma->undoRect[tile_index] = image_undo_push_tile(last_projIma->ima, last_projIma->ibuf, is_float ? (&tmpibuf_float) : (&tmpibuf), x_tile, y_tile);
- }
- else {
- tilerect = last_projIma->undoRect[tile_index];
- }
-
- /* This is a BIT ODD, but overwrite the undo tiles image info with this pixels original color
- * because allocating the tiles along the way slows down painting */
-
- if (is_float) {
- float *rgba_fp = (float *)tilerect + (((projPixel->x_px - x_round) + (projPixel->y_px - y_round) * IMAPAINT_TILE_SIZE)) * 4;
- copy_v4_v4(rgba_fp, projPixel->origColor.f);
- }
- else {
- ((unsigned int *)tilerect)[(projPixel->x_px - x_round) + (projPixel->y_px - y_round) * IMAPAINT_TILE_SIZE] = projPixel->origColor.uint;
- }
- }
- }
- }
-
- if (tmpibuf) IMB_freeImBuf(tmpibuf);
- if (tmpibuf_float) IMB_freeImBuf(tmpibuf_float);
- }
- /* done calculating undo data */
+ 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);
}
BKE_image_release_ibuf(ps->reproject_image, ps->reproject_ibuf, NULL);
@@ -3378,6 +3478,14 @@ 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();
#ifndef PROJ_DEBUG_NOSEAMBLEED
if (ps->seam_bleed_px > 0.0f) {
@@ -3388,6 +3496,11 @@ static void project_paint_end(ProjPaintState *ps)
}
#endif
+ if (ps->blurkernel) {
+ paint_delete_blur_kernel(ps->blurkernel);
+ MEM_freeN(ps->blurkernel);
+ }
+
if (ps->vertFlags) MEM_freeN(ps->vertFlags);
for (a = 0; a < ps->thread_tot; a++) {
@@ -3480,7 +3593,7 @@ static bool project_bucket_iter_init(ProjPaintState *ps, const float mval_f[2])
{
if (ps->source == PROJ_SRC_VIEW) {
float min_brush[2], max_brush[2];
- const float radius = (float)BKE_brush_size_get(ps->scene, ps->brush);
+ const float radius = ps->brush_size;
/* so we don't have a bucket bounds that is way too small to paint into */
// if (radius < 1.0f) radius = 1.0f; // this doesn't work yet :/
@@ -3518,7 +3631,7 @@ static bool project_bucket_iter_init(ProjPaintState *ps, const float mval_f[2])
static bool project_bucket_iter_next(ProjPaintState *ps, int *bucket_index, rctf *bucket_bounds, const float mval[2])
{
- const int diameter = 2 * BKE_brush_size_get(ps->scene, ps->brush);
+ const int diameter = 2 * ps->brush_size;
if (ps->thread_tot > 1)
BLI_lock_thread(LOCK_CUSTOM1);
@@ -3580,7 +3693,7 @@ static void do_projectpaint_clone(ProjPaintState *ps, ProjPixel *projPixel, floa
clone_rgba[3] = (unsigned char)(clone_pt[3] * mask);
if (ps->do_masking) {
- IMB_blend_color_byte(projPixel->pixel.ch_pt, projPixel->origColor.ch, clone_rgba, ps->blend);
+ IMB_blend_color_byte(projPixel->pixel.ch_pt, projPixel->origColor.ch_pt, clone_rgba, ps->blend);
}
else {
IMB_blend_color_byte(projPixel->pixel.ch_pt, projPixel->pixel.ch_pt, clone_rgba, ps->blend);
@@ -3598,7 +3711,7 @@ static void do_projectpaint_clone_f(ProjPaintState *ps, ProjPixel *projPixel, fl
mul_v4_v4fl(clone_rgba, clone_pt, mask);
if (ps->do_masking) {
- IMB_blend_color_float(projPixel->pixel.f_pt, projPixel->origColor.f, clone_rgba, ps->blend);
+ IMB_blend_color_float(projPixel->pixel.f_pt, projPixel->origColor.f_pt, clone_rgba, ps->blend);
}
else {
IMB_blend_color_float(projPixel->pixel.f_pt, projPixel->pixel.f_pt, clone_rgba, ps->blend);
@@ -3636,42 +3749,58 @@ static void do_projectpaint_smear_f(ProjPaintState *ps, ProjPixel *projPixel, fl
BLI_linklist_prepend_arena(smearPixels_f, (void *)projPixel, smearArena);
}
-/* do_projectpaint_soften for float & byte
- */
-static float inv_pow2(float f)
-{
- f = 1.0f - f;
- f = f * f;
- return 1.0f - f;
-}
-
static void do_projectpaint_soften_f(ProjPaintState *ps, ProjPixel *projPixel, float mask,
MemArena *softenArena, LinkNode **softenPixels)
{
- unsigned int accum_tot = 0;
- unsigned int i;
-
+ float accum_tot = 0.0;
+ int xk, yk;
+ BlurKernel *kernel = ps->blurkernel;
float *rgba = projPixel->newColor.f;
- /* sigh, mask values tend to need to be a _lot_ stronger with blur */
- mask = inv_pow2(mask);
-
/* rather then painting, accumulate surrounding colors */
zero_v4(rgba);
- for (i = 0; i < PROJ_PIXEL_SOFTEN_TOT; i++) {
- float co_ofs[2];
- float rgba_tmp[4];
- sub_v2_v2v2(co_ofs, projPixel->projCoSS, proj_pixel_soften_v2[i]);
- if (project_paint_PickColor(ps, co_ofs, rgba_tmp, NULL, true)) {
- add_v4_v4(rgba, rgba_tmp);
- accum_tot++;
+ for (yk = 0; yk < kernel->side; yk++) {
+ for (xk = 0; xk < kernel->side; xk++) {
+ float rgba_tmp[4];
+ float co_ofs[2] = {xk - kernel->pixel_len, yk - kernel->pixel_len};
+
+ add_v2_v2(co_ofs, projPixel->projCoSS);
+
+ if (project_paint_PickColor(ps, co_ofs, rgba_tmp, NULL, true)) {
+ float weight = kernel->wdata[xk + yk * kernel->side];
+ mul_v4_fl(rgba_tmp, weight);
+ add_v4_v4(rgba, rgba_tmp);
+ accum_tot += weight;
+ }
}
}
if (LIKELY(accum_tot != 0)) {
mul_v4_fl(rgba, 1.0f / (float)accum_tot);
- blend_color_interpolate_float(rgba, rgba, projPixel->pixel.f_pt, mask);
+
+ if (ps->mode == BRUSH_STROKE_INVERT) {
+ /* subtract blurred image from normal image gives high pass filter */
+ sub_v3_v3v3(rgba, projPixel->pixel.f_pt, rgba);
+
+ /* now rgba_ub contains the edge result, but this should be converted to luminance to avoid
+ * colored speckles appearing in final image, and also to check for threshold */
+ rgba[0] = rgba[1] = rgba[2] = rgb_to_grayscale(rgba);
+ if (fabsf(rgba[0]) > ps->brush->sharp_threshold) {
+ float alpha = projPixel->pixel.f_pt[3];
+ projPixel->pixel.f_pt[3] = rgba[3] = mask;
+
+ /* add to enhance edges */
+ blend_color_add_float(rgba, projPixel->pixel.f_pt, rgba);
+ projPixel->pixel.f_pt[3] = alpha;
+ }
+ else
+ return;
+ }
+ else {
+ blend_color_interpolate_float(rgba, rgba, projPixel->pixel.f_pt, mask);
+ }
+
BLI_linklist_prepend_arena(softenPixels, (void *)projPixel, softenArena);
}
}
@@ -3679,24 +3808,27 @@ static void do_projectpaint_soften_f(ProjPaintState *ps, ProjPixel *projPixel, f
static void do_projectpaint_soften(ProjPaintState *ps, ProjPixel *projPixel, float mask,
MemArena *softenArena, LinkNode **softenPixels)
{
- unsigned int accum_tot = 0;
- unsigned int i;
-
+ float accum_tot = 0;
+ int xk, yk;
+ BlurKernel *kernel = ps->blurkernel;
float rgba[4]; /* convert to byte after */
- /* sigh, mask values tend to need to be a _lot_ stronger with blur */
- mask = inv_pow2(mask);
-
/* rather then painting, accumulate surrounding colors */
zero_v4(rgba);
- for (i = 0; i < PROJ_PIXEL_SOFTEN_TOT; i++) {
- float co_ofs[2];
- float rgba_tmp[4];
- sub_v2_v2v2(co_ofs, projPixel->projCoSS, proj_pixel_soften_v2[i]);
- if (project_paint_PickColor(ps, co_ofs, rgba_tmp, NULL, true)) {
- add_v4_v4(rgba, rgba_tmp);
- accum_tot++;
+ for (yk = 0; yk < kernel->side; yk++) {
+ for (xk = 0; xk < kernel->side; xk++) {
+ float rgba_tmp[4];
+ float co_ofs[2] = {xk - kernel->pixel_len, yk - kernel->pixel_len};
+
+ add_v2_v2(co_ofs, projPixel->projCoSS);
+
+ if (project_paint_PickColor(ps, co_ofs, rgba_tmp, NULL, true)) {
+ float weight = kernel->wdata[xk + yk * kernel->side];
+ mul_v4_fl(rgba_tmp, weight);
+ add_v4_v4(rgba, rgba_tmp);
+ accum_tot += weight;
+ }
}
}
@@ -3704,9 +3836,34 @@ static void do_projectpaint_soften(ProjPaintState *ps, ProjPixel *projPixel, flo
unsigned char *rgba_ub = projPixel->newColor.ch;
mul_v4_fl(rgba, 1.0f / (float)accum_tot);
- premul_float_to_straight_uchar(rgba_ub, rgba);
- blend_color_interpolate_byte(rgba_ub, rgba_ub, projPixel->pixel.ch_pt, mask);
+ if (ps->mode == BRUSH_STROKE_INVERT) {
+ float rgba_pixel[4];
+
+ straight_uchar_to_premul_float(rgba_pixel, projPixel->pixel.ch_pt);
+
+ /* subtract blurred image from normal image gives high pass filter */
+ sub_v3_v3v3(rgba, rgba_pixel, rgba);
+ /* now rgba_ub contains the edge result, but this should be converted to luminance to avoid
+ * colored speckles appearing in final image, and also to check for threshold */
+ rgba[0] = rgba[1] = rgba[2] = rgb_to_grayscale(rgba);
+ if (fabsf(rgba[0]) > ps->brush->sharp_threshold) {
+ float alpha = rgba_pixel[3];
+ rgba[3] = rgba_pixel[3] = mask;
+
+ /* add to enhance edges */
+ blend_color_add_float(rgba, rgba_pixel, rgba);
+
+ rgba[3] = alpha;
+ premul_float_to_straight_uchar(rgba_ub, rgba);
+ }
+ else
+ return;
+ }
+ else {
+ premul_float_to_straight_uchar(rgba_ub, rgba);
+ blend_color_interpolate_byte(rgba_ub, rgba_ub, projPixel->pixel.ch_pt, mask);
+ }
BLI_linklist_prepend_arena(softenPixels, (void *)projPixel, softenArena);
}
}
@@ -3716,7 +3873,7 @@ static void do_projectpaint_draw(ProjPaintState *ps, ProjPixel *projPixel, const
float rgb[3];
unsigned char rgba_ub[4];
- copy_v3_v3(rgb, ps->brush->rgb);
+ copy_v3_v3(rgb, ps->paint_color);
if (ps->is_texbrush) {
mul_v3_v3(rgb, texrgb);
@@ -3728,7 +3885,7 @@ static void do_projectpaint_draw(ProjPaintState *ps, ProjPixel *projPixel, const
rgba_ub[3] = f_to_char(mask);
if (ps->do_masking) {
- IMB_blend_color_byte(projPixel->pixel.ch_pt, projPixel->origColor.ch, rgba_ub, ps->blend);
+ IMB_blend_color_byte(projPixel->pixel.ch_pt, projPixel->origColor.ch_pt, rgba_ub, ps->blend);
}
else {
IMB_blend_color_byte(projPixel->pixel.ch_pt, projPixel->pixel.ch_pt, rgba_ub, ps->blend);
@@ -3739,7 +3896,7 @@ static void do_projectpaint_draw_f(ProjPaintState *ps, ProjPixel *projPixel, con
{
float rgba[4];
- srgb_to_linearrgb_v3_v3(rgba, ps->brush->rgb);
+ copy_v3_v3(rgba, ps->paint_color_linear);
if (ps->is_texbrush)
mul_v3_v3(rgba, texrgb);
@@ -3748,13 +3905,42 @@ static void do_projectpaint_draw_f(ProjPaintState *ps, ProjPixel *projPixel, con
rgba[3] = mask;
if (ps->do_masking) {
- IMB_blend_color_float(projPixel->pixel.f_pt, projPixel->origColor.f, rgba, ps->blend);
+ IMB_blend_color_float(projPixel->pixel.f_pt, projPixel->origColor.f_pt, rgba, ps->blend);
+ }
+ else {
+ IMB_blend_color_float(projPixel->pixel.f_pt, projPixel->pixel.f_pt, rgba, ps->blend);
+ }
+}
+
+static void do_projectpaint_mask(ProjPaintState *ps, ProjPixel *projPixel, float mask)
+{
+ unsigned char rgba_ub[4];
+ rgba_ub[0] = rgba_ub[1] = rgba_ub[2] = ps->stencil_value * 255.0f;
+ rgba_ub[3] = f_to_char(mask);
+
+ if (ps->do_masking) {
+ IMB_blend_color_byte(projPixel->pixel.ch_pt, projPixel->origColor.ch_pt, rgba_ub, ps->blend);
+ }
+ else {
+ IMB_blend_color_byte(projPixel->pixel.ch_pt, projPixel->pixel.ch_pt, rgba_ub, ps->blend);
+ }
+}
+
+static void do_projectpaint_mask_f(ProjPaintState *ps, ProjPixel *projPixel, float mask)
+{
+ float rgba[4];
+ rgba[0] = rgba[1] = rgba[2] = ps->stencil_value;
+ rgba[3] = mask;
+
+ if (ps->do_masking) {
+ IMB_blend_color_float(projPixel->pixel.f_pt, projPixel->origColor.f_pt, rgba, ps->blend);
}
else {
IMB_blend_color_float(projPixel->pixel.f_pt, projPixel->pixel.f_pt, rgba, ps->blend);
}
}
+
/* run this for single and multithreaded painting */
static void *do_projectpaint_thread(void *ph_v)
{
@@ -3788,7 +3974,7 @@ static void *do_projectpaint_thread(void *ph_v)
float co[2];
unsigned short mask_short;
const float brush_alpha = BKE_brush_alpha_get(ps->scene, brush);
- const float brush_radius = (float)BKE_brush_size_get(ps->scene, brush);
+ 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;
@@ -3838,32 +4024,102 @@ static void *do_projectpaint_thread(void *ph_v)
}
/* end copy */
- if (is_floatbuf) {
- /* re-project buffer is assumed byte - TODO, allow float */
- bicubic_interpolation_color(ps->reproject_ibuf, projPixel->newColor.ch, NULL,
- projPixel->projCoSS[0], projPixel->projCoSS[1]);
- if (projPixel->newColor.ch[3]) {
- float newColor_f[4];
- float mask = ((float)projPixel->mask) * (1.0f / 65535.0f);
+ /* fill tools */
+ if (ps->source == PROJ_SRC_VIEW_FILL) {
+ if (brush->flag & BRUSH_USE_GRADIENT) {
+ /* these could probably be cached instead of being done per pixel */
+ float tangent[2];
+ float line_len_sq_inv, line_len;
+ float f;
+ float color_f[4];
+ float p[2] = {projPixel->projCoSS[0] - lastpos[0], projPixel->projCoSS[1] - lastpos[1]};
+
+ sub_v2_v2v2(tangent, pos, lastpos);
+ line_len = len_squared_v2(tangent);
+ line_len_sq_inv = 1.0f / line_len;
+ line_len = sqrt(line_len);
+
+ switch (brush->gradient_fill_mode) {
+ case BRUSH_GRADIENT_LINEAR:
+ {
+ f = dot_v2v2(p, tangent) * line_len_sq_inv;
+ break;
+ }
+ case BRUSH_GRADIENT_RADIAL:
+ {
+ f = len_v2(p) / line_len;
+ break;
+ }
+ }
+ do_colorband(brush->gradient, f, color_f);
+ color_f[3] *= ((float)projPixel->mask) * (1.0f / 65535.0f) * brush->alpha;
+
+ if (is_floatbuf) {
+ /* convert to premultipied */
+ mul_v3_fl(color_f, color_f[3]);
+ IMB_blend_color_float(projPixel->pixel.f_pt, projPixel->origColor.f_pt,
+ color_f, ps->blend);
+ }
+ else {
+ rgba_float_to_uchar(projPixel->newColor.ch, color_f);
+ IMB_blend_color_byte(projPixel->pixel.ch_pt, projPixel->origColor.ch_pt,
+ projPixel->newColor.ch, ps->blend);
+ }
+ }
+ else {
+ if (is_floatbuf) {
+ float newColor_f[4];
+ newColor_f[3] = ((float)projPixel->mask) * (1.0f / 65535.0f) * brush->alpha;
+ copy_v3_v3(newColor_f, ps->paint_color_linear);
- straight_uchar_to_premul_float(newColor_f, projPixel->newColor.ch);
- IMB_colormanagement_colorspace_to_scene_linear_v4(newColor_f, true, ps->reproject_ibuf->rect_colorspace);
- mul_v4_v4fl(newColor_f, newColor_f, mask);
+ IMB_blend_color_float(projPixel->pixel.f_pt, projPixel->origColor.f_pt,
+ newColor_f, ps->blend);
+ }
+ else {
+ float mask = ((float)projPixel->mask) * (1.0f / 65535.0f);
+ projPixel->newColor.ch[3] = mask * 255 * brush->alpha;
- blend_color_mix_float(projPixel->pixel.f_pt, projPixel->origColor.f,
- newColor_f);
+ rgb_float_to_uchar(projPixel->newColor.ch, ps->paint_color);
+ IMB_blend_color_byte(projPixel->pixel.ch_pt, projPixel->origColor.ch_pt,
+ projPixel->newColor.ch, ps->blend);
+ }
}
+
+ last_partial_redraw_cell = last_projIma->partRedrawRect + projPixel->bb_cell_index;
+ last_partial_redraw_cell->x1 = min_ii(last_partial_redraw_cell->x1, (int)projPixel->x_px);
+ last_partial_redraw_cell->y1 = min_ii(last_partial_redraw_cell->y1, (int)projPixel->y_px);
+
+ last_partial_redraw_cell->x2 = max_ii(last_partial_redraw_cell->x2, (int)projPixel->x_px + 1);
+ last_partial_redraw_cell->y2 = max_ii(last_partial_redraw_cell->y2, (int)projPixel->y_px + 1);
}
else {
- /* re-project buffer is assumed byte - TODO, allow float */
- bicubic_interpolation_color(ps->reproject_ibuf, projPixel->newColor.ch, NULL,
- projPixel->projCoSS[0], projPixel->projCoSS[1]);
- if (projPixel->newColor.ch[3]) {
- float mask = ((float)projPixel->mask) * (1.0f / 65535.0f);
- projPixel->newColor.ch[3] *= mask;
-
- blend_color_mix_byte(projPixel->pixel.ch_pt, projPixel->origColor.ch,
- projPixel->newColor.ch);
+ if (is_floatbuf) {
+ /* re-project buffer is assumed byte - TODO, allow float */
+ bicubic_interpolation_color(ps->reproject_ibuf, projPixel->newColor.ch, NULL,
+ projPixel->projCoSS[0], projPixel->projCoSS[1]);
+ if (projPixel->newColor.ch[3]) {
+ float newColor_f[4];
+ float mask = ((float)projPixel->mask) * (1.0f / 65535.0f);
+
+ straight_uchar_to_premul_float(newColor_f, projPixel->newColor.ch);
+ IMB_colormanagement_colorspace_to_scene_linear_v4(newColor_f, true, ps->reproject_ibuf->rect_colorspace);
+ mul_v4_v4fl(newColor_f, newColor_f, mask);
+
+ blend_color_mix_float(projPixel->pixel.f_pt, projPixel->origColor.f_pt,
+ newColor_f);
+ }
+ }
+ else {
+ /* re-project buffer is assumed byte - TODO, allow float */
+ bicubic_interpolation_color(ps->reproject_ibuf, projPixel->newColor.ch, NULL,
+ projPixel->projCoSS[0], projPixel->projCoSS[1]);
+ if (projPixel->newColor.ch[3]) {
+ float mask = ((float)projPixel->mask) * (1.0f / 65535.0f);
+ projPixel->newColor.ch[3] *= mask;
+
+ blend_color_mix_byte(projPixel->pixel.ch_pt, projPixel->origColor.ch_pt,
+ projPixel->newColor.ch);
+ }
}
}
}
@@ -3885,7 +4141,7 @@ static void *do_projectpaint_thread(void *ph_v)
if (falloff > 0.0f) {
float texrgb[3];
- float mask = falloff;
+ float mask;
if (ps->do_masking) {
/* masking to keep brush contribution to a pixel limited. note we do not do
@@ -3894,20 +4150,24 @@ static void *do_projectpaint_thread(void *ph_v)
*
* Instead we use a formula that adds up but approaches brush_alpha slowly
* and never exceeds it, which gives nice smooth results. */
- float mask_accum = projPixel->mask_accum;
+ float mask_accum = *projPixel->mask_accum;
+ float max_mask = brush_alpha * falloff * 65535.0f;
if (ps->is_maskbrush) {
float texmask = BKE_brush_sample_masktex(ps->scene, ps->brush, projPixel->projCoSS, thread_index, pool);
- CLAMP(texmask, 0.0f, 1.0f);
- mask = mask_accum + (brush_alpha * texmask * 65535.0f - mask_accum) * mask;
- }
- else {
- mask = mask_accum + (brush_alpha * 65535.0f - mask_accum) * mask;
+ max_mask *= texmask;
}
+
+ if (brush->flag & BRUSH_ACCUMULATE)
+ mask = mask_accum + max_mask;
+ else
+ mask = mask_accum + (max_mask - mask_accum * falloff);
+
+ mask = min_ff(mask, 65535.0f);
mask_short = (unsigned short)mask;
- if (mask_short > projPixel->mask_accum) {
- projPixel->mask_accum = mask_short;
+ if (mask_short > *projPixel->mask_accum) {
+ *projPixel->mask_accum = mask_short;
mask = mask_short * (1.0f / 65535.0f);
}
else {
@@ -3916,7 +4176,7 @@ static void *do_projectpaint_thread(void *ph_v)
}
}
else {
- mask *= brush_alpha;
+ mask = brush_alpha * falloff;
if (ps->is_maskbrush) {
float texmask = BKE_brush_sample_masktex(ps->scene, ps->brush, projPixel->projCoSS, thread_index, pool);
CLAMP(texmask, 0.0f, 1.0f);
@@ -3945,10 +4205,6 @@ static void *do_projectpaint_thread(void *ph_v)
mask *= texrgba[3];
}
- if (ps->is_maskbrush_tiled) {
- mask *= BKE_brush_sample_masktex(ps->scene, ps->brush, projPixel->projCoSS, thread_index, pool);
- }
-
/* extra mask for normal, layer stencil, .. */
mask *= ((float)projPixel->mask) * (1.0f / 65535.0f);
@@ -3964,6 +4220,9 @@ static void *do_projectpaint_thread(void *ph_v)
}
/* end copy */
+ /* validate undo tile, since we will modify t*/
+ *projPixel->valid = true;
+
last_partial_redraw_cell = last_projIma->partRedrawRect + projPixel->bb_cell_index;
last_partial_redraw_cell->x1 = min_ii(last_partial_redraw_cell->x1, (int)projPixel->x_px);
last_partial_redraw_cell->y1 = min_ii(last_partial_redraw_cell->y1, (int)projPixel->y_px);
@@ -3987,6 +4246,10 @@ static void *do_projectpaint_thread(void *ph_v)
if (is_floatbuf) do_projectpaint_soften_f(ps, projPixel, mask, softenArena, &softenPixels_f);
else do_projectpaint_soften(ps, projPixel, mask, softenArena, &softenPixels);
break;
+ case PAINT_TOOL_MASK:
+ if (is_floatbuf) do_projectpaint_mask_f(ps, projPixel, mask);
+ else do_projectpaint_mask(ps, projPixel, mask);
+ break;
default:
if (is_floatbuf) do_projectpaint_draw_f(ps, projPixel, texrgb, mask);
else do_projectpaint_draw(ps, projPixel, texrgb, mask);
@@ -3995,8 +4258,8 @@ static void *do_projectpaint_thread(void *ph_v)
}
if (lock_alpha) {
- if (is_floatbuf) projPixel->pixel.f_pt[3] = projPixel->origColor.f[3];
- else projPixel->pixel.ch_pt[3] = projPixel->origColor.ch[3];
+ if (is_floatbuf) projPixel->pixel.f_pt[3] = projPixel->origColor.f_pt[3];
+ else projPixel->pixel.ch_pt[3] = projPixel->origColor.ch_pt[3];
}
/* done painting */
@@ -4114,14 +4377,17 @@ static bool project_paint_op(void *state, const float lastpos[2], const float po
}
-void paint_proj_stroke(bContext *C, void *pps, const float prev_pos[2], const float pos[2])
+void paint_proj_stroke(const bContext *C, void *pps, const float prev_pos[2], const float pos[2], float pressure, float distance, float size)
{
ProjPaintState *ps = pps;
+ Brush *brush = ps->brush;
+ Scene *scene = ps->scene;
int a;
+ ps->brush_size = size;
+
/* clone gets special treatment here to avoid going through image initialization */
if (ps->tool == PAINT_TOOL_CLONE && ps->mode == BRUSH_STROKE_INVERT) {
- Scene *scene = ps->scene;
View3D *v3d = ps->v3d;
float *cursor = ED_view3d_cursor3d_get(scene, v3d);
int mval_i[2] = {(int)pos[0], (int)pos[1]};
@@ -4136,6 +4402,25 @@ void paint_proj_stroke(bContext *C, void *pps, const float prev_pos[2], const fl
return;
}
+ /* handle gradient and inverted stroke color here */
+ if (ps->tool == PAINT_TOOL_DRAW) {
+ paint_brush_color_get(scene, brush, false, ps->mode == BRUSH_STROKE_INVERT, distance, pressure, ps->paint_color, NULL);
+ srgb_to_linearrgb_v3_v3(ps->paint_color_linear, ps->paint_color);
+ }
+ else if (ps->tool == PAINT_TOOL_FILL) {
+ copy_v3_v3(ps->paint_color, BKE_brush_color_get(scene, brush));
+ srgb_to_linearrgb_v3_v3(ps->paint_color_linear, ps->paint_color);
+ }
+ else if (ps->tool == PAINT_TOOL_MASK) {
+ ps->stencil_value = brush->weight;
+
+ if ((ps->mode == BRUSH_STROKE_INVERT) ^
+ ((scene->toolsettings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_STENCIL_INV) != 0))
+ {
+ ps->stencil_value = 1.0f - ps->stencil_value;
+ }
+ }
+
/* continue adding to existing partial redraw rects until redraw */
if (!ps->need_redraw) {
for (a = 0; a < ps->image_tot; a++)
@@ -4160,30 +4445,24 @@ static void project_state_init(bContext *C, Object *ob, ProjPaintState *ps, int
Brush *brush = ps->brush;
ps->tool = brush->imagepaint_tool;
ps->blend = brush->blend;
+ /* only check for inversion for the soften tool, elsewhere, a resident brush inversion flag can cause issues */
+ if (brush->imagepaint_tool == PAINT_TOOL_SOFTEN) {
+ ps->mode = ((ps->mode == BRUSH_STROKE_INVERT) ^ ((brush->flag & BRUSH_DIR_IN) != 0) ?
+ BRUSH_STROKE_INVERT : BRUSH_STROKE_NORMAL);
+
+ ps->blurkernel = paint_new_blur_kernel(brush);
+ }
/* disable for 3d mapping also because painting on mirrored mesh can create "stripes" */
- ps->do_masking = (brush->flag & BRUSH_AIRBRUSH ||
- (brush->imagepaint_tool == PAINT_TOOL_SMEAR) ||
- (brush->mtex.tex && !ELEM3(brush->mtex.brush_map_mode, MTEX_MAP_MODE_TILED, MTEX_MAP_MODE_STENCIL, MTEX_MAP_MODE_3D)))
- ? false : true;
+ ps->do_masking = paint_use_opacity_masking(brush);
ps->is_texbrush = (brush->mtex.tex && brush->imagepaint_tool == PAINT_TOOL_DRAW) ? true : false;
- ps->is_maskbrush = false;
- ps->is_maskbrush_tiled = false;
- if (brush->mask_mtex.tex) {
- if (ELEM(brush->mask_mtex.brush_map_mode, MTEX_MAP_MODE_STENCIL, MTEX_MAP_MODE_TILED)) {
- ps->is_maskbrush_tiled = true;
- }
- else {
- ps->is_maskbrush = true;
- }
- }
+ ps->is_maskbrush = (brush->mask_mtex.tex) ? true : false;
}
else {
/* brush may be NULL*/
ps->do_masking = false;
ps->is_texbrush = false;
ps->is_maskbrush = false;
- ps->is_maskbrush_tiled = false;
}
/* sizeof(ProjPixel), since we alloc this a _lot_ */
@@ -4198,6 +4477,7 @@ static void project_state_init(bContext *C, Object *ob, ProjPaintState *ps, int
ps->scene = scene;
ps->ob = ob; /* allow override of active object */
+ ps->stencil_ima = settings->imapaint.stencil;
/* setup projection painting data */
ps->do_backfacecull = (settings->imapaint.flag & IMAGEPAINT_PROJECT_BACKFACE) ? 0 : 1;
ps->do_occlude = (settings->imapaint.flag & IMAGEPAINT_PROJECT_XRAY) ? 0 : 1;
@@ -4207,8 +4487,11 @@ static void project_state_init(bContext *C, Object *ob, ProjPaintState *ps, int
if (ps->tool == PAINT_TOOL_CLONE)
ps->do_layer_clone = (settings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_CLONE) ? 1 : 0;
- ps->do_layer_stencil = (settings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_STENCIL) ? 1 : 0;
- ps->do_layer_stencil_inv = (settings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_STENCIL_INV) ? 1 : 0;
+ ps->do_stencil_brush = ps->brush->imagepaint_tool == PAINT_TOOL_MASK;
+ /* deactivate stenciling for the stencil brush :) */
+ ps->do_layer_stencil = ((settings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_STENCIL) &&
+ !(ps->do_stencil_brush) && ps->stencil_ima);
+ ps->do_layer_stencil_inv = ((settings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_STENCIL_INV) != 0);
#ifndef PROJ_DEBUG_NOSEAMBLEED
@@ -4236,6 +4519,7 @@ 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");
+
project_state_init(C, ob, ps, mode);
if (ps->tool == PAINT_TOOL_CLONE && mode == BRUSH_STROKE_INVERT) {
@@ -4268,6 +4552,10 @@ void *paint_proj_new_stroke(bContext *C, Object *ob, const float mouse[2], int m
paint_proj_begin_clone(ps, mouse);
+ /* special full screen draw mode for fill tool */
+ if (ps->tool == PAINT_TOOL_FILL)
+ ps->source = PROJ_SRC_VIEW_FILL;
+
return ps;
}
@@ -4316,8 +4604,11 @@ static int texture_paint_camera_project_exec(bContext *C, wmOperator *op)
int orig_brush_size;
IDProperty *idgroup;
IDProperty *view_data = NULL;
+ Object *ob = OBACT;
+
+ paint_proj_mesh_data_ensure(C, ob, op);
- project_state_init(C, OBACT, &ps, BRUSH_STROKE_NORMAL);
+ project_state_init(C, ob, &ps, BRUSH_STROKE_NORMAL);
if (ps.ob == NULL || ps.ob->type != OB_MESH) {
BKE_report(op->reports, RPT_ERROR, "No active mesh object");
@@ -4365,7 +4656,6 @@ static int texture_paint_camera_project_exec(bContext *C, wmOperator *op)
/* override */
ps.is_texbrush = false;
ps.is_maskbrush = false;
- ps.is_maskbrush_tiled = false;
ps.do_masking = false;
orig_brush_size = BKE_brush_size_get(scene, ps.brush);
BKE_brush_size_set(scene, ps.brush, 32); /* cover the whole image */
@@ -4375,7 +4665,7 @@ static int texture_paint_camera_project_exec(bContext *C, wmOperator *op)
scene->toolsettings->imapaint.flag |= IMAGEPAINT_DRAWING;
ED_undo_paint_push_begin(UNDO_PAINT_IMAGE, op->type->name,
- ED_image_undo_restore, ED_image_undo_free);
+ ED_image_undo_restore, ED_image_undo_free, NULL);
/* allocate and initialize spatial data structures */
project_paint_begin(&ps);
@@ -4508,3 +4798,162 @@ void PAINT_OT_image_from_view(wmOperatorType *ot)
RNA_def_string_file_name(ot->srna, "filepath", NULL, FILE_MAX, "File Path", "Name of the file");
}
+
+/* Add layer operator */
+
+static EnumPropertyItem layer_type_items[] = {
+ {MAP_COL, "DIFFUSE_COLOR", 0, "Diffuse Color", ""},
+ {MAP_REF, "DIFFUSE_INTENSITY", 0, "Diffuse Intensity", ""},
+ {MAP_ALPHA, "ALPHA", 0, "Alpha", ""},
+ {MAP_TRANSLU, "TRANSLUCENCY", 0, "Translucency", ""},
+ {MAP_COLSPEC, "SPECULAR_COLOR", 0, "Specular Color", ""},
+ {MAP_SPEC, "SPECULAR_INTENSITY", 0, "Specular Intensity", ""},
+ {MAP_HAR, "SPECULAR_HARDNESS", 0, "Specular Hardness", ""},
+ {MAP_AMB, "AMBIENT", 0, "Ambient", ""},
+ {MAP_EMIT, "EMMIT", 0, "Emmit", ""},
+ {MAP_COLMIR, "MIRROR_COLOR", 0, "Mirror Color", ""},
+ {MAP_RAYMIRR, "RAYMIRROR", 0, "Ray Mirror", ""},
+ {MAP_NORM, "NORMAL", 0, "Normal", ""},
+ {MAP_WARP, "WARP", 0, "Warp", ""},
+ {MAP_DISPLACE, "DISPLACE", 0, "Displace", ""},
+ {0, NULL, 0, NULL, NULL}
+};
+
+bool proj_paint_add_slot(bContext *C, Material *ma, wmOperator *op)
+{
+ Object *ob = CTX_data_active_object(C);
+ Scene *scene = CTX_data_scene(C);
+ bool use_nodes = BKE_scene_use_new_shading_nodes(scene);
+
+ if (!ob)
+ return false;
+
+ if (!ma)
+ ma = give_current_material(ob, ob->actcol);
+
+ if (ma) {
+
+ if (use_nodes) {
+ /* not supported for now */
+ }
+ else {
+ MTex *mtex = add_mtex_id(&ma->id, -1);
+
+ /* successful creation of mtex layer, now create set */
+ if (mtex) {
+ Main *bmain = CTX_data_main(C);
+ Image *ima;
+ int type = MAP_COL;
+
+ if (op)
+ type = RNA_enum_get(op->ptr, "type");
+
+ mtex->tex = add_texture(bmain, DATA_(layer_type_items[type].name));
+ mtex->mapto = type;
+
+ if (mtex->tex) {
+ float color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
+ char imagename[MAX_ID_NAME - 2] = "Material Diffuse Color";
+ int width = 1024;
+ int height = 1024;
+ bool use_float = false;
+ short gen_type = IMA_GENTYPE_BLANK;
+ bool alpha = false;
+
+ if (op) {
+ width = RNA_int_get(op->ptr, "width");
+ height = RNA_int_get(op->ptr, "height");
+ use_float = RNA_boolean_get(op->ptr, "float");
+ gen_type = RNA_enum_get(op->ptr, "generated_type");
+ RNA_float_get_array(op->ptr, "color", color);
+ alpha = RNA_boolean_get(op->ptr, "alpha");
+ RNA_string_get(op->ptr, "name", imagename);
+ }
+
+ if (!use_float) {
+ /* crappy workaround because we only upload straight color to OpenGL and that makes
+ * painting result on viewport too opaque */
+ color[3] = 1.0;
+ }
+
+ ima = mtex->tex->ima = BKE_image_add_generated(bmain, width, height, imagename, alpha ? 32 : 24, use_float,
+ gen_type, color);
+
+ BKE_texpaint_slot_refresh_cache(ma, false);
+ BKE_image_signal(ima, NULL, IMA_SIGNAL_USER_NEW_IMAGE);
+ WM_event_add_notifier(C, NC_TEXTURE | NA_ADDED, mtex->tex);
+ WM_event_add_notifier(C, NC_IMAGE | NA_ADDED, ima);
+ ED_area_tag_redraw(CTX_wm_area(C));
+ }
+
+ WM_event_add_notifier(C, NC_TEXTURE, CTX_data_scene(C));
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+static int texture_paint_add_texture_paint_slot_exec(bContext *C, wmOperator *op)
+{
+ return proj_paint_add_slot(C, NULL, op);
+}
+
+
+static int texture_paint_add_texture_paint_slot_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ char imagename[MAX_ID_NAME - 2];
+ Object *ob = CTX_data_active_object(C);
+ Material *ma = give_current_material(ob, ob->actcol);
+ int type = RNA_enum_get(op->ptr, "type");
+
+ type = RNA_enum_from_value(layer_type_items, type);
+
+ /* get the name of the texture layer type */
+ BLI_assert(type != -1);
+
+ /* take the second letter to avoid the ID identifier */
+ BLI_snprintf(imagename, FILE_MAX, "%s %s", &ma->id.name[2], layer_type_items[type].name);
+
+ RNA_string_set(op->ptr, "name", imagename);
+ return WM_operator_props_dialog_popup(C, op, 15 * UI_UNIT_X, 5 * UI_UNIT_Y);
+}
+
+#define IMA_DEF_NAME N_("Untitled")
+
+
+void PAINT_OT_add_texture_paint_slot(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+ static float default_color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
+
+ /* identifiers */
+ ot->name = "Add Texture Paint Slot";
+ ot->description = "Add a texture paint slot";
+ ot->idname = "PAINT_OT_add_texture_paint_slot";
+
+ /* api callbacks */
+ ot->invoke = texture_paint_add_texture_paint_slot_invoke;
+ ot->exec = texture_paint_add_texture_paint_slot_exec;
+ ot->poll = ED_operator_region_view3d_active;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ prop = RNA_def_enum(ot->srna, "type", layer_type_items, 0, "Type", "Merge method to use");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+ RNA_def_string(ot->srna, "name", IMA_DEF_NAME, MAX_ID_NAME - 2, "Name", "Image datablock name");
+ prop = RNA_def_int(ot->srna, "width", 1024, 1, INT_MAX, "Width", "Image width", 1, 16384);
+ RNA_def_property_subtype(prop, PROP_PIXEL);
+ prop = RNA_def_int(ot->srna, "height", 1024, 1, INT_MAX, "Height", "Image height", 1, 16384);
+ RNA_def_property_subtype(prop, PROP_PIXEL);
+ prop = RNA_def_float_color(ot->srna, "color", 4, NULL, 0.0f, FLT_MAX, "Color", "Default fill color", 0.0f, 1.0f);
+ RNA_def_property_subtype(prop, PROP_COLOR_GAMMA);
+ RNA_def_property_float_array_default(prop, default_color);
+ RNA_def_boolean(ot->srna, "alpha", 1, "Alpha", "Create an image with an alpha channel");
+ RNA_def_enum(ot->srna, "generated_type", image_generated_type_items, IMA_GENTYPE_BLANK,
+ "Generated Type", "Fill the image with a grid for UV map testing");
+ RNA_def_boolean(ot->srna, "float", 0, "32 bit Float", "Create image with 32 bit floating point bit depth");
+}
diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h
index b20c1756d75..fb4bedb6906 100644
--- a/source/blender/editors/sculpt_paint/paint_intern.h
+++ b/source/blender/editors/sculpt_paint/paint_intern.h
@@ -38,7 +38,9 @@ struct bglMats;
struct Brush;
struct ImagePool;
struct ColorSpace;
+struct ColorManagedDisplay;
struct ListBase;
+struct Material;
struct Mesh;
struct MTex;
struct Object;
@@ -65,7 +67,7 @@ typedef void (*StrokeUpdateStep)(struct bContext *C, struct PaintStroke *stroke,
typedef void (*StrokeRedraw)(const struct bContext *C, struct PaintStroke *stroke, bool final);
typedef void (*StrokeDone)(const struct bContext *C, struct PaintStroke *stroke);
-struct PaintStroke *paint_stroke_new(struct bContext *C,
+struct PaintStroke *paint_stroke_new(struct bContext *C, struct wmOperator *op,
StrokeGetLocation get_location, StrokeTestStart test_start,
StrokeUpdateStep update_step, StrokeRedraw redraw,
StrokeDone done, int event_type);
@@ -84,6 +86,7 @@ int paint_stroke_exec(struct bContext *C, struct wmOperator *op);
void paint_stroke_cancel(struct bContext *C, struct wmOperator *op);
struct ViewContext *paint_stroke_view_context(struct PaintStroke *stroke);
void *paint_stroke_mode_data(struct PaintStroke *stroke);
+float paint_stroke_distance_get(struct PaintStroke *stroke);
void paint_stroke_set_mode_data(struct PaintStroke *stroke, void *mode_data);
int paint_poll(struct bContext *C);
void paint_cursor_start(struct bContext *C, int (*poll)(struct bContext *C));
@@ -117,7 +120,7 @@ void PAINT_OT_weight_gradient(struct wmOperatorType *ot);
void PAINT_OT_vertex_paint_toggle(struct wmOperatorType *ot);
void PAINT_OT_vertex_paint(struct wmOperatorType *ot);
-unsigned int vpaint_get_current_col(struct VPaint *vp);
+unsigned int vpaint_get_current_col(struct Scene *scene, struct VPaint *vp);
/* paint_vertex_proj.c */
@@ -144,32 +147,42 @@ typedef struct ImagePaintPartialRedraw {
#define IMAPAINT_TILE_NUMBER(size) (((size) + IMAPAINT_TILE_SIZE - 1) >> IMAPAINT_TILE_BITS)
int image_texture_paint_poll(struct bContext *C);
-void *image_undo_find_tile(struct Image *ima, struct ImBuf *ibuf, int x_tile, int y_tile, unsigned short **mask);
-void *image_undo_push_tile(struct Image *ima, struct ImBuf *ibuf, struct ImBuf **tmpibuf, int x_tile, int y_tile);
+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_remove_masks(void);
+void image_undo_init_locks(void);
+void image_undo_end_locks(void);
+
void imapaint_image_update(struct SpaceImage *sima, struct Image *image, struct ImBuf *ibuf, short texpaint);
struct ImagePaintPartialRedraw *get_imapaintpartial(void);
void set_imapaintpartial(struct ImagePaintPartialRedraw *ippr);
void imapaint_region_tiles(struct ImBuf *ibuf, int x, int y, int w, int h, int *tx, int *ty, int *tw, int *th);
int get_imapaint_zoom(struct bContext *C, float *zoomx, float *zoomy);
-void *paint_2d_new_stroke(struct bContext *, struct wmOperator *);
+void *paint_2d_new_stroke(struct bContext *, struct wmOperator *, int mode);
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], int eraser);
+void paint_2d_stroke(void *ps, const float prev_mval[2], const float mval[2], int eraser, float pressure, float distance, float size);
+void paint_2d_bucket_fill(const struct bContext *C, const float color[3], struct Brush *br, const float mouse_init[2], void *ps);
+void paint_2d_gradient_fill (const struct bContext *C, struct Brush *br, const float mouse_init[2], const float mouse_final[2], void *ps);
void *paint_proj_new_stroke(struct bContext *C, struct Object *ob, const float mouse[2], int mode);
-void paint_proj_stroke(struct bContext *C, void *ps, const float prevmval_i[2], const float mval_i[2]);
-void paint_proj_redraw(const bContext *C, void *pps, bool final);
+void paint_proj_stroke(const struct bContext *C, void *ps, const float prevmval_i[2], const float mval_i[2], float pressure, float distance, float size);
+void paint_proj_redraw(const struct bContext *C, void *pps, bool final);
void paint_proj_stroke_done(void *ps);
+void paint_proj_mesh_data_ensure(bContext *C, struct Object *ob, struct wmOperator *op);
+bool proj_paint_add_slot(bContext *C, struct Material *ma, struct wmOperator *op);
+
+void paint_brush_color_get(struct Scene *scene, struct Brush *br, bool color_correction, bool invert, float distance, float pressure, float color[3], struct ColorManagedDisplay *display);
+bool paint_use_opacity_masking(struct Brush *brush);
void paint_brush_init_tex(struct Brush *brush);
void paint_brush_exit_tex(struct Brush *brush);
void PAINT_OT_grab_clone(struct wmOperatorType *ot);
void PAINT_OT_sample_color(struct wmOperatorType *ot);
+void PAINT_OT_brush_colors_flip(struct wmOperatorType *ot);
void PAINT_OT_texture_paint_toggle(struct wmOperatorType *ot);
void PAINT_OT_project_image(struct wmOperatorType *ot);
void PAINT_OT_image_from_view(struct wmOperatorType *ot);
-
-/* new texture painting */
+void PAINT_OT_add_texture_paint_slot(struct wmOperatorType *ot);
void PAINT_OT_image_paint(struct wmOperatorType *ot);
/* uv sculpting */
@@ -202,7 +215,7 @@ float paint_calc_object_space_radius(struct ViewContext *vc, const float center[
float paint_get_tex_pixel(struct MTex *mtex, float u, float v, struct ImagePool *pool, int thread);
void paint_get_tex_pixel_col(struct MTex *mtex, float u, float v, float rgba[4], struct ImagePool *pool, int thread, bool convert, struct ColorSpace *colorspace);
-void paint_sample_color(const struct bContext *C, struct ARegion *ar, int x, int y);
+void paint_sample_color(bContext *C, struct ARegion *ar, int x, int y, bool texpaint_proj, bool palette);
void BRUSH_OT_curve_preset(struct wmOperatorType *ot);
void PAINT_OT_face_select_linked(struct wmOperatorType *ot);
@@ -213,8 +226,10 @@ void PAINT_OT_face_select_reveal(struct wmOperatorType *ot);
void PAINT_OT_vert_select_all(struct wmOperatorType *ot);
void PAINT_OT_vert_select_ungrouped(struct wmOperatorType *ot);
+
int vert_paint_poll(struct bContext *C);
int mask_paint_poll(struct bContext *C);
+int paint_curve_poll(struct bContext *C);
int facemask_paint_poll(struct bContext *C);
void flip_v3_v3(float out[3], const float in[3], const char symm);
@@ -229,7 +244,6 @@ typedef enum BrushStrokeMode {
/* paint_undo.c */
struct ListBase *undo_paint_push_get_list(int type);
void undo_paint_push_count_alloc(int type, int size);
-bool sculpt_undo_cleanup(struct bContext *C, struct ListBase *lb);
/* paint_hide.c */
@@ -258,4 +272,29 @@ typedef enum {
void PAINT_OT_mask_flood_fill(struct wmOperatorType *ot);
void PAINT_OT_mask_lasso_gesture(struct wmOperatorType *ot);
+/* paint_curve.c */
+void PAINTCURVE_OT_new(struct wmOperatorType *ot);
+void PAINTCURVE_OT_add_point(struct wmOperatorType *ot);
+void PAINTCURVE_OT_delete_point(struct wmOperatorType *ot);
+void PAINTCURVE_OT_select(struct wmOperatorType *ot);
+void PAINTCURVE_OT_slide(struct wmOperatorType *ot);
+void PAINTCURVE_OT_draw(struct wmOperatorType *ot);
+void PAINTCURVE_OT_cursor(struct wmOperatorType *ot);
+
+/* image painting blur kernel */
+typedef struct {
+ float *wdata; /* actual kernel */
+ int side; /* kernel side */
+ int side_squared; /* data side */
+ int pixel_len; /* pixels around center that kernel is wide */
+} BlurKernel;
+
+enum BlurKernelType;
+/* can be extended to other blur kernels later */
+BlurKernel *paint_new_blur_kernel(struct Brush *br);
+void paint_delete_blur_kernel(BlurKernel *);
+
+/* paint curve defines */
+#define PAINT_CURVE_NUM_SEGMENTS 40
+
#endif /* __PAINT_INTERN_H__ */
diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c
index b3f81f379f3..8faa4cfaf33 100644
--- a/source/blender/editors/sculpt_paint/paint_mask.c
+++ b/source/blender/editors/sculpt_paint/paint_mask.c
@@ -115,7 +115,7 @@ static int mask_flood_fill_exec(bContext *C, wmOperator *op)
sculpt_undo_push_begin("Mask flood fill");
-#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (i = 0; i < totnode; i++) {
PBVHVertexIter vi;
@@ -236,7 +236,7 @@ int ED_sculpt_mask_box_select(struct bContext *C, ViewContext *vc, const rcti *r
BKE_pbvh_search_gather(pbvh, BKE_pbvh_node_planes_contain_AABB, clip_planes_final, &nodes, &totnode);
-#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (i = 0; i < totnode; i++) {
PBVHVertexIter vi;
bool any_masked = false;
@@ -385,7 +385,7 @@ static int paint_mask_gesture_lasso_exec(bContext *C, wmOperator *op)
/* gather nodes inside lasso's enclosing rectangle (should greatly help with bigger meshes) */
BKE_pbvh_search_gather(pbvh, BKE_pbvh_node_planes_contain_AABB, clip_planes_final, &nodes, &totnode);
-#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (i = 0; i < totnode; i++) {
PBVHVertexIter vi;
bool any_masked = false;
diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c
index 9021581d47f..3605ce5f280 100644
--- a/source/blender/editors/sculpt_paint/paint_ops.c
+++ b/source/blender/editors/sculpt_paint/paint_ops.c
@@ -149,11 +149,112 @@ static void BRUSH_OT_scale_size(wmOperatorType *ot)
RNA_def_float(ot->srna, "scalar", 1, 0, 2, "Scalar", "Factor to scale brush size by", 0, 2);
}
+/* Palette operators */
+
+static int palette_new_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Paint *paint = BKE_paint_get_active_from_context(C);
+ Main *bmain = CTX_data_main(C);
+ Palette *palette;
+
+ palette = BKE_palette_add(bmain, "Palette");
+
+ BKE_paint_palette_set(paint, palette);
+
+ return OPERATOR_FINISHED;
+}
+
+static void PALETTE_OT_new(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add New Palette";
+ ot->description = "Add new palette";
+ ot->idname = "PALETTE_OT_new";
+
+ /* api callbacks */
+ ot->exec = palette_new_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+static int palette_poll(bContext *C)
+{
+ Paint *paint = BKE_paint_get_active_from_context(C);
+
+ if (paint && paint->palette != NULL)
+ return true;
+
+ return false;
+}
+
+static int palette_color_add_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Scene *scene = CTX_data_scene(C);
+ Paint *paint = BKE_paint_get_active_from_context(C);
+ Brush *brush = paint->brush;
+ PaintMode mode = BKE_paintmode_get_active_from_context(C);
+ Palette *palette = paint->palette;
+ PaletteColor *color = BKE_palette_color_add(palette);
+
+ if (ELEM(mode, PAINT_TEXTURE_PROJECTIVE, PAINT_TEXTURE_2D, PAINT_VERTEX)) {
+ copy_v3_v3(color->rgb, BKE_brush_color_get(scene, brush));
+ color->value = 0.0;
+ }
+ else if (mode == PAINT_WEIGHT) {
+ zero_v3(color->rgb);
+ color->value = brush->weight;
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+static void PALETTE_OT_color_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "New Palette Color";
+ ot->description = "Add new color to active palette";
+ ot->idname = "PALETTE_OT_color_add";
+
+ /* api callbacks */
+ ot->exec = palette_color_add_exec;
+ ot->poll = palette_poll;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+
+static int palette_color_delete_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Paint *paint = BKE_paint_get_active_from_context(C);
+ Palette *palette = paint->palette;
+
+ BKE_palette_color_delete(palette);
+
+ return OPERATOR_FINISHED;
+}
+
+static void PALETTE_OT_color_delete(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Delete Palette Color";
+ ot->description = "Remove active color from palette";
+ ot->idname = "PALETTE_OT_color_delete";
+
+ /* api callbacks */
+ ot->exec = palette_color_delete_exec;
+ ot->poll = palette_poll;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+
+
static int vertex_color_set_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
Object *obact = CTX_data_active_object(C);
- unsigned int paintcol = vpaint_get_current_col(scene->toolsettings->vpaint);
+ unsigned int paintcol = vpaint_get_current_col(scene, scene->toolsettings->vpaint);
if (ED_vpaint_fill(obact, paintcol)) {
ED_region_tag_redraw(CTX_wm_region(C)); // XXX - should redraw all 3D views
@@ -332,6 +433,7 @@ static int brush_generic_tool_set(Main *bmain, Paint *paint, const int tool,
if (brush) {
BKE_paint_brush_set(paint, brush);
BKE_paint_invalidate_overlay_all();
+
WM_main_add_notifier(NC_BRUSH | NA_EDITED, brush);
return OPERATOR_FINISHED;
}
@@ -928,8 +1030,37 @@ static void ed_keymap_stencil(wmKeyMap *keymap)
/**************************** registration **********************************/
+void ED_operatormacros_paint(void)
+{
+ wmOperatorType *ot;
+ wmOperatorTypeMacro *otmacro;
+
+ ot = WM_operatortype_append_macro("PAINTCURVE_OT_add_point_slide", "Add Curve Point and Slide",
+ "Add new curve point and slide it", OPTYPE_UNDO);
+ ot->description = "Add new curve point and slide it";
+ WM_operatortype_macro_define(ot, "PAINTCURVE_OT_add_point");
+ otmacro = WM_operatortype_macro_define(ot, "PAINTCURVE_OT_slide");
+ RNA_boolean_set(otmacro->ptr, "align", true);
+ RNA_boolean_set(otmacro->ptr, "select", false);
+}
+
+
void ED_operatortypes_paint(void)
{
+ /* palette */
+ WM_operatortype_append(PALETTE_OT_new);
+ WM_operatortype_append(PALETTE_OT_color_add);
+ WM_operatortype_append(PALETTE_OT_color_delete);
+
+ /* paint curve */
+ WM_operatortype_append(PAINTCURVE_OT_new);
+ WM_operatortype_append(PAINTCURVE_OT_add_point);
+ WM_operatortype_append(PAINTCURVE_OT_delete_point);
+ WM_operatortype_append(PAINTCURVE_OT_select);
+ WM_operatortype_append(PAINTCURVE_OT_slide);
+ WM_operatortype_append(PAINTCURVE_OT_draw);
+ WM_operatortype_append(PAINTCURVE_OT_cursor);
+
/* brush */
WM_operatortype_append(BRUSH_OT_add);
WM_operatortype_append(BRUSH_OT_scale_size);
@@ -950,6 +1081,8 @@ void ED_operatortypes_paint(void)
WM_operatortype_append(PAINT_OT_grab_clone);
WM_operatortype_append(PAINT_OT_project_image);
WM_operatortype_append(PAINT_OT_image_from_view);
+ WM_operatortype_append(PAINT_OT_brush_colors_flip);
+ WM_operatortype_append(PAINT_OT_add_texture_paint_slot);
/* weight */
WM_operatortype_append(PAINT_OT_weight_paint_toggle);
@@ -1119,12 +1252,44 @@ static void paint_partial_visibility_keys(wmKeyMap *keymap)
RNA_enum_set(kmi->ptr, "area", PARTIALVIS_ALL);
}
+
+static void paint_keymap_curve(wmKeyMap *keymap)
+{
+ wmKeyMapItem *kmi;
+
+ WM_keymap_add_item(keymap, "PAINTCURVE_OT_add_point_slide", ACTIONMOUSE, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_add_item(keymap, "PAINTCURVE_OT_select", SELECTMOUSE, KM_PRESS, 0, 0);
+ kmi = WM_keymap_add_item(keymap, "PAINTCURVE_OT_select", SELECTMOUSE, KM_PRESS, KM_SHIFT, 0);
+ RNA_boolean_set(kmi->ptr, "extend", true);
+ WM_keymap_add_item(keymap, "PAINTCURVE_OT_slide", ACTIONMOUSE, KM_PRESS, 0, 0);
+ kmi = WM_keymap_add_item(keymap, "PAINTCURVE_OT_slide", ACTIONMOUSE, KM_PRESS, KM_SHIFT, 0);
+ RNA_boolean_set(kmi->ptr, "align", true);
+ kmi = WM_keymap_add_item(keymap, "PAINTCURVE_OT_select", AKEY, KM_PRESS, 0, 0);
+ RNA_boolean_set(kmi->ptr, "toggle", true);
+
+ WM_keymap_add_item(keymap, "PAINTCURVE_OT_cursor", ACTIONMOUSE, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "PAINTCURVE_OT_delete_point", XKEY, KM_PRESS, 0, 0);
+
+ WM_keymap_add_item(keymap, "PAINTCURVE_OT_draw", RETKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "PAINTCURVE_OT_draw", PADENTER, KM_PRESS, 0, 0);
+
+ WM_keymap_add_item(keymap, "TRANSFORM_OT_translate", GKEY, KM_PRESS, 0, 0);
+ kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_translate", EVT_TWEAK_S, KM_ANY, 0, 0);
+ WM_keymap_add_item(keymap, "TRANSFORM_OT_rotate", RKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "TRANSFORM_OT_resize", SKEY, KM_PRESS, 0, 0);
+}
+
void ED_keymap_paint(wmKeyConfig *keyconf)
{
wmKeyMap *keymap;
wmKeyMapItem *kmi;
int i;
+ keymap = WM_keymap_find(keyconf, "Paint Curve", 0, 0);
+ keymap->poll = paint_curve_poll;
+
+ paint_keymap_curve(keymap);
+
/* Sculpt mode */
keymap = WM_keymap_find(keyconf, "Sculpt", 0, 0);
keymap->poll = sculpt_mode_poll;
@@ -1191,7 +1356,7 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
RNA_boolean_set(kmi->ptr, "create_missing", 1);
/* */
- kmi = WM_keymap_add_item(keymap, "WM_OT_context_menu_enum", AKEY, KM_PRESS, 0, 0);
+ kmi = WM_keymap_add_item(keymap, "WM_OT_context_menu_enum", EKEY, KM_PRESS, 0, 0);
RNA_string_set(kmi->ptr, "data_path", "tool_settings.sculpt.brush.stroke_method");
kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", SKEY, KM_PRESS, KM_SHIFT, 0);
@@ -1225,7 +1390,7 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
kmi = WM_keymap_add_item(keymap, "WM_OT_context_menu_enum", RKEY, KM_PRESS, 0, 0);
RNA_string_set(kmi->ptr, "data_path", "tool_settings.vertex_paint.brush.texture_angle_source_random");
- kmi = WM_keymap_add_item(keymap, "WM_OT_context_menu_enum", AKEY, KM_PRESS, 0, 0);
+ kmi = WM_keymap_add_item(keymap, "WM_OT_context_menu_enum", EKEY, KM_PRESS, 0, 0);
RNA_string_set(kmi->ptr, "data_path", "tool_settings.vertex_paint.brush.stroke_method");
/* Weight Paint mode */
@@ -1250,7 +1415,7 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
ed_keymap_stencil(keymap);
- kmi = WM_keymap_add_item(keymap, "WM_OT_context_menu_enum", AKEY, KM_PRESS, 0, 0);
+ kmi = WM_keymap_add_item(keymap, "WM_OT_context_menu_enum", EKEY, KM_PRESS, 0, 0);
RNA_string_set(kmi->ptr, "data_path", "tool_settings.vertex_paint.brush.stroke_method");
kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", MKEY, KM_PRESS, 0, 0); /* face mask toggle */
@@ -1283,6 +1448,7 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
RNA_enum_set(WM_keymap_add_item(keymap, "PAINT_OT_image_paint", LEFTMOUSE, KM_PRESS, 0, 0)->ptr, "mode", BRUSH_STROKE_NORMAL);
RNA_enum_set(WM_keymap_add_item(keymap, "PAINT_OT_image_paint", LEFTMOUSE, KM_PRESS, KM_CTRL, 0)->ptr, "mode", BRUSH_STROKE_INVERT);
+ WM_keymap_add_item(keymap, "PAINT_OT_brush_colors_flip", XKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "PAINT_OT_grab_clone", RIGHTMOUSE, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "PAINT_OT_sample_color", SKEY, KM_PRESS, 0, 0);
@@ -1301,7 +1467,7 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
kmi = WM_keymap_add_item(keymap, "WM_OT_context_menu_enum", RKEY, KM_PRESS, 0, 0);
RNA_string_set(kmi->ptr, "data_path", "tool_settings.image_paint.brush.texture_angle_source_random");
- kmi = WM_keymap_add_item(keymap, "WM_OT_context_menu_enum", AKEY, KM_PRESS, 0, 0);
+ kmi = WM_keymap_add_item(keymap, "WM_OT_context_menu_enum", EKEY, KM_PRESS, 0, 0);
RNA_string_set(kmi->ptr, "data_path", "tool_settings.image_paint.brush.stroke_method");
/* face-mask mode */
diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c
index 5133f51a6fd..47a772af9e4 100644
--- a/source/blender/editors/sculpt_paint/paint_stroke.c
+++ b/source/blender/editors/sculpt_paint/paint_stroke.c
@@ -36,16 +36,19 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "BLI_rand.h"
+#include "BLI_listbase.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_brush_types.h"
+#include "DNA_curve_types.h"
#include "RNA_access.h"
#include "BKE_context.h"
#include "BKE_paint.h"
#include "BKE_brush.h"
+#include "BKE_curve.h"
#include "BKE_colortools.h"
#include "BKE_image.h"
@@ -72,7 +75,7 @@ typedef struct PaintSample {
typedef struct PaintStroke {
void *mode_data;
- void *smooth_stroke_cursor;
+ void *stroke_cursor;
wmTimer *timer;
/* Cached values */
@@ -81,6 +84,9 @@ typedef struct PaintStroke {
Brush *brush;
UnifiedPaintSettings *ups;
+ /* used for lines and curves */
+ ListBase line;
+
/* Paint stroke can use up to PAINT_MAX_INPUT_SAMPLES prior inputs
* to smooth the stroke */
PaintSample samples[PAINT_MAX_INPUT_SAMPLES];
@@ -88,6 +94,8 @@ typedef struct PaintStroke {
int cur_sample;
float last_mouse_position[2];
+ /* space distance covered so far */
+ float stroke_distance;
/* Set whether any stroke step has yet occurred
* e.g. in sculpt mode, stroke doesn't start until cursor
@@ -116,18 +124,17 @@ typedef struct PaintStroke {
StrokeDone done;
} PaintStroke;
-/*** Cursor ***/
-static void paint_draw_smooth_stroke(bContext *C, int x, int y, void *customdata)
+/*** Cursors ***/
+static void paint_draw_smooth_cursor(bContext *C, int x, int y, void *customdata)
{
Paint *paint = BKE_paint_get_active_from_context(C);
Brush *brush = BKE_paint_brush(paint);
PaintStroke *stroke = customdata;
- if (stroke && brush && (brush->flag & BRUSH_SMOOTH_STROKE)) {
- glColor4ubv(paint->paint_cursor_col);
+ if (stroke && brush) {
glEnable(GL_LINE_SMOOTH);
glEnable(GL_BLEND);
-
+ glColor4ubv(paint->paint_cursor_col);
sdrawline(x, y, (int)stroke->last_mouse_position[0],
(int)stroke->last_mouse_position[1]);
glDisable(GL_BLEND);
@@ -135,12 +142,39 @@ static void paint_draw_smooth_stroke(bContext *C, int x, int y, void *customdata
}
}
+static void paint_draw_line_cursor(bContext *C, int x, int y, void *customdata)
+{
+ Paint *paint = BKE_paint_get_active_from_context(C);
+ PaintStroke *stroke = customdata;
+
+ glEnable(GL_LINE_SMOOTH);
+ glEnable(GL_BLEND);
+
+ glEnable(GL_LINE_STIPPLE);
+ glLineStipple(3, 0xAAAA);
+
+ glColor4ub(0, 0, 0, paint->paint_cursor_col[3]);
+ glLineWidth(3.0);
+ sdrawline((int)stroke->last_mouse_position[0], (int)stroke->last_mouse_position[1],
+ x, y);
+
+ glColor4ub(255, 255, 255, paint->paint_cursor_col[3]);
+ glLineWidth(1.0);
+ sdrawline((int)stroke->last_mouse_position[0], (int)stroke->last_mouse_position[1],
+ x, y);
+
+ glDisable(GL_LINE_STIPPLE);
+
+ glDisable(GL_BLEND);
+ glDisable(GL_LINE_SMOOTH);
+}
+
static bool paint_tool_require_location(Brush *brush, PaintMode mode)
{
switch (mode) {
case PAINT_SCULPT:
- if (ELEM4(brush->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_ROTATE,
- SCULPT_TOOL_SNAKE_HOOK, SCULPT_TOOL_THUMB))
+ if (ELEM(brush->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_ROTATE,
+ SCULPT_TOOL_SNAKE_HOOK, SCULPT_TOOL_THUMB))
{
return false;
}
@@ -155,13 +189,18 @@ static bool paint_tool_require_location(Brush *brush, PaintMode mode)
}
/* Initialize the stroke cache variants from operator properties */
-static void paint_brush_update(bContext *C, Brush *brush, PaintMode mode,
- struct PaintStroke *stroke,
- const float mouse[2], float pressure)
+static bool paint_brush_update(bContext *C,
+ Brush *brush,
+ PaintMode mode,
+ struct PaintStroke *stroke,
+ const float mouse_init[2],
+ float mouse[2], float pressure,
+ float location[3])
{
Scene *scene = CTX_data_scene(C);
- UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
-
+ UnifiedPaintSettings *ups = stroke->ups;
+ bool location_sampled = false;
+ bool location_success = false;
/* XXX: Use pressure value from first brush step for brushes which don't
* support strokes (grab, thumb). They depends on initial state and
* brush coord/pressure/etc.
@@ -222,14 +261,14 @@ static void paint_brush_update(bContext *C, Brush *brush, PaintMode mode,
else {
copy_v2_v2(ups->tex_mouse, mouse);
}
- }
- /* take care of mask texture, if any */
- if (brush->mask_mtex.tex) {
- if (brush->mask_mtex.brush_map_mode == MTEX_MAP_MODE_RANDOM)
- BKE_brush_randomize_texture_coordinates(ups, true);
- else {
- copy_v2_v2(ups->mask_tex_mouse, mouse);
+ /* take care of mask texture, if any */
+ if (brush->mask_mtex.tex) {
+ if (brush->mask_mtex.brush_map_mode == MTEX_MAP_MODE_RANDOM)
+ BKE_brush_randomize_texture_coordinates(ups, true);
+ else {
+ copy_v2_v2(ups->mask_tex_mouse, mouse);
+ }
}
}
@@ -246,14 +285,14 @@ static void paint_brush_update(bContext *C, Brush *brush, PaintMode mode,
ups->brush_rotation = atan2(dx, dy) + M_PI;
if (brush->flag & BRUSH_EDGE_TO_EDGE) {
- float out[3];
-
halfway[0] = dx * 0.5f + stroke->initial_mouse[0];
halfway[1] = dy * 0.5f + stroke->initial_mouse[1];
if (stroke->get_location) {
- if (stroke->get_location(C, out, halfway)) {
+ if (stroke->get_location(C, location, halfway)) {
hit = true;
+ location_sampled = true;
+ location_success = true;
}
else if (!paint_tool_require_location(brush, mode)) {
hit = true;
@@ -266,17 +305,43 @@ static void paint_brush_update(bContext *C, Brush *brush, PaintMode mode,
if (hit) {
copy_v2_v2(ups->anchored_initial_mouse, halfway);
copy_v2_v2(ups->tex_mouse, halfway);
+ copy_v2_v2(ups->mask_tex_mouse, halfway);
+ copy_v2_v2(mouse, halfway);
ups->anchored_size /= 2.0f;
ups->pixel_radius /= 2.0f;
+ stroke->stroke_distance = ups->pixel_radius;
}
- else
+ else {
copy_v2_v2(ups->anchored_initial_mouse, stroke->initial_mouse);
-
+ copy_v2_v2(mouse, stroke->initial_mouse);
+ stroke->stroke_distance = ups->pixel_radius;
+ }
+ ups->pixel_radius /= stroke->zoom_2d;
ups->draw_anchored = true;
}
else if (brush->flag & BRUSH_RAKE) {
- paint_calculate_rake_rotation(ups, mouse);
+ /* here we are using the initial mouse coordinate because we do not want the rake
+ * result to depend on jittering */
+ if (!stroke->brush_init)
+ copy_v2_v2(ups->last_rake, mouse_init);
+ else
+ paint_calculate_rake_rotation(ups, mouse_init);
}
+
+ if (!location_sampled) {
+ if (stroke->get_location) {
+ if (stroke->get_location(C, location, mouse))
+ location_success = true;
+ else if (!paint_tool_require_location(brush, mode))
+ location_success = true;
+ }
+ else {
+ zero_v3(location);
+ location_success = true;
+ }
+ }
+
+ return location_success;
}
@@ -284,12 +349,11 @@ static void paint_brush_update(bContext *C, Brush *brush, PaintMode mode,
static void paint_brush_stroke_add_step(bContext *C, wmOperator *op, const float mouse_in[2], float pressure)
{
Scene *scene = CTX_data_scene(C);
- wmWindow *window = CTX_wm_window(C);
- ARegion *ar = CTX_wm_region(C);
Paint *paint = BKE_paint_get_active_from_context(C);
PaintMode mode = BKE_paintmode_get_active_from_context(C);
Brush *brush = BKE_paint_brush(paint);
PaintStroke *stroke = op->customdata;
+ UnifiedPaintSettings *ups = stroke->ups;
float mouse_out[2];
PointerRNA itemptr;
float location[3];
@@ -315,8 +379,6 @@ static void paint_brush_stroke_add_step(bContext *C, wmOperator *op, const float
copy_v2_v2(stroke->last_mouse_position, mouse_in);
stroke->last_pressure = pressure;
- paint_brush_update(C, brush, mode, stroke, mouse_in, pressure);
-
{
float delta[2];
float factor = stroke->zoom_2d;
@@ -336,22 +398,13 @@ static void paint_brush_stroke_add_step(bContext *C, wmOperator *op, const float
}
}
- /* TODO: can remove the if statement once all modes have this */
- if (stroke->get_location) {
- if (!stroke->get_location(C, location, mouse_out)) {
- if (paint_tool_require_location(brush, mode)) {
- if (ar && (paint->flags & PAINT_SHOW_BRUSH))
- WM_paint_cursor_tag_redraw(window, ar);
- return;
- }
- }
+ if (!paint_brush_update(C, brush, mode, stroke, mouse_in, mouse_out, pressure, location)) {
+ return;
}
- else
- zero_v3(location);
/* Add to stroke */
RNA_collection_add(op->ptr, "stroke", &itemptr);
-
+ RNA_float_set(&itemptr, "size", ups->pixel_radius);
RNA_float_set_array(&itemptr, "location", location);
RNA_float_set_array(&itemptr, "mouse", mouse_out);
RNA_boolean_set(&itemptr, "pen_flip", stroke->pen_flip);
@@ -362,20 +415,12 @@ static void paint_brush_stroke_add_step(bContext *C, wmOperator *op, const float
/* don't record this for now, it takes up a lot of memory when doing long
* strokes with small brush size, and operators have register disabled */
RNA_collection_clear(op->ptr, "stroke");
-
- /* always redraw region if brush is shown */
- if (ar && (paint->flags & PAINT_SHOW_BRUSH))
- WM_paint_cursor_tag_redraw(window, ar);
}
/* Returns zero if no sculpt changes should be made, non-zero otherwise */
static int paint_smooth_stroke(PaintStroke *stroke, float output[2], float *outpressure,
const PaintSample *sample, PaintMode mode)
{
- output[0] = sample->mouse[0];
- output[1] = sample->mouse[1];
- *outpressure = sample->pressure;
-
if (paint_supports_smooth_stroke(stroke->brush, mode)) {
float radius = stroke->brush->smooth_stroke_radius * stroke->zoom_2d;
float u = stroke->brush->smooth_stroke_factor, v = 1.0f - u;
@@ -391,6 +436,11 @@ static int paint_smooth_stroke(PaintStroke *stroke, float output[2], float *outp
output[1] = sample->mouse[1] * v + stroke->last_mouse_position[1] * u;
*outpressure = sample->pressure * v + stroke->last_pressure * u;
}
+ else {
+ output[0] = sample->mouse[0];
+ output[1] = sample->mouse[1];
+ *outpressure = sample->pressure;
+ }
return 1;
}
@@ -413,6 +463,55 @@ static float paint_space_stroke_spacing(const Scene *scene, PaintStroke *stroke,
return max_ff(1.0, size_clamp * spacing / 50.0f);
}
+
+
+static float paint_stroke_overlapped_curve(Brush *br, float x, float spacing)
+{
+ int i;
+ const int n = 100 / spacing;
+ const float h = spacing / 50.0f;
+ const float x0 = x - 1;
+
+ float sum;
+
+ sum = 0;
+ for (i = 0; i < n; i++) {
+ float xx;
+
+ xx = fabs(x0 + i * h);
+
+ if (xx < 1.0f)
+ sum += BKE_brush_curve_strength(br, xx, 1);
+ }
+
+ return sum;
+}
+
+static float paint_stroke_integrate_overlap(Brush *br, float factor)
+{
+ int i;
+ int m;
+ float g;
+ float max;
+
+ float spacing = br->spacing * factor;
+
+ if (!(br->flag & BRUSH_SPACE_ATTEN && (br->spacing < 100)))
+ return 1.0;
+
+ m = 10;
+ g = 1.0f / m;
+ max = 0;
+ for (i = 0; i < m; i++) {
+ float overlap = paint_stroke_overlapped_curve(br, i * g, spacing);
+
+ if (overlap > max)
+ max = overlap;
+ }
+
+ return 1.0f / max;
+}
+
static float paint_space_stroke_spacing_variable(const Scene *scene, PaintStroke *stroke, float pressure, float dpressure, float length)
{
if (BKE_brush_use_size_pressure(scene, stroke->brush)) {
@@ -444,40 +543,42 @@ static int paint_space_stroke(bContext *C, wmOperator *op, const float final_mou
{
const Scene *scene = CTX_data_scene(C);
PaintStroke *stroke = op->customdata;
- PaintMode mode = BKE_paintmode_get_active_from_context(C);
+ UnifiedPaintSettings *ups = stroke->ups;
int cnt = 0;
- if (paint_space_stroke_enabled(stroke->brush, mode)) {
- float pressure, dpressure;
- float mouse[2], dmouse[2];
- float length;
+ float pressure, dpressure;
+ float mouse[2], dmouse[2];
+ float length;
+ float no_pressure_spacing = paint_space_stroke_spacing(scene, stroke, 1.0f, 1.0f);
- sub_v2_v2v2(dmouse, final_mouse, stroke->last_mouse_position);
+ sub_v2_v2v2(dmouse, final_mouse, stroke->last_mouse_position);
- pressure = stroke->last_pressure;
- dpressure = final_pressure - stroke->last_pressure;
+ pressure = stroke->last_pressure;
+ dpressure = final_pressure - stroke->last_pressure;
- length = normalize_v2(dmouse);
+ length = normalize_v2(dmouse);
- while (length > 0.0f) {
- float spacing = paint_space_stroke_spacing_variable(scene, stroke, pressure, dpressure, length);
-
- if (length >= spacing) {
- mouse[0] = stroke->last_mouse_position[0] + dmouse[0] * spacing;
- mouse[1] = stroke->last_mouse_position[1] + dmouse[1] * spacing;
- pressure = stroke->last_pressure + (spacing / length) * dpressure;
+ while (length > 0.0f) {
+ float spacing = paint_space_stroke_spacing_variable(scene, stroke, pressure, dpressure, length);
- paint_brush_stroke_add_step(C, op, mouse, pressure);
+ if (length >= spacing) {
+ mouse[0] = stroke->last_mouse_position[0] + dmouse[0] * spacing;
+ mouse[1] = stroke->last_mouse_position[1] + dmouse[1] * spacing;
+ pressure = stroke->last_pressure + (spacing / length) * dpressure;
- length -= spacing;
- pressure = stroke->last_pressure;
- dpressure = final_pressure - stroke->last_pressure;
+ ups->overlap_factor = paint_stroke_integrate_overlap(stroke->brush, spacing / no_pressure_spacing);
- cnt++;
- }
- else {
- break;
- }
+ stroke->stroke_distance += spacing / stroke->zoom_2d;
+ paint_brush_stroke_add_step(C, op, mouse, pressure);
+
+ length -= spacing;
+ pressure = stroke->last_pressure;
+ dpressure = final_pressure - stroke->last_pressure;
+
+ cnt++;
+ }
+ else {
+ break;
}
}
@@ -487,6 +588,7 @@ static int paint_space_stroke(bContext *C, wmOperator *op, const float final_mou
/**** Public API ****/
PaintStroke *paint_stroke_new(bContext *C,
+ wmOperator *op,
StrokeGetLocation get_location,
StrokeTestStart test_start,
StrokeUpdateStep update_step,
@@ -497,6 +599,7 @@ PaintStroke *paint_stroke_new(bContext *C,
ToolSettings *toolsettings = CTX_data_tool_settings(C);
UnifiedPaintSettings *ups = &toolsettings->unified_paint_settings;
Brush *br = stroke->brush = BKE_paint_brush(BKE_paint_get_active_from_context(C));
+ float zoomx, zoomy;
view3d_set_viewcontext(C, &stroke->vc);
if (stroke->vc.v3d)
@@ -510,6 +613,18 @@ PaintStroke *paint_stroke_new(bContext *C,
stroke->event_type = event_type; /* for modal, return event */
stroke->ups = ups;
+ get_imapaint_zoom(C, &zoomx, &zoomy);
+ stroke->zoom_2d = max_ff(zoomx, zoomy);
+
+ if ((br->flag & BRUSH_CURVE) &&
+ RNA_struct_property_is_set(op->ptr, "mode"))
+ {
+ RNA_enum_set(op->ptr, "mode", BRUSH_STROKE_NORMAL);
+ }
+ /* initialize here */
+ ups->overlap_factor = 1.0;
+ ups->stroke_active = true;
+
/* initialize here to avoid initialization conflict with threaded strokes */
curvemapping_initialize(br->curve);
@@ -521,8 +636,7 @@ PaintStroke *paint_stroke_new(bContext *C,
void paint_stroke_data_free(struct wmOperator *op)
{
BKE_paint_set_overlay_override(0);
- MEM_freeN(op->customdata);
- op->customdata = NULL;
+ MEM_SAFE_FREE(op->customdata);
}
static void stroke_done(struct bContext *C, struct wmOperator *op)
@@ -552,8 +666,10 @@ static void stroke_done(struct bContext *C, struct wmOperator *op)
stroke->timer);
}
- if (stroke->smooth_stroke_cursor)
- WM_paint_cursor_end(CTX_wm_manager(C), stroke->smooth_stroke_cursor);
+ if (stroke->stroke_cursor)
+ WM_paint_cursor_end(CTX_wm_manager(C), stroke->stroke_cursor);
+
+ BLI_freelistN(&stroke->line);
paint_stroke_data_free(op);
}
@@ -566,7 +682,7 @@ bool paint_space_stroke_enabled(Brush *br, PaintMode mode)
static bool sculpt_is_grab_tool(Brush *br)
{
- return ELEM4(br->sculpt_tool,
+ return ELEM(br->sculpt_tool,
SCULPT_TOOL_GRAB,
SCULPT_TOOL_THUMB,
SCULPT_TOOL_ROTATE,
@@ -584,6 +700,16 @@ bool paint_supports_dynamic_size(Brush *br, PaintMode mode)
if (sculpt_is_grab_tool(br))
return false;
break;
+
+ case PAINT_TEXTURE_2D: /* fall through */
+ case PAINT_TEXTURE_PROJECTIVE:
+ if ((br->imagepaint_tool == PAINT_TOOL_FILL) &&
+ (br->flag & BRUSH_USE_GRADIENT))
+ {
+ return false;
+ }
+ break;
+
default:
break;
}
@@ -593,8 +719,7 @@ bool paint_supports_dynamic_size(Brush *br, PaintMode mode)
bool paint_supports_smooth_stroke(Brush *br, PaintMode mode)
{
if (!(br->flag & BRUSH_SMOOTH_STROKE) ||
- (br->flag & BRUSH_ANCHORED) ||
- (br->flag & BRUSH_DRAG_DOT))
+ (br->flag & (BRUSH_ANCHORED | BRUSH_DRAG_DOT | BRUSH_LINE)))
{
return false;
}
@@ -613,7 +738,7 @@ bool paint_supports_smooth_stroke(Brush *br, PaintMode mode)
bool paint_supports_texture(PaintMode mode)
{
/* ommit: PAINT_WEIGHT, PAINT_SCULPT_UV, PAINT_INVALID */
- return ELEM4(mode, PAINT_SCULPT, PAINT_VERTEX, PAINT_TEXTURE_PROJECTIVE, PAINT_TEXTURE_2D);
+ return ELEM(mode, PAINT_SCULPT, PAINT_VERTEX, PAINT_TEXTURE_PROJECTIVE, PAINT_TEXTURE_2D);
}
/* return true if the brush size can change during paint (normally used for pressure) */
@@ -701,28 +826,141 @@ static void paint_stroke_sample_average(const PaintStroke *stroke,
/*printf("avg=(%f, %f), num=%d\n", average->mouse[0], average->mouse[1], stroke->num_samples);*/
}
+/**
+ * Slightly different version of spacing for line/curve strokes,
+ * makes sure the dabs stay on the line path.
+ */
+static void paint_line_strokes_spacing(
+ bContext *C, wmOperator *op, PaintStroke *stroke, float spacing, float *length_residue,
+ const float old_pos[2], const float new_pos[2])
+{
+ UnifiedPaintSettings *ups = stroke->ups;
+
+ float mouse[2], dmouse[2];
+ float length;
+
+ sub_v2_v2v2(dmouse, new_pos, old_pos);
+ copy_v2_v2(stroke->last_mouse_position, old_pos);
+
+ length = normalize_v2(dmouse);
+
+ BLI_assert(length >= 0.0f);
+
+ if (length == 0.0f)
+ return;
+
+ while (length > 0.0f) {
+ float spacing_final = spacing - *length_residue;
+ length += *length_residue;
+ *length_residue = 0.0;
+
+ if (length >= spacing) {
+ mouse[0] = stroke->last_mouse_position[0] + dmouse[0] * spacing_final;
+ mouse[1] = stroke->last_mouse_position[1] + dmouse[1] * spacing_final;
+
+ ups->overlap_factor = paint_stroke_integrate_overlap(stroke->brush, 1.0);
+
+ stroke->stroke_distance += spacing / stroke->zoom_2d;
+ paint_brush_stroke_add_step(C, op, mouse, 1.0);
+
+ length -= spacing;
+ spacing_final = spacing;
+ }
+ else {
+ break;
+ }
+ }
+
+ *length_residue = length;
+}
+
+
+static void paint_stroke_line_end(bContext *C, wmOperator *op, PaintStroke *stroke, float mouse[2])
+{
+ Brush *br = stroke->brush;
+ if (stroke->stroke_started && (br->flag & BRUSH_LINE)) {
+ stroke->ups->overlap_factor = paint_stroke_integrate_overlap(br, 1.0);
+
+ paint_brush_stroke_add_step(C, op, stroke->last_mouse_position, 1.0);
+ paint_space_stroke(C, op, mouse, 1.0);
+ }
+}
+
+static bool paint_stroke_curve_end(bContext *C, wmOperator *op, PaintStroke *stroke)
+{
+ Brush *br = stroke->brush;
+ if (br->flag & BRUSH_CURVE) {
+ const Scene *scene = CTX_data_scene(C);
+ const float spacing = paint_space_stroke_spacing(scene, stroke, 1.0f, 1.0f);
+ PaintCurve *pc = br->paint_curve;
+ PaintCurvePoint *pcp;
+ float length_residue = 0.0f;
+ int i;
+
+ if (!pc)
+ return true;
+
+ pcp = pc->points;
+ stroke->ups->overlap_factor = paint_stroke_integrate_overlap(br, 1.0);
+
+ for (i = 0; i < pc->tot_points - 1; i++, pcp++) {
+ int j;
+ float data[(PAINT_CURVE_NUM_SEGMENTS + 1) * 2];
+ PaintCurvePoint *pcp_next = pcp + 1;
+
+ for (j = 0; j < 2; j++)
+ BKE_curve_forward_diff_bezier(
+ pcp->bez.vec[1][j],
+ pcp->bez.vec[2][j],
+ pcp_next->bez.vec[0][j],
+ pcp_next->bez.vec[1][j],
+ data + j, PAINT_CURVE_NUM_SEGMENTS, sizeof(float[2]));
+
+
+ for (j = 0; j < PAINT_CURVE_NUM_SEGMENTS; j++) {
+ if (!stroke->stroke_started) {
+ stroke->last_pressure = 1.0;
+ copy_v2_v2(stroke->last_mouse_position, data + 2 * j);
+ stroke->stroke_started = stroke->test_start(C, op, stroke->last_mouse_position);
+
+ if (stroke->stroke_started) {
+ paint_brush_stroke_add_step(C, op, data + 2 * j, 1.0);
+ paint_line_strokes_spacing(C, op, stroke, spacing, &length_residue, data + 2 * j, data + 2 * (j + 1));
+ }
+ }
+ else {
+ paint_line_strokes_spacing(C, op, stroke, spacing, &length_residue, data + 2 * j, data + 2 * (j + 1));
+ }
+ }
+ }
+
+ stroke_done(C, op);
+ return true;
+ }
+
+ return false;
+}
+
+
int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
Paint *p = BKE_paint_get_active_from_context(C);
PaintMode mode = BKE_paintmode_get_active_from_context(C);
PaintStroke *stroke = op->customdata;
+ Brush *br = stroke->brush;
PaintSample sample_average;
float mouse[2];
bool first_dab = false;
bool first_modal = false;
- float zoomx, zoomy;
bool redraw = false;
float pressure;
- /* see if tablet affects event */
- pressure = WM_event_tablet_data(event, &stroke->pen_flip, NULL);
+ /* see if tablet affects event. Line, anchored and drag dot strokes do not support pressure */
+ pressure = (br->flag & (BRUSH_LINE | BRUSH_ANCHORED | BRUSH_DRAG_DOT)) ? 1.0f : WM_event_tablet_data(event, &stroke->pen_flip, NULL);
paint_stroke_add_sample(p, stroke, event->mval[0], event->mval[1], pressure);
paint_stroke_sample_average(stroke, &sample_average);
- get_imapaint_zoom(C, &zoomx, &zoomy);
- stroke->zoom_2d = max_ff(zoomx, zoomy);
-
/* let NDOF motion pass through to the 3D view so we can paint and rotate simultaneously!
* this isn't perfect... even when an extra MOUSEMOVE is spoofed, the stroke discards it
* since the 2D deltas are zero -- code in this file needs to be updated to use the
@@ -732,8 +970,12 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* one time initialization */
if (!stroke->stroke_init) {
- stroke->smooth_stroke_cursor =
- WM_paint_cursor_activate(CTX_wm_manager(C), paint_poll, paint_draw_smooth_stroke, stroke);
+ if (paint_stroke_curve_end(C, op, stroke))
+ return OPERATOR_FINISHED;
+
+ if (paint_supports_smooth_stroke(br, mode))
+ stroke->stroke_cursor =
+ WM_paint_cursor_activate(CTX_wm_manager(C), paint_poll, paint_draw_smooth_cursor, stroke);
stroke->stroke_init = true;
first_modal = true;
@@ -747,9 +989,14 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
BLI_assert((stroke->stroke_started & ~1) == 0); /* 0/1 */
if (stroke->stroke_started) {
- if (stroke->brush->flag & BRUSH_AIRBRUSH)
+ if (br->flag & BRUSH_AIRBRUSH)
stroke->timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, stroke->brush->rate);
+ if (br->flag & BRUSH_LINE) {
+ stroke->stroke_cursor =
+ WM_paint_cursor_activate(CTX_wm_manager(C), paint_poll, paint_draw_line_cursor, stroke);
+ }
+
first_dab = true;
}
}
@@ -765,20 +1012,42 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
return OPERATOR_CANCELLED;
}
- if (event->type == stroke->event_type && event->val == KM_RELEASE && !first_modal) {
+ if (event->type == stroke->event_type && !first_modal) {
+ if (event->val == KM_RELEASE) {
+ paint_stroke_line_end (C, op, stroke, sample_average.mouse);
+ stroke_done(C, op);
+ return OPERATOR_FINISHED;
+ }
+ }
+ else if (ELEM(event->type, RETKEY, SPACEKEY)) {
+ paint_stroke_line_end(C, op, stroke, sample_average.mouse);
stroke_done(C, op);
return OPERATOR_FINISHED;
}
- else if (first_modal || (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) ||
- (event->type == TIMER && (event->customdata == stroke->timer)) )
+ else if ((br->flag & BRUSH_LINE) && stroke->stroke_started &&
+ (first_modal || (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE))))
+ {
+ if (br->flag & BRUSH_RAKE) {
+ copy_v2_v2(stroke->ups->last_rake, stroke->last_mouse_position);
+ paint_calculate_rake_rotation(stroke->ups, sample_average.mouse);
+ }
+ }
+ else if (first_modal ||
+ /* regular dabs */
+ (!(br->flag & (BRUSH_AIRBRUSH)) && (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE))) ||
+ /* airbrush */
+ ((br->flag & BRUSH_AIRBRUSH) && event->type == TIMER && event->customdata == stroke->timer))
{
if (paint_smooth_stroke(stroke, mouse, &pressure, &sample_average, mode)) {
if (stroke->stroke_started) {
- if (paint_space_stroke_enabled(stroke->brush, mode)) {
+ if (paint_space_stroke_enabled(br, mode)) {
if (paint_space_stroke(C, op, mouse, pressure))
redraw = true;
}
else {
+ float dmouse[2];
+ sub_v2_v2v2(dmouse, mouse, stroke->last_mouse_position);
+ stroke->stroke_distance += len_v2(dmouse);
paint_brush_stroke_add_step(C, op, mouse, pressure);
redraw = true;
}
@@ -789,19 +1058,27 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* we want the stroke to have the first daub at the start location
* instead of waiting till we have moved the space distance */
if (first_dab &&
- paint_space_stroke_enabled(stroke->brush, mode) &&
- !(stroke->brush->flag & BRUSH_ANCHORED) &&
- !(stroke->brush->flag & BRUSH_SMOOTH_STROKE))
+ paint_space_stroke_enabled(br, mode) &&
+ !(br->flag & BRUSH_SMOOTH_STROKE))
{
- paint_brush_stroke_add_step(C, op, mouse, pressure);
+ stroke->ups->overlap_factor = paint_stroke_integrate_overlap(br, 1.0);
+ paint_brush_stroke_add_step(C, op, sample_average.mouse, sample_average.pressure);
redraw = true;
}
/* do updates for redraw. if event is inbetween mousemove there are more
* coming, so postpone potentially slow redraw updates until all are done */
- if (event->type != INBETWEEN_MOUSEMOVE)
+ if (event->type != INBETWEEN_MOUSEMOVE) {
+ wmWindow *window = CTX_wm_window(C);
+ ARegion *ar = CTX_wm_region(C);
+
+ /* At the very least, invalidate the cursor */
+ if (ar && (p->flags & PAINT_SHOW_BRUSH))
+ WM_paint_cursor_tag_redraw(window, ar);
+
if (redraw && stroke->redraw)
stroke->redraw(C, stroke, false);
+ }
return OPERATOR_RUNNING_MODAL;
}
@@ -843,6 +1120,11 @@ void *paint_stroke_mode_data(struct PaintStroke *stroke)
return stroke->mode_data;
}
+float paint_stroke_distance_get(struct PaintStroke *stroke)
+{
+ return stroke->stroke_distance;
+}
+
void paint_stroke_set_mode_data(PaintStroke *stroke, void *mode_data)
{
stroke->mode_data = mode_data;
@@ -856,6 +1138,6 @@ int paint_poll(bContext *C)
ARegion *ar = CTX_wm_region(C);
return p && ob && BKE_paint_brush(p) &&
- (sa && sa->spacetype == SPACE_VIEW3D) &&
+ (sa && ELEM(sa->spacetype, SPACE_VIEW3D, SPACE_IMAGE)) &&
(ar && ar->regiontype == RGN_TYPE_WINDOW);
}
diff --git a/source/blender/editors/sculpt_paint/paint_undo.c b/source/blender/editors/sculpt_paint/paint_undo.c
index c5c747dbab4..20e3155c01d 100644
--- a/source/blender/editors/sculpt_paint/paint_undo.c
+++ b/source/blender/editors/sculpt_paint/paint_undo.c
@@ -51,19 +51,17 @@ typedef struct UndoElem {
UndoRestoreCb restore;
UndoFreeCb free;
+ UndoCleanupCb cleanup;
} UndoElem;
-typedef bool (*UndoCleanupCb)(struct bContext *C, ListBase *lb);
-
typedef struct UndoStack {
int type;
ListBase elems;
UndoElem *current;
- UndoCleanupCb cleanup;
} UndoStack;
-static UndoStack ImageUndoStack = {UNDO_PAINT_IMAGE, {NULL, NULL}, NULL, NULL};
-static UndoStack MeshUndoStack = {UNDO_PAINT_MESH, {NULL, NULL}, NULL, sculpt_undo_cleanup};
+static UndoStack ImageUndoStack = {UNDO_PAINT_IMAGE, {NULL, NULL}, NULL};
+static UndoStack MeshUndoStack = {UNDO_PAINT_MESH, {NULL, NULL}, NULL};
/* Generic */
@@ -81,7 +79,7 @@ static void undo_elem_free(UndoStack *UNUSED(stack), UndoElem *uel)
}
}
-static void undo_stack_push_begin(UndoStack *stack, const char *name, UndoRestoreCb restore, UndoFreeCb free)
+static void undo_stack_push_begin(UndoStack *stack, const char *name, UndoRestoreCb restore, UndoFreeCb free, UndoCleanupCb cleanup)
{
UndoElem *uel;
int nr;
@@ -101,6 +99,7 @@ static void undo_stack_push_begin(UndoStack *stack, const char *name, UndoRestor
stack->current = uel = MEM_callocN(sizeof(UndoElem), "undo file");
uel->restore = restore;
uel->free = free;
+ uel->cleanup = cleanup;
BLI_addtail(&stack->elems, uel);
/* name can be a dynamic string */
@@ -179,25 +178,24 @@ static void undo_stack_cleanup(UndoStack *stack, bContext *C)
UndoElem *uel = stack->elems.first;
bool stack_reset = false;
- if (stack->cleanup) {
- while (uel) {
- if (stack->cleanup(C, &uel->elems)) {
- UndoElem *uel_tmp = uel->next;
- if (stack->current == uel) {
- stack->current = NULL;
- stack_reset = true;
- }
- undo_elem_free(stack, uel);
- BLI_freelinkN(&stack->elems, uel);
- uel = uel_tmp;
+ while (uel) {
+ if (uel->cleanup && uel->cleanup(C, &uel->elems)) {
+ UndoElem *uel_tmp = uel->next;
+ if (stack->current == uel) {
+ stack->current = NULL;
+ stack_reset = true;
}
- else
- uel = uel->next;
- }
- if (stack_reset) {
- stack->current = stack->elems.last;
+ undo_elem_free(stack, uel);
+ BLI_freelinkN(&stack->elems, uel);
+ uel = uel_tmp;
}
+ else
+ uel = uel->next;
+ }
+ if (stack_reset) {
+ stack->current = stack->elems.last;
}
+
}
static int undo_stack_step(bContext *C, UndoStack *stack, int step, const char *name)
@@ -255,23 +253,25 @@ static void undo_stack_free(UndoStack *stack)
/* Exported Functions */
-void ED_undo_paint_push_begin(int type, const char *name, UndoRestoreCb restore, UndoFreeCb free)
+void ED_undo_paint_push_begin(int type, const char *name, UndoRestoreCb restore, UndoFreeCb free, UndoCleanupCb cleanup)
{
if (type == UNDO_PAINT_IMAGE)
- undo_stack_push_begin(&ImageUndoStack, name, restore, free);
+ undo_stack_push_begin(&ImageUndoStack, name, restore, free, cleanup);
else if (type == UNDO_PAINT_MESH)
- undo_stack_push_begin(&MeshUndoStack, name, restore, free);
+ undo_stack_push_begin(&MeshUndoStack, name, restore, free, cleanup);
}
ListBase *undo_paint_push_get_list(int type)
{
if (type == UNDO_PAINT_IMAGE) {
- if (ImageUndoStack.current)
+ if (ImageUndoStack.current) {
return &ImageUndoStack.current->elems;
+ }
}
else if (type == UNDO_PAINT_MESH) {
- if (MeshUndoStack.current)
+ if (MeshUndoStack.current) {
return &MeshUndoStack.current->elems;
+ }
}
return NULL;
diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c
index 25308f6595e..0d463172f99 100644
--- a/source/blender/editors/sculpt_paint/paint_utils.c
+++ b/source/blender/editors/sculpt_paint/paint_utils.c
@@ -35,23 +35,28 @@
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
+#include "DNA_material_types.h"
#include "DNA_scene_types.h"
#include "DNA_brush_types.h"
#include "BLI_math.h"
+#include "BLI_math_color.h"
#include "BLI_utildefines.h"
#include "BLI_listbase.h"
#include "BLI_rect.h"
#include "BLF_translation.h"
+#include "BKE_scene.h"
#include "BKE_brush.h"
#include "BKE_context.h"
#include "BKE_DerivedMesh.h"
+#include "BKE_material.h"
#include "BKE_image.h"
#include "BKE_paint.h"
#include "BKE_report.h"
+#include "BKE_image.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -67,6 +72,10 @@
#include "ED_view3d.h"
#include "ED_screen.h"
+#include "ED_uvedit.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
#include "BLI_sys_types.h"
#include "ED_mesh.h" /* for face mask functions */
@@ -205,6 +214,175 @@ void paint_get_tex_pixel_col(MTex *mtex, float u, float v, float rgba[4], struct
CLAMP(rgba[3], 0.0f, 1.0f);
}
+/* 3D Paint */
+
+static void imapaint_project(float matrix[4][4], const float co[3], float pco[4])
+{
+ copy_v3_v3(pco, co);
+ pco[3] = 1.0f;
+
+ mul_m4_v4(matrix, pco);
+}
+
+static void imapaint_tri_weights(float matrix[4][4], GLint view[4],
+ const float v1[3], const float v2[3], const float v3[3],
+ const float co[2], float w[3])
+{
+ float pv1[4], pv2[4], pv3[4], h[3], divw;
+ float wmat[3][3], invwmat[3][3];
+
+ /* compute barycentric coordinates */
+
+ /* project the verts */
+ imapaint_project(matrix, v1, pv1);
+ imapaint_project(matrix, v2, pv2);
+ imapaint_project(matrix, v3, pv3);
+
+ /* do inverse view mapping, see gluProject man page */
+ h[0] = (co[0] - view[0]) * 2.0f / view[2] - 1.0f;
+ h[1] = (co[1] - view[1]) * 2.0f / view[3] - 1.0f;
+ h[2] = 1.0f;
+
+ /* solve for (w1,w2,w3)/perspdiv in:
+ * h * perspdiv = Project * Model * (w1 * v1 + w2 * v2 + w3 * v3) */
+
+ wmat[0][0] = pv1[0]; wmat[1][0] = pv2[0]; wmat[2][0] = pv3[0];
+ wmat[0][1] = pv1[1]; wmat[1][1] = pv2[1]; wmat[2][1] = pv3[1];
+ wmat[0][2] = pv1[3]; wmat[1][2] = pv2[3]; wmat[2][2] = pv3[3];
+
+ invert_m3_m3(invwmat, wmat);
+ mul_m3_v3(invwmat, h);
+
+ copy_v3_v3(w, h);
+
+ /* w is still divided by perspdiv, make it sum to one */
+ divw = w[0] + w[1] + w[2];
+ if (divw != 0.0f) {
+ mul_v3_fl(w, 1.0f / divw);
+ }
+}
+
+/* compute uv coordinates of mouse in face */
+static void imapaint_pick_uv(Scene *scene, Object *ob, unsigned int faceindex, const int xy[2], float uv[2])
+{
+ DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
+ MTFace *tf_base, *tf;
+ Material *ma;
+ TexPaintSlot *slot;
+ int numfaces = dm->getNumTessFaces(dm), a, findex;
+ float p[2], w[3], absw, minabsw;
+ MFace mf;
+ MVert mv[4];
+ float matrix[4][4], proj[4][4];
+ GLint view[4];
+
+ /* compute barycentric coordinates */
+
+ /* double lookup */
+ const int *index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
+ const int *index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX);
+ if (index_mf_to_mpoly == NULL) {
+ index_mp_to_orig = NULL;
+ }
+
+ /* get the needed opengl matrices */
+ glGetIntegerv(GL_VIEWPORT, view);
+ glGetFloatv(GL_MODELVIEW_MATRIX, (float *)matrix);
+ glGetFloatv(GL_PROJECTION_MATRIX, (float *)proj);
+ view[0] = view[1] = 0;
+ mul_m4_m4m4(matrix, matrix, ob->obmat);
+ mul_m4_m4m4(matrix, proj, matrix);
+
+ minabsw = 1e10;
+ uv[0] = uv[1] = 0.0;
+
+ /* test all faces in the derivedmesh with the original index of the picked face */
+ for (a = 0; a < numfaces; a++) {
+ findex = index_mf_to_mpoly ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, a) : a;
+
+ if (findex == faceindex) {
+ dm->getTessFace(dm, a, &mf);
+
+ ma = dm->mat[mf.mat_nr];
+ slot = &ma->texpaintslot[ma->paint_active_slot];
+
+ dm->getVert(dm, mf.v1, &mv[0]);
+ dm->getVert(dm, mf.v2, &mv[1]);
+ dm->getVert(dm, mf.v3, &mv[2]);
+ if (mf.v4)
+ dm->getVert(dm, mf.v4, &mv[3]);
+
+ if (!slot->uvname || !(tf_base = CustomData_get_layer_named(&dm->faceData, CD_MTFACE, slot->uvname)))
+ tf_base = CustomData_get_layer(&dm->faceData, CD_MTFACE);
+
+ tf = &tf_base[a];
+
+ p[0] = xy[0];
+ p[1] = xy[1];
+
+ if (mf.v4) {
+ /* the triangle with the largest absolute values is the one
+ * with the most negative weights */
+ imapaint_tri_weights(matrix, view, mv[0].co, mv[1].co, mv[3].co, p, w);
+ absw = fabsf(w[0]) + fabsf(w[1]) + fabsf(w[2]);
+ if (absw < minabsw) {
+ uv[0] = tf->uv[0][0] * w[0] + tf->uv[1][0] * w[1] + tf->uv[3][0] * w[2];
+ uv[1] = tf->uv[0][1] * w[0] + tf->uv[1][1] * w[1] + tf->uv[3][1] * w[2];
+ minabsw = absw;
+ }
+
+ imapaint_tri_weights(matrix, view, mv[1].co, mv[2].co, mv[3].co, p, w);
+ absw = fabsf(w[0]) + fabsf(w[1]) + fabsf(w[2]);
+ if (absw < minabsw) {
+ uv[0] = tf->uv[1][0] * w[0] + tf->uv[2][0] * w[1] + tf->uv[3][0] * w[2];
+ uv[1] = tf->uv[1][1] * w[0] + tf->uv[2][1] * w[1] + tf->uv[3][1] * w[2];
+ minabsw = absw;
+ }
+ }
+ else {
+ imapaint_tri_weights(matrix, view, mv[0].co, mv[1].co, mv[2].co, p, w);
+ absw = fabsf(w[0]) + fabsf(w[1]) + fabsf(w[2]);
+ if (absw < minabsw) {
+ uv[0] = tf->uv[0][0] * w[0] + tf->uv[1][0] * w[1] + tf->uv[2][0] * w[2];
+ uv[1] = tf->uv[0][1] * w[0] + tf->uv[1][1] * w[1] + tf->uv[2][1] * w[2];
+ minabsw = absw;
+ }
+ }
+ }
+ }
+
+ dm->release(dm);
+}
+
+/* returns 0 if not found, otherwise 1 */
+static int imapaint_pick_face(ViewContext *vc, const int mval[2], unsigned int *r_index, unsigned int totface)
+{
+ if (totface == 0)
+ return 0;
+
+ /* sample only on the exact position */
+ *r_index = view3d_sample_backbuf(vc, mval[0], mval[1]);
+
+ if ((*r_index) == 0 || (*r_index) > (unsigned int)totface) {
+ return 0;
+ }
+
+ (*r_index)--;
+
+ return 1;
+}
+
+
+static Image *imapaint_face_image(DerivedMesh *dm, int face_index)
+{
+ Image *ima;
+ MFace *mf = dm->getTessFaceArray(dm) + face_index;
+ Material *ma = dm->mat[mf->mat_nr];
+ ima = ma->texpaintslot[ma->paint_active_slot].ima;
+
+ return ima;
+}
+
/* Uses symm to selectively flip any axis of a coordinate. */
void flip_v3_v3(float out[3], const float in[3], const char symm)
{
@@ -223,25 +401,123 @@ void flip_v3_v3(float out[3], const float in[3], const char symm)
}
/* used for both 3d view and image window */
-void paint_sample_color(const bContext *C, ARegion *ar, int x, int y) /* frontbuf */
+void paint_sample_color(bContext *C, ARegion *ar, int x, int y, bool texpaint_proj, bool use_palette)
{
+ Scene *scene = CTX_data_scene(C);
+ Paint *paint = BKE_paint_get_active_from_context(C);
+ Palette *palette = BKE_paint_palette(paint);
+ PaletteColor *color;
Brush *br = BKE_paint_brush(BKE_paint_get_active_from_context(C));
unsigned int col;
- const char *cp;
+ const unsigned char *cp;
CLAMP(x, 0, ar->winx);
CLAMP(y, 0, ar->winy);
- glReadBuffer(GL_FRONT);
- glReadPixels(x + ar->winrct.xmin, y + ar->winrct.ymin, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col);
- glReadBuffer(GL_BACK);
+ if (use_palette) {
+ if (!palette) {
+ palette = BKE_palette_add(CTX_data_main(C), "Palette");
+ BKE_paint_palette_set(paint, palette);
+ }
+
+ color = BKE_palette_color_add(palette);
+ }
+
+
+ if (CTX_wm_view3d(C) && texpaint_proj) {
+ /* first try getting a colour directly from the mesh faces if possible */
+ Object *ob = OBACT;
+ bool sample_success = false;
+
+ if (ob) {
+ DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
+
+ ViewContext vc;
+ const int mval[2] = {x, y};
+ unsigned int faceindex;
+ unsigned int totface = dm->getNumTessFaces(dm);
+ MTFace *dm_mtface = dm->getTessFaceDataArray(dm, CD_MTFACE);
+
+ DM_update_materials(dm, ob);
+
+ if (dm_mtface) {
+ view3d_set_viewcontext(C, &vc);
+
+ view3d_operator_needs_opengl(C);
+
+ if (imapaint_pick_face(&vc, mval, &faceindex, totface)) {
+ Image *image = imapaint_face_image(dm, faceindex);
+
+ ImBuf *ibuf = BKE_image_acquire_ibuf(image, NULL, NULL);
+ if (ibuf && ibuf->rect) {
+ float uv[2];
+ float u, v;
+ imapaint_pick_uv(scene, ob, faceindex, mval, uv);
+ sample_success = true;
+
+ u = fmodf(uv[0], 1.0f);
+ v = fmodf(uv[1], 1.0f);
+
+ if (u < 0.0f) u += 1.0f;
+ if (v < 0.0f) v += 1.0f;
+
+ u = u * ibuf->x - 0.5f;
+ v = v * ibuf->y - 0.5f;
+
+ if (ibuf->rect_float) {
+ float rgba_f[4];
+ bilinear_interpolation_color_wrap(ibuf, NULL, rgba_f, u, v);
+ straight_to_premul_v4(rgba_f);
+ if (use_palette) {
+ linearrgb_to_srgb_v3_v3(color->rgb, rgba_f);
+ }
+ else {
+ linearrgb_to_srgb_v3_v3(rgba_f, rgba_f);
+ BKE_brush_color_set(scene, br, rgba_f);
+ }
+ }
+ else {
+ unsigned char rgba[4];
+ bilinear_interpolation_color_wrap(ibuf, rgba, NULL, u, v);
+ if (use_palette) {
+ rgb_uchar_to_float(color->rgb, rgba);
+ }
+ else {
+ float rgba_f[3];
+ rgb_uchar_to_float(rgba_f, rgba);
+ BKE_brush_color_set(scene, br, rgba_f);
+ }
+ }
+ }
+
+ BKE_image_release_ibuf(image, ibuf, NULL);
+ }
+ }
+ dm->release(dm);
+ }
- cp = (char *)&col;
+ if (!sample_success) {
+ glReadBuffer(GL_FRONT);
+ glReadPixels(x + ar->winrct.xmin, y + ar->winrct.ymin, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col);
+ glReadBuffer(GL_BACK);
+ }
+ else
+ return;
+ }
+ else {
+ glReadBuffer(GL_FRONT);
+ glReadPixels(x + ar->winrct.xmin, y + ar->winrct.ymin, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col);
+ glReadBuffer(GL_BACK);
+ }
+ cp = (unsigned char *)&col;
- if (br) {
- br->rgb[0] = cp[0] / 255.0f;
- br->rgb[1] = cp[1] / 255.0f;
- br->rgb[2] = cp[2] / 255.0f;
+ if (use_palette) {
+ rgb_uchar_to_float(color->rgb, cp);
+ }
+ else {
+ float rgba_f[3];
+ rgb_uchar_to_float(rgba_f, cp);
+ BKE_brush_color_set(scene, br, rgba_f);
}
}
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index 969c5a09a82..2929a96db29 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -197,11 +197,11 @@ static int *get_indexarray(Mesh *me)
return MEM_mallocN(sizeof(int) * (me->totpoly + 1), "vertexpaint");
}
-unsigned int vpaint_get_current_col(VPaint *vp)
+unsigned int vpaint_get_current_col(Scene *scene, VPaint *vp)
{
Brush *brush = BKE_paint_brush(&vp->paint);
unsigned char col[4];
- rgb_float_to_uchar(col, brush->rgb);
+ rgb_float_to_uchar(col, BKE_brush_color_get(scene, brush));
col[3] = 255; /* alpha isn't used, could even be removed to speedup paint a little */
return *(unsigned int *)col;
}
@@ -2547,14 +2547,17 @@ static int wpaint_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
int retval;
- op->customdata = paint_stroke_new(C, NULL, wpaint_stroke_test_start,
+ op->customdata = paint_stroke_new(C, op, NULL, wpaint_stroke_test_start,
wpaint_stroke_update_step, NULL,
wpaint_stroke_done, event->type);
+ if ((retval = op->type->modal(C, op, event)) == OPERATOR_FINISHED) {
+ paint_stroke_data_free(op);
+ return OPERATOR_FINISHED;
+ }
/* add modal handler */
WM_event_add_modal_handler(C, op);
- retval = op->type->modal(C, op, event);
OPERATOR_RETVAL_CHECK(retval);
BLI_assert(retval == OPERATOR_RUNNING_MODAL);
@@ -2563,7 +2566,7 @@ static int wpaint_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static int wpaint_exec(bContext *C, wmOperator *op)
{
- op->customdata = paint_stroke_new(C, NULL, wpaint_stroke_test_start,
+ op->customdata = paint_stroke_new(C, op, NULL, wpaint_stroke_test_start,
wpaint_stroke_update_step, NULL,
wpaint_stroke_done, 0);
@@ -2778,7 +2781,8 @@ static void vpaint_build_poly_facemap(struct VPaintData *vd, Mesh *me)
static bool vpaint_stroke_test_start(bContext *C, struct wmOperator *op, const float UNUSED(mouse[2]))
{
- ToolSettings *ts = CTX_data_tool_settings(C);
+ Scene *scene = CTX_data_scene(C);
+ ToolSettings *ts = scene->toolsettings;
struct PaintStroke *stroke = op->customdata;
VPaint *vp = ts->vpaint;
Brush *brush = BKE_paint_brush(&vp->paint);
@@ -2810,7 +2814,7 @@ static bool vpaint_stroke_test_start(bContext *C, struct wmOperator *op, const f
vpd->vp_handle = ED_vpaint_proj_handle_create(vpd->vc.scene, ob, &vpd->vertexcosnos);
vpd->indexar = get_indexarray(me);
- vpd->paintcol = vpaint_get_current_col(vp);
+ vpd->paintcol = vpaint_get_current_col(scene, vp);
vpd->is_texbrush = !(brush->vertexpaint_tool == PAINT_BLEND_BLUR) &&
brush->mtex.tex;
@@ -3062,14 +3066,18 @@ static int vpaint_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
int retval;
- op->customdata = paint_stroke_new(C, NULL, vpaint_stroke_test_start,
+ op->customdata = paint_stroke_new(C, op, NULL, vpaint_stroke_test_start,
vpaint_stroke_update_step, NULL,
vpaint_stroke_done, event->type);
+ if ((retval = op->type->modal(C, op, event)) == OPERATOR_FINISHED) {
+ paint_stroke_data_free(op);
+ return OPERATOR_FINISHED;
+ }
+
/* add modal handler */
WM_event_add_modal_handler(C, op);
- retval = op->type->modal(C, op, event);
OPERATOR_RETVAL_CHECK(retval);
BLI_assert(retval == OPERATOR_RUNNING_MODAL);
@@ -3078,7 +3086,7 @@ static int vpaint_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static int vpaint_exec(bContext *C, wmOperator *op)
{
- op->customdata = paint_stroke_new(C, NULL, vpaint_stroke_test_start,
+ op->customdata = paint_stroke_new(C, op, NULL, vpaint_stroke_test_start,
vpaint_stroke_update_step, NULL,
vpaint_stroke_done, 0);
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 12223effcf5..261da79e35c 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -359,19 +359,19 @@ static int sculpt_stroke_dynamic_topology(const SculptSession *ss,
!(brush->flag & BRUSH_ANCHORED) &&
!(brush->flag & BRUSH_DRAG_DOT) &&
- (!ELEM6(brush->sculpt_tool,
- /* These brushes, as currently coded, cannot
- * support dynamic topology */
- SCULPT_TOOL_GRAB,
- SCULPT_TOOL_ROTATE,
- SCULPT_TOOL_THUMB,
- SCULPT_TOOL_LAYER,
+ (!ELEM(brush->sculpt_tool,
+ /* These brushes, as currently coded, cannot
+ * support dynamic topology */
+ SCULPT_TOOL_GRAB,
+ SCULPT_TOOL_ROTATE,
+ SCULPT_TOOL_THUMB,
+ SCULPT_TOOL_LAYER,
- /* These brushes could handle dynamic topology,
- * but user feedback indicates it's better not
- * to */
- SCULPT_TOOL_SMOOTH,
- SCULPT_TOOL_MASK)));
+ /* These brushes could handle dynamic topology,
+ * but user feedback indicates it's better not
+ * to */
+ SCULPT_TOOL_SMOOTH,
+ SCULPT_TOOL_MASK)));
}
/*** paint mesh ***/
@@ -396,7 +396,7 @@ static void paint_mesh_restore_co(Sculpt *sd, Object *ob)
* entries might be inserted by sculpt_undo_push_node() into the
* GHash used internally by BM_log_original_vert_co() by a
* different thread. [#33787] */
-#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP && !ss->bm)
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && !ss->bm && totnode > SCULPT_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
SculptUndoNode *unode;
SculptUndoType type = (brush->sculpt_tool == SCULPT_TOOL_MASK ?
@@ -663,47 +663,6 @@ static bool sculpt_brush_test_cyl(SculptBrushTest *test, float co[3], float loca
/* ===== Sculpting =====
*
*/
-
-static float overlapped_curve(Brush *br, float x)
-{
- int i;
- const int n = 100 / br->spacing;
- const float h = br->spacing / 50.0f;
- const float x0 = x - 1;
-
- float sum;
-
- sum = 0;
- for (i = 0; i < n; i++) {
- float xx;
-
- xx = fabsf(x0 + i * h);
-
- if (xx < 1.0f)
- sum += BKE_brush_curve_strength(br, xx, 1);
- }
-
- return sum;
-}
-
-static float integrate_overlap(Brush *br)
-{
- int i;
- int m = 10;
- float g = 1.0f / m;
- float max;
-
- max = 0;
- for (i = 0; i < m; i++) {
- float overlap = overlapped_curve(br, i * g);
-
- if (overlap > max)
- max = overlap;
- }
-
- return max;
-}
-
static void flip_v3(float v[3], const char symm)
{
flip_v3_v3(v, v, symm);
@@ -776,7 +735,7 @@ static float calc_symmetry_feather(Sculpt *sd, StrokeCache *cache)
/* Return modified brush strength. Includes the direction of the brush, positive
* values pull vertices, negative values push. Uses tablet pressure and a
* special multiplier found experimentally to scale the strength factor. */
-static float brush_strength(Sculpt *sd, StrokeCache *cache, float feather)
+static float brush_strength(Sculpt *sd, StrokeCache *cache, float feather, UnifiedPaintSettings *ups)
{
const Scene *scene = cache->vc->scene;
Brush *brush = BKE_paint_brush(&sd->paint);
@@ -788,13 +747,10 @@ static float brush_strength(Sculpt *sd, StrokeCache *cache, float feather)
float pressure = BKE_brush_use_alpha_pressure(scene, brush) ? cache->pressure : 1;
float pen_flip = cache->pen_flip ? -1 : 1;
float invert = cache->invert ? -1 : 1;
- float accum = integrate_overlap(brush);
+ float overlap = ups->overlap_factor;
/* spacing is integer percentage of radius, divide by 50 to get
* normalized diameter */
- float overlap = (brush->flag & BRUSH_SPACE_ATTEN &&
- brush->flag & BRUSH_SPACE &&
- !(brush->flag & BRUSH_ANCHORED) &&
- (brush->spacing < 100)) ? 1.0f / accum : 1;
+
float flip = dir * invert * pen_flip;
switch (brush->sculpt_tool) {
@@ -1040,7 +996,7 @@ static void calc_area_normal(Sculpt *sd, Object *ob, float an[3], PBVHNode **nod
zero_v3(an);
-#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
PBVHVertexIter vd;
SculptBrushTest test;
@@ -1236,14 +1192,14 @@ static int brush_needs_sculpt_normal(const Brush *brush)
SCULPT_TOOL_SNAKE_HOOK) &&
(brush->normal_weight > 0)) ||
- ELEM7(brush->sculpt_tool,
- SCULPT_TOOL_BLOB,
- SCULPT_TOOL_CREASE,
- SCULPT_TOOL_DRAW,
- SCULPT_TOOL_LAYER,
- SCULPT_TOOL_NUDGE,
- SCULPT_TOOL_ROTATE,
- SCULPT_TOOL_THUMB) ||
+ ELEM(brush->sculpt_tool,
+ SCULPT_TOOL_BLOB,
+ SCULPT_TOOL_CREASE,
+ SCULPT_TOOL_DRAW,
+ SCULPT_TOOL_LAYER,
+ SCULPT_TOOL_NUDGE,
+ SCULPT_TOOL_ROTATE,
+ SCULPT_TOOL_THUMB) ||
(brush->mtex.brush_map_mode == MTEX_MAP_MODE_AREA));
}
@@ -1646,7 +1602,7 @@ static void smooth(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode,
for (iteration = 0; iteration <= count; ++iteration) {
float strength = (iteration != count) ? 1.0f : last;
-#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
switch (type) {
case PBVH_GRIDS:
@@ -1682,7 +1638,7 @@ static void do_mask_brush_draw(Sculpt *sd, Object *ob, PBVHNode **nodes, int tot
int n;
/* threaded loop over nodes */
-#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
PBVHVertexIter vd;
SculptBrushTest test;
@@ -1735,7 +1691,7 @@ static void do_draw_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
mul_v3_fl(offset, bstrength);
/* threaded loop over nodes */
-#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
PBVHVertexIter vd;
SculptBrushTest test;
@@ -1790,7 +1746,7 @@ static void do_crease_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod
if (brush->sculpt_tool == SCULPT_TOOL_BLOB) flippedbstrength *= -1.0f;
/* threaded loop over nodes */
-#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
PBVHVertexIter vd;
SculptBrushTest test;
@@ -1833,7 +1789,7 @@ static void do_pinch_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
float bstrength = ss->cache->bstrength;
int n;
-#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
PBVHVertexIter vd;
SculptBrushTest test;
@@ -1880,7 +1836,7 @@ static void do_grab_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
add_v3_v3(grab_delta, ss->cache->sculpt_normal_symm);
}
-#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
PBVHVertexIter vd;
SculptBrushTest test;
@@ -1928,7 +1884,7 @@ static void do_nudge_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
cross_v3_v3v3(tmp, ss->cache->sculpt_normal_symm, grab_delta);
cross_v3_v3v3(cono, tmp, ss->cache->sculpt_normal_symm);
-#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
PBVHVertexIter vd;
SculptBrushTest test;
@@ -1976,7 +1932,7 @@ static void do_snake_hook_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int to
add_v3_v3(grab_delta, ss->cache->sculpt_normal_symm);
}
-#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
PBVHVertexIter vd;
SculptBrushTest test;
@@ -2016,7 +1972,7 @@ static void do_thumb_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
cross_v3_v3v3(tmp, ss->cache->sculpt_normal_symm, grab_delta);
cross_v3_v3v3(cono, tmp, ss->cache->sculpt_normal_symm);
-#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
PBVHVertexIter vd;
SculptBrushTest test;
@@ -2059,7 +2015,7 @@ static void do_rotate_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod
static const int flip[8] = { 1, -1, -1, 1, -1, 1, 1, -1 };
float angle = ss->cache->vertex_rotation * flip[ss->cache->mirror_symmetry_pass];
-#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
PBVHVertexIter vd;
SculptBrushTest test;
@@ -2112,7 +2068,7 @@ static void do_layer_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
mul_v3_v3v3(offset, ss->cache->scale, ss->cache->sculpt_normal_symm);
-#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
PBVHVertexIter vd;
SculptBrushTest test;
@@ -2175,7 +2131,7 @@ static void do_inflate_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno
float bstrength = ss->cache->bstrength;
int n;
-#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
PBVHVertexIter vd;
SculptBrushTest test;
@@ -2220,7 +2176,7 @@ static void calc_flatten_center(Sculpt *sd, Object *ob, PBVHNode **nodes, int to
zero_v3(fc);
-#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
PBVHVertexIter vd;
SculptBrushTest test;
@@ -2327,7 +2283,7 @@ static void calc_area_normal_and_flatten_center(Sculpt *sd, Object *ob,
/* for flatten center */
zero_v3(fc);
-#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
PBVHVertexIter vd;
SculptBrushTest test;
@@ -2579,7 +2535,7 @@ static void do_flatten_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno
mul_v3_fl(temp, displace);
add_v3_v3(fc, temp);
-#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
PBVHVertexIter vd;
SculptBrushTest test;
@@ -2651,7 +2607,7 @@ static void do_clay_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
/* add_v3_v3v3(p, ss->cache->location, an); */
-#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
PBVHVertexIter vd;
SculptBrushTest test;
@@ -2752,7 +2708,7 @@ static void do_clay_strips_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int t
mul_m4_m4m4(tmat, mat, scale);
invert_m4_m4(mat, tmat);
-#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
PBVHVertexIter vd;
SculptBrushTest test;
@@ -2816,7 +2772,7 @@ static void do_fill_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
mul_v3_fl(temp, displace);
add_v3_v3(fc, temp);
-#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
PBVHVertexIter vd;
SculptBrushTest test;
@@ -2880,7 +2836,7 @@ static void do_scrape_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod
mul_v3_fl(temp, displace);
add_v3_v3(fc, temp);
-#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
PBVHVertexIter vd;
SculptBrushTest test;
@@ -2934,7 +2890,7 @@ static void do_gravity(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, fl
mul_v3_fl(offset, bstrength);
/* threaded loop over nodes */
-#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
PBVHVertexIter vd;
SculptBrushTest test;
@@ -3030,11 +2986,11 @@ static void sculpt_topology_update(Sculpt *sd, Object *ob, Brush *brush)
radius = ss->cache->radius * 1.25f;
data.radius_squared = radius * radius;
- data.original = ELEM4(brush->sculpt_tool,
- SCULPT_TOOL_GRAB,
- SCULPT_TOOL_ROTATE,
- SCULPT_TOOL_THUMB,
- SCULPT_TOOL_LAYER) ? true : ss->cache->original;
+ data.original = ELEM(brush->sculpt_tool,
+ SCULPT_TOOL_GRAB,
+ SCULPT_TOOL_ROTATE,
+ SCULPT_TOOL_THUMB,
+ SCULPT_TOOL_LAYER) ? true : ss->cache->original;
BKE_pbvh_search_gather(ss->pbvh, sculpt_search_sphere_cb, &data, &nodes, &totnode);
@@ -3092,18 +3048,18 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush)
data.ss = ss;
data.sd = sd;
data.radius_squared = ss->cache->radius_squared;
- data.original = ELEM4(brush->sculpt_tool,
- SCULPT_TOOL_GRAB,
- SCULPT_TOOL_ROTATE,
- SCULPT_TOOL_THUMB,
- SCULPT_TOOL_LAYER) ? true : ss->cache->original;
+ data.original = ELEM(brush->sculpt_tool,
+ SCULPT_TOOL_GRAB,
+ SCULPT_TOOL_ROTATE,
+ SCULPT_TOOL_THUMB,
+ SCULPT_TOOL_LAYER) ? true : ss->cache->original;
BKE_pbvh_search_gather(ss->pbvh, sculpt_search_sphere_cb, &data, &nodes, &totnode);
/* Only act if some verts are inside the brush area */
if (totnode) {
float location[3];
-#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
sculpt_undo_push_node(ob, nodes[n],
brush->sculpt_tool == SCULPT_TOOL_MASK ?
@@ -3233,10 +3189,10 @@ static void sculpt_combine_proxies(Sculpt *sd, Object *ob)
ss->cache->supports_gravity)
{
/* these brushes start from original coordinates */
- const bool use_orco = ELEM3(brush->sculpt_tool, SCULPT_TOOL_GRAB,
- SCULPT_TOOL_ROTATE, SCULPT_TOOL_THUMB);
+ const bool use_orco = ELEM(brush->sculpt_tool, SCULPT_TOOL_GRAB,
+ SCULPT_TOOL_ROTATE, SCULPT_TOOL_THUMB);
-#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
PBVHVertexIter vd;
PBVHProxyNode *proxies;
@@ -3329,7 +3285,7 @@ static void sculpt_flush_stroke_deform(Sculpt *sd, Object *ob)
BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
-#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (n = 0; n < totnode; n++) {
PBVHVertexIter vd;
@@ -3377,7 +3333,7 @@ static void calc_brushdata_symm(Sculpt *sd, StrokeCache *cache, const char symm,
/* XXX This reduces the length of the grab delta if it approaches the line of symmetry
* XXX However, a different approach appears to be needed */
#if 0
- if (sd->flags & SCULPT_SYMMETRY_FEATHER) {
+ if (sd->paint.symmetry_flags & SCULPT_SYMMETRY_FEATHER) {
float frac = 1.0f / max_overlap_count(sd);
float reduce = (feather - frac) / (1 - frac);
@@ -3437,7 +3393,7 @@ static void sculpt_fix_noise_tear(Sculpt *sd, Object *ob)
}
static void do_symmetrical_brush_actions(Sculpt *sd, Object *ob,
- BrushActionFunc action)
+ BrushActionFunc action, UnifiedPaintSettings *ups)
{
Brush *brush = BKE_paint_brush(&sd->paint);
SculptSession *ss = ob->sculpt;
@@ -3447,7 +3403,7 @@ static void do_symmetrical_brush_actions(Sculpt *sd, Object *ob,
float feather = calc_symmetry_feather(sd, ss->cache);
- cache->bstrength = brush_strength(sd, cache, feather);
+ cache->bstrength = brush_strength(sd, cache, feather, ups);
cache->symmetry = symm;
/* symm is a bit combination of XYZ - 1 is mirror X; 2 is Y; 3 is XY; 4 is Z; 5 is XZ; 6 is YZ; 7 is XYZ */
@@ -3733,8 +3689,8 @@ static void sculpt_update_cache_invariants(bContext *C, Sculpt *sd, SculptSessio
/* not very nice, but with current events system implementation
* we can't handle brush appearance inversion hotkey separately (sergey) */
- if (cache->invert) brush->flag |= BRUSH_INVERTED;
- else brush->flag &= ~BRUSH_INVERTED;
+ if (cache->invert) ups->draw_inverted = true;
+ else ups->draw_inverted = false;
/* Alt-Smooth */
if (cache->alt_smooth) {
@@ -3780,7 +3736,7 @@ static void sculpt_update_cache_invariants(bContext *C, Sculpt *sd, SculptSessio
mul_m3_v3(mat, viewDir);
normalize_v3_v3(cache->true_view_normal, viewDir);
- cache->supports_gravity = (!ELEM3(brush->sculpt_tool, SCULPT_TOOL_MASK, SCULPT_TOOL_SMOOTH, SCULPT_TOOL_SIMPLIFY) &&
+ cache->supports_gravity = (!ELEM(brush->sculpt_tool, SCULPT_TOOL_MASK, SCULPT_TOOL_SMOOTH, SCULPT_TOOL_SIMPLIFY) &&
(sd->gravity_factor > 0.0f));
/* get gravity vector in world space */
if (cache->supports_gravity) {
@@ -3838,10 +3794,10 @@ static void sculpt_update_cache_invariants(bContext *C, Sculpt *sd, SculptSessio
cache->original = 1;
}
- if (ELEM9(brush->sculpt_tool,
- SCULPT_TOOL_DRAW, SCULPT_TOOL_CREASE, SCULPT_TOOL_BLOB,
- SCULPT_TOOL_LAYER, SCULPT_TOOL_INFLATE, SCULPT_TOOL_CLAY,
- SCULPT_TOOL_CLAY_STRIPS, SCULPT_TOOL_ROTATE, SCULPT_TOOL_FLATTEN))
+ if (ELEM(brush->sculpt_tool,
+ SCULPT_TOOL_DRAW, SCULPT_TOOL_CREASE, SCULPT_TOOL_BLOB,
+ SCULPT_TOOL_LAYER, SCULPT_TOOL_INFLATE, SCULPT_TOOL_CLAY,
+ SCULPT_TOOL_CLAY_STRIPS, SCULPT_TOOL_ROTATE, SCULPT_TOOL_FLATTEN))
{
if (!(brush->flag & BRUSH_ACCUMULATE)) {
cache->original = 1;
@@ -3868,10 +3824,10 @@ static void sculpt_update_brush_delta(UnifiedPaintSettings *ups, Object *ob, Bru
};
int tool = brush->sculpt_tool;
- if (ELEM5(tool,
- SCULPT_TOOL_GRAB, SCULPT_TOOL_NUDGE,
- SCULPT_TOOL_CLAY_STRIPS, SCULPT_TOOL_SNAKE_HOOK,
- SCULPT_TOOL_THUMB))
+ if (ELEM(tool,
+ SCULPT_TOOL_GRAB, SCULPT_TOOL_NUDGE,
+ SCULPT_TOOL_CLAY_STRIPS, SCULPT_TOOL_SNAKE_HOOK,
+ SCULPT_TOOL_THUMB))
{
float grab_location[3], imat[4][4], delta[3], loc[3];
@@ -3992,16 +3948,9 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob,
cache->radius_squared = cache->radius * cache->radius;
if (brush->flag & BRUSH_ANCHORED) {
+ /* true location has been calculated as part of the stroke system already here */
if (brush->flag & BRUSH_EDGE_TO_EDGE) {
- float halfway[2];
- float out[3];
- halfway[0] = 0.5f * (cache->mouse[0] + cache->initial_mouse[0]);
- halfway[1] = 0.5f * (cache->mouse[1] + cache->initial_mouse[1]);
-
- if (sculpt_stroke_get_location(C, out, halfway)) {
- copy_v3_v3(cache->anchored_location, out);
- copy_v3_v3(cache->true_location, cache->anchored_location);
- }
+ RNA_float_get_array(ptr, "location", cache->true_location);
}
cache->radius = paint_calc_object_space_radius(cache->vc,
@@ -4393,10 +4342,10 @@ static void sculpt_stroke_update_step(bContext *C, struct PaintStroke *UNUSED(st
}
if (sculpt_stroke_dynamic_topology(ss, brush)) {
- do_symmetrical_brush_actions(sd, ob, sculpt_topology_update);
+ do_symmetrical_brush_actions(sd, ob, sculpt_topology_update, ups);
}
- do_symmetrical_brush_actions(sd, ob, do_brush_action);
+ do_symmetrical_brush_actions(sd, ob, do_brush_action, ups);
sculpt_combine_proxies(sd, ob);
@@ -4446,8 +4395,9 @@ static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(str
/* Finished */
if (ss->cache) {
+ UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings;
Brush *brush = BKE_paint_brush(&sd->paint);
- brush->flag &= ~BRUSH_INVERTED;
+ ups->draw_inverted = false;
sculpt_stroke_modifiers_check(C, ob);
@@ -4506,7 +4456,7 @@ static int sculpt_brush_stroke_invoke(bContext *C, wmOperator *op, const wmEvent
if (!sculpt_brush_stroke_init(C, op))
return OPERATOR_CANCELLED;
- stroke = paint_stroke_new(C, sculpt_stroke_get_location,
+ stroke = paint_stroke_new(C, op, sculpt_stroke_get_location,
sculpt_stroke_test_start,
sculpt_stroke_update_step, NULL,
sculpt_stroke_done, event->type);
@@ -4521,10 +4471,13 @@ static int sculpt_brush_stroke_invoke(bContext *C, wmOperator *op, const wmEvent
return OPERATOR_PASS_THROUGH;
}
+ if ((retval = op->type->modal(C, op, event)) == OPERATOR_FINISHED) {
+ paint_stroke_data_free(op);
+ return OPERATOR_FINISHED;
+ }
/* add modal handler */
WM_event_add_modal_handler(C, op);
- retval = op->type->modal(C, op, event);
OPERATOR_RETVAL_CHECK(retval);
BLI_assert(retval == OPERATOR_RUNNING_MODAL);
@@ -4536,7 +4489,7 @@ static int sculpt_brush_stroke_exec(bContext *C, wmOperator *op)
if (!sculpt_brush_stroke_init(C, op))
return OPERATOR_CANCELLED;
- op->customdata = paint_stroke_new(C, sculpt_stroke_get_location, sculpt_stroke_test_start,
+ op->customdata = paint_stroke_new(C, op, sculpt_stroke_get_location, sculpt_stroke_test_start,
sculpt_stroke_update_step, NULL, sculpt_stroke_done, 0);
/* frees op->customdata */
@@ -4856,7 +4809,7 @@ static int sculpt_dynamic_topology_toggle_invoke(bContext *C, wmOperator *op, co
bool modifiers = false;
for (i = 0; i < CD_NUMTYPES; i++) {
- if (!ELEM7(i, CD_MVERT, CD_MEDGE, CD_MFACE, CD_MLOOP, CD_MPOLY, CD_PAINT_MASK, CD_ORIGINDEX) &&
+ if (!ELEM(i, CD_MVERT, CD_MEDGE, CD_MFACE, CD_MLOOP, CD_MPOLY, CD_PAINT_MASK, CD_ORIGINDEX) &&
(CustomData_has_layer(&me->vdata, i) ||
CustomData_has_layer(&me->edata, i) ||
CustomData_has_layer(&me->fdata, i)))
@@ -5062,11 +5015,11 @@ static int sculpt_mode_toggle_exec(bContext *C, wmOperator *op)
ts->sculpt->paint.flags |= PAINT_SHOW_BRUSH;
/* Make sure at least dyntopo subdivision is enabled */
- ts->sculpt->flags |= SCULPT_DYNTOPO_SUBDIVIDE;
+ ts->sculpt->flags |= SCULPT_DYNTOPO_SUBDIVIDE | SCULPT_DYNTOPO_COLLAPSE;
}
if (!ts->sculpt->detail_size) {
- ts->sculpt->detail_size = 30;
+ ts->sculpt->detail_size = 12;
}
if (ts->sculpt->constant_detail == 0.0f)
diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h
index cd79f525d82..a61f571fdf6 100644
--- a/source/blender/editors/sculpt_paint/sculpt_intern.h
+++ b/source/blender/editors/sculpt_paint/sculpt_intern.h
@@ -130,4 +130,11 @@ void sculpt_vertcos_to_key(Object *ob, KeyBlock *kb, float (*vertCos)[3]);
void sculpt_update_object_bounding_box(struct Object *ob);
+/* Setting zero so we can catch bugs in OpenMP/sculpt. */
+#ifdef DEBUG
+# define SCULPT_OMP_LIMIT 0
+#else
+# define SCULPT_OMP_LIMIT 4
+#endif
+
#endif
diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c
index 0d49049c78e..91f80a4fc40 100644
--- a/source/blender/editors/sculpt_paint/sculpt_undo.c
+++ b/source/blender/editors/sculpt_paint/sculpt_undo.c
@@ -291,7 +291,7 @@ static void sculpt_undo_bmesh_restore_generic(bContext *C,
BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
-#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP)
+#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (i = 0; i < totnode; i++) {
BKE_pbvh_node_mark_redraw(nodes[i]);
}
@@ -543,7 +543,7 @@ static void sculpt_undo_free(ListBase *lb)
}
}
-bool sculpt_undo_cleanup(bContext *C, ListBase *lb)
+static bool sculpt_undo_cleanup(bContext *C, ListBase *lb)
{
Object *ob = CTX_data_active_object(C);
SculptUndoNode *unode;
@@ -551,10 +551,8 @@ bool sculpt_undo_cleanup(bContext *C, ListBase *lb)
unode = lb->first;
if (unode && strcmp(unode->idname, ob->id.name) != 0) {
- for (unode = lb->first; unode; unode = unode->next) {
- if (unode->bm_entry)
- BM_log_cleanup_entry(unode->bm_entry);
- }
+ if (unode->bm_entry)
+ BM_log_cleanup_entry(unode->bm_entry);
return true;
}
@@ -881,7 +879,7 @@ SculptUndoNode *sculpt_undo_push_node(Object *ob, PBVHNode *node,
void sculpt_undo_push_begin(const char *name)
{
ED_undo_paint_push_begin(UNDO_PAINT_MESH, name,
- sculpt_undo_restore, sculpt_undo_free);
+ sculpt_undo_restore, sculpt_undo_free, sculpt_undo_cleanup);
}
void sculpt_undo_push_end(void)
diff --git a/source/blender/editors/sculpt_paint/sculpt_uv.c b/source/blender/editors/sculpt_paint/sculpt_uv.c
index 797a881ce79..292d6236bab 100644
--- a/source/blender/editors/sculpt_paint/sculpt_uv.c
+++ b/source/blender/editors/sculpt_paint/sculpt_uv.c
@@ -239,12 +239,14 @@ void ED_space_image_uv_sculpt_update(wmWindowManager *wm, ToolSettings *settings
BKE_paint_init(&settings->uvsculpt->paint, PAINT_CURSOR_SCULPT);
- WM_paint_cursor_activate(wm, uv_sculpt_brush_poll,
- brush_drawcursor_uvsculpt, NULL);
+ settings->uvsculpt->paint.paint_cursor = WM_paint_cursor_activate(wm, uv_sculpt_brush_poll,
+ brush_drawcursor_uvsculpt, NULL);
}
else {
- if (settings->uvsculpt)
- settings->uvsculpt->paint.flags &= ~PAINT_SHOW_BRUSH;
+ if (settings->uvsculpt) {
+ WM_paint_cursor_end(wm, settings->uvsculpt->paint.paint_cursor);
+ settings->uvsculpt->paint.paint_cursor = NULL;
+ }
}
}
diff --git a/source/blender/editors/space_action/action_draw.c b/source/blender/editors/space_action/action_draw.c
index b2e55085579..335949e8495 100644
--- a/source/blender/editors/space_action/action_draw.c
+++ b/source/blender/editors/space_action/action_draw.c
@@ -219,7 +219,7 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
if (acf->has_setting(ac, ale, ACHANNEL_SETTING_SELECT))
sel = ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_SELECT);
- if (ELEM3(ac->datatype, ANIMCONT_ACTION, ANIMCONT_DOPESHEET, ANIMCONT_SHAPEKEY)) {
+ if (ELEM(ac->datatype, ANIMCONT_ACTION, ANIMCONT_DOPESHEET, ANIMCONT_SHAPEKEY)) {
switch (ale->type) {
case ANIMTYPE_SUMMARY:
{
diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c
index cf18cffefb6..ddfca98a119 100644
--- a/source/blender/editors/space_action/action_select.c
+++ b/source/blender/editors/space_action/action_select.c
@@ -1086,8 +1086,9 @@ static void mouse_action_keys(bAnimContext *ac, const int mval[2], short select_
View2D *v2d = &ac->ar->v2d;
bDopeSheet *ads = NULL;
int channel_index;
- short found = 0;
- float selx = 0.0f;
+ bool found = false;
+ float frame = 0.0f; /* frame of keyframe under mouse - NLA corrections not applied/included */
+ float selx = 0.0f; /* frame of keyframe under mouse */
float x, y;
rctf rectf;
@@ -1179,7 +1180,8 @@ static void mouse_action_keys(bAnimContext *ac, const int mval[2], short select_
* requiring to map each frame once again...
*/
selx = BKE_nla_tweakedit_remap(adt, ak->cfra, NLATIME_CONVERT_UNMAP);
- found = 1;
+ frame = ak->cfra;
+ found = true;
break;
}
else if (ak->cfra < rectf.xmin)
@@ -1258,8 +1260,11 @@ static void mouse_action_keys(bAnimContext *ac, const int mval[2], short select_
if (found) {
/* apply selection to keyframes */
if (column) {
- /* select all keyframes in the same frame as the one we hit on the active channel */
- actkeys_mselect_column(ac, select_mode, selx);
+ /* select all keyframes in the same frame as the one we hit on the active channel
+ * [T41077]: "frame" not "selx" here (i.e. no NLA corrections yet) as the code here
+ * does that itself again as it needs to work on multiple datablocks
+ */
+ actkeys_mselect_column(ac, select_mode, frame);
}
else if (same_channel) {
/* select all keyframes in the active channel */
diff --git a/source/blender/editors/space_api/spacetypes.c b/source/blender/editors/space_api/spacetypes.c
index 7a74a58c69d..b171e7a5f88 100644
--- a/source/blender/editors/space_api/spacetypes.c
+++ b/source/blender/editors/space_api/spacetypes.c
@@ -144,6 +144,7 @@ void ED_spacetypes_init(void)
ED_operatormacros_curve();
ED_operatormacros_mask();
ED_operatormacros_sequencer();
+ ED_operatormacros_paint();
/* register dropboxes (can use macros) */
spacetypes = BKE_spacetypes_list();
diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c
index 8917704b731..524a42ba388 100644
--- a/source/blender/editors/space_buttons/buttons_context.c
+++ b/source/blender/editors/space_buttons/buttons_context.c
@@ -200,7 +200,7 @@ static int buttons_context_path_data(ButsContextPath *path, int type)
/* if we already have a data, we're done */
if (RNA_struct_is_a(ptr->type, &RNA_Mesh) && (type == -1 || type == OB_MESH)) return 1;
- else if (RNA_struct_is_a(ptr->type, &RNA_Curve) && (type == -1 || ELEM3(type, OB_CURVE, OB_SURF, OB_FONT))) return 1;
+ else if (RNA_struct_is_a(ptr->type, &RNA_Curve) && (type == -1 || ELEM(type, OB_CURVE, OB_SURF, OB_FONT))) return 1;
else if (RNA_struct_is_a(ptr->type, &RNA_Armature) && (type == -1 || type == OB_ARMATURE)) return 1;
else if (RNA_struct_is_a(ptr->type, &RNA_MetaBall) && (type == -1 || type == OB_MBALL)) return 1;
else if (RNA_struct_is_a(ptr->type, &RNA_Lattice) && (type == -1 || type == OB_LATTICE)) return 1;
@@ -230,7 +230,7 @@ static int buttons_context_path_modifier(ButsContextPath *path)
if (buttons_context_path_object(path)) {
ob = path->ptr[path->len - 1].data;
- if (ob && ELEM5(ob->type, OB_MESH, OB_CURVE, OB_FONT, OB_SURF, OB_LATTICE))
+ if (ob && ELEM(ob->type, OB_MESH, OB_CURVE, OB_FONT, OB_SURF, OB_LATTICE))
return 1;
}
@@ -638,7 +638,7 @@ static int buttons_shading_context(const bContext *C, int mainb)
{
Object *ob = CTX_data_active_object(C);
- if (ELEM3(mainb, BCONTEXT_MATERIAL, BCONTEXT_WORLD, BCONTEXT_TEXTURE))
+ if (ELEM(mainb, BCONTEXT_MATERIAL, BCONTEXT_WORLD, BCONTEXT_TEXTURE))
return 1;
if (mainb == BCONTEXT_DATA && ob && ELEM(ob->type, OB_LAMP, OB_CAMERA))
return 1;
@@ -1120,7 +1120,7 @@ void buttons_context_draw(const bContext *C, uiLayout *layout)
name = RNA_struct_name_get_alloc(ptr, namebuf, sizeof(namebuf), NULL);
if (name) {
- if (!ELEM3(sbuts->mainb, BCONTEXT_RENDER, BCONTEXT_SCENE, BCONTEXT_RENDER_LAYER) && ptr->type == &RNA_Scene)
+ if (!ELEM(sbuts->mainb, BCONTEXT_RENDER, BCONTEXT_SCENE, BCONTEXT_RENDER_LAYER) && ptr->type == &RNA_Scene)
uiItemLDrag(row, ptr, "", icon); /* save some space */
else
uiItemLDrag(row, ptr, name, icon);
diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c
index 1c3bad9757d..8c6bf67c9a8 100644
--- a/source/blender/editors/space_buttons/space_buttons.c
+++ b/source/blender/editors/space_buttons/space_buttons.c
@@ -358,7 +358,7 @@ static void buttons_area_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *
case NC_ANIMATION:
switch (wmn->data) {
case ND_KEYFRAME:
- if (ELEM3(wmn->action, NA_EDITED, NA_ADDED, NA_REMOVED))
+ if (ELEM(wmn->action, NA_EDITED, NA_ADDED, NA_REMOVED))
ED_area_tag_redraw(sa);
break;
}
diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c
index 9a939bdc2ca..b5c08e7a08a 100644
--- a/source/blender/editors/space_clip/clip_draw.c
+++ b/source/blender/editors/space_clip/clip_draw.c
@@ -1728,7 +1728,7 @@ void clip_draw_main(const bContext *C, SpaceClip *sc, ARegion *ar)
smat[1][1] = 1.0f / height;
invert_m4_m4(ismat, smat);
- mul_serie_m4(sc->unistabmat, smat, sc->stabmat, ismat, NULL, NULL, NULL, NULL, NULL);
+ mul_m4_series(sc->unistabmat, smat, sc->stabmat, ismat);
}
}
else if ((sc->flag & SC_MUTE_FOOTAGE) == 0) {
diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c
index d3be25050c8..a6fbb0c399d 100644
--- a/source/blender/editors/space_clip/space_clip.c
+++ b/source/blender/editors/space_clip/space_clip.c
@@ -846,7 +846,7 @@ static int clip_context(const bContext *C, const char *member, bContextDataResul
static int clip_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
{
if (drag->type == WM_DRAG_PATH)
- if (ELEM4(drag->icon, 0, ICON_FILE_IMAGE, ICON_FILE_MOVIE, ICON_FILE_BLANK)) /* rule might not work? */
+ if (ELEM(drag->icon, 0, ICON_FILE_IMAGE, ICON_FILE_MOVIE, ICON_FILE_BLANK)) /* rule might not work? */
return true;
return false;
diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c
index ce14471f608..abbffcd8546 100644
--- a/source/blender/editors/space_clip/tracking_ops.c
+++ b/source/blender/editors/space_clip/tracking_ops.c
@@ -2277,7 +2277,7 @@ static void set_axis(Scene *scene, Object *ob, MovieClip *clip, MovieTrackingOb
copy_v3_v3(lmat[3], obmat[3]);
invert_m4_m4(ilmat, lmat);
- mul_serie_m4(mat, lmat, mat, ilmat, obmat, NULL, NULL, NULL, NULL);
+ mul_m4_series(mat, lmat, mat, ilmat, obmat);
}
else {
mul_m4_m4m4(mat, obmat, mat);
@@ -2996,7 +2996,7 @@ void CLIP_OT_detect_features(wmOperatorType *ot)
/* properties */
RNA_def_enum(ot->srna, "placement", placement_items, 0, "Placement", "Placement for detected features");
RNA_def_int(ot->srna, "margin", 16, 0, INT_MAX, "Margin", "Only features further than margin pixels from the image edges are considered", 0, 300);
- RNA_def_float(ot->srna, "threshold", 1.0f, 0.0001f, FLT_MAX, "Threshold", "Threshold level to consider feature good enough for tracking", 0.0001f, FLT_MAX);
+ RNA_def_float(ot->srna, "threshold", 0.5f, 0.0001f, FLT_MAX, "Threshold", "Threshold level to consider feature good enough for tracking", 0.0001f, FLT_MAX);
RNA_def_int(ot->srna, "min_distance", 120, 0, INT_MAX, "Distance", "Minimal distance accepted between two features", 0, 300);
}
diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c
index 3a493c0338c..d5be04cff20 100644
--- a/source/blender/editors/space_file/space_file.c
+++ b/source/blender/editors/space_file/space_file.c
@@ -422,7 +422,7 @@ static void file_keymap(struct wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "FILE_OT_select", LEFTMOUSE, KM_CLICK, 0, 0);
kmi = WM_keymap_add_item(keymap, "FILE_OT_select", LEFTMOUSE, KM_CLICK, KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "extend", true);
- kmi = WM_keymap_add_item(keymap, "FILE_OT_select", LEFTMOUSE, KM_CLICK, KM_ALT, 0);
+ kmi = WM_keymap_add_item(keymap, "FILE_OT_select", LEFTMOUSE, KM_CLICK, KM_CTRL | KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "extend", true);
RNA_boolean_set(kmi->ptr, "fill", true);
diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c
index 1f1aac8c456..c8298927f7d 100644
--- a/source/blender/editors/space_graph/graph_edit.c
+++ b/source/blender/editors/space_graph/graph_edit.c
@@ -1707,7 +1707,7 @@ static int graphkeys_euler_filter_exec(bContext *C, wmOperator *op)
*/
if (strstr(fcu->rna_path, "rotation_euler") == NULL)
continue;
- else if (ELEM3(fcu->array_index, 0, 1, 2) == 0) {
+ else if (ELEM(fcu->array_index, 0, 1, 2) == 0) {
BKE_reportf(op->reports, RPT_WARNING,
"Euler Rotation F-Curve has invalid index (ID='%s', Path='%s', Index=%d)",
(ale->id) ? ale->id->name : TIP_("<No ID>"), fcu->rna_path, fcu->array_index);
@@ -1750,7 +1750,7 @@ static int graphkeys_euler_filter_exec(bContext *C, wmOperator *op)
/* sanity check: ensure that there are enough F-Curves to work on in this group */
/* TODO: also enforce assumption that there be a full set of keyframes at each position by ensuring that totvert counts are same? */
- if (ELEM3(NULL, euf->fcurves[0], euf->fcurves[1], euf->fcurves[2])) {
+ if (ELEM(NULL, euf->fcurves[0], euf->fcurves[1], euf->fcurves[2])) {
/* report which components are missing */
BKE_reportf(op->reports, RPT_WARNING,
"Missing %s%s%s component(s) of euler rotation for ID='%s' and RNA-Path='%s'",
diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c
index 3675282654f..7e90008d8d2 100644
--- a/source/blender/editors/space_image/image_buttons.c
+++ b/source/blender/editors/space_image/image_buttons.c
@@ -843,14 +843,14 @@ void uiTemplateImageSettings(uiLayout *layout, PointerRNA *imfptr, int color_man
uiItemR(sub, imfptr, "color_mode", UI_ITEM_R_EXPAND, IFACE_("Color"), ICON_NONE);
/* only display depth setting if multiple depths can be used */
- if ((ELEM7(depth_ok,
- R_IMF_CHAN_DEPTH_1,
- R_IMF_CHAN_DEPTH_8,
- R_IMF_CHAN_DEPTH_10,
- R_IMF_CHAN_DEPTH_12,
- R_IMF_CHAN_DEPTH_16,
- R_IMF_CHAN_DEPTH_24,
- R_IMF_CHAN_DEPTH_32)) == 0)
+ if ((ELEM(depth_ok,
+ R_IMF_CHAN_DEPTH_1,
+ R_IMF_CHAN_DEPTH_8,
+ R_IMF_CHAN_DEPTH_10,
+ R_IMF_CHAN_DEPTH_12,
+ R_IMF_CHAN_DEPTH_16,
+ R_IMF_CHAN_DEPTH_24,
+ R_IMF_CHAN_DEPTH_32)) == 0)
{
row = uiLayoutRow(col, false);
diff --git a/source/blender/editors/space_image/image_edit.c b/source/blender/editors/space_image/image_edit.c
index a2f7d9e7d6c..24b1c54dd9f 100644
--- a/source/blender/editors/space_image/image_edit.c
+++ b/source/blender/editors/space_image/image_edit.c
@@ -28,6 +28,7 @@
* \ingroup spimage
*/
+#include "DNA_brush_types.h"
#include "DNA_mask_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
@@ -297,44 +298,51 @@ bool ED_space_image_show_render(SpaceImage *sima)
bool ED_space_image_show_paint(SpaceImage *sima)
{
if (ED_space_image_show_render(sima))
- return 0;
+ return false;
return (sima->mode == SI_MODE_PAINT);
}
+bool ED_space_image_show_texpaint(SpaceImage *sima, Object *ob)
+{
+ return (ob && ob->type == OB_MESH &&
+ ob->mode == OB_MODE_TEXTURE_PAINT &&
+ !(sima->flag & SI_NO_DRAW_TEXPAINT));
+}
+
bool ED_space_image_show_uvedit(SpaceImage *sima, Object *obedit)
{
if (sima && (ED_space_image_show_render(sima) || ED_space_image_show_paint(sima)))
- return 0;
+ return false;
if (obedit && obedit->type == OB_MESH) {
struct BMEditMesh *em = BKE_editmesh_from_object(obedit);
- int ret;
+ bool ret;
ret = EDBM_mtexpoly_check(em);
return ret;
}
- return 0;
+ return false;
}
bool ED_space_image_show_uvshadow(SpaceImage *sima, Object *obedit)
{
if (ED_space_image_show_render(sima))
- return 0;
+ return false;
if (ED_space_image_show_paint(sima))
if (obedit && obedit->type == OB_MESH) {
struct BMEditMesh *em = BKE_editmesh_from_object(obedit);
- int ret;
+ bool ret;
ret = EDBM_mtexpoly_check(em);
- return ret;
+ return ret && !(sima->flag & SI_NO_DRAW_TEXPAINT);
}
- return 0;
+ return false;
}
/* matches clip function */
@@ -361,6 +369,21 @@ int ED_space_image_maskedit_poll(bContext *C)
return false;
}
+bool ED_space_image_paint_curve(const bContext *C)
+{
+ SpaceImage *sima = CTX_wm_space_image(C);
+
+ if (sima && sima->mode == SI_MODE_PAINT) {
+ Brush *br = CTX_data_tool_settings(C)->imapaint.paint.brush;
+
+ if (br && (br->flag & BRUSH_CURVE))
+ return true;
+ }
+
+ return false;
+}
+
+
int ED_space_image_maskedit_mask_poll(bContext *C)
{
if (ED_space_image_maskedit_poll(C)) {
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index 4ae05d8f64f..66bd346ae69 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -1383,7 +1383,7 @@ static int save_image_options_init(SaveImageOptions *simopts, SpaceImage *sima,
/* sanitize all settings */
/* unlikely but just in case */
- if (ELEM3(simopts->im_format.planes, R_IMF_PLANES_BW, R_IMF_PLANES_RGB, R_IMF_PLANES_RGBA) == 0) {
+ if (ELEM(simopts->im_format.planes, R_IMF_PLANES_BW, R_IMF_PLANES_RGB, R_IMF_PLANES_RGBA) == 0) {
simopts->im_format.planes = R_IMF_PLANES_RGBA;
}
@@ -1904,6 +1904,7 @@ static int image_new_exec(bContext *C, wmOperator *op)
char *name = _name;
float color[4];
int width, height, floatbuf, gen_type, alpha;
+ bool stencil;
/* retrieve state */
sima = CTX_wm_space_image(C);
@@ -1923,7 +1924,8 @@ static int image_new_exec(bContext *C, wmOperator *op)
gen_type = RNA_enum_get(op->ptr, "generated_type");
RNA_float_get_array(op->ptr, "color", color);
alpha = RNA_boolean_get(op->ptr, "alpha");
-
+ stencil = RNA_boolean_get(op->ptr, "texstencil");
+
if (!alpha)
color[3] = 1.0f;
@@ -1955,6 +1957,13 @@ static int image_new_exec(bContext *C, wmOperator *op)
tex->ima = ima;
ED_area_tag_redraw(CTX_wm_area(C));
}
+ else if (stencil) {
+ ImagePaintSettings *imapaint = &(CTX_data_tool_settings(C)->imapaint);
+
+ if (imapaint->stencil)
+ id_us_min(&imapaint->stencil->id);
+ imapaint->stencil = ima;
+ }
}
BKE_image_signal(ima, (sima) ? &sima->iuser : NULL, IMA_SIGNAL_USER_NEW_IMAGE);
@@ -2003,6 +2012,9 @@ void IMAGE_OT_new(wmOperatorType *ot)
RNA_def_enum(ot->srna, "generated_type", image_generated_type_items, IMA_GENTYPE_BLANK,
"Generated Type", "Fill the image with a grid for UV map testing");
RNA_def_boolean(ot->srna, "float", 0, "32 bit Float", "Create image with 32 bit floating point bit depth");
+ prop = RNA_def_boolean(ot->srna, "texstencil", 0, "Stencil", "Set Image as stencil");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+
}
#undef IMA_DEF_NAME
@@ -2037,7 +2049,7 @@ static int image_invert_exec(bContext *C, wmOperator *op)
if (support_undo) {
ED_undo_paint_push_begin(UNDO_PAINT_IMAGE, op->type->name,
- ED_image_undo_restore, ED_image_undo_free);
+ ED_image_undo_restore, ED_image_undo_free, NULL);
/* 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();
diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c
index 0fb93ad27ee..375a0ddeac3 100644
--- a/source/blender/editors/space_image/space_image.c
+++ b/source/blender/editors/space_image/space_image.c
@@ -349,7 +349,7 @@ static void image_keymap(struct wmKeyConfig *keyconf)
static int image_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
{
if (drag->type == WM_DRAG_PATH)
- if (ELEM3(drag->icon, 0, ICON_FILE_IMAGE, ICON_FILE_BLANK)) /* rule might not work? */
+ if (ELEM(drag->icon, 0, ICON_FILE_IMAGE, ICON_FILE_BLANK)) /* rule might not work? */
return 1;
return 0;
}
@@ -633,6 +633,12 @@ static void image_main_area_init(wmWindowManager *wm, ARegion *ar)
WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
/* image paint polls for mode */
+ keymap = WM_keymap_find(wm->defaultconf, "Curve", 0, 0);
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+
+ keymap = WM_keymap_find(wm->defaultconf, "Paint Curve", 0, 0);
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
+
keymap = WM_keymap_find(wm->defaultconf, "Image Paint", 0, 0);
WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
@@ -657,6 +663,7 @@ static void image_main_area_draw(const bContext *C, ARegion *ar)
Object *obact = CTX_data_active_object(C);
Object *obedit = CTX_data_edit_object(C);
Mask *mask = NULL;
+ bool curve = false;
Scene *scene = CTX_data_scene(C);
View2D *v2d = &ar->v2d;
//View2DScrollers *scrollers;
@@ -702,6 +709,9 @@ static void image_main_area_draw(const bContext *C, ARegion *ar)
else if (sima->mode == SI_MODE_MASK) {
mask = ED_space_image_get_mask(sima);
}
+ else if (ED_space_image_paint_curve(C)) {
+ curve = true;
+ }
ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
@@ -753,6 +763,11 @@ static void image_main_area_draw(const bContext *C, ARegion *ar)
draw_image_cursor(ar, sima->cursor);
UI_view2d_view_restore(C);
}
+ else if (curve) {
+ UI_view2d_view_ortho(v2d);
+ draw_image_cursor(ar, sima->cursor);
+ UI_view2d_view_restore(C);
+ }
draw_image_cache(C, ar);
diff --git a/source/blender/editors/space_logic/logic_window.c b/source/blender/editors/space_logic/logic_window.c
index 9f3fc53482a..dd152022762 100644
--- a/source/blender/editors/space_logic/logic_window.c
+++ b/source/blender/editors/space_logic/logic_window.c
@@ -1832,7 +1832,7 @@ static void draw_actuator_motion(uiLayout *layout, PointerRNA *ptr)
uiItemR(row, ptr, "offset_rotation", 0, NULL, ICON_NONE);
uiItemR(split, ptr, "use_local_rotation", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
- if (ELEM3(physics_type, OB_BODY_TYPE_DYNAMIC, OB_BODY_TYPE_RIGID, OB_BODY_TYPE_SOFT)) {
+ if (ELEM(physics_type, OB_BODY_TYPE_DYNAMIC, OB_BODY_TYPE_RIGID, OB_BODY_TYPE_SOFT)) {
uiItemL(layout, IFACE_("Dynamic Object Settings:"), ICON_NONE);
split = uiLayoutSplit(layout, 0.9, false);
row = uiLayoutRow(split, false);
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index ef23fc24194..6fa9290c732 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -2307,6 +2307,12 @@ static void node_composit_buts_cornerpin(uiLayout *UNUSED(layout), bContext *UNU
{
}
+static void node_composit_buts_sunbeams(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+ uiItemR(layout, ptr, "source", UI_ITEM_R_EXPAND, "", ICON_NONE);
+ uiItemR(layout, ptr, "ray_length", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+}
+
/* only once called */
static void node_composit_set_butfunc(bNodeType *ntype)
{
@@ -2531,6 +2537,9 @@ static void node_composit_set_butfunc(bNodeType *ntype)
case CMP_NODE_CORNERPIN:
ntype->draw_buttons = node_composit_buts_cornerpin;
break;
+ case CMP_NODE_SUNBEAMS:
+ ntype->draw_buttons = node_composit_buts_sunbeams;
+ break;
}
}
diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c
index 1c41ce9d86d..8422df35063 100644
--- a/source/blender/editors/space_node/node_edit.c
+++ b/source/blender/editors/space_node/node_edit.c
@@ -640,10 +640,10 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node)
/* tree specific activate calls */
if (ntree->type == NTREE_SHADER) {
/* when we select a material, active texture is cleared, for buttons */
- if (node->id && ELEM3(GS(node->id->name), ID_MA, ID_LA, ID_WO))
+ if (node->id && ELEM(GS(node->id->name), ID_MA, ID_LA, ID_WO))
nodeClearActiveID(ntree, ID_TE);
- if (ELEM4(node->type, SH_NODE_OUTPUT, SH_NODE_OUTPUT_MATERIAL,
+ if (ELEM(node->type, SH_NODE_OUTPUT, SH_NODE_OUTPUT_MATERIAL,
SH_NODE_OUTPUT_WORLD, SH_NODE_OUTPUT_LAMP))
{
bNode *tnode;
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index 1f728b380d6..7eb90953df4 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -638,7 +638,7 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar
uiButSetFlag(bt, UI_BUT_DRAG_LOCK);
layflag++; /* is lay_xor */
- if (ELEM8(passflag, SCE_PASS_SPEC, SCE_PASS_SHADOW, SCE_PASS_AO, SCE_PASS_REFLECT, SCE_PASS_REFRACT,
+ if (ELEM(passflag, SCE_PASS_SPEC, SCE_PASS_SHADOW, SCE_PASS_AO, SCE_PASS_REFLECT, SCE_PASS_REFRACT,
SCE_PASS_INDIRECT, SCE_PASS_EMIT, SCE_PASS_ENVIRONMENT))
{
bt = uiDefIconButBitI(block, TOG, passflag, 0, (*layflag & passflag) ? ICON_DOT : ICON_BLANK1,
diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c
index 17e1e032bbf..ef621407abd 100644
--- a/source/blender/editors/space_outliner/outliner_edit.c
+++ b/source/blender/editors/space_outliner/outliner_edit.c
@@ -215,15 +215,15 @@ void OUTLINER_OT_item_openclose(wmOperatorType *ot)
static void do_item_rename(ARegion *ar, TreeElement *te, TreeStoreElem *tselem, ReportList *reports)
{
/* can't rename rna datablocks entries or listbases */
- if (ELEM4(tselem->type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM, TSE_ID_BASE)) {
+ if (ELEM(tselem->type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM, TSE_ID_BASE)) {
/* do nothing */;
}
- else if (ELEM10(tselem->type, TSE_ANIM_DATA, TSE_NLA, TSE_DEFGROUP_BASE, TSE_CONSTRAINT_BASE, TSE_MODIFIER_BASE,
- TSE_DRIVER_BASE, TSE_POSE_BASE, TSE_POSEGRP_BASE, TSE_R_LAYER_BASE, TSE_R_PASS))
+ else if (ELEM(tselem->type, TSE_ANIM_DATA, TSE_NLA, TSE_DEFGROUP_BASE, TSE_CONSTRAINT_BASE, TSE_MODIFIER_BASE,
+ TSE_DRIVER_BASE, TSE_POSE_BASE, TSE_POSEGRP_BASE, TSE_R_LAYER_BASE, TSE_R_PASS))
{
BKE_report(reports, RPT_WARNING, "Cannot edit builtin name");
}
- else if (ELEM3(tselem->type, TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP)) {
+ else if (ELEM(tselem->type, TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP)) {
BKE_report(reports, RPT_WARNING, "Cannot edit sequence name");
}
else if (tselem->id->lib) {
@@ -1654,7 +1654,7 @@ static int outliner_parenting_poll(bContext *C)
SpaceOops *soops = CTX_wm_space_outliner(C);
if (soops) {
- return ELEM4(soops->outlinevis, SO_ALL_SCENES, SO_CUR_SCENE, SO_VISIBLE, SO_GROUPS);
+ return ELEM(soops->outlinevis, SO_ALL_SCENES, SO_CUR_SCENE, SO_VISIBLE, SO_GROUPS);
}
return false;
diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c
index d7521edd57a..6f5bf712d55 100644
--- a/source/blender/editors/space_outliner/outliner_select.c
+++ b/source/blender/editors/space_outliner/outliner_select.c
@@ -948,7 +948,7 @@ static bool do_outliner_item_activate(bContext *C, Scene *scene, ARegion *ar, Sp
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
}
- else if (ELEM5(te->idcode, ID_ME, ID_CU, ID_MB, ID_LT, ID_AR)) {
+ else if (ELEM(te->idcode, ID_ME, ID_CU, ID_MB, ID_LT, ID_AR)) {
WM_operator_name_call(C, "OBJECT_OT_editmode_toggle", WM_OP_INVOKE_REGION_WIN, NULL);
}
else { // rest of types
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c
index d1e9b3d34b7..d09ed1a100e 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -1339,7 +1339,7 @@ static int do_outliner_operation_event(bContext *C, Scene *scene, ARegion *ar, S
else if (datalevel == TSE_DRIVER_BASE) {
/* do nothing... no special ops needed yet */
}
- else if (ELEM3(datalevel, TSE_R_LAYER_BASE, TSE_R_LAYER, TSE_R_PASS)) {
+ else if (ELEM(datalevel, TSE_R_LAYER_BASE, TSE_R_LAYER, TSE_R_PASS)) {
/*WM_operator_name_call(C, "OUTLINER_OT_renderdata_operation", WM_OP_INVOKE_REGION_WIN, NULL)*/
}
else {
diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c
index 520cd9a544d..5801dd126e3 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -821,7 +821,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
TreeStoreElem *tselem;
ID *id = idv;
- if (ELEM3(type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) {
+ if (ELEM(type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) {
id = ((PointerRNA *)idv)->id.data;
if (!id) id = ((PointerRNA *)idv)->data;
}
@@ -847,10 +847,10 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
te->parent = parent;
te->index = index; // for data arays
- if (ELEM3(type, TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP)) {
+ if (ELEM(type, TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP)) {
/* pass */
}
- else if (ELEM3(type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) {
+ else if (ELEM(type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) {
/* pass */
}
else if (type == TSE_ANIM_DATA) {
@@ -985,7 +985,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
te->directdata = seq;
te->name = seq->strip->stripdata->name;
}
- else if (ELEM3(type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) {
+ else if (ELEM(type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) {
PointerRNA pptr, propptr, *ptr = (PointerRNA *)idv;
PropertyRNA *prop, *iterprop;
PropertyType proptype;
@@ -1062,7 +1062,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
else if (tot)
te->flag |= TE_LAZY_CLOSED;
}
- else if (ELEM3(proptype, PROP_BOOLEAN, PROP_INT, PROP_FLOAT)) {
+ else if (ELEM(proptype, PROP_BOOLEAN, PROP_INT, PROP_FLOAT)) {
tot = RNA_property_array_length(ptr, prop);
if (TSELEM_OPEN(tselem, soops)) {
diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c
index 41c5b00b381..504d9628d98 100644
--- a/source/blender/editors/space_outliner/space_outliner.c
+++ b/source/blender/editors/space_outliner/space_outliner.c
@@ -143,7 +143,7 @@ static int outliner_parent_clear_poll(bContext *C, wmDrag *drag, const wmEvent *
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
- if (!ELEM4(soops->outlinevis, SO_ALL_SCENES, SO_CUR_SCENE, SO_VISIBLE, SO_GROUPS)) {
+ if (!ELEM(soops->outlinevis, SO_ALL_SCENES, SO_CUR_SCENE, SO_VISIBLE, SO_GROUPS)) {
return false;
}
@@ -156,7 +156,7 @@ static int outliner_parent_clear_poll(bContext *C, wmDrag *drag, const wmEvent *
switch (te->idcode) {
case ID_SCE:
- return (ELEM3(tselem->type, TSE_R_LAYER_BASE, TSE_R_LAYER, TSE_R_PASS));
+ return (ELEM(tselem->type, TSE_R_LAYER_BASE, TSE_R_LAYER, TSE_R_PASS));
case ID_OB:
return (ELEM(tselem->type, TSE_MODIFIER_BASE, TSE_CONSTRAINT_BASE));
/* Other codes to ignore? */
diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c
index 4ad5ed8bb80..dab51f752b4 100644
--- a/source/blender/editors/space_sequencer/sequencer_draw.c
+++ b/source/blender/editors/space_sequencer/sequencer_draw.c
@@ -142,19 +142,21 @@ static void get_seq_color3ubv(Scene *curscene, Sequence *seq, unsigned char col[
case SEQ_TYPE_GLOW:
case SEQ_TYPE_MULTICAM:
case SEQ_TYPE_ADJUSTMENT:
+ case SEQ_TYPE_GAUSSIAN_BLUR:
UI_GetThemeColor3ubv(TH_SEQ_EFFECT, col);
/* slightly offset hue to distinguish different effects */
- if (seq->type == SEQ_TYPE_ADD) rgb_byte_set_hue_float_offset(col, 0.04);
- else if (seq->type == SEQ_TYPE_SUB) rgb_byte_set_hue_float_offset(col, 0.08);
- else if (seq->type == SEQ_TYPE_MUL) rgb_byte_set_hue_float_offset(col, 0.12);
- else if (seq->type == SEQ_TYPE_ALPHAOVER) rgb_byte_set_hue_float_offset(col, 0.16);
- else if (seq->type == SEQ_TYPE_ALPHAUNDER) rgb_byte_set_hue_float_offset(col, 0.20);
- else if (seq->type == SEQ_TYPE_OVERDROP) rgb_byte_set_hue_float_offset(col, 0.24);
- else if (seq->type == SEQ_TYPE_GLOW) rgb_byte_set_hue_float_offset(col, 0.28);
- else if (seq->type == SEQ_TYPE_TRANSFORM) rgb_byte_set_hue_float_offset(col, 0.36);
- else if (seq->type == SEQ_TYPE_MULTICAM) rgb_byte_set_hue_float_offset(col, 0.32);
- else if (seq->type == SEQ_TYPE_ADJUSTMENT) rgb_byte_set_hue_float_offset(col, 0.40);
+ if (seq->type == SEQ_TYPE_ADD) rgb_byte_set_hue_float_offset(col, 0.04);
+ else if (seq->type == SEQ_TYPE_SUB) rgb_byte_set_hue_float_offset(col, 0.08);
+ else if (seq->type == SEQ_TYPE_MUL) rgb_byte_set_hue_float_offset(col, 0.12);
+ else if (seq->type == SEQ_TYPE_ALPHAOVER) rgb_byte_set_hue_float_offset(col, 0.16);
+ else if (seq->type == SEQ_TYPE_ALPHAUNDER) rgb_byte_set_hue_float_offset(col, 0.20);
+ else if (seq->type == SEQ_TYPE_OVERDROP) rgb_byte_set_hue_float_offset(col, 0.24);
+ else if (seq->type == SEQ_TYPE_GLOW) rgb_byte_set_hue_float_offset(col, 0.28);
+ else if (seq->type == SEQ_TYPE_TRANSFORM) rgb_byte_set_hue_float_offset(col, 0.36);
+ else if (seq->type == SEQ_TYPE_MULTICAM) rgb_byte_set_hue_float_offset(col, 0.32);
+ else if (seq->type == SEQ_TYPE_ADJUSTMENT) rgb_byte_set_hue_float_offset(col, 0.40);
+ else if (seq->type == SEQ_TYPE_GAUSSIAN_BLUR) rgb_byte_set_hue_float_offset(col, 0.42);
break;
case SEQ_TYPE_COLOR:
diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c
index 3c17b2986ff..dcf13dbf43f 100644
--- a/source/blender/editors/space_sequencer/sequencer_edit.c
+++ b/source/blender/editors/space_sequencer/sequencer_edit.c
@@ -86,6 +86,7 @@ EnumPropertyItem sequencer_prop_effect_types[] = {
{SEQ_TYPE_SPEED, "SPEED", 0, "Speed", "Color effect strip type"},
{SEQ_TYPE_MULTICAM, "MULTICAM", 0, "Multicam Selector", ""},
{SEQ_TYPE_ADJUSTMENT, "ADJUSTMENT", 0, "Adjustment Layer", ""},
+ {SEQ_TYPE_GAUSSIAN_BLUR, "GAUSSIAN_BLUR", 0, "Gaussian Blur", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -1918,9 +1919,12 @@ static int sequencer_separate_images_exec(bContext *C, wmOperator *op)
strip_new = seq_new->strip;
strip_new->us = 1;
- /* new stripdata */
- se_new = strip_new->stripdata;
+ /* new stripdata (only one element now!) */
+ /* Note this assume all elements (images) have the same dimension, since we only copy the name here. */
+ se_new = MEM_reallocN(strip_new->stripdata, sizeof(*se_new));
BLI_strncpy(se_new->name, se->name, sizeof(se_new->name));
+ strip_new->stripdata = se_new;
+
BKE_sequence_calc(scene, seq_new);
if (step > 1) {
diff --git a/source/blender/editors/space_sequencer/sequencer_select.c b/source/blender/editors/space_sequencer/sequencer_select.c
index 9826ef10902..8e49d5649f3 100644
--- a/source/blender/editors/space_sequencer/sequencer_select.c
+++ b/source/blender/editors/space_sequencer/sequencer_select.c
@@ -912,7 +912,7 @@ static EnumPropertyItem sequencer_prop_select_grouped_types[] = {
#define SEQ_IS_EFFECT(_seq) ((_seq->type & SEQ_TYPE_EFFECT) != 0)
-#define SEQ_USE_DATA(_seq) (ELEM3(_seq->type, SEQ_TYPE_SCENE, SEQ_TYPE_MOVIECLIP, SEQ_TYPE_MASK) || SEQ_HAS_PATH(_seq))
+#define SEQ_USE_DATA(_seq) (ELEM(_seq->type, SEQ_TYPE_SCENE, SEQ_TYPE_MOVIECLIP, SEQ_TYPE_MASK) || SEQ_HAS_PATH(_seq))
static bool select_grouped_type(Editing *ed, Sequence *actseq)
{
@@ -1035,7 +1035,7 @@ static bool select_grouped_effect(Editing *ed, Sequence *actseq)
SEQP_BEGIN (ed, seq)
{
- if (ELEM3(actseq, seq->seq1, seq->seq2, seq->seq3)) {
+ if (ELEM(actseq, seq->seq1, seq->seq2, seq->seq3)) {
effects[seq->type] = true;
}
}
diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c
index a94b73802b2..c0cfaed7867 100644
--- a/source/blender/editors/space_sequencer/space_sequencer.c
+++ b/source/blender/editors/space_sequencer/space_sequencer.c
@@ -279,24 +279,40 @@ static void sequencer_refresh(const bContext *C, ScrArea *sa)
}
break;
case SEQ_VIEW_SEQUENCE_PREVIEW:
- if (ar_main && (ar_main->flag & RGN_FLAG_HIDDEN)) {
- ar_main->flag &= ~RGN_FLAG_HIDDEN;
- ar_main->v2d.flag &= ~V2D_IS_INITIALISED;
- view_changed = true;
- }
- if (ar_preview && (ar_preview->flag & RGN_FLAG_HIDDEN)) {
- ar_preview->flag &= ~RGN_FLAG_HIDDEN;
- ar_preview->v2d.flag &= ~V2D_IS_INITIALISED;
- ar_preview->v2d.cur = ar_preview->v2d.tot;
- view_changed = true;
- }
- if (ar_main && ar_main->alignment != RGN_ALIGN_NONE) {
- ar_main->alignment = RGN_ALIGN_NONE;
- view_changed = true;
- }
- if (ar_preview && ar_preview->alignment != RGN_ALIGN_TOP) {
- ar_preview->alignment = RGN_ALIGN_TOP;
- view_changed = true;
+ if (ar_main && ar_preview) {
+ /* Get available height (without DPI correction). */
+ const float height = (sa->winy - ED_area_headersize()) / UI_DPI_FAC;
+
+ /* We reuse hidden area's size, allows to find same layout as before if we just switch
+ * between one 'full window' view and the combined one. This gets lost if we switch to both
+ * 'full window' views before, though... Better than nothing. */
+ if (ar_main->flag & RGN_FLAG_HIDDEN) {
+ ar_main->flag &= ~RGN_FLAG_HIDDEN;
+ ar_main->v2d.flag &= ~V2D_IS_INITIALISED;
+ ar_preview->sizey = (int)(height - ar_main->sizey);
+ view_changed = true;
+ }
+ if (ar_preview->flag & RGN_FLAG_HIDDEN) {
+ ar_preview->flag &= ~RGN_FLAG_HIDDEN;
+ ar_preview->v2d.flag &= ~V2D_IS_INITIALISED;
+ ar_preview->v2d.cur = ar_preview->v2d.tot;
+ ar_main->sizey = (int)(height - ar_preview->sizey);
+ view_changed = true;
+ }
+ if (ar_main->alignment != RGN_ALIGN_NONE) {
+ ar_main->alignment = RGN_ALIGN_NONE;
+ view_changed = true;
+ }
+ if (ar_preview->alignment != RGN_ALIGN_TOP) {
+ ar_preview->alignment = RGN_ALIGN_TOP;
+ view_changed = true;
+ }
+ /* Final check that both preview and main height are reasonable! */
+ if (ar_preview->sizey < 10 || ar_main->sizey < 10 || ar_preview->sizey + ar_main->sizey > height) {
+ ar_preview->sizey = (int)(height * 0.4f + 0.5f);
+ ar_main->sizey = (int)(height - ar_preview->sizey);
+ view_changed = true;
+ }
}
break;
}
@@ -339,40 +355,6 @@ static void sequencer_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn
}
}
-/* *********************** sequencer (main) region ************************ */
-/* add handlers, stuff you only do once or on area/region changes */
-static void sequencer_main_area_init(wmWindowManager *wm, ARegion *ar)
-{
- wmKeyMap *keymap;
- ListBase *lb;
-
- UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
-
-// keymap = WM_keymap_find(wm->defaultconf, "Mask Editing", 0, 0);
-// WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
-
- keymap = WM_keymap_find(wm->defaultconf, "SequencerCommon", SPACE_SEQ, 0);
- WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
-
- /* own keymap */
- keymap = WM_keymap_find(wm->defaultconf, "Sequencer", SPACE_SEQ, 0);
- WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
-
- /* add drop boxes */
- lb = WM_dropboxmap_find("Sequencer", SPACE_SEQ, RGN_TYPE_WINDOW);
-
- WM_event_add_dropbox_handler(&ar->handlers, lb);
-
-}
-
-static void sequencer_main_area_draw(const bContext *C, ARegion *ar)
-{
-// ScrArea *sa = CTX_wm_area(C);
-
- /* NLE - strip editing timeline interface */
- draw_timeline_seq(C, ar);
-}
-
/* ************* dropboxes ************* */
static int image_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
@@ -396,7 +378,7 @@ static int movie_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
int hand;
if (drag->type == WM_DRAG_PATH)
- if (ELEM3(drag->icon, 0, ICON_FILE_MOVIE, ICON_FILE_BLANK)) /* rule might not work? */
+ if (ELEM(drag->icon, 0, ICON_FILE_MOVIE, ICON_FILE_BLANK)) /* rule might not work? */
if (find_nearest_seq(scene, &ar->v2d, &hand, event->mval) == NULL)
return 1;
return 0;
@@ -439,7 +421,7 @@ static void sequencer_drop_copy(wmDrag *drag, wmDropBox *drop)
static void sequencer_dropboxes(void)
{
ListBase *lb = WM_dropboxmap_find("Sequencer", SPACE_SEQ, RGN_TYPE_WINDOW);
-
+
WM_dropbox_add(lb, "SEQUENCER_OT_image_strip_add", image_drop_poll, sequencer_drop_copy);
WM_dropbox_add(lb, "SEQUENCER_OT_movie_strip_add", movie_drop_poll, sequencer_drop_copy);
WM_dropbox_add(lb, "SEQUENCER_OT_sound_strip_add", sound_drop_poll, sequencer_drop_copy);
@@ -469,16 +451,37 @@ static int sequencer_context(const bContext *C, const char *member, bContextData
return false;
}
-
+/* *********************** sequencer (main) region ************************ */
/* add handlers, stuff you only do once or on area/region changes */
-static void sequencer_header_area_init(wmWindowManager *UNUSED(wm), ARegion *ar)
+static void sequencer_main_area_init(wmWindowManager *wm, ARegion *ar)
{
- ED_region_header_init(ar);
+ wmKeyMap *keymap;
+ ListBase *lb;
+
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
+
+#if 0
+ keymap = WM_keymap_find(wm->defaultconf, "Mask Editing", 0, 0);
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+#endif
+
+ keymap = WM_keymap_find(wm->defaultconf, "SequencerCommon", SPACE_SEQ, 0);
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+
+ /* own keymap */
+ keymap = WM_keymap_find(wm->defaultconf, "Sequencer", SPACE_SEQ, 0);
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+
+ /* add drop boxes */
+ lb = WM_dropboxmap_find("Sequencer", SPACE_SEQ, RGN_TYPE_WINDOW);
+
+ WM_event_add_dropbox_handler(&ar->handlers, lb);
}
-static void sequencer_header_area_draw(const bContext *C, ARegion *ar)
+static void sequencer_main_area_draw(const bContext *C, ARegion *ar)
{
- ED_region_header(C, ar);
+ /* NLE - strip editing timeline interface */
+ draw_timeline_seq(C, ar);
}
static void sequencer_main_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
@@ -512,15 +515,29 @@ static void sequencer_main_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa
}
}
+/* *********************** header region ************************ */
+/* add handlers, stuff you only do once or on area/region changes */
+static void sequencer_header_area_init(wmWindowManager *UNUSED(wm), ARegion *ar)
+{
+ ED_region_header_init(ar);
+}
+
+static void sequencer_header_area_draw(const bContext *C, ARegion *ar)
+{
+ ED_region_header(C, ar);
+}
+
/* *********************** preview region ************************ */
static void sequencer_preview_area_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
-
-// keymap = WM_keymap_find(wm->defaultconf, "Mask Editing", 0, 0);
-// WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+
+#if 0
+ keymap = WM_keymap_find(wm->defaultconf, "Mask Editing", 0, 0);
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+#endif
keymap = WM_keymap_find(wm->defaultconf, "SequencerCommon", SPACE_SEQ, 0);
WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
@@ -593,7 +610,6 @@ static void sequencer_preview_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED
break;
}
break;
-
case NC_MASK:
if (wmn->action == NA_EDITED) {
ED_region_tag_redraw(ar);
@@ -654,10 +670,10 @@ void ED_spacetype_sequencer(void)
{
SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype sequencer");
ARegionType *art;
-
+
st->spaceid = SPACE_SEQ;
strncpy(st->name, "Sequencer", BKE_ST_MAXNAME);
-
+
st->new = sequencer_new;
st->free = sequencer_free;
st->init = sequencer_init;
@@ -682,13 +698,12 @@ void ED_spacetype_sequencer(void)
/* preview */
art = MEM_callocN(sizeof(ARegionType), "spacetype sequencer region");
art->regionid = RGN_TYPE_PREVIEW;
- art->prefsizey = 240; // XXX
art->init = sequencer_preview_area_init;
art->draw = sequencer_preview_area_draw;
art->listener = sequencer_preview_area_listener;
art->keymapflag = ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_GPENCIL;
BLI_addhead(&st->regiontypes, art);
-
+
/* regions: listview/buttons */
art = MEM_callocN(sizeof(ARegionType), "spacetype sequencer region");
art->regionid = RGN_TYPE_UI;
@@ -698,7 +713,7 @@ void ED_spacetype_sequencer(void)
art->init = sequencer_buttons_area_init;
art->draw = sequencer_buttons_area_draw;
BLI_addhead(&st->regiontypes, art);
-
+
sequencer_buttons_register(art);
/* regions: header */
@@ -706,13 +721,13 @@ void ED_spacetype_sequencer(void)
art->regionid = RGN_TYPE_HEADER;
art->prefsizey = HEADERY;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER;
-
+
art->init = sequencer_header_area_init;
art->draw = sequencer_header_area_draw;
art->listener = sequencer_main_area_listener;
-
+
BLI_addhead(&st->regiontypes, art);
-
+
BKE_spacetype_register(st);
/* set the sequencer callback when not in background mode */
diff --git a/source/blender/editors/space_text/text_draw.c b/source/blender/editors/space_text/text_draw.c
index 6a98fd802f9..6ca6b2af1fd 100644
--- a/source/blender/editors/space_text/text_draw.c
+++ b/source/blender/editors/space_text/text_draw.c
@@ -1460,7 +1460,7 @@ void text_scroll_to_cursor(SpaceText *st, ScrArea *sa)
ARegion *ar = NULL;
int i, x, winx = 0;
- if (ELEM3(NULL, st, st->text, st->text->curl)) return;
+ if (ELEM(NULL, st, st->text, st->text->curl)) return;
text = st->text;
diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c
index 245cdadc7a2..e01a9d4b470 100644
--- a/source/blender/editors/space_view3d/drawarmature.c
+++ b/source/blender/editors/space_view3d/drawarmature.c
@@ -67,6 +67,7 @@
#include "view3d_intern.h"
+#include "GPU_select.h"
/* *************** Armature Drawing - Coloring API ***************************** */
@@ -93,7 +94,7 @@ static void set_pchan_colorset(Object *ob, bPoseChannel *pchan)
short color_index = 0;
/* sanity check */
- if (ELEM4(NULL, ob, arm, pose, pchan)) {
+ if (ELEM(NULL, ob, arm, pose, pchan)) {
bcolor = NULL;
return;
}
@@ -551,7 +552,7 @@ static void draw_bone_points(const short dt, int armflag, unsigned int boneflag,
/* Draw root point if we are not connected */
if ((boneflag & BONE_CONNECTED) == 0) {
if (id != -1)
- glLoadName(id | BONESEL_ROOT);
+ GPU_select_load_id(id | BONESEL_ROOT);
if (dt <= OB_WIRE) {
if (armflag & ARM_EDITMODE) {
@@ -574,7 +575,7 @@ static void draw_bone_points(const short dt, int armflag, unsigned int boneflag,
/* Draw tip point */
if (id != -1)
- glLoadName(id | BONESEL_TIP);
+ GPU_select_load_id(id | BONESEL_TIP);
if (dt <= OB_WIRE) {
if (armflag & ARM_EDITMODE) {
@@ -787,7 +788,7 @@ static void draw_sphere_bone_wire(float smat[4][4], float imat[4][4],
/* Draw root point if we are not connected */
if ((boneflag & BONE_CONNECTED) == 0) {
if (id != -1)
- glLoadName(id | BONESEL_ROOT);
+ GPU_select_load_id(id | BONESEL_ROOT);
drawcircball(GL_LINE_LOOP, headvec, head, imat);
}
@@ -799,7 +800,7 @@ static void draw_sphere_bone_wire(float smat[4][4], float imat[4][4],
}
if (id != -1)
- glLoadName(id | BONESEL_TIP);
+ GPU_select_load_id(id | BONESEL_TIP);
drawcircball(GL_LINE_LOOP, tailvec, tail, imat);
@@ -830,7 +831,7 @@ static void draw_sphere_bone_wire(float smat[4][4], float imat[4][4],
cross_v3_v3v3(norvect, vec, imat[2]);
if (id != -1)
- glLoadName(id | BONESEL_BONE);
+ GPU_select_load_id(id | BONESEL_BONE);
glBegin(GL_LINES);
@@ -907,7 +908,7 @@ static void draw_sphere_bone(const short dt, int armflag, int boneflag, short co
/* Draw root point if we are not connected */
if ((boneflag & BONE_CONNECTED) == 0) {
if (id != -1)
- glLoadName(id | BONESEL_ROOT);
+ GPU_select_load_id(id | BONESEL_ROOT);
gluSphere(qobj, head, 16, 10);
}
@@ -918,7 +919,7 @@ static void draw_sphere_bone(const short dt, int armflag, int boneflag, short co
}
if (id != -1)
- glLoadName(id | BONESEL_TIP);
+ GPU_select_load_id(id | BONESEL_TIP);
glTranslatef(0.0f, 0.0f, length);
gluSphere(qobj, tail, 16, 10);
@@ -939,7 +940,7 @@ static void draw_sphere_bone(const short dt, int armflag, int boneflag, short co
if (length > (head + tail)) {
if (id != -1)
- glLoadName(id | BONESEL_BONE);
+ GPU_select_load_id(id | BONESEL_BONE);
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(-1.0f, -1.0f);
@@ -1009,7 +1010,7 @@ static void draw_line_bone(int armflag, int boneflag, short constflag, unsigned
/* Draw root point if we are not connected */
if ((boneflag & BONE_CONNECTED) == 0) {
if (G.f & G_PICKSEL) { /* no bitmap in selection mode, crashes 3d cards... */
- glLoadName(id | BONESEL_ROOT);
+ GPU_select_load_id(id | BONESEL_ROOT);
glBegin(GL_POINTS);
glVertex3f(0.0f, 0.0f, 0.0f);
glEnd();
@@ -1021,7 +1022,7 @@ static void draw_line_bone(int armflag, int boneflag, short constflag, unsigned
}
if (id != -1)
- glLoadName((GLuint) id | BONESEL_BONE);
+ GPU_select_load_id((GLuint) id | BONESEL_BONE);
glBegin(GL_LINES);
glVertex3f(0.0f, 0.0f, 0.0f);
@@ -1031,7 +1032,7 @@ static void draw_line_bone(int armflag, int boneflag, short constflag, unsigned
/* tip */
if (G.f & G_PICKSEL) {
/* no bitmap in selection mode, crashes 3d cards... */
- glLoadName(id | BONESEL_TIP);
+ GPU_select_load_id(id | BONESEL_TIP);
glBegin(GL_POINTS);
glVertex3f(0.0f, 1.0f, 0.0f);
glEnd();
@@ -1043,7 +1044,7 @@ static void draw_line_bone(int armflag, int boneflag, short constflag, unsigned
/* further we send no names */
if (id != -1)
- glLoadName(id & 0xFFFF); /* object tag, for bordersel optim */
+ GPU_select_load_id(id & 0xFFFF); /* object tag, for bordersel optim */
if (armflag & ARM_POSEMODE)
set_pchan_glColor(PCHAN_COLOR_LINEBONE, boneflag, constflag);
@@ -1161,7 +1162,7 @@ static void draw_b_bone(const short dt, int armflag, int boneflag, short constfl
}
if (id != -1) {
- glLoadName((GLuint) id | BONESEL_BONE);
+ GPU_select_load_id((GLuint) id | BONESEL_BONE);
}
/* set up solid drawing */
@@ -1266,13 +1267,13 @@ static void draw_wire_bone(const short dt, int armflag, int boneflag, short cons
/* this chunk not in object mode */
if (armflag & (ARM_EDITMODE | ARM_POSEMODE)) {
if (id != -1)
- glLoadName((GLuint) id | BONESEL_BONE);
+ GPU_select_load_id((GLuint) id | BONESEL_BONE);
draw_wire_bone_segments(pchan, bbones, length, segments);
/* further we send no names */
if (id != -1)
- glLoadName(id & 0xFFFF); /* object tag, for bordersel optim */
+ GPU_select_load_id(id & 0xFFFF); /* object tag, for bordersel optim */
}
/* colors for modes */
@@ -1315,7 +1316,7 @@ static void draw_bone(const short dt, int armflag, int boneflag, short constflag
/* now draw the bone itself */
if (id != -1) {
- glLoadName((GLuint) id | BONESEL_BONE);
+ GPU_select_load_id((GLuint) id | BONESEL_BONE);
}
/* wire? */
@@ -1370,7 +1371,7 @@ static void draw_custom_bone(Scene *scene, View3D *v3d, RegionView3D *rv3d, Obje
}
if (id != -1) {
- glLoadName((GLuint) id | BONESEL_BONE);
+ GPU_select_load_id((GLuint) id | BONESEL_BONE);
}
draw_object_instance(scene, v3d, rv3d, ob, dt, armflag & ARM_POSEMODE);
@@ -1812,12 +1813,12 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
index += 0x10000; /* pose bones count in higher 2 bytes only */
}
- /* very very confusing... but in object mode, solid draw, we cannot do glLoadName yet,
+ /* very very confusing... but in object mode, solid draw, we cannot do GPU_select_load_id yet,
* stick bones and/or wire custom-shapes are drawn in next loop
*/
- if (ELEM(arm->drawtype, ARM_LINE, ARM_WIRE) == 0 && (draw_wire == false)) {
+ if (ELEM(arm->drawtype, ARM_LINE, ARM_WIRE) == 0 && (draw_wire == false) && index != -1) {
/* object tag, for bordersel optim */
- glLoadName(index & 0xFFFF);
+ GPU_select_load_id(index & 0xFFFF);
index = -1;
}
}
@@ -1881,9 +1882,9 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
index += 0x10000; /* pose bones count in higher 2 bytes only */
}
/* stick or wire bones have not been drawn yet so don't clear object selection in this case */
- if (ELEM(arm->drawtype, ARM_LINE, ARM_WIRE) == 0 && draw_wire) {
+ if (ELEM(arm->drawtype, ARM_LINE, ARM_WIRE) == 0 && draw_wire && index != -1) {
/* object tag, for bordersel optim */
- glLoadName(index & 0xFFFF);
+ GPU_select_load_id(index & 0xFFFF);
index = -1;
}
}
@@ -1926,7 +1927,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
*/
if ((do_dashed & 2) && ((bone->flag & BONE_CONNECTED) == 0)) {
if (arm->flag & ARM_POSEMODE) {
- glLoadName(index & 0xFFFF); /* object tag, for bordersel optim */
+ GPU_select_load_id(index & 0xFFFF); /* object tag, for bordersel optim */
UI_ThemeColor(TH_WIRE);
}
setlinestyle(3);
@@ -1946,7 +1947,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
if (constflag & PCHAN_HAS_TARGET) glColor3ub(200, 120, 0);
else glColor3ub(200, 200, 50); /* add theme! */
- glLoadName(index & 0xFFFF);
+ GPU_select_load_id(index & 0xFFFF);
pchan_draw_IK_root_lines(pchan, !(do_dashed & 2));
}
}
@@ -1954,7 +1955,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
if (bone->flag & BONE_SELECTED) {
glColor3ub(150, 200, 50); /* add theme! */
- glLoadName(index & 0xFFFF);
+ GPU_select_load_id(index & 0xFFFF);
pchan_draw_IK_root_lines(pchan, !(do_dashed & 2));
}
}
@@ -2020,7 +2021,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
/* draw DoFs */
if (arm->flag & ARM_POSEMODE) {
- if (((base->flag & OB_FROMDUPLI) == 0)) {
+ if (((base->flag & OB_FROMDUPLI) == 0) && ((v3d->flag & V3D_HIDE_HELPLINES) == 0)) {
draw_pose_dofs(ob);
}
}
@@ -2174,7 +2175,7 @@ static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, const short dt)
/* if wire over solid, set offset */
index = -1;
- glLoadName(-1);
+ GPU_select_load_id(-1);
if (ELEM(arm->drawtype, ARM_LINE, ARM_WIRE)) {
if (G.f & G_PICKSEL)
index = 0;
@@ -2223,7 +2224,7 @@ static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, const short dt)
/* offset to parent */
if (eBone->parent) {
UI_ThemeColor(TH_WIRE_EDIT);
- glLoadName(-1); /* -1 here is OK! */
+ GPU_select_load_id(-1); /* -1 here is OK! */
setlinestyle(3);
glBegin(GL_LINES);
@@ -2240,7 +2241,7 @@ static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, const short dt)
/* restore */
if (index != -1) {
- glLoadName(-1);
+ GPU_select_load_id(-1);
}
if (ELEM(arm->drawtype, ARM_LINE, ARM_WIRE)) {
diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c
index bf0b7850839..89babf977e1 100644
--- a/source/blender/editors/space_view3d/drawmesh.c
+++ b/source/blender/editors/space_view3d/drawmesh.c
@@ -212,12 +212,16 @@ static Material *give_current_material_or_def(Object *ob, int matnr)
static struct TextureDrawState {
Object *ob;
+ Image *stencil;
+ bool stencil_invert;
bool use_game_mat;
int is_lit, is_tex;
int color_profile;
bool use_backface_culling;
unsigned char obcol[4];
-} Gtexdraw = {NULL, false, 0, 0, 0, false, {0, 0, 0, 0}};
+ float stencil_col[4];
+ bool is_texpaint;
+} Gtexdraw = {NULL, NULL, false, false, 0, 0, 0, false, {0, 0, 0, 0}, {0.0f, 0.0f, 0.0f, 1.0f}, false};
static bool set_draw_settings_cached(int clearcache, MTFace *texface, Material *ma, struct TextureDrawState gtexdraw)
{
@@ -229,13 +233,15 @@ static bool set_draw_settings_cached(int clearcache, MTFace *texface, Material *
static int c_lit;
static int c_has_texface;
- Object *litob = NULL; /* to get mode to turn off mipmap in painting mode */
int backculled = 1;
int alphablend = GPU_BLEND_SOLID;
int textured = 0;
int lit = 0;
int has_texface = texface != NULL;
bool need_set_tpage = false;
+ bool texpaint = ((gtexdraw.ob->mode & OB_MODE_TEXTURE_PAINT) != 0);
+
+ Image *ima = NULL;
if (ma != NULL) {
if (ma->mode & MA_TRANSP) {
@@ -248,10 +254,10 @@ static bool set_draw_settings_cached(int clearcache, MTFace *texface, Material *
memset(&c_texface, 0, sizeof(MTFace));
c_badtex = false;
c_has_texface = -1;
+ c_ma = NULL;
}
else {
textured = gtexdraw.is_tex;
- litob = gtexdraw.ob;
}
/* convert number of lights into boolean */
@@ -266,14 +272,16 @@ static bool set_draw_settings_cached(int clearcache, MTFace *texface, Material *
}
}
- if (texface) {
+ if (texface && !texpaint) {
textured = textured && (texface->tpage);
/* no material, render alpha if texture has depth=32 */
if (!ma && BKE_image_has_alpha(texface->tpage))
alphablend = GPU_BLEND_ALPHA;
}
-
+ else if (texpaint && ma) {
+ ima = ma->texpaintslot ? ma->texpaintslot[ma->paint_active_slot].ima : NULL;
+ }
else
textured = 0;
@@ -287,11 +295,25 @@ static bool set_draw_settings_cached(int clearcache, MTFace *texface, Material *
/* need to re-set tpage if textured flag changed or existsment of texface changed.. */
need_set_tpage = textured != c_textured || has_texface != c_has_texface;
/* ..or if settings inside texface were changed (if texface was used) */
- need_set_tpage |= texface && memcmp(&c_texface, texface, sizeof(c_texface));
+ need_set_tpage |= (texpaint && c_ma != ma) || (texface && memcmp(&c_texface, texface, sizeof(c_texface)));
if (need_set_tpage) {
if (textured) {
- c_badtex = !GPU_set_tpage(texface, !(litob->mode & OB_MODE_TEXTURE_PAINT), alphablend);
+ if (texpaint) {
+ c_badtex = false;
+ if (GPU_verify_image(ima, NULL, 0, 1, 0, false)) {
+ glEnable(GL_TEXTURE_2D);
+ }
+ else {
+ c_badtex = true;
+ GPU_clear_tpage(true);
+ glDisable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ }
+ }
+ else {
+ c_badtex = !GPU_set_tpage(texface, !texpaint, alphablend);
+ }
}
else {
GPU_set_tpage(NULL, 0, 0);
@@ -325,6 +347,7 @@ static bool set_draw_settings_cached(int clearcache, MTFace *texface, Material *
glDisable(GL_COLOR_MATERIAL);
}
c_lit = lit;
+ c_ma = ma;
}
return c_badtex;
@@ -335,6 +358,7 @@ static void draw_textured_begin(Scene *scene, View3D *v3d, RegionView3D *rv3d, O
unsigned char obcol[4];
bool is_tex, solidtex;
Mesh *me = ob->data;
+ ImagePaintSettings *imapaint = &scene->toolsettings->imapaint;
/* XXX scene->obedit warning */
@@ -364,8 +388,34 @@ static void draw_textured_begin(Scene *scene, View3D *v3d, RegionView3D *rv3d, O
else is_tex = false;
Gtexdraw.ob = ob;
+ Gtexdraw.stencil = (imapaint->flag & IMAGEPAINT_PROJECT_LAYER_STENCIL) ? imapaint->stencil : NULL;
+ Gtexdraw.stencil_invert = ((imapaint->flag & IMAGEPAINT_PROJECT_LAYER_STENCIL_INV) != 0);
+ Gtexdraw.is_texpaint = (ob->mode == OB_MODE_TEXTURE_PAINT);
+ copy_v3_v3(Gtexdraw.stencil_col, imapaint->stencil_col);
Gtexdraw.is_tex = is_tex;
+ /* load the stencil texture here */
+ if (Gtexdraw.is_texpaint && (Gtexdraw.stencil != NULL)) {
+ glActiveTexture(GL_TEXTURE1);
+ if (GPU_verify_image(Gtexdraw.stencil, NULL, false, false, false, false)) {
+ glEnable(GL_TEXTURE_2D);
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
+ glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE);
+ glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS);
+ glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_RGB, GL_TEXTURE);
+ glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_CONSTANT);
+ glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
+ glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, Gtexdraw.stencil_col);
+ if (!Gtexdraw.stencil_invert) {
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_ONE_MINUS_SRC_COLOR);
+ }
+ else {
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_COLOR);
+ }
+ }
+ glActiveTexture(GL_TEXTURE0);
+ }
+
Gtexdraw.color_profile = BKE_scene_check_color_management_enabled(scene);
Gtexdraw.use_game_mat = (RE_engines_find(scene->r.engine)->flag & RE_GAME) != 0;
Gtexdraw.use_backface_culling = (v3d->flag2 & V3D_BACKFACE_CULLING) != 0;
@@ -379,8 +429,24 @@ static void draw_textured_begin(Scene *scene, View3D *v3d, RegionView3D *rv3d, O
static void draw_textured_end(void)
{
- /* switch off textures */
- GPU_set_tpage(NULL, 0, 0);
+ if (Gtexdraw.ob->mode & OB_MODE_TEXTURE_PAINT) {
+ if (Gtexdraw.stencil != NULL) {
+ glActiveTexture(GL_TEXTURE1);
+ glDisable(GL_TEXTURE_2D);
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_COLOR);
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glActiveTexture(GL_TEXTURE0);
+ }
+ /* manual reset, since we don't use tpage */
+ glBindTexture(GL_TEXTURE_2D, 0);
+ /* force switch off textures */
+ GPU_clear_tpage(true);
+ }
+ else {
+ /* switch off textures */
+ GPU_set_tpage(NULL, 0, 0);
+ }
glShadeModel(GL_FLAT);
glDisable(GL_CULL_FACE);
@@ -456,7 +522,7 @@ static DMDrawOption draw_tface__set_draw(MTFace *tface, const bool UNUSED(has_mc
if (ma && (ma->game.flag & GEMAT_INVISIBLE)) return 0;
- if (tface)
+ if (tface || Gtexdraw.is_texpaint)
set_draw_settings_cached(0, tface, ma, Gtexdraw);
/* always use color from mcol, as set in update_tface_color_layer */
@@ -770,7 +836,8 @@ static void draw_mesh_textured_old(Scene *scene, View3D *v3d, RegionView3D *rv3d
Object *ob, DerivedMesh *dm, const int draw_flags)
{
Mesh *me = ob->data;
-
+ DMDrawFlag uvflag = DM_DRAW_USE_ACTIVE_UV;
+
/* correct for negative scale */
if (ob->transflag & OB_NEG_SCALE) glFrontFace(GL_CW);
else glFrontFace(GL_CCW);
@@ -780,6 +847,10 @@ static void draw_mesh_textured_old(Scene *scene, View3D *v3d, RegionView3D *rv3d
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+ if (ob->mode & OB_MODE_TEXTURE_PAINT) {
+ uvflag = DM_DRAW_USE_TEXPAINT_UV;
+ }
+
if (ob->mode & OB_MODE_EDIT) {
drawEMTFMapped_userData data;
@@ -789,7 +860,7 @@ static void draw_mesh_textured_old(Scene *scene, View3D *v3d, RegionView3D *rv3d
data.mf = DM_get_tessface_data_layer(dm, CD_MFACE);
data.tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
- dm->drawMappedFacesTex(dm, draw_em_tf_mapped__set_draw, compareDrawOptionsEm, &data);
+ dm->drawMappedFacesTex(dm, draw_em_tf_mapped__set_draw, compareDrawOptionsEm, &data, 0);
}
else if (draw_flags & DRAW_FACE_SELECT) {
if (ob->mode & OB_MODE_WEIGHT_PAINT)
@@ -801,15 +872,15 @@ static void draw_mesh_textured_old(Scene *scene, View3D *v3d, RegionView3D *rv3d
userData.mf = DM_get_tessface_data_layer(dm, CD_MFACE);
userData.tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
userData.me = me;
- dm->drawMappedFacesTex(dm, me->mpoly ? draw_tface_mapped__set_draw : NULL, compareDrawOptions, &userData);
+ dm->drawMappedFacesTex(dm, me->mpoly ? draw_tface_mapped__set_draw : NULL, compareDrawOptions, &userData, uvflag);
}
}
else {
if (GPU_buffer_legacy(dm)) {
if (draw_flags & DRAW_MODIFIERS_PREVIEW)
- dm->drawFacesTex(dm, draw_mcol__set_draw_legacy, NULL, NULL);
+ dm->drawFacesTex(dm, draw_mcol__set_draw_legacy, NULL, NULL, uvflag);
else
- dm->drawFacesTex(dm, draw_tface__set_draw_legacy, NULL, NULL);
+ dm->drawFacesTex(dm, draw_tface__set_draw_legacy, NULL, NULL, uvflag);
}
else {
drawTFace_userData userData;
@@ -820,7 +891,7 @@ static void draw_mesh_textured_old(Scene *scene, View3D *v3d, RegionView3D *rv3d
userData.tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
userData.me = NULL;
- dm->drawFacesTex(dm, draw_tface__set_draw, compareDrawOptions, &userData);
+ dm->drawFacesTex(dm, draw_tface__set_draw, compareDrawOptions, &userData, uvflag);
}
}
@@ -870,7 +941,7 @@ static void tex_mat_set_texture_cb(void *userData, int mat_nr, void *attribs)
int texture_set = 0;
/* draw image texture if we find one */
- if (ED_object_get_active_image(data->ob, mat_nr, &ima, &iuser, &node)) {
+ if (ED_object_get_active_image(data->ob, mat_nr, &ima, &iuser, &node, NULL)) {
/* get openl texture */
int mipmap = 1;
int bindcode = (ima) ? GPU_verify_image(ima, iuser, 0, 0, mipmap, false) : 0;
@@ -955,7 +1026,8 @@ void draw_mesh_textured(Scene *scene, View3D *v3d, RegionView3D *rv3d,
/* if not cycles, or preview-modifiers, or drawing matcaps */
if ((draw_flags & DRAW_MODIFIERS_PREVIEW) ||
(v3d->flag2 & V3D_SHOW_SOLID_MATCAP) ||
- (BKE_scene_use_new_shading_nodes(scene) == false))
+ (BKE_scene_use_new_shading_nodes(scene) == false) ||
+ ((ob->mode & OB_MODE_TEXTURE_PAINT) && ELEM(v3d->drawtype, OB_TEXTURE, OB_SOLID)))
{
draw_mesh_textured_old(scene, v3d, rv3d, ob, dm, draw_flags);
return;
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index c1689ef06db..13e010d2f97 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -86,6 +86,7 @@
#include "GPU_draw.h"
#include "GPU_extensions.h"
+#include "GPU_select.h"
#include "ED_mesh.h"
#include "ED_particle.h"
@@ -301,7 +302,7 @@ bool draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, const char dt)
if (BKE_scene_use_new_shading_nodes(scene))
return false;
- return (scene->gm.matmode == GAME_MAT_GLSL) && (dt > OB_SOLID);
+ return ((scene->gm.matmode == GAME_MAT_GLSL) || (v3d->drawtype == OB_MATERIAL)) && (dt > OB_SOLID);
}
static bool check_alpha_pass(Base *base)
@@ -1586,7 +1587,7 @@ static void draw_viewport_object_reconstruction(Scene *scene, Base *base, View3D
continue;
if (dflag & DRAW_PICKING)
- glLoadName(base->selcol + (tracknr << 16));
+ GPU_select_load_id(base->selcol + (tracknr << 16));
glPushMatrix();
glTranslatef(track->bundle_pos[0], track->bundle_pos[1], track->bundle_pos[2]);
@@ -1737,7 +1738,7 @@ static void draw_viewport_reconstruction(Scene *scene, Base *base, View3D *v3d,
}
if (dflag & DRAW_PICKING)
- glLoadName(base->selcol);
+ GPU_select_load_id(base->selcol);
}
/* flag similar to draw_object() */
@@ -4868,7 +4869,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
normalize_v3(imat[1]);
}
- if (ELEM3(draw_as, PART_DRAW_DOT, PART_DRAW_CROSS, PART_DRAW_LINE) &&
+ if (ELEM(draw_as, PART_DRAW_DOT, PART_DRAW_CROSS, PART_DRAW_LINE) &&
(part->draw_col > PART_DRAW_COL_MAT))
{
create_cdata = 1;
@@ -6479,7 +6480,7 @@ static bool drawmball(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
if (G.f & G_PICKSEL) {
ml->selcol1 = code;
- glLoadName(code++);
+ GPU_select_load_id(code++);
}
}
drawcircball(GL_LINE_LOOP, &(ml->x), ml->rad, imat);
@@ -6493,7 +6494,7 @@ static bool drawmball(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
if (G.f & G_PICKSEL) {
ml->selcol2 = code;
- glLoadName(code++);
+ GPU_select_load_id(code++);
}
drawcircball(GL_LINE_LOOP, &(ml->x), ml->rad * atanf(ml->s) / (float)M_PI_2, imat);
}
@@ -6782,7 +6783,7 @@ static void draw_bounding_volume(Object *ob, char type)
if (ob->type == OB_MESH) {
bb = BKE_mesh_boundbox_get(ob);
}
- else if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
+ else if (ELEM(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
bb = BKE_curve_boundbox_get(ob);
}
else if (ob->type == OB_MBALL) {
@@ -6839,7 +6840,7 @@ static void drawtexspace(Object *ob)
if (ob->type == OB_MESH) {
BKE_mesh_texspace_get(ob->data, loc, NULL, size);
}
- else if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
+ else if (ELEM(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
BKE_curve_texspace_get(ob->data, loc, NULL, size);
}
else if (ob->type == OB_MBALL) {
@@ -6877,7 +6878,7 @@ static void drawObjectSelect(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f);
glDepthMask(0);
- if (ELEM3(ob->type, OB_FONT, OB_CURVE, OB_SURF)) {
+ if (ELEM(ob->type, OB_FONT, OB_CURVE, OB_SURF)) {
DerivedMesh *dm = ob->derivedFinal;
bool has_faces = false;
@@ -6921,7 +6922,7 @@ static void drawObjectSelect(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
static void draw_wire_extra(Scene *scene, RegionView3D *rv3d, Object *ob, const unsigned char ob_wire_col[4])
{
- if (ELEM4(ob->type, OB_FONT, OB_CURVE, OB_SURF, OB_MBALL)) {
+ if (ELEM(ob->type, OB_FONT, OB_CURVE, OB_SURF, OB_MBALL)) {
if (scene->obedit == ob) {
UI_ThemeColor(TH_WIRE_EDIT);
@@ -6933,7 +6934,7 @@ static void draw_wire_extra(Scene *scene, RegionView3D *rv3d, Object *ob, const
ED_view3d_polygon_offset(rv3d, 1.0);
glDepthMask(0); /* disable write in zbuffer, selected edge wires show better */
- if (ELEM3(ob->type, OB_FONT, OB_CURVE, OB_SURF)) {
+ if (ELEM(ob->type, OB_FONT, OB_CURVE, OB_SURF)) {
if (ED_view3d_boundbox_clip(rv3d, ob->bb)) {
if (ob->derivedFinal) {
@@ -7182,7 +7183,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
if (ob->restrictflag & OB_RESTRICT_RENDER)
return;
- if (!has_particles && (ob->transflag & OB_DUPLI))
+ if (!has_particles && (ob->transflag & (OB_DUPLI & ~OB_DUPLIFRAMES)))
return;
}
}
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index 77a5ac1f689..8b76ec3a56d 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -43,6 +43,7 @@
#include "BLI_utildefines.h"
#include "BKE_context.h"
+#include "BKE_depsgraph.h"
#include "BKE_icons.h"
#include "BKE_library.h"
#include "BKE_main.h"
@@ -286,7 +287,7 @@ static void view3d_stop_render_preview(wmWindowManager *wm, ARegion *ar)
}
}
-void ED_view3d_shade_update(Main *bmain, View3D *v3d, ScrArea *sa)
+void ED_view3d_shade_update(Main *bmain, Scene *scene, View3D *v3d, ScrArea *sa)
{
wmWindowManager *wm = bmain->wm.first;
@@ -298,6 +299,10 @@ void ED_view3d_shade_update(Main *bmain, View3D *v3d, ScrArea *sa)
view3d_stop_render_preview(wm, ar);
}
}
+ else if (scene->obedit != NULL && scene->obedit->type == OB_MESH) {
+ /* Tag mesh to load edit data. */
+ DAG_id_tag_update(scene->obedit->data, 0);
+ }
}
/* ******************** default callbacks for view3d space ***************** */
@@ -483,6 +488,12 @@ static void view3d_main_area_init(wmWindowManager *wm, ARegion *ar)
keymap = WM_keymap_find(wm->defaultconf, "Object Mode", 0, 0);
WM_event_add_keymap_handler(&ar->handlers, keymap);
+ keymap = WM_keymap_find(wm->defaultconf, "Paint Curve", 0, 0);
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
+
+ keymap = WM_keymap_find(wm->defaultconf, "Curve", 0, 0);
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
+
keymap = WM_keymap_find(wm->defaultconf, "Image Paint", 0, 0);
WM_event_add_keymap_handler(&ar->handlers, keymap);
@@ -673,7 +684,7 @@ static void view3d_dropboxes(void)
WM_dropbox_add(lb, "MESH_OT_drop_named_image", view3d_ima_mesh_drop_poll, view3d_id_path_drop_copy);
WM_dropbox_add(lb, "OBJECT_OT_drop_named_image", view3d_ima_empty_drop_poll, view3d_id_path_drop_copy);
WM_dropbox_add(lb, "VIEW3D_OT_background_image_add", view3d_ima_bg_drop_poll, view3d_id_path_drop_copy);
- WM_dropbox_add(lb, "OBJECT_OT_group_instance_add", view3d_group_drop_poll, view3d_group_drop_copy);
+ WM_dropbox_add(lb, "OBJECT_OT_group_instance_add", view3d_group_drop_poll, view3d_group_drop_copy);
}
@@ -779,7 +790,7 @@ static void view3d_main_area_listener(bScreen *sc, ScrArea *sa, ARegion *ar, wmN
break;
case ND_NLA:
case ND_KEYFRAME:
- if (ELEM3(wmn->action, NA_EDITED, NA_ADDED, NA_REMOVED))
+ if (ELEM(wmn->action, NA_EDITED, NA_ADDED, NA_REMOVED))
ED_region_tag_redraw(ar);
break;
case ND_ANIMCHAN:
@@ -860,14 +871,18 @@ static void view3d_main_area_listener(bScreen *sc, ScrArea *sa, ARegion *ar, wmN
switch (wmn->data) {
case ND_SHADING:
case ND_NODES:
+ {
+ Object *ob = OBACT;
if ((v3d->drawtype == OB_MATERIAL) ||
+ (ob && (ob->mode == OB_MODE_TEXTURE_PAINT)) ||
(v3d->drawtype == OB_TEXTURE &&
- (scene->gm.matmode == GAME_MAT_GLSL ||
- BKE_scene_use_new_shading_nodes(scene))))
+ (scene->gm.matmode == GAME_MAT_GLSL ||
+ BKE_scene_use_new_shading_nodes(scene))))
{
ED_region_tag_redraw(ar);
}
break;
+ }
case ND_SHADING_DRAW:
case ND_SHADING_LINKS:
ED_region_tag_redraw(ar);
@@ -905,7 +920,7 @@ static void view3d_main_area_listener(bScreen *sc, ScrArea *sa, ARegion *ar, wmN
ED_region_tag_redraw(ar);
break;
case NC_MOVIECLIP:
- if (wmn->data == ND_DISPLAY)
+ if (wmn->data == ND_DISPLAY || wmn->action == NA_EDITED)
ED_region_tag_redraw(ar);
break;
case NC_SPACE:
@@ -1030,7 +1045,7 @@ static void view3d_buttons_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa
break;
case ND_NLA:
case ND_KEYFRAME:
- if (ELEM3(wmn->action, NA_EDITED, NA_ADDED, NA_REMOVED))
+ if (ELEM(wmn->action, NA_EDITED, NA_ADDED, NA_REMOVED))
ED_region_tag_redraw(ar);
break;
}
@@ -1099,6 +1114,11 @@ static void view3d_buttons_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa
if (wmn->data == ND_DATA || wmn->action == NA_EDITED)
ED_region_tag_redraw(ar);
break;
+ case NC_IMAGE:
+ /* Update for the image layers in texture paint. */
+ if (wmn->action == NA_EDITED)
+ 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 dd08339cc94..004b3e1b7d3 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -881,7 +881,7 @@ static void draw_selected_name(Scene *scene, Object *ob, rcti *rect)
}
}
}
- else if (ELEM3(ob->type, OB_MESH, OB_LATTICE, OB_CURVE)) {
+ else if (ELEM(ob->type, OB_MESH, OB_LATTICE, OB_CURVE)) {
Key *key = NULL;
KeyBlock *kb = NULL;
@@ -1287,6 +1287,12 @@ static void backdrawview3d(Scene *scene, ARegion *ar, View3D *v3d)
{
/* do nothing */
}
+ /* texture paint mode sampling */
+ else if (base && (base->object->mode & OB_MODE_TEXTURE_PAINT) &&
+ (v3d->drawtype > OB_WIRE))
+ {
+ /* do nothing */
+ }
else if ((base && (base->object->mode & OB_MODE_PARTICLE_EDIT)) &&
v3d->drawtype > OB_WIRE && (v3d->flag & V3D_ZBUF_SELECT))
{
@@ -2509,7 +2515,7 @@ CustomDataMask ED_view3d_datamask(Scene *scene, View3D *v3d)
mask |= CD_MASK_ORCO;
}
else {
- if (scene->gm.matmode == GAME_MAT_GLSL)
+ if (scene->gm.matmode == GAME_MAT_GLSL || v3d->drawtype == OB_MATERIAL)
mask |= CD_MASK_ORCO;
}
}
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index e3260dba485..4ca9eea578c 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -307,12 +307,12 @@ static void view3d_boxview_clip(ScrArea *sa)
}
for (val = 0; val < 8; val++) {
- if (ELEM4(val, 0, 3, 4, 7))
+ if (ELEM(val, 0, 3, 4, 7))
bb->vec[val][0] = -x1 - ofs[0];
else
bb->vec[val][0] = x1 - ofs[0];
- if (ELEM4(val, 0, 1, 4, 5))
+ if (ELEM(val, 0, 1, 4, 5))
bb->vec[val][1] = -y1 - ofs[1];
else
bb->vec[val][1] = y1 - ofs[1];
@@ -465,11 +465,13 @@ void ED_view3d_quadview_update(ScrArea *sa, ARegion *ar, bool do_clip)
* properties are always being edited, weak */
viewlock = rv3d->viewlock;
- if ((viewlock & RV3D_LOCKED) == 0)
+ if ((viewlock & RV3D_LOCKED) == 0) {
+ do_clip = (viewlock & RV3D_BOXCLIP) != 0;
viewlock = 0;
- else if ((viewlock & RV3D_BOXVIEW) == 0) {
- viewlock &= ~RV3D_BOXCLIP;
+ }
+ else if ((viewlock & RV3D_BOXVIEW) == 0 && (viewlock & RV3D_BOXCLIP) != 0) {
do_clip = true;
+ viewlock &= ~RV3D_BOXCLIP;
}
for (; ar; ar = ar->prev) {
@@ -3243,6 +3245,8 @@ static int render_border_exec(bContext *C, wmOperator *op)
void VIEW3D_OT_render_border(wmOperatorType *ot)
{
+ PropertyRNA *prop;
+
/* identifiers */
ot->name = "Set Render Border";
ot->description = "Set the boundaries of the border render and enable border render";
@@ -3262,7 +3266,8 @@ void VIEW3D_OT_render_border(wmOperatorType *ot)
/* rna */
WM_operator_properties_border(ot);
- RNA_def_boolean(ot->srna, "camera_only", 0, "Camera Only", "Set render border for camera view and final render only");
+ prop = RNA_def_boolean(ot->srna, "camera_only", 0, "Camera Only", "Set render border for camera view and final render only");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
}
/* ********************* Clear render border operator ****************** */
@@ -4435,7 +4440,7 @@ void ED_view3d_cursor3d_position(bContext *C, float fp[3], const int mval[2])
}
}
-static void view3d_cursor3d_update(bContext *C, const int *mval)
+void ED_view3d_cursor3d_update(bContext *C, const int mval[2])
{
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
@@ -4451,7 +4456,7 @@ static void view3d_cursor3d_update(bContext *C, const int *mval)
static int view3d_cursor3d_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- view3d_cursor3d_update(C, event->mval);
+ ED_view3d_cursor3d_update(C, event->mval);
op->customdata = SET_INT_IN_POINTER(event->type);
WM_event_add_modal_handler(C, op);
@@ -4468,7 +4473,7 @@ static int view3d_cursor3d_modal(bContext *C, wmOperator *op, const wmEvent *eve
switch (event->type) {
case MOUSEMOVE:
- view3d_cursor3d_update(C, event->mval);
+ ED_view3d_cursor3d_update(C, event->mval);
break;
case LEFTMOUSE:
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c
index e3d0e87066b..a88724a1cdd 100644
--- a/source/blender/editors/space_view3d/view3d_header.c
+++ b/source/blender/editors/space_view3d/view3d_header.c
@@ -32,6 +32,7 @@
#include <stdio.h>
#include <stdlib.h>
+#include "DNA_brush_types.h"
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
@@ -45,6 +46,7 @@
#include "BKE_depsgraph.h"
#include "BKE_main.h"
#include "BKE_modifier.h"
+#include "BKE_paint.h"
#include "BKE_screen.h"
#include "BKE_editmesh.h"
@@ -308,7 +310,7 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C)
/* mode */
if (ob) {
modeselect = ob->mode;
- is_paint = ELEM4(ob->mode, OB_MODE_SCULPT, OB_MODE_VERTEX_PAINT, OB_MODE_WEIGHT_PAINT, OB_MODE_TEXTURE_PAINT);
+ is_paint = ELEM(ob->mode, OB_MODE_SCULPT, OB_MODE_VERTEX_PAINT, OB_MODE_WEIGHT_PAINT, OB_MODE_TEXTURE_PAINT);
}
else {
modeselect = OB_MODE_OBJECT;
@@ -336,8 +338,7 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C)
uiItemR(layout, &v3dptr, "viewport_shade", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
if (obedit == NULL && is_paint) {
-
- if (ob->mode & OB_MODE_WEIGHT_PAINT) {
+ if (ob->mode & OB_MODE_ALL_PAINT) {
/* Only for Weight Paint. makes no sense in other paint modes. */
row = uiLayoutRow(layout, true);
uiItemR(row, &v3dptr, "pivot_point", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index f61f58c12db..46ea52054c5 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -1194,15 +1194,32 @@ static short selectbuffer_ret_hits_5(unsigned int *buffer, const short hits15, c
/* we want a select buffer with bones, if there are... */
/* so check three selection levels and compare */
-static short mixed_bones_object_selectbuffer(ViewContext *vc, unsigned int *buffer, const int mval[2])
+static short mixed_bones_object_selectbuffer(ViewContext *vc, unsigned int *buffer, const int mval[2], bool *p_do_nearest, bool enumerate)
{
rcti rect;
int offs;
short hits15, hits9 = 0, hits5 = 0;
bool has_bones15 = false, has_bones9 = false, has_bones5 = false;
-
+ static int last_mval[2] = {-100, -100};
+ bool do_nearest = false;
+ View3D *v3d = vc->v3d;
+
+ /* define if we use solid nearest select or not */
+ if (v3d->drawtype > OB_WIRE) {
+ do_nearest = true;
+ if (len_manhattan_v2v2_int(mval, last_mval) < 3) {
+ do_nearest = false;
+ }
+ }
+ copy_v2_v2_int(last_mval, mval);
+
+ if (p_do_nearest)
+ *p_do_nearest = do_nearest;
+
+ do_nearest = do_nearest && !enumerate;
+
BLI_rcti_init(&rect, mval[0] - 14, mval[0] + 14, mval[1] - 14, mval[1] + 14);
- hits15 = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect);
+ hits15 = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect, do_nearest);
if (hits15 == 1) {
return selectbuffer_ret_hits_15(buffer, hits15);
}
@@ -1211,7 +1228,7 @@ static short mixed_bones_object_selectbuffer(ViewContext *vc, unsigned int *buff
offs = 4 * hits15;
BLI_rcti_init(&rect, mval[0] - 9, mval[0] + 9, mval[1] - 9, mval[1] + 9);
- hits9 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect);
+ hits9 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, do_nearest);
if (hits9 == 1) {
return selectbuffer_ret_hits_9(buffer, hits15, hits9);
}
@@ -1220,7 +1237,7 @@ static short mixed_bones_object_selectbuffer(ViewContext *vc, unsigned int *buff
offs += 4 * hits9;
BLI_rcti_init(&rect, mval[0] - 5, mval[0] + 5, mval[1] - 5, mval[1] + 5);
- hits5 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect);
+ hits5 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, do_nearest);
if (hits5 == 1) {
return selectbuffer_ret_hits_5(buffer, hits15, hits9, hits5);
}
@@ -1242,25 +1259,13 @@ static short mixed_bones_object_selectbuffer(ViewContext *vc, unsigned int *buff
}
/* returns basact */
-static Base *mouse_select_eval_buffer(ViewContext *vc, unsigned int *buffer, int hits, const int mval[2],
- Base *startbase, bool has_bones)
+static Base *mouse_select_eval_buffer(ViewContext *vc, unsigned int *buffer, int hits,
+ Base *startbase, bool has_bones, bool do_nearest)
{
Scene *scene = vc->scene;
View3D *v3d = vc->v3d;
Base *base, *basact = NULL;
- static int lastmval[2] = {-100, -100};
int a;
- bool do_nearest = false;
-
- /* define if we use solid nearest select or not */
- if (v3d->drawtype > OB_WIRE) {
- do_nearest = true;
- if (ABS(mval[0] - lastmval[0]) < 3 && ABS(mval[1] - lastmval[1]) < 3) {
- if (!has_bones) /* hrms, if theres bones we always do nearest */
- do_nearest = false;
- }
- }
- lastmval[0] = mval[0]; lastmval[1] = mval[1];
if (do_nearest) {
unsigned int min = 0xFFFFFFFF;
@@ -1343,16 +1348,17 @@ Base *ED_view3d_give_base_under_cursor(bContext *C, const int mval[2])
Base *basact = NULL;
unsigned int buffer[4 * MAXPICKBUF];
int hits;
+ bool do_nearest;
/* setup view context for argument to callbacks */
view3d_operator_needs_opengl(C);
view3d_set_viewcontext(C, &vc);
- hits = mixed_bones_object_selectbuffer(&vc, buffer, mval);
+ hits = mixed_bones_object_selectbuffer(&vc, buffer, mval, &do_nearest, false);
if (hits > 0) {
const bool has_bones = selectbuffer_has_bones(buffer, hits);
- basact = mouse_select_eval_buffer(&vc, buffer, hits, mval, vc.scene->base.first, has_bones);
+ basact = mouse_select_eval_buffer(&vc, buffer, hits, vc.scene->base.first, has_bones, do_nearest);
}
return basact;
@@ -1439,10 +1445,11 @@ static bool mouse_select(bContext *C, const int mval[2],
}
else {
unsigned int buffer[4 * MAXPICKBUF];
+ bool do_nearest;
/* if objects have posemode set, the bones are in the same selection buffer */
- hits = mixed_bones_object_selectbuffer(&vc, buffer, mval);
+ hits = mixed_bones_object_selectbuffer(&vc, buffer, mval, &do_nearest, enumerate);
if (hits > 0) {
/* note: bundles are handling in the same way as bones */
@@ -1453,7 +1460,7 @@ static bool mouse_select(bContext *C, const int mval[2],
basact = object_mouse_select_menu(C, &vc, buffer, hits, mval, toggle);
}
else {
- basact = mouse_select_eval_buffer(&vc, buffer, hits, mval, startbase, has_bones);
+ basact = mouse_select_eval_buffer(&vc, buffer, hits, startbase, has_bones, do_nearest);
}
if (has_bones && basact) {
@@ -1511,7 +1518,7 @@ static bool mouse_select(bContext *C, const int mval[2],
if (!changed) {
/* fallback to regular object selection if no new bundles were selected,
* allows to select object parented to reconstruction object */
- basact = mouse_select_eval_buffer(&vc, buffer, hits, mval, startbase, 0);
+ basact = mouse_select_eval_buffer(&vc, buffer, hits, startbase, 0, do_nearest);
}
}
}
@@ -1873,7 +1880,7 @@ static int do_meta_box_select(ViewContext *vc, rcti *rect, bool select, bool ext
unsigned int buffer[4 * MAXPICKBUF];
short hits;
- hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, rect);
+ hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, rect, false);
if (extend == false && select)
BKE_mball_deselect_all(mb);
@@ -1907,7 +1914,7 @@ static int do_armature_box_select(ViewContext *vc, rcti *rect, bool select, bool
unsigned int buffer[4 * MAXPICKBUF];
short hits;
- hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, rect);
+ hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, rect, false);
/* clear flag we use to detect point was affected */
for (ebone = arm->edbo->first; ebone; ebone = ebone->next)
@@ -2001,7 +2008,7 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, b
/* selection buffer now has bones potentially too, so we add MAXPICKBUF */
vbuffer = MEM_mallocN(4 * (totobj + MAXPICKBUF) * sizeof(unsigned int), "selection buffer");
- hits = view3d_opengl_select(vc, vbuffer, 4 * (totobj + MAXPICKBUF), rect);
+ hits = view3d_opengl_select(vc, vbuffer, 4 * (totobj + MAXPICKBUF), rect, false);
/*
* LOGIC NOTES (theeth):
* The buffer and ListBase have the same relative order, which makes the selection
diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c
index 716f4b10fae..6d28accbc7b 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -56,6 +56,7 @@
#include "BIF_glutil.h"
#include "GPU_draw.h"
+#include "GPU_select.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -955,6 +956,78 @@ void view3d_viewmatrix_set(Scene *scene, View3D *v3d, RegionView3D *rv3d)
}
}
+static void view3d_select_loop(ViewContext *vc, Scene *scene, View3D *v3d, ARegion *ar, bool use_obedit_skip)
+{
+ short code = 1;
+ char dt;
+ short dtx;
+
+ if (vc->obedit && vc->obedit->type == OB_MBALL) {
+ draw_object(scene, ar, v3d, BASACT, DRAW_PICKING | DRAW_CONSTCOLOR);
+ }
+ else if ((vc->obedit && vc->obedit->type == OB_ARMATURE)) {
+ /* if not drawing sketch, draw bones */
+ if (!BDR_drawSketchNames(vc)) {
+ draw_object(scene, ar, v3d, BASACT, DRAW_PICKING | DRAW_CONSTCOLOR);
+ }
+ }
+ else {
+ Base *base;
+
+ v3d->xray = true; /* otherwise it postpones drawing */
+ for (base = scene->base.first; base; base = base->next) {
+ if (base->lay & v3d->lay) {
+
+ if ((base->object->restrictflag & OB_RESTRICT_SELECT) ||
+ (use_obedit_skip && (scene->obedit->data == base->object->data)))
+ {
+ base->selcol = 0;
+ }
+ else {
+ base->selcol = code;
+
+ if (GPU_select_load_id(code)) {
+ draw_object(scene, ar, v3d, base, DRAW_PICKING | DRAW_CONSTCOLOR);
+
+ /* we draw duplicators for selection too */
+ if ((base->object->transflag & OB_DUPLI)) {
+ ListBase *lb;
+ DupliObject *dob;
+ Base tbase;
+
+ tbase.flag = OB_FROMDUPLI;
+ lb = object_duplilist(G.main->eval_ctx, scene, base->object);
+
+ for (dob = lb->first; dob; dob = dob->next) {
+ float omat[4][4];
+
+ tbase.object = dob->ob;
+ copy_m4_m4(omat, dob->ob->obmat);
+ copy_m4_m4(dob->ob->obmat, dob->mat);
+
+ /* extra service: draw the duplicator in drawtype of parent */
+ /* MIN2 for the drawtype to allow bounding box objects in groups for lods */
+ dt = tbase.object->dt; tbase.object->dt = MIN2(tbase.object->dt, base->object->dt);
+ dtx = tbase.object->dtx; tbase.object->dtx = base->object->dtx;
+
+ draw_object(scene, ar, v3d, &tbase, DRAW_PICKING | DRAW_CONSTCOLOR);
+
+ tbase.object->dt = dt;
+ tbase.object->dtx = dtx;
+
+ copy_m4_m4(dob->ob->obmat, omat);
+ }
+ free_object_duplilist(lb);
+ }
+ }
+ code++;
+ }
+ }
+ }
+ v3d->xray = false; /* restore */
+ }
+}
+
/**
* \warning be sure to account for a negative return value
* This is an error, "Too many objects in select buffer"
@@ -962,17 +1035,16 @@ void view3d_viewmatrix_set(Scene *scene, View3D *v3d, RegionView3D *rv3d)
*
* \note (vc->obedit == NULL) can be set to explicitly skip edit-object selection.
*/
-short view3d_opengl_select(ViewContext *vc, unsigned int *buffer, unsigned int bufsize, const rcti *input)
+short view3d_opengl_select(ViewContext *vc, unsigned int *buffer, unsigned int bufsize, const rcti *input, bool do_nearest)
{
Scene *scene = vc->scene;
View3D *v3d = vc->v3d;
ARegion *ar = vc->ar;
- rctf rect;
- short code, hits;
- char dt;
- short dtx;
+ rctf rect, selrect;
+ short hits;
const bool use_obedit_skip = (scene->obedit != NULL) && (vc->obedit == NULL);
-
+ const bool do_passes = do_nearest && GPU_select_query_check_active();
+
G.f |= G_PICKSEL;
/* case not a border select */
@@ -985,6 +1057,8 @@ short view3d_opengl_select(ViewContext *vc, unsigned int *buffer, unsigned int b
else {
BLI_rctf_rcti_copy(&rect, input);
}
+
+ selrect = rect;
view3d_winmatrix_set(ar, v3d, &rect);
mul_m4_m4m4(vc->rv3d->persmat, vc->rv3d->winmat, vc->rv3d->viewmat);
@@ -997,78 +1071,24 @@ short view3d_opengl_select(ViewContext *vc, unsigned int *buffer, unsigned int b
if (vc->rv3d->rflag & RV3D_CLIPPING)
ED_view3d_clipping_set(vc->rv3d);
- glSelectBuffer(bufsize, (GLuint *)buffer);
- glRenderMode(GL_SELECT);
- glInitNames(); /* these two calls whatfor? It doesnt work otherwise */
- glPushName(-1);
- code = 1;
+ if (do_passes)
+ GPU_select_begin(buffer, bufsize, &selrect, GPU_SELECT_NEAREST_FIRST_PASS, 0);
+ else
+ GPU_select_begin(buffer, bufsize, &selrect, GPU_SELECT_ALL, 0);
+
+ view3d_select_loop(vc, scene, v3d, ar, use_obedit_skip);
+
+ hits = GPU_select_end();
- if (vc->obedit && vc->obedit->type == OB_MBALL) {
- draw_object(scene, ar, v3d, BASACT, DRAW_PICKING | DRAW_CONSTCOLOR);
- }
- else if ((vc->obedit && vc->obedit->type == OB_ARMATURE)) {
- /* if not drawing sketch, draw bones */
- if (!BDR_drawSketchNames(vc)) {
- draw_object(scene, ar, v3d, BASACT, DRAW_PICKING | DRAW_CONSTCOLOR);
- }
- }
- else {
- Base *base;
-
- v3d->xray = true; /* otherwise it postpones drawing */
- for (base = scene->base.first; base; base = base->next) {
- if (base->lay & v3d->lay) {
-
- if ((base->object->restrictflag & OB_RESTRICT_SELECT) ||
- (use_obedit_skip && (scene->obedit->data == base->object->data)))
- {
- base->selcol = 0;
- }
- else {
- base->selcol = code;
- glLoadName(code);
- draw_object(scene, ar, v3d, base, DRAW_PICKING | DRAW_CONSTCOLOR);
-
- /* we draw duplicators for selection too */
- if ((base->object->transflag & OB_DUPLI)) {
- ListBase *lb;
- DupliObject *dob;
- Base tbase;
-
- tbase.flag = OB_FROMDUPLI;
- lb = object_duplilist(G.main->eval_ctx, scene, base->object);
-
- for (dob = lb->first; dob; dob = dob->next) {
- float omat[4][4];
-
- tbase.object = dob->ob;
- copy_m4_m4(omat, dob->ob->obmat);
- copy_m4_m4(dob->ob->obmat, dob->mat);
-
- /* extra service: draw the duplicator in drawtype of parent */
- /* MIN2 for the drawtype to allow bounding box objects in groups for lods */
- dt = tbase.object->dt; tbase.object->dt = MIN2(tbase.object->dt, base->object->dt);
- dtx = tbase.object->dtx; tbase.object->dtx = base->object->dtx;
-
- draw_object(scene, ar, v3d, &tbase, DRAW_PICKING | DRAW_CONSTCOLOR);
-
- tbase.object->dt = dt;
- tbase.object->dtx = dtx;
-
- copy_m4_m4(dob->ob->obmat, omat);
- }
- free_object_duplilist(lb);
- }
- code++;
- }
- }
- }
- v3d->xray = false; /* restore */
+ /* second pass, to get the closest object to camera */
+ if (do_passes) {
+ GPU_select_begin(buffer, bufsize, &selrect, GPU_SELECT_NEAREST_SECOND_PASS, hits);
+
+ view3d_select_loop(vc, scene, v3d, ar, use_obedit_skip);
+
+ GPU_select_end();
}
-
- glPopName(); /* see above (pushname) */
- hits = glRenderMode(GL_RENDER);
-
+
G.f &= ~G_PICKSEL;
view3d_winmatrix_set(ar, v3d, NULL);
mul_m4_m4m4(vc->rv3d->persmat, vc->rv3d->winmat, vc->rv3d->viewmat);
@@ -1285,7 +1305,7 @@ static bool view3d_localview_init(
return ok;
}
-static void restore_localviewdata(wmWindowManager *wm, wmWindow *win, Main *bmain, ScrArea *sa, const int smooth_viewtx)
+static void restore_localviewdata(wmWindowManager *wm, wmWindow *win, Main *bmain, Scene *scene, ScrArea *sa, const int smooth_viewtx)
{
const bool free = true;
ARegion *ar;
@@ -1335,7 +1355,7 @@ static void restore_localviewdata(wmWindowManager *wm, wmWindow *win, Main *bmai
}
}
- ED_view3d_shade_update(bmain, v3d, sa);
+ ED_view3d_shade_update(bmain, scene, v3d, sa);
}
}
}
@@ -1352,7 +1372,7 @@ static bool view3d_localview_exit(
locallay = v3d->lay & 0xFF000000;
- restore_localviewdata(wm, win, bmain, sa, smooth_viewtx);
+ restore_localviewdata(wm, win, bmain, scene, sa, smooth_viewtx);
/* for when in other window the layers have changed */
if (v3d->scenelock) v3d->lay = scene->lay;
diff --git a/source/blender/editors/transform/CMakeLists.txt b/source/blender/editors/transform/CMakeLists.txt
index 7765dd511b4..3ad5d94efd6 100644
--- a/source/blender/editors/transform/CMakeLists.txt
+++ b/source/blender/editors/transform/CMakeLists.txt
@@ -24,6 +24,7 @@ set(INC
../../blenkernel
../../blenlib
../../bmesh
+ ../../gpu
../../ikplugin
../../makesdna
../../makesrna
diff --git a/source/blender/editors/transform/SConscript b/source/blender/editors/transform/SConscript
index f3c8c13647a..4f47062e3a3 100644
--- a/source/blender/editors/transform/SConscript
+++ b/source/blender/editors/transform/SConscript
@@ -40,6 +40,7 @@ incs = [
'../../ikplugin',
'../../makesdna',
'../../makesrna',
+ '../../gpu',
'../../windowmanager',
]
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index a53b4a75b20..58dee620a61 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -86,6 +86,9 @@
#include "transform.h"
+/* Disabling, since when you type you know what you are doing, and being able to set it to zero is handy. */
+// #define USE_NUM_NO_ZERO
+
#define MAX_INFO_LEN 256
static void drawTransformApply(const struct bContext *C, ARegion *ar, void *arg);
@@ -190,9 +193,9 @@ static bool transdata_check_local_center(TransInfo *t, short around)
{
return ((around == V3D_LOCAL) && (
(t->flag & (T_OBJECT | T_POSE)) ||
- (t->obedit && ELEM4(t->obedit->type, OB_MESH, OB_CURVE, OB_MBALL, OB_ARMATURE)) ||
+ (t->obedit && ELEM(t->obedit->type, OB_MESH, OB_CURVE, OB_MBALL, OB_ARMATURE)) ||
(t->spacetype == SPACE_IPO) ||
- (t->options & (CTX_MOVIECLIP | CTX_MASK)))
+ (t->options & (CTX_MOVIECLIP | CTX_MASK | CTX_PAINT_CURVE)))
);
}
@@ -263,17 +266,27 @@ static void convertViewVec2D_mask(View2D *v2d, float r_vec[3], int dx, int dy)
void convertViewVec(TransInfo *t, float r_vec[3], int dx, int dy)
{
if ((t->spacetype == SPACE_VIEW3D) && (t->ar->regiontype == RGN_TYPE_WINDOW)) {
- const float mval_f[2] = {(float)dx, (float)dy};
- ED_view3d_win_to_delta(t->ar, mval_f, r_vec, t->zfac);
+ if (t->options & CTX_PAINT_CURVE) {
+ r_vec[0] = dx;
+ r_vec[1] = dy;
+ }
+ else { const float mval_f[2] = {(float)dx, (float)dy};
+ ED_view3d_win_to_delta(t->ar, mval_f, r_vec, t->zfac);
+ }
}
else if (t->spacetype == SPACE_IMAGE) {
float aspx, aspy;
if (t->options & CTX_MASK) {
-
convertViewVec2D_mask(t->view, r_vec, dx, dy);
ED_space_image_get_aspect(t->sa->spacedata.first, &aspx, &aspy);
}
+ else if (t->options & CTX_PAINT_CURVE) {
+ r_vec[0] = dx;
+ r_vec[1] = dy;
+
+ aspx = aspy = 1.0;
+ }
else {
convertViewVec2D(t->view, r_vec, dx, dy);
ED_space_image_get_uv_aspect(t->sa->spacedata.first, &aspx, &aspy);
@@ -351,6 +364,10 @@ void projectIntViewEx(TransInfo *t, const float vec[3], int adr[2], const eV3DPr
adr[0] = v[0];
adr[1] = v[1];
}
+ else if (t->options & CTX_PAINT_CURVE) {
+ adr[0] = vec[0];
+ adr[1] = vec[1];
+ }
else {
float aspx, aspy, v[2];
@@ -452,7 +469,11 @@ void projectFloatViewEx(TransInfo *t, const float vec[3], float adr[2], const eV
switch (t->spacetype) {
case SPACE_VIEW3D:
{
- if (t->ar->regiontype == RGN_TYPE_WINDOW) {
+ if (t->options & CTX_PAINT_CURVE) {
+ adr[0] = vec[0];
+ adr[1] = vec[1];
+ }
+ else if (t->ar->regiontype == RGN_TYPE_WINDOW) {
/* allow points behind the view [#33643] */
if (ED_view3d_project_float_global(t->ar, vec, adr, flag) != V3D_PROJ_RET_OK) {
/* XXX, 2.64 and prior did this, weak! */
@@ -480,7 +501,7 @@ void projectFloatView(TransInfo *t, const float vec[3], float adr[2])
void applyAspectRatio(TransInfo *t, float vec[2])
{
- if ((t->spacetype == SPACE_IMAGE) && (t->mode == TFM_TRANSLATION)) {
+ if ((t->spacetype == SPACE_IMAGE) && (t->mode == TFM_TRANSLATION) && !(t->options & CTX_PAINT_CURVE)) {
SpaceImage *sima = t->sa->spacedata.first;
float aspx, aspy;
@@ -557,17 +578,23 @@ void removeAspectRatio(TransInfo *t, float vec[2])
static void viewRedrawForce(const bContext *C, TransInfo *t)
{
if (t->spacetype == SPACE_VIEW3D) {
- /* Do we need more refined tags? */
- if (t->flag & T_POSE)
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
- else
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+ if (t->options & CTX_PAINT_CURVE) {
+ wmWindow *window = CTX_wm_window(C);
+ WM_paint_cursor_tag_redraw(window, t->ar);
+ }
+ else {
+ /* Do we need more refined tags? */
+ if (t->flag & T_POSE)
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
+ else
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
- /* for realtime animation record - send notifiers recognised by animation editors */
- // XXX: is this notifier a lame duck?
- if ((t->animtimer) && IS_AUTOKEY_ON(t->scene))
- WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, NULL);
-
+ /* for realtime animation record - send notifiers recognised by animation editors */
+ // XXX: is this notifier a lame duck?
+ if ((t->animtimer) && IS_AUTOKEY_ON(t->scene))
+ WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, NULL);
+
+ }
}
else if (t->spacetype == SPACE_ACTION) {
//SpaceAction *saction = (SpaceAction *)t->sa->spacedata.first;
@@ -593,6 +620,10 @@ static void viewRedrawForce(const bContext *C, TransInfo *t)
WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
}
+ else if (t->options & CTX_PAINT_CURVE) {
+ wmWindow *window = CTX_wm_window(C);
+ WM_paint_cursor_tag_redraw(window, t->ar);
+ }
else {
// XXX how to deal with lock?
SpaceImage *sima = (SpaceImage *)t->sa->spacedata.first;
@@ -646,7 +677,7 @@ static void viewRedrawPost(bContext *C, TransInfo *t)
allqueue(REDRAWIMAGE, 0);
allqueue(REDRAWVIEW3D, 0);
}
- else if (ELEM3(t->spacetype, SPACE_ACTION, SPACE_NLA, SPACE_IPO)) {
+ else if (ELEM(t->spacetype, SPACE_ACTION, SPACE_NLA, SPACE_IPO)) {
allqueue(REDRAWVIEW3D, 0);
allqueue(REDRAWACTION, 0);
allqueue(REDRAWNLA, 0);
@@ -969,7 +1000,7 @@ int transformEvent(TransInfo *t, const wmEvent *event)
break;
case TFM_MODAL_TRANSLATE:
/* only switch when... */
- if (ELEM5(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_EDGE_SLIDE, TFM_VERT_SLIDE)) {
+ if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_EDGE_SLIDE, TFM_VERT_SLIDE)) {
resetTransModal(t);
resetTransRestrictions(t);
restoreTransObjects(t);
@@ -1025,7 +1056,7 @@ int transformEvent(TransInfo *t, const wmEvent *event)
case TFM_MODAL_ROTATE:
/* only switch when... */
if (!(t->options & CTX_TEXTURE) && !(t->options & (CTX_MOVIECLIP | CTX_MASK))) {
- if (ELEM6(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_TRANSLATION, TFM_EDGE_SLIDE, TFM_VERT_SLIDE)) {
+ if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_TRANSLATION, TFM_EDGE_SLIDE, TFM_VERT_SLIDE)) {
resetTransModal(t);
resetTransRestrictions(t);
@@ -1045,7 +1076,7 @@ int transformEvent(TransInfo *t, const wmEvent *event)
break;
case TFM_MODAL_RESIZE:
/* only switch when... */
- if (ELEM5(t->mode, TFM_ROTATION, TFM_TRANSLATION, TFM_TRACKBALL, TFM_EDGE_SLIDE, TFM_VERT_SLIDE)) {
+ if (ELEM(t->mode, TFM_ROTATION, TFM_TRANSLATION, TFM_TRACKBALL, TFM_EDGE_SLIDE, TFM_VERT_SLIDE)) {
/* Scale isn't normally very useful after extrude along normals, see T39756 */
if ((t->con.mode & CON_APPLY) && (t->con.orientation == V3D_MANIP_NORMAL)) {
@@ -1308,7 +1339,7 @@ int transformEvent(TransInfo *t, const wmEvent *event)
break;
case GKEY:
/* only switch when... */
- if (ELEM3(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL) ) {
+ if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL)) {
resetTransModal(t);
resetTransRestrictions(t);
restoreTransObjects(t);
@@ -1320,7 +1351,7 @@ int transformEvent(TransInfo *t, const wmEvent *event)
break;
case SKEY:
/* only switch when... */
- if (ELEM3(t->mode, TFM_ROTATION, TFM_TRANSLATION, TFM_TRACKBALL) ) {
+ if (ELEM(t->mode, TFM_ROTATION, TFM_TRANSLATION, TFM_TRACKBALL)) {
resetTransModal(t);
resetTransRestrictions(t);
restoreTransObjects(t);
@@ -1333,7 +1364,7 @@ int transformEvent(TransInfo *t, const wmEvent *event)
case RKEY:
/* only switch when... */
if (!(t->options & CTX_TEXTURE)) {
- if (ELEM4(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_TRANSLATION) ) {
+ if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_TRANSLATION)) {
resetTransModal(t);
resetTransRestrictions(t);
@@ -2065,7 +2096,7 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
* moded are available from manipulator and doing such check could
* lead to keymap conflicts for other modes (see #31584)
*/
- if (ELEM3(mode, TFM_TRANSLATION, TFM_ROTATION, TFM_RESIZE)) {
+ if (ELEM(mode, TFM_TRANSLATION, TFM_ROTATION, TFM_RESIZE)) {
wmKeyMapItem *kmi;
for (kmi = t->keymap->items.first; kmi; kmi = kmi->next) {
@@ -3085,9 +3116,11 @@ static void initResize(TransInfo *t)
t->num.flag |= NUM_AFFECT_ALL;
if (!t->obedit) {
t->flag |= T_NO_ZERO;
+#ifdef USE_NUM_NO_ZERO
t->num.val_flag[0] |= NUM_NO_ZERO;
t->num.val_flag[1] |= NUM_NO_ZERO;
t->num.val_flag[2] |= NUM_NO_ZERO;
+#endif
}
t->idx_max = 2;
@@ -3377,9 +3410,11 @@ static void initSkinResize(TransInfo *t)
t->num.flag |= NUM_AFFECT_ALL;
if (!t->obedit) {
t->flag |= T_NO_ZERO;
+#ifdef USE_NUM_NO_ZERO
t->num.val_flag[0] |= NUM_NO_ZERO;
t->num.val_flag[1] |= NUM_NO_ZERO;
t->num.val_flag[2] |= NUM_NO_ZERO;
+#endif
}
t->idx_max = 2;
@@ -3592,8 +3627,15 @@ static void initRotation(TransInfo *t)
if (t->flag & T_2D_EDIT)
t->flag |= T_NO_CONSTRAINT;
- negate_v3_v3(t->axis, t->viewinv[2]);
- normalize_v3(t->axis);
+ if (t->options & CTX_PAINT_CURVE) {
+ t->axis[0] = 0.0;
+ t->axis[1] = 0.0;
+ t->axis[2] = -1.0;
+ }
+ else {
+ negate_v3_v3(t->axis, t->viewinv[2]);
+ normalize_v3(t->axis);
+ }
copy_v3_v3(t->axis_orig, t->axis);
}
@@ -3627,7 +3669,7 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short
if (td->flag & TD_USEQUAT) {
- mul_serie_m3(fmat, td->mtx, mat, td->smtx, NULL, NULL, NULL, NULL, NULL);
+ mul_m3_series(fmat, td->smtx, mat, td->mtx);
mat3_to_quat(quat, fmat); // Actual transform
if (td->ext->quat) {
@@ -3697,7 +3739,7 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short
if ((t->flag & T_V3D_ALIGN) == 0) { /* align mode doesn't rotate objects itself */
/* euler or quaternion/axis-angle? */
if (td->ext->rotOrder == ROT_MODE_QUAT) {
- mul_serie_m3(fmat, td->ext->r_mtx, mat, td->ext->r_smtx, NULL, NULL, NULL, NULL, NULL);
+ mul_m3_series(fmat, td->ext->r_smtx, mat, td->ext->r_mtx);
mat3_to_quat(quat, fmat); /* Actual transform */
@@ -3712,7 +3754,7 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short
axis_angle_to_quat(iquat, td->ext->irotAxis, td->ext->irotAngle);
- mul_serie_m3(fmat, td->ext->r_mtx, mat, td->ext->r_smtx, NULL, NULL, NULL, NULL, NULL);
+ mul_m3_series(fmat, td->ext->r_smtx, mat, td->ext->r_mtx);
mat3_to_quat(quat, fmat); /* Actual transform */
mul_qt_qtqt(tquat, quat, iquat);
@@ -3769,7 +3811,7 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short
if ((td->ext->rotOrder == ROT_MODE_QUAT) || (td->flag & TD_USEQUAT)) {
/* can be called for texture space translate for example, then opt out */
if (td->ext->quat) {
- mul_serie_m3(fmat, td->mtx, mat, td->smtx, NULL, NULL, NULL, NULL, NULL);
+ mul_m3_series(fmat, td->smtx, mat, td->mtx);
mat3_to_quat(quat, fmat); // Actual transform
mul_qt_qtqt(td->ext->quat, quat, td->ext->iquat);
@@ -3783,7 +3825,7 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short
axis_angle_to_quat(iquat, td->ext->irotAxis, td->ext->irotAngle);
- mul_serie_m3(fmat, td->mtx, mat, td->smtx, NULL, NULL, NULL, NULL, NULL);
+ mul_m3_series(fmat, td->smtx, mat, td->mtx);
mat3_to_quat(quat, fmat); // Actual transform
mul_qt_qtqt(tquat, quat, iquat);
@@ -4480,7 +4522,9 @@ static void initCurveShrinkFatten(TransInfo *t)
t->num.unit_type[0] = B_UNIT_NONE;
t->flag |= T_NO_ZERO;
+#ifdef USE_NUM_NO_ZERO
t->num.val_flag[0] |= NUM_NO_ZERO;
+#endif
t->flag |= T_NO_CONSTRAINT;
}
@@ -4555,7 +4599,9 @@ static void initMaskShrinkFatten(TransInfo *t)
t->num.unit_type[0] = B_UNIT_NONE;
t->flag |= T_NO_ZERO;
+#ifdef USE_NUM_NO_ZERO
t->num.val_flag[0] |= NUM_NO_ZERO;
+#endif
t->flag |= T_NO_CONSTRAINT;
}
@@ -7707,7 +7753,7 @@ bool checkUseAxisMatrix(TransInfo *t)
{
/* currently only checks for editmode */
if (t->flag & T_EDIT) {
- if ((t->around == V3D_LOCAL) && (ELEM4(t->obedit->type, OB_MESH, OB_CURVE, OB_MBALL, OB_ARMATURE))) {
+ if ((t->around == V3D_LOCAL) && (ELEM(t->obedit->type, OB_MESH, OB_CURVE, OB_MBALL, OB_ARMATURE))) {
/* not all editmode supports axis-matrix */
return true;
}
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index 0bccf177128..012f9185d8b 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -130,15 +130,15 @@ typedef struct TransDataExtension {
// float drotAxis[3]; /* Initial object drotAxis, TODO: not yet implemented */
float dquat[4]; /* Initial object dquat */
float dscale[3]; /* Initial object dscale */
- float *rot; /* Rotation of the data to transform (Faculative) */
+ float *rot; /* Rotation of the data to transform */
float irot[3]; /* Initial rotation */
- float *quat; /* Rotation quaternion of the data to transform (Faculative) */
+ float *quat; /* Rotation quaternion of the data to transform */
float iquat[4]; /* Initial rotation quaternion */
- float *rotAngle; /* Rotation angle of the data to transform (Faculative) */
+ float *rotAngle; /* Rotation angle of the data to transform */
float irotAngle; /* Initial rotation angle */
- float *rotAxis; /* Rotation axis of the data to transform (Faculative) */
+ float *rotAxis; /* Rotation axis of the data to transform */
float irotAxis[4]; /* Initial rotation axis */
- float *size; /* Size of the data to transform (Faculative) */
+ float *size; /* Size of the data to transform */
float isize[3]; /* Initial size */
float obmat[4][4]; /* Object matrix */
float l_smtx[3][3]; /* use instead of td->smtx, It is the same but without the 'bone->bone_mat', see TD_PBONE_LOCAL_MTX_C */
@@ -532,6 +532,7 @@ void flushTransNodes(TransInfo *t);
void flushTransSeq(TransInfo *t);
void flushTransTracking(TransInfo *t);
void flushTransMasking(TransInfo *t);
+void flushTransPaintCurve(TransInfo *t);
void restoreBones(TransInfo *t);
/*********************** exported from transform_manipulator.c ********** */
diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c
index 79f266df607..d8f17315c01 100644
--- a/source/blender/editors/transform/transform_constraints.c
+++ b/source/blender/editors/transform/transform_constraints.c
@@ -663,7 +663,7 @@ void drawConstraint(TransInfo *t)
{
TransCon *tc = &(t->con);
- if (!ELEM3(t->spacetype, SPACE_VIEW3D, SPACE_IMAGE, SPACE_NODE))
+ if (!ELEM(t->spacetype, SPACE_VIEW3D, SPACE_IMAGE, SPACE_NODE))
return;
if (!(tc->mode & CON_APPLY))
return;
@@ -756,6 +756,9 @@ void drawPropCircle(const struct bContext *C, TransInfo *t)
/* untested - mask aspect is TODO */
ED_space_image_get_aspect(t->sa->spacedata.first, &aspx, &aspy);
}
+ else if (t->options & CTX_PAINT_CURVE) {
+ aspx = aspy = 1.0;
+ }
else {
ED_space_image_get_uv_aspect(t->sa->spacedata.first, &aspx, &aspy);
}
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index 0696ca55431..a5f57a0c464 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -33,6 +33,7 @@
#include <math.h>
#include "DNA_anim_types.h"
+#include "DNA_brush_types.h"
#include "DNA_armature_types.h"
#include "DNA_lattice_types.h"
#include "DNA_mesh_types.h"
@@ -80,6 +81,7 @@
#include "BKE_node.h"
#include "BKE_object.h"
#include "BKE_particle.h"
+#include "BKE_paint.h"
#include "BKE_pointcache.h"
#include "BKE_report.h"
#include "BKE_rigidbody.h"
@@ -124,8 +126,8 @@
static void transform_around_single_fallback(TransInfo *t)
{
if ((t->total == 1) &&
- (ELEM3(t->around, V3D_CENTER, V3D_CENTROID, V3D_ACTIVE)) &&
- (ELEM3(t->mode, TFM_RESIZE, TFM_ROTATION, TFM_TRACKBALL)))
+ (ELEM(t->around, V3D_CENTER, V3D_CENTROID, V3D_ACTIVE)) &&
+ (ELEM(t->mode, TFM_RESIZE, TFM_ROTATION, TFM_TRACKBALL)))
{
t->around = V3D_LOCAL;
}
@@ -282,7 +284,7 @@ static void createTransTexspace(TransInfo *t)
}
id = ob->data;
- if (id == NULL || !ELEM3(GS(id->name), ID_ME, ID_CU, ID_MB)) {
+ if (id == NULL || !ELEM(GS(id->name), ID_ME, ID_CU, ID_MB)) {
BKE_report(t->reports, RPT_ERROR, "Unsupported object type for text-space transform");
t->total = 0;
return;
@@ -584,12 +586,12 @@ static void add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, Tr
if (constraints_list_needinv(t, &pchan->constraints)) {
copy_m3_m4(tmat, pchan->constinv);
invert_m3_m3(cmat, tmat);
- mul_serie_m3(td->mtx, pmat, omat, cmat, NULL, NULL, NULL, NULL, NULL);
- mul_serie_m3(td->ext->r_mtx, rpmat, omat, cmat, NULL, NULL, NULL, NULL, NULL);
+ mul_m3_series(td->mtx, cmat, omat, pmat);
+ mul_m3_series(td->ext->r_mtx, cmat, omat, rpmat);
}
else {
- mul_serie_m3(td->mtx, pmat, omat, NULL, NULL, NULL, NULL, NULL, NULL);
- mul_serie_m3(td->ext->r_mtx, rpmat, omat, NULL, NULL, NULL, NULL, NULL, NULL);
+ mul_m3_series(td->mtx, omat, pmat);
+ mul_m3_series(td->ext->r_mtx, omat, rpmat);
}
invert_m3_m3(td->ext->r_smtx, td->ext->r_mtx);
}
@@ -2368,8 +2370,7 @@ static void createTransEditVerts(TransInfo *t)
quat_to_mat3(qmat, quats[BM_elem_index_get(eve)]);
if (defmats)
- mul_serie_m3(mat, mtx, qmat, defmats[a],
- NULL, NULL, NULL, NULL, NULL);
+ mul_m3_series(mat, defmats[a], qmat, mtx);
else
mul_m3_m3m3(mat, mtx, qmat);
}
@@ -3707,7 +3708,7 @@ static void bezt_to_transdata(TransData *td, TransData2D *td2d, TransDataGraph *
static bool graph_edit_is_translation_mode(TransInfo *t)
{
- return ELEM4(t->mode, TFM_TRANSLATION, TFM_TIME_TRANSLATE, TFM_TIME_SLIDE, TFM_TIME_DUPLICATE);
+ return ELEM(t->mode, TFM_TRANSLATION, TFM_TIME_TRANSLATE, TFM_TIME_SLIDE, TFM_TIME_DUPLICATE);
}
static bool graph_edit_use_local_center(TransInfo *t)
@@ -4767,12 +4768,12 @@ static bool constraints_list_needinv(TransInfo *t, ListBase *list)
if ((con->flag & CONSTRAINT_DISABLE) == 0 && (con->enforce != 0.0f)) {
/* (affirmative) returns for specific constraints here... */
/* constraints that require this regardless */
- if (ELEM5(con->type,
- CONSTRAINT_TYPE_CHILDOF,
- CONSTRAINT_TYPE_FOLLOWPATH,
- CONSTRAINT_TYPE_CLAMPTO,
- CONSTRAINT_TYPE_OBJECTSOLVER,
- CONSTRAINT_TYPE_FOLLOWTRACK))
+ if (ELEM(con->type,
+ CONSTRAINT_TYPE_CHILDOF,
+ CONSTRAINT_TYPE_FOLLOWPATH,
+ CONSTRAINT_TYPE_CLAMPTO,
+ CONSTRAINT_TYPE_OBJECTSOLVER,
+ CONSTRAINT_TYPE_FOLLOWTRACK))
{
return true;
}
@@ -5848,6 +5849,9 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
+ else if (t->options & CTX_PAINT_CURVE) {
+ /* pass */
+ }
else if ((t->scene->basact) &&
(ob = t->scene->basact->object) &&
(ob->mode & OB_MODE_PARTICLE_EDIT) &&
@@ -7027,6 +7031,173 @@ void flushTransMasking(TransInfo *t)
}
}
+typedef struct TransDataPaintCurve {
+ PaintCurvePoint *pcp; /* initial curve point */
+ char id;
+} TransDataPaintCurve;
+
+
+#define PC_IS_ANY_SEL(pc) (((pc)->bez.f1 | (pc)->bez.f2 | (pc)->bez.f3) & SELECT)
+
+static void PaintCurveConvertHandle(PaintCurvePoint *pcp, int id, TransData2D *td2d, TransDataPaintCurve *tdpc, TransData *td)
+{
+ BezTriple *bezt = &pcp->bez;
+ copy_v2_v2(td2d->loc, bezt->vec[id]);
+ td2d->loc[2] = 0.0f;
+ td2d->loc2d = bezt->vec[id];
+
+ td->flag = 0;
+ td->loc = td2d->loc;
+ copy_v3_v3(td->center, bezt->vec[1]);
+ copy_v3_v3(td->iloc, td->loc);
+
+ memset(td->axismtx, 0, sizeof(td->axismtx));
+ td->axismtx[2][2] = 1.0f;
+
+ td->ext = NULL;
+ td->val = NULL;
+ td->flag |= TD_SELECTED;
+ td->dist = 0.0;
+
+ unit_m3(td->mtx);
+ unit_m3(td->smtx);
+
+ tdpc->id = id;
+ tdpc->pcp = pcp;
+}
+
+static void PaintCurvePointToTransData(PaintCurvePoint *pcp, TransData *td, TransData2D *td2d, TransDataPaintCurve *tdpc)
+{
+ BezTriple *bezt = &pcp->bez;
+
+ if (pcp->bez.f2 == SELECT) {
+ int i;
+ for (i = 0; i < 3; i++) {
+ copy_v2_v2(td2d->loc, bezt->vec[i]);
+ td2d->loc[2] = 0.0f;
+ td2d->loc2d = bezt->vec[i];
+
+ td->flag = 0;
+ td->loc = td2d->loc;
+ copy_v3_v3(td->center, bezt->vec[1]);
+ copy_v3_v3(td->iloc, td->loc);
+
+ memset(td->axismtx, 0, sizeof(td->axismtx));
+ td->axismtx[2][2] = 1.0f;
+
+ td->ext = NULL;
+ td->val = NULL;
+ td->flag |= TD_SELECTED;
+ td->dist = 0.0;
+
+ unit_m3(td->mtx);
+ unit_m3(td->smtx);
+
+ tdpc->id = i;
+ tdpc->pcp = pcp;
+
+ td++;
+ td2d++;
+ tdpc++;
+ }
+ }
+ else {
+ if (bezt->f3 & SELECT) {
+ PaintCurveConvertHandle(pcp, 2, td2d, tdpc, td);
+ td2d++;
+ tdpc++;
+ td++;
+ }
+
+ if (bezt->f1 & SELECT) {
+ PaintCurveConvertHandle(pcp, 0, td2d, tdpc, td);
+ }
+ }
+}
+
+static void createTransPaintCurveVerts(bContext *C, TransInfo *t)
+{
+ Paint *paint = BKE_paint_get_active_from_context(C);
+ PaintCurve *pc;
+ PaintCurvePoint *pcp;
+ Brush *br;
+ TransData *td = NULL;
+ TransData2D *td2d = NULL;
+ TransDataPaintCurve *tdpc = NULL;
+ int i;
+ int total = 0;
+
+ t->total = 0;
+
+ if (!paint || !paint->brush || !paint->brush->paint_curve)
+ return;
+
+ br = paint->brush;
+ pc = br->paint_curve;
+
+ for (pcp = pc->points, i = 0; i < pc->tot_points; i++, pcp++) {
+ if (PC_IS_ANY_SEL(pcp)) {
+ if (pcp->bez.f2 & SELECT) {
+ total += 3;
+ continue;
+ }
+ else {
+ if (pcp->bez.f1 & SELECT)
+ total++;
+ if (pcp->bez.f3 & SELECT)
+ total++;
+ }
+ }
+ }
+
+ if (!total)
+ return;
+
+ t->total = total;
+ td2d = t->data2d = MEM_callocN(t->total * sizeof(TransData2D), "TransData2D");
+ td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransData");
+ tdpc = t->customData = MEM_callocN(t->total * sizeof(TransDataPaintCurve), "TransDataPaintCurve");
+ t->flag |= T_FREE_CUSTOMDATA;
+
+ for (pcp = pc->points, i = 0; i < pc->tot_points; i++, pcp++) {
+ if (PC_IS_ANY_SEL(pcp)) {
+ PaintCurvePointToTransData (pcp, td, td2d, tdpc);
+
+ if (pcp->bez.f2 & SELECT) {
+ td += 3;
+ td2d += 3;
+ tdpc += 3;
+ }
+ else {
+ if (pcp->bez.f1 & SELECT) {
+ td++;
+ td2d++;
+ tdpc++;
+ }
+ if (pcp->bez.f3 & SELECT) {
+ td++;
+ td2d++;
+ tdpc++;
+ }
+ }
+ }
+ }
+}
+
+
+void flushTransPaintCurve(TransInfo *t)
+{
+ int i;
+ TransData2D *td2d = t->data2d;
+ TransDataPaintCurve *tdpc = (TransDataPaintCurve *)t->customData;
+
+ for (i = 0; i < t->total; i++, tdpc++, td2d++) {
+ PaintCurvePoint *pcp = tdpc->pcp;
+ copy_v2_v2(pcp->bez.vec[tdpc->id], td2d->loc);
+ }
+}
+
+
void createTransData(bContext *C, TransInfo *t)
{
Scene *scene = t->scene;
@@ -7059,6 +7230,10 @@ void createTransData(bContext *C, TransInfo *t)
sort_trans_data_dist(t);
}
}
+ else if (t->options & CTX_PAINT_CURVE) {
+ if (!ELEM(t->mode, TFM_SHEAR, TFM_SHRINKFATTEN))
+ createTransPaintCurveVerts(C, t);
+ }
else if (t->obedit) {
createTransUVs(C, t);
if (t->data && (t->flag & T_PROP_EDIT)) {
@@ -7165,7 +7340,7 @@ void createTransData(bContext *C, TransInfo *t)
// XXX active-layer checking isn't done as that should probably be checked through context instead
createTransPose(t, ob);
}
- else if (ob && (ob->mode & OB_MODE_WEIGHT_PAINT)) {
+ else if (ob && (ob->mode & OB_MODE_WEIGHT_PAINT) && !(t->options & CTX_PAINT_CURVE)) {
/* important that ob_armature can be set even when its not selected [#23412]
* lines below just check is also visible */
Object *ob_armature = modifiers_isDeformedByArmature(ob);
@@ -7190,12 +7365,11 @@ void createTransData(bContext *C, TransInfo *t)
sort_trans_data_dist(t);
}
}
- else if (ob && (ob->mode & (OB_MODE_ALL_PAINT))) {
- /* sculpt mode and project paint have own undo stack
- * transform ops redo clears sculpt/project undo stack.
- *
- * Could use 'OB_MODE_ALL_PAINT' since there are key conflicts,
- * transform + paint isn't well supported. */
+ else if (ob && (ob->mode & OB_MODE_ALL_PAINT)) {
+ if ((t->options & CTX_PAINT_CURVE) && !ELEM(t->mode, TFM_SHEAR, TFM_SHRINKFATTEN)) {
+ t->flag |= T_POINTS | T_2D_EDIT;
+ createTransPaintCurveVerts(C, t);
+ }
}
else {
createTransObject(C, t);
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index 7d30af0c144..03f09d3b758 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -38,6 +38,7 @@
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
+#include "DNA_brush_types.h"
#include "DNA_lattice_types.h"
#include "DNA_screen_types.h"
#include "DNA_sequence_types.h"
@@ -75,6 +76,7 @@
#include "BKE_lattice.h"
#include "BKE_nla.h"
#include "BKE_context.h"
+#include "BKE_paint.h"
#include "BKE_sequencer.h"
#include "BKE_editmesh.h"
#include "BKE_tracking.h"
@@ -100,6 +102,7 @@
#include "WM_api.h"
#include "UI_resources.h"
+#include "UI_view2d.h"
#include "transform.h"
@@ -264,7 +267,7 @@ static void animrecord_check_state(Scene *scene, ID *id, wmTimer *animtimer)
ScreenAnimData *sad = (animtimer) ? animtimer->customdata : NULL;
/* sanity checks */
- if (ELEM3(NULL, scene, id, sad))
+ if (ELEM(NULL, scene, id, sad))
return;
/* check if we need a new strip if:
@@ -655,6 +658,9 @@ static void recalcData_image(TransInfo *t)
if (t->options & CTX_MASK) {
recalcData_mask_common(t);
}
+ else if (t->options & CTX_PAINT_CURVE) {
+ flushTransPaintCurve(t);
+ }
else if (t->obedit && t->obedit->type == OB_MESH) {
SpaceImage *sima = t->sa->spacedata.first;
@@ -819,7 +825,7 @@ static void recalcData_objects(TransInfo *t)
}
}
- if (!ELEM3(t->mode, TFM_BONE_ROLL, TFM_BONE_ENVELOPE, TFM_BONESIZE)) {
+ if (!ELEM(t->mode, TFM_BONE_ROLL, TFM_BONE_ENVELOPE, TFM_BONESIZE)) {
/* fix roll */
for (i = 0; i < t->total; i++, td++) {
if (td->extra) {
@@ -967,6 +973,9 @@ void recalcData(TransInfo *t)
else if (t->options & CTX_EDGE) {
recalcData_objects(t);
}
+ else if (t->options & CTX_PAINT_CURVE) {
+ flushTransPaintCurve(t);
+ }
else if (t->spacetype == SPACE_IMAGE) {
recalcData_image(t);
}
@@ -1075,6 +1084,7 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
ARegion *ar = CTX_wm_region(C);
ScrArea *sa = CTX_wm_area(C);
Object *obedit = CTX_data_edit_object(C);
+ Object *ob = CTX_data_active_object(C);
PropertyRNA *prop;
t->scene = sce;
@@ -1195,11 +1205,18 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
/* exceptional case */
if (t->around == V3D_LOCAL && (t->settings->selectmode & SCE_SELECT_FACE)) {
- if (ELEM3(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL)) {
+ if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL)) {
t->options |= CTX_NO_PET;
}
}
+ if (ob && ob->mode & OB_MODE_ALL_PAINT) {
+ Paint *p = BKE_paint_get_active_from_context(C);
+ if (p && p->brush && (p->brush->flag & BRUSH_CURVE)) {
+ t->options |= CTX_PAINT_CURVE;
+ }
+ }
+
/* initialize UV transform from */
if (op && ((prop = RNA_struct_find_property(op->ptr, "correct_uv")))) {
if (RNA_property_is_set(op->ptr, prop)) {
@@ -1228,9 +1245,13 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
else if (sima->mode == SI_MODE_MASK) {
t->options |= CTX_MASK;
}
- else {
- /* image not in uv edit, nor in mask mode, can happen for some tools */
+ else if (sima->mode == SI_MODE_PAINT) {
+ Paint *p = &sce->toolsettings->imapaint.paint;
+ if (p->brush && (p->brush->flag & BRUSH_CURVE)) {
+ t->options |= CTX_PAINT_CURVE;
+ }
}
+ /* image not in uv edit, nor in mask mode, can happen for some tools */
}
else if (t->spacetype == SPACE_NODE) {
// XXX for now, get View2D from the active region
@@ -1411,7 +1432,7 @@ void postTrans(bContext *C, TransInfo *t)
}
if (t->spacetype == SPACE_IMAGE) {
- if (t->options & CTX_MASK) {
+ if (t->options & (CTX_MASK | CTX_PAINT_CURVE)) {
/* pass */
}
else {
@@ -1541,6 +1562,13 @@ void calculateCenterCursor(TransInfo *t, float r_center[3])
invert_m3_m3(imat, mat);
mul_m3_v3(imat, r_center);
}
+ else if (t->options & CTX_PAINT_CURVE) {
+ if (ED_view3d_project_float_global(t->ar, cursor, r_center, V3D_PROJ_TEST_NOP) != V3D_PROJ_RET_OK) {
+ r_center[0] = t->ar->winx / 2.0f;
+ r_center[1] = t->ar->winy / 2.0f;
+ }
+ r_center[2] = 0.0f;
+ }
}
void calculateCenterCursor2D(TransInfo *t, float r_center[2])
@@ -1588,6 +1616,12 @@ void calculateCenterCursor2D(TransInfo *t, float r_center[2])
r_center[0] = co[0] * aspx;
r_center[1] = co[1] * aspy;
}
+ else if (t->options & CTX_PAINT_CURVE) {
+ if (t->spacetype == SPACE_IMAGE) {
+ r_center[0] = UI_view2d_view_to_region_x(&t->ar->v2d, cursor[0]);
+ r_center[1] = UI_view2d_view_to_region_y(&t->ar->v2d, cursor[1]);
+ }
+ }
else {
r_center[0] = cursor[0] * aspx;
r_center[1] = cursor[1] * aspy;
@@ -1775,6 +1809,14 @@ bool calculateCenterActive(TransInfo *t, bool select_only, float r_center[3])
}
}
}
+ else if (t->options & CTX_PAINT_CURVE) {
+ Paint *p = BKE_paint_get_active(t->scene);
+ Brush *br = p->brush;
+ PaintCurve *pc = br->paint_curve;
+ copy_v3_v3(r_center, pc->points[pc->add_index - 1].bez.vec[1]);
+ r_center[2] = 0.0f;
+ ok = true;
+ }
else {
/* object mode */
Scene *scene = t->scene;
diff --git a/source/blender/editors/transform/transform_manipulator.c b/source/blender/editors/transform/transform_manipulator.c
index b1512f7b855..df501ca5da9 100644
--- a/source/blender/editors/transform/transform_manipulator.c
+++ b/source/blender/editors/transform/transform_manipulator.c
@@ -75,6 +75,8 @@
/* local module include */
#include "transform.h"
+#include "GPU_select.h"
+
/* return codes for select, and drawing flags */
#define MAN_TRANS_X (1 << 0)
@@ -878,8 +880,8 @@ static void draw_manipulator_axes_single(View3D *v3d, RegionView3D *rv3d, int co
/* axes */
if (flagx) {
if (is_picksel) {
- if (flagx & MAN_SCALE_X) glLoadName(MAN_SCALE_X);
- else if (flagx & MAN_TRANS_X) glLoadName(MAN_TRANS_X);
+ if (flagx & MAN_SCALE_X) GPU_select_load_id(MAN_SCALE_X);
+ else if (flagx & MAN_TRANS_X) GPU_select_load_id(MAN_TRANS_X);
}
else {
manipulator_setcolor(v3d, 'X', colcode, axisBlendAngle(rv3d->tw_idot[0]));
@@ -893,8 +895,8 @@ static void draw_manipulator_axes_single(View3D *v3d, RegionView3D *rv3d, int co
case 1:
if (flagy) {
if (is_picksel) {
- if (flagy & MAN_SCALE_Y) glLoadName(MAN_SCALE_Y);
- else if (flagy & MAN_TRANS_Y) glLoadName(MAN_TRANS_Y);
+ if (flagy & MAN_SCALE_Y) GPU_select_load_id(MAN_SCALE_Y);
+ else if (flagy & MAN_TRANS_Y) GPU_select_load_id(MAN_TRANS_Y);
}
else {
manipulator_setcolor(v3d, 'Y', colcode, axisBlendAngle(rv3d->tw_idot[1]));
@@ -908,8 +910,8 @@ static void draw_manipulator_axes_single(View3D *v3d, RegionView3D *rv3d, int co
case 2:
if (flagz) {
if (is_picksel) {
- if (flagz & MAN_SCALE_Z) glLoadName(MAN_SCALE_Z);
- else if (flagz & MAN_TRANS_Z) glLoadName(MAN_TRANS_Z);
+ if (flagz & MAN_SCALE_Z) GPU_select_load_id(MAN_SCALE_Z);
+ else if (flagz & MAN_TRANS_Z) GPU_select_load_id(MAN_TRANS_Z);
}
else {
manipulator_setcolor(v3d, 'Z', colcode, axisBlendAngle(rv3d->tw_idot[2]));
@@ -995,7 +997,7 @@ static void draw_manipulator_rotate(
/* Screen aligned trackball rot circle */
if (drawflags & MAN_ROT_T) {
- if (is_picksel) glLoadName(MAN_ROT_T);
+ if (is_picksel) GPU_select_load_id(MAN_ROT_T);
else UI_ThemeColor(TH_TRANSFORM);
drawcircball(GL_LINE_LOOP, unitmat[3], 0.2f * size, unitmat);
@@ -1003,7 +1005,7 @@ static void draw_manipulator_rotate(
/* Screen aligned view rot circle */
if (drawflags & MAN_ROT_V) {
- if (is_picksel) glLoadName(MAN_ROT_V);
+ if (is_picksel) GPU_select_load_id(MAN_ROT_V);
else UI_ThemeColor(TH_TRANSFORM);
drawcircball(GL_LINE_LOOP, unitmat[3], 1.2f * size, unitmat);
@@ -1082,7 +1084,7 @@ static void draw_manipulator_rotate(
/* Z circle */
if (drawflags & MAN_ROT_Z) {
preOrthoFront(ortho, matt, 2);
- if (is_picksel) glLoadName(MAN_ROT_Z);
+ if (is_picksel) GPU_select_load_id(MAN_ROT_Z);
else manipulator_setcolor(v3d, 'Z', colcode, 255);
drawcircball(GL_LINE_LOOP, unitmat[3], 1.0, unitmat);
postOrtho(ortho);
@@ -1090,7 +1092,7 @@ static void draw_manipulator_rotate(
/* X circle */
if (drawflags & MAN_ROT_X) {
preOrthoFront(ortho, matt, 0);
- if (is_picksel) glLoadName(MAN_ROT_X);
+ if (is_picksel) GPU_select_load_id(MAN_ROT_X);
else manipulator_setcolor(v3d, 'X', colcode, 255);
glRotatef(90.0, 0.0, 1.0, 0.0);
drawcircball(GL_LINE_LOOP, unitmat[3], 1.0, unitmat);
@@ -1100,7 +1102,7 @@ static void draw_manipulator_rotate(
/* Y circle */
if (drawflags & MAN_ROT_Y) {
preOrthoFront(ortho, matt, 1);
- if (is_picksel) glLoadName(MAN_ROT_Y);
+ if (is_picksel) GPU_select_load_id(MAN_ROT_Y);
else manipulator_setcolor(v3d, 'Y', colcode, 255);
glRotatef(-90.0, 1.0, 0.0, 0.0);
drawcircball(GL_LINE_LOOP, unitmat[3], 1.0, unitmat);
@@ -1117,7 +1119,7 @@ static void draw_manipulator_rotate(
/* Z circle */
if (drawflags & MAN_ROT_Z) {
preOrthoFront(ortho, rv3d->twmat, 2);
- if (is_picksel) glLoadName(MAN_ROT_Z);
+ if (is_picksel) GPU_select_load_id(MAN_ROT_Z);
else manipulator_setcolor(v3d, 'Z', colcode, 255);
partial_doughnut(cusize / 4.0f, 1.0f, 0, 48, 8, 48);
postOrtho(ortho);
@@ -1125,7 +1127,7 @@ static void draw_manipulator_rotate(
/* X circle */
if (drawflags & MAN_ROT_X) {
preOrthoFront(ortho, rv3d->twmat, 0);
- if (is_picksel) glLoadName(MAN_ROT_X);
+ if (is_picksel) GPU_select_load_id(MAN_ROT_X);
else manipulator_setcolor(v3d, 'X', colcode, 255);
glRotatef(90.0, 0.0, 1.0, 0.0);
partial_doughnut(cusize / 4.0f, 1.0f, 0, 48, 8, 48);
@@ -1135,7 +1137,7 @@ static void draw_manipulator_rotate(
/* Y circle */
if (drawflags & MAN_ROT_Y) {
preOrthoFront(ortho, rv3d->twmat, 1);
- if (is_picksel) glLoadName(MAN_ROT_Y);
+ if (is_picksel) GPU_select_load_id(MAN_ROT_Y);
else manipulator_setcolor(v3d, 'Y', colcode, 255);
glRotatef(-90.0, 1.0, 0.0, 0.0);
partial_doughnut(cusize / 4.0f, 1.0f, 0, 48, 8, 48);
@@ -1152,7 +1154,7 @@ static void draw_manipulator_rotate(
if (drawflags & MAN_ROT_Z) {
preOrthoFront(ortho, rv3d->twmat, 2);
glPushMatrix();
- if (is_picksel) glLoadName(MAN_ROT_Z);
+ if (is_picksel) GPU_select_load_id(MAN_ROT_Z);
else manipulator_setcolor(v3d, 'Z', colcode, 255);
partial_doughnut(0.7f * cusize, 1.0f, 31, 33, 8, 64);
@@ -1165,7 +1167,7 @@ static void draw_manipulator_rotate(
if (drawflags & MAN_ROT_Y) {
preOrthoFront(ortho, rv3d->twmat, 1);
glPushMatrix();
- if (is_picksel) glLoadName(MAN_ROT_Y);
+ if (is_picksel) GPU_select_load_id(MAN_ROT_Y);
else manipulator_setcolor(v3d, 'Y', colcode, 255);
glRotatef(90.0, 1.0, 0.0, 0.0);
@@ -1180,7 +1182,7 @@ static void draw_manipulator_rotate(
if (drawflags & MAN_ROT_X) {
preOrthoFront(ortho, rv3d->twmat, 0);
glPushMatrix();
- if (is_picksel) glLoadName(MAN_ROT_X);
+ if (is_picksel) GPU_select_load_id(MAN_ROT_X);
else manipulator_setcolor(v3d, 'X', colcode, 255);
glRotatef(-90.0, 0.0, 1.0, 0.0);
@@ -1283,7 +1285,7 @@ static void draw_manipulator_scale(
int shift = 0; // XXX
/* center circle, do not add to selection when shift is pressed (planar constraint) */
- if (is_picksel && shift == 0) glLoadName(MAN_SCALE_C);
+ if (is_picksel && shift == 0) GPU_select_load_id(MAN_SCALE_C);
else manipulator_setcolor(v3d, 'C', colcode, 255);
glPushMatrix();
@@ -1324,7 +1326,7 @@ static void draw_manipulator_scale(
case 0: /* X cube */
if (drawflags & MAN_SCALE_X) {
glTranslatef(dz, 0.0, 0.0);
- if (is_picksel) glLoadName(MAN_SCALE_X);
+ if (is_picksel) GPU_select_load_id(MAN_SCALE_X);
else manipulator_setcolor(v3d, 'X', colcode, axisBlendAngle(rv3d->tw_idot[0]));
drawsolidcube(cusize);
glTranslatef(-dz, 0.0, 0.0);
@@ -1333,7 +1335,7 @@ static void draw_manipulator_scale(
case 1: /* Y cube */
if (drawflags & MAN_SCALE_Y) {
glTranslatef(0.0, dz, 0.0);
- if (is_picksel) glLoadName(MAN_SCALE_Y);
+ if (is_picksel) GPU_select_load_id(MAN_SCALE_Y);
else manipulator_setcolor(v3d, 'Y', colcode, axisBlendAngle(rv3d->tw_idot[1]));
drawsolidcube(cusize);
glTranslatef(0.0, -dz, 0.0);
@@ -1342,7 +1344,7 @@ static void draw_manipulator_scale(
case 2: /* Z cube */
if (drawflags & MAN_SCALE_Z) {
glTranslatef(0.0, 0.0, dz);
- if (is_picksel) glLoadName(MAN_SCALE_Z);
+ if (is_picksel) GPU_select_load_id(MAN_SCALE_Z);
else manipulator_setcolor(v3d, 'Z', colcode, axisBlendAngle(rv3d->tw_idot[2]));
drawsolidcube(cusize);
glTranslatef(0.0, 0.0, -dz);
@@ -1357,7 +1359,7 @@ static void draw_manipulator_scale(
if (shift) {
glTranslatef(0.0, -dz, 0.0);
- glLoadName(MAN_SCALE_C);
+ GPU_select_load_id(MAN_SCALE_C);
glBegin(GL_POINTS);
glVertex3f(0.0, 0.0, 0.0);
glEnd();
@@ -1419,7 +1421,7 @@ static void draw_manipulator_translate(
glDisable(GL_DEPTH_TEST);
/* center circle, do not add to selection when shift is pressed (planar constraint) */
- if (is_picksel && shift == 0) glLoadName(MAN_TRANS_C);
+ if (is_picksel && shift == 0) GPU_select_load_id(MAN_TRANS_C);
else manipulator_setcolor(v3d, 'C', colcode, 255);
glPushMatrix();
@@ -1432,7 +1434,7 @@ static void draw_manipulator_translate(
glMultMatrixf(rv3d->twmat);
/* axis */
- glLoadName(-1);
+ GPU_select_load_id(-1);
// translate drawn as last, only axis when no combo with scale, or for ghosting
if ((combo & V3D_MANIP_SCALE) == 0 || colcode == MAN_GHOST) {
@@ -1455,7 +1457,7 @@ static void draw_manipulator_translate(
case 0: /* Z Cone */
if (drawflags & MAN_TRANS_Z) {
glTranslatef(0.0, 0.0, dz);
- if (is_picksel) glLoadName(MAN_TRANS_Z);
+ if (is_picksel) GPU_select_load_id(MAN_TRANS_Z);
else manipulator_setcolor(v3d, 'Z', colcode, axisBlendAngle(rv3d->tw_idot[2]));
draw_cone(qobj, cylen, cywid);
glTranslatef(0.0, 0.0, -dz);
@@ -1464,7 +1466,7 @@ static void draw_manipulator_translate(
case 1: /* X Cone */
if (drawflags & MAN_TRANS_X) {
glTranslatef(dz, 0.0, 0.0);
- if (is_picksel) glLoadName(MAN_TRANS_X);
+ if (is_picksel) GPU_select_load_id(MAN_TRANS_X);
else manipulator_setcolor(v3d, 'X', colcode, axisBlendAngle(rv3d->tw_idot[0]));
glRotatef(90.0, 0.0, 1.0, 0.0);
draw_cone(qobj, cylen, cywid);
@@ -1475,7 +1477,7 @@ static void draw_manipulator_translate(
case 2: /* Y Cone */
if (drawflags & MAN_TRANS_Y) {
glTranslatef(0.0, dz, 0.0);
- if (is_picksel) glLoadName(MAN_TRANS_Y);
+ if (is_picksel) GPU_select_load_id(MAN_TRANS_Y);
else manipulator_setcolor(v3d, 'Y', colcode, axisBlendAngle(rv3d->tw_idot[1]));
glRotatef(-90.0, 1.0, 0.0, 0.0);
draw_cone(qobj, cylen, cywid);
@@ -1523,7 +1525,7 @@ static void draw_manipulator_rotate_cyl(
unit_m4(unitmat);
- if (is_picksel) glLoadName(MAN_ROT_V);
+ if (is_picksel) GPU_select_load_id(MAN_ROT_V);
UI_ThemeColor(TH_TRANSFORM);
drawcircball(GL_LINE_LOOP, unitmat[3], 1.2f * size, unitmat);
@@ -1576,7 +1578,7 @@ static void draw_manipulator_rotate_cyl(
case 0: /* X cylinder */
if (drawflags & MAN_ROT_X) {
glTranslatef(1.0, 0.0, 0.0);
- if (is_picksel) glLoadName(MAN_ROT_X);
+ if (is_picksel) GPU_select_load_id(MAN_ROT_X);
glRotatef(90.0, 0.0, 1.0, 0.0);
manipulator_setcolor(v3d, 'X', colcode, 255);
draw_cylinder(qobj, cylen, cywid);
@@ -1587,7 +1589,7 @@ static void draw_manipulator_rotate_cyl(
case 1: /* Y cylinder */
if (drawflags & MAN_ROT_Y) {
glTranslatef(0.0, 1.0, 0.0);
- if (is_picksel) glLoadName(MAN_ROT_Y);
+ if (is_picksel) GPU_select_load_id(MAN_ROT_Y);
glRotatef(-90.0, 1.0, 0.0, 0.0);
manipulator_setcolor(v3d, 'Y', colcode, 255);
draw_cylinder(qobj, cylen, cywid);
@@ -1598,7 +1600,7 @@ static void draw_manipulator_rotate_cyl(
case 2: /* Z cylinder */
if (drawflags & MAN_ROT_Z) {
glTranslatef(0.0, 0.0, 1.0);
- if (is_picksel) glLoadName(MAN_ROT_Z);
+ if (is_picksel) GPU_select_load_id(MAN_ROT_Z);
manipulator_setcolor(v3d, 'Z', colcode, 255);
draw_cylinder(qobj, cylen, cywid);
glTranslatef(0.0, 0.0, -1.0);
@@ -1710,10 +1712,11 @@ static int manipulator_selectbuf(ScrArea *sa, ARegion *ar, const int mval[2], fl
{
View3D *v3d = sa->spacedata.first;
RegionView3D *rv3d = ar->regiondata;
- rctf rect;
+ rctf rect, selrect;
GLuint buffer[64]; // max 4 items per select, so large enuf
short hits;
const bool is_picksel = true;
+ const bool do_passes = GPU_select_query_check_active();
/* XXX check a bit later on this... (ton) */
extern void view3d_winmatrix_set(ARegion *ar, View3D *v3d, rctf *rect);
@@ -1728,13 +1731,15 @@ static int manipulator_selectbuf(ScrArea *sa, ARegion *ar, const int mval[2], fl
rect.ymin = mval[1] - hotspot;
rect.ymax = mval[1] + hotspot;
+ selrect = rect;
+
view3d_winmatrix_set(ar, v3d, &rect);
mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat);
- glSelectBuffer(64, buffer);
- glRenderMode(GL_SELECT);
- glInitNames(); /* these two calls whatfor? It doesn't work otherwise */
- glPushName(-2);
+ if (do_passes)
+ GPU_select_begin(buffer, 64, &selrect, GPU_SELECT_NEAREST_FIRST_PASS, 0);
+ else
+ GPU_select_begin(buffer, 64, &selrect, GPU_SELECT_ALL, 0);
/* do the drawing */
if (v3d->twtype & V3D_MANIP_ROTATE) {
@@ -1746,8 +1751,23 @@ static int manipulator_selectbuf(ScrArea *sa, ARegion *ar, const int mval[2], fl
if (v3d->twtype & V3D_MANIP_TRANSLATE)
draw_manipulator_translate(v3d, rv3d, MAN_TRANS_C & rv3d->twdrawflag, v3d->twtype, MAN_RGB, false, is_picksel);
- glPopName();
- hits = glRenderMode(GL_RENDER);
+ hits = GPU_select_end();
+
+ if (do_passes) {
+ GPU_select_begin(buffer, 64, &selrect, GPU_SELECT_NEAREST_SECOND_PASS, hits);
+
+ /* do the drawing */
+ if (v3d->twtype & V3D_MANIP_ROTATE) {
+ if (G.debug_value == 3) draw_manipulator_rotate_cyl(v3d, rv3d, MAN_ROT_C & rv3d->twdrawflag, v3d->twtype, MAN_RGB, false, is_picksel);
+ else draw_manipulator_rotate(v3d, rv3d, MAN_ROT_C & rv3d->twdrawflag, v3d->twtype, false, is_picksel);
+ }
+ if (v3d->twtype & V3D_MANIP_SCALE)
+ draw_manipulator_scale(v3d, rv3d, MAN_SCALE_C & rv3d->twdrawflag, v3d->twtype, MAN_RGB, false, is_picksel);
+ if (v3d->twtype & V3D_MANIP_TRANSLATE)
+ draw_manipulator_translate(v3d, rv3d, MAN_TRANS_C & rv3d->twdrawflag, v3d->twtype, MAN_RGB, false, is_picksel);
+
+ GPU_select_end();
+ }
view3d_winmatrix_set(ar, v3d, NULL);
mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat);
diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c
index ba90926df3b..69d135b8550 100644
--- a/source/blender/editors/transform/transform_orientations.c
+++ b/source/blender/editors/transform/transform_orientations.c
@@ -756,7 +756,7 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3],
if (flag) {
float tvec[3];
if ((v3d->around == V3D_LOCAL) ||
- ELEM3(flag, SEL_F2, SEL_F1 | SEL_F3, SEL_F1 | SEL_F2 | SEL_F3))
+ ELEM(flag, SEL_F2, SEL_F1 | SEL_F3, SEL_F1 | SEL_F2 | SEL_F3))
{
BKE_nurb_bezt_calc_normal(nu, bezt, tvec);
add_v3_v3(normal, tvec);
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
index 451837fd311..abef2c9fc30 100644
--- a/source/blender/editors/transform/transform_snap.c
+++ b/source/blender/editors/transform/transform_snap.c
@@ -117,8 +117,8 @@ int BIF_snappingSupported(Object *obedit)
{
int status = 0;
- if (obedit == NULL || ELEM5(obedit->type, OB_MESH, OB_ARMATURE, OB_CURVE, OB_LATTICE, OB_MBALL)) /* only support object mesh, armature, curves */
- {
+ /* only support object mesh, armature, curves */
+ if (obedit == NULL || ELEM(obedit->type, OB_MESH, OB_ARMATURE, OB_CURVE, OB_LATTICE, OB_MBALL)) {
status = 1;
}
@@ -337,6 +337,46 @@ void applyProject(TransInfo *t)
mul_m3_v3(td->smtx, tvec);
add_v3_v3(td->loc, tvec);
+
+ if (t->tsnap.align && (t->flag & T_OBJECT)) {
+ /* handle alignment as well */
+ const float *original_normal;
+ float axis[3];
+ float mat[3][3];
+ float angle;
+ float totmat[3][3], smat[3][3];
+ float eul[3], fmat[3][3], quat[4];
+ float obmat[3][3];
+
+ /* In pose mode, we want to align normals with Y axis of bones... */
+ original_normal = td->axismtx[2];
+
+ cross_v3_v3v3(axis, original_normal, no);
+ angle = saacos(dot_v3v3(original_normal, no));
+
+ axis_angle_to_quat(quat, axis, angle);
+
+ quat_to_mat3(mat, quat);
+
+ mul_m3_m3m3(totmat, mat, td->mtx);
+ mul_m3_m3m3(smat, td->smtx, totmat);
+
+ /* calculate the total rotatation in eulers */
+ add_v3_v3v3(eul, td->ext->irot, td->ext->drot); /* we have to correct for delta rot */
+ eulO_to_mat3(obmat, eul, td->ext->rotOrder);
+ /* mat = transform, obmat = object rotation */
+ mul_m3_m3m3(fmat, smat, obmat);
+
+ mat3_to_compatible_eulO(eul, td->ext->rot, td->ext->rotOrder, fmat);
+
+ /* correct back for delta rot */
+ sub_v3_v3v3(eul, eul, td->ext->drot);
+
+ /* and apply */
+ copy_v3_v3(td->ext->rot, eul);
+
+ /* TODO support constraints for rotation too? see ElementRotation */
+ }
}
}
@@ -505,7 +545,7 @@ static void initSnappingMode(TransInfo *t)
/* Edit mode */
if (t->tsnap.applySnap != NULL && // A snapping function actually exist
- (obedit != NULL && ELEM5(obedit->type, OB_MESH, OB_ARMATURE, OB_CURVE, OB_LATTICE, OB_MBALL)) ) // Temporary limited to edit mode meshes, armature, curves, mballs
+ (obedit != NULL && ELEM(obedit->type, OB_MESH, OB_ARMATURE, OB_CURVE, OB_LATTICE, OB_MBALL)) ) // Temporary limited to edit mode meshes, armature, curves, mballs
{
/* Exclude editmesh if using proportional edit */
if ((obedit->type == OB_MESH) && (t->flag & T_PROP_EDIT)) {
@@ -588,7 +628,7 @@ void initSnapping(TransInfo *t, wmOperator *op)
}
/* use scene defaults only when transform is modal */
else if (t->flag & T_MODAL) {
- if (ELEM3(t->spacetype, SPACE_VIEW3D, SPACE_IMAGE, SPACE_NODE)) {
+ if (ELEM(t->spacetype, SPACE_VIEW3D, SPACE_IMAGE, SPACE_NODE)) {
if (ts->snap_flag & SCE_SNAP) {
t->modifiers |= MOD_SNAP;
}
@@ -658,7 +698,8 @@ static void setSnappingCallback(TransInfo *t)
void addSnapPoint(TransInfo *t)
{
- if (t->tsnap.status & POINT_INIT) {
+ /* Currently only 3D viewport works for snapping points. */
+ if (t->tsnap.status & POINT_INIT && t->spacetype == SPACE_VIEW3D) {
TransSnapPoint *p = MEM_callocN(sizeof(TransSnapPoint), "SnapPoint");
t->tsnap.selectedPoint = p;
@@ -1492,6 +1533,8 @@ static bool snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMes
const float mval[2], float r_loc[3], float r_no[3], float *r_dist_px, float *r_depth, bool do_bb)
{
bool retval = false;
+ const bool do_ray_start_correction = (snap_mode == SCE_SNAP_MODE_FACE && ar &&
+ !((RegionView3D *)ar->regiondata)->is_persp);
int totvert = dm->getNumVerts(dm);
if (totvert > 0) {
@@ -1518,6 +1561,28 @@ static bool snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMes
return retval;
}
}
+ else if (do_ray_start_correction) {
+ /* We *need* a reasonably valid len_diff in this case.
+ * Use BHVTree to find the closest face from ray_start_local.
+ */
+ BVHTreeFromMesh treeData;
+ BVHTreeNearest nearest;
+ len_diff = 0.0f; /* In case BVHTree would fail for some reason... */
+
+ treeData.em_evil = em;
+ bvhtree_from_mesh_faces(&treeData, dm, 0.0f, 2, 6);
+ if (treeData.tree != NULL) {
+ nearest.index = -1;
+ nearest.dist_sq = FLT_MAX;
+ /* Compute and store result. */
+ BLI_bvhtree_find_nearest(treeData.tree, ray_start_local, &nearest,
+ treeData.nearest_callback, &treeData);
+ if (nearest.index != -1) {
+ len_diff = sqrtf(nearest.dist_sq);
+ }
+ }
+ free_bvhtree_from_mesh(&treeData);
+ }
switch (snap_mode) {
case SCE_SNAP_MODE_FACE:
@@ -1529,7 +1594,7 @@ static bool snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMes
* been *inside* boundbox, leading to snap failures (see T38409).
* Note also ar might be null (see T38435), in this case we assume ray_start is ok!
*/
- if (ar && !((RegionView3D *)ar->regiondata)->is_persp) {
+ if (do_ray_start_correction) {
float ray_org_local[3];
copy_v3_v3(ray_org_local, ray_origin);
@@ -2383,6 +2448,9 @@ static void applyGridIncrement(TransInfo *t, float *val, int max_index, float fa
if (t->options & CTX_MASK) {
ED_space_image_get_aspect(t->sa->spacedata.first, asp, asp + 1);
}
+ else if (t->options & CTX_PAINT_CURVE) {
+ asp[0] = asp[1] = 1.0;
+ }
else {
ED_space_image_get_uv_aspect(t->sa->spacedata.first, asp, asp + 1);
}
diff --git a/source/blender/editors/util/ed_transverts.c b/source/blender/editors/util/ed_transverts.c
index 3bd927e5b25..104b628c25a 100644
--- a/source/blender/editors/util/ed_transverts.c
+++ b/source/blender/editors/util/ed_transverts.c
@@ -192,7 +192,7 @@ static void set_mapped_co(void *vuserdata, int index, const float co[3],
bool ED_transverts_check_obedit(Object *obedit)
{
- return (ELEM6(obedit->type, OB_ARMATURE, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE, OB_MBALL));
+ return (ELEM(obedit->type, OB_ARMATURE, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE, OB_MBALL));
}
void ED_transverts_create_from_obedit(TransVertStore *tvs, Object *obedit, const int mode)
diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c
index 47fbfbe3eba..56b12fcdcda 100644
--- a/source/blender/editors/util/ed_util.c
+++ b/source/blender/editors/util/ed_util.c
@@ -86,7 +86,7 @@ void ED_editors_init(bContext *C)
/* This is called during initialization, so we don't want to store any reports */
ReportList *reports = CTX_wm_reports(C);
- int reports_flag_prev = reports->flag &= ~RPT_STORE;
+ int reports_flag_prev = reports->flag & ~RPT_STORE;
SWAP(int, reports->flag, reports_flag_prev);
diff --git a/source/blender/editors/util/numinput.c b/source/blender/editors/util/numinput.c
index a618ab8419b..fd8f16f5d02 100644
--- a/source/blender/editors/util/numinput.c
+++ b/source/blender/editors/util/numinput.c
@@ -98,7 +98,7 @@ void outputNumInput(NumInput *n, char *str, const float scale_length)
const short i = (n->flag & NUM_AFFECT_ALL && n->idx != j && !(n->val_flag[j] & NUM_EDITED)) ? 0 : j;
/* Use scale_length if needed! */
- const float fac = ELEM3(n->unit_type[j], B_UNIT_LENGTH, B_UNIT_AREA, B_UNIT_VOLUME) ? scale_length : 1.0f;
+ const float fac = ELEM(n->unit_type[j], B_UNIT_LENGTH, B_UNIT_AREA, B_UNIT_VOLUME) ? scale_length : 1.0f;
if (n->val_flag[i] & NUM_EDITED) {
/* Get the best precision, allows us to draw '10.0001' as '10' instead! */
@@ -189,15 +189,15 @@ bool applyNumInput(NumInput *n, float *vec)
if (n->val_flag[i] & NUM_NO_NEGATIVE && val < 0.0f) {
val = 0.0f;
}
- if (n->val_flag[i] & NUM_NO_ZERO && val == 0.0f) {
- val = 0.0001f;
- }
if (n->val_flag[i] & NUM_NO_FRACTION && val != floorf(val)) {
val = floorf(val + 0.5f);
if (n->val_flag[i] & NUM_NO_ZERO && val == 0.0f) {
val = 1.0f;
}
}
+ else if (n->val_flag[i] & NUM_NO_ZERO && val == 0.0f) {
+ val = 0.0001f;
+ }
}
vec[j] = val;
}
@@ -480,7 +480,7 @@ bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event)
default_unit = "r";
/* Use scale_length if needed! */
- if (ELEM3(n->unit_type[idx], B_UNIT_LENGTH, B_UNIT_AREA, B_UNIT_VOLUME))
+ if (ELEM(n->unit_type[idx], B_UNIT_LENGTH, B_UNIT_AREA, B_UNIT_VOLUME))
fac /= sce->unit.scale_length;
BLI_strncpy(str_unit_convert, n->str, sizeof(str_unit_convert));
diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c
index a1cc23f735b..36c96a8d011 100644
--- a/source/blender/editors/uvedit/uvedit_draw.c
+++ b/source/blender/editors/uvedit/uvedit_draw.c
@@ -33,6 +33,7 @@
#include <stdlib.h>
#include <string.h>
+#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
@@ -48,6 +49,8 @@
#include "BKE_DerivedMesh.h"
#include "BKE_editmesh.h"
+#include "BKE_material.h"
+
#include "BKE_scene.h"
#include "BIF_gl.h"
@@ -403,20 +406,28 @@ static void draw_uvs_other_mesh_new_shading(Object *ob, const Image *curimage)
int a;
BLI_bitmap *mat_test_array;
bool ok = false;
+ int totcol = 0;
if (me->mloopuv == NULL) {
return;
}
- if (ob->totcol == 0) {
+ if (curimage && ob->totcol == 0) {
return;
}
- mat_test_array = BLI_BITMAP_NEW_ALLOCA(ob->totcol);
+ totcol = max_ii(ob->totcol, 1);
+ mat_test_array = BLI_BITMAP_NEW_ALLOCA(totcol);
- for (a = 0; a < ob->totcol; a++) {
+ for (a = 0; a < totcol; a++) {
Image *image;
- ED_object_get_active_image(ob, a + 1, &image, NULL, NULL);
+
+ /* if no materials, assume a default material with no image */
+ if (ob->totcol)
+ ED_object_get_active_image(ob, a + 1, &image, NULL, NULL, NULL);
+ else
+ image = NULL;
+
if (image == curimage) {
BLI_BITMAP_ENABLE(mat_test_array, a);
ok = true;
@@ -429,7 +440,7 @@ static void draw_uvs_other_mesh_new_shading(Object *ob, const Image *curimage)
for (a = me->totpoly; a != 0; a--, mpoly++) {
const int mat_nr = mpoly->mat_nr;
- if ((mat_nr >= ob->totcol) ||
+ if ((mat_nr >= totcol) ||
(BLI_BITMAP_TEST(mat_test_array, mat_nr)) == 0)
{
continue;
@@ -471,13 +482,39 @@ static void draw_uvs_texpaint(SpaceImage *sima, Scene *scene, Object *ob)
{
const bool new_shading_nodes = BKE_scene_use_new_shading_nodes(scene);
Image *curimage = ED_space_image(sima);
+ Mesh *me = ob->data;
+ Material *ma;
if (sima->flag & SI_DRAW_OTHER) {
draw_uvs_other(scene, ob, curimage, new_shading_nodes);
}
UI_ThemeColor(TH_UV_SHADOW);
- draw_uvs_other_mesh(ob, curimage, new_shading_nodes);
+
+ ma = give_current_material(ob, ob->actcol);
+
+ if (me->mtpoly) {
+ MPoly *mpoly = me->mpoly;
+ MLoopUV *mloopuv, *mloopuv_base;
+ int a, b;
+ if (!(ma && ma->texpaintslot && ma->texpaintslot[ma->paint_active_slot].uvname &&
+ (mloopuv = CustomData_get_layer_named(&me->ldata, CD_MLOOPUV, ma->texpaintslot[ma->paint_active_slot].uvname))))
+ {
+ mloopuv = me->mloopuv;
+ }
+
+ mloopuv_base = mloopuv;
+
+ for (a = me->totpoly; a > 0; a--, mpoly++) {
+ glBegin(GL_LINE_LOOP);
+
+ mloopuv = mloopuv_base + mpoly->loopstart;
+ for (b = 0; b < mpoly->totloop; b++, mloopuv++) {
+ glVertex2fv(mloopuv->uv);
+ }
+ glEnd();
+ }
+ }
}
#ifdef USE_EDBM_LOOPTRIS
@@ -540,7 +577,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
if (new_shading_nodes) {
if (efa_act) {
- ED_object_get_active_image(obedit, efa_act->mat_nr + 1, &curimage, NULL, NULL);
+ ED_object_get_active_image(obedit, efa_act->mat_nr + 1, &curimage, NULL, NULL, NULL);
}
else {
curimage = ima;
@@ -914,7 +951,7 @@ void draw_uvedit_main(SpaceImage *sima, ARegion *ar, Scene *scene, Object *obedi
ToolSettings *toolsettings = scene->toolsettings;
int show_uvedit, show_uvshadow, show_texpaint_uvshadow;
- show_texpaint_uvshadow = (obact && obact->type == OB_MESH && obact->mode == OB_MODE_TEXTURE_PAINT);
+ show_texpaint_uvshadow = ED_space_image_show_texpaint(sima, obact);
show_uvedit = ED_space_image_show_uvedit(sima, obedit);
show_uvshadow = ED_space_image_show_uvshadow(sima, obedit);
diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c
index 6cf34d9f93f..0d8b5a524b6 100644
--- a/source/blender/editors/uvedit/uvedit_ops.c
+++ b/source/blender/editors/uvedit/uvedit_ops.c
@@ -137,21 +137,24 @@ static bool is_image_texture_node(bNode *node)
}
bool ED_object_get_active_image(Object *ob, int mat_nr,
- Image **r_ima, ImageUser **r_iuser, bNode **r_node)
+ Image **r_ima, ImageUser **r_iuser, bNode **r_node, bNodeTree **r_ntree)
{
Material *ma = give_current_material(ob, mat_nr);
- bNode *node = (ma && ma->use_nodes) ? nodeGetActiveTexture(ma->nodetree) : NULL;
+ bNodeTree *ntree = (ma && ma->use_nodes) ? ma->nodetree : NULL;
+ bNode *node = (ntree) ? nodeGetActiveTexture(ntree) : NULL;
if (node && is_image_texture_node(node)) {
if (r_ima) *r_ima = (Image *)node->id;
if (r_iuser) *r_iuser = NULL;
if (r_node) *r_node = node;
+ if (r_ntree) *r_ntree = ntree;
return true;
}
if (r_ima) *r_ima = NULL;
if (r_iuser) *r_iuser = NULL;
if (r_node) *r_node = node;
+ if (r_ntree) *r_ntree = ntree;
return false;
}
@@ -3827,7 +3830,8 @@ static void UV_OT_reveal(wmOperatorType *ot)
static int uv_set_2d_cursor_poll(bContext *C)
{
return ED_operator_uvedit_space_image(C) ||
- ED_space_image_maskedit_poll(C);
+ ED_space_image_maskedit_poll(C) ||
+ ED_space_image_paint_curve(C);
}
static int uv_set_2d_cursor_exec(bContext *C, wmOperator *op)
diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
index 21e7bb00204..335d8e6589e 100644
--- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c
+++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
@@ -201,7 +201,7 @@ void uvedit_get_aspect(Scene *scene, Object *ob, BMEditMesh *em, float *aspx, fl
if (efa) {
if (BKE_scene_use_new_shading_nodes(scene)) {
- ED_object_get_active_image(ob, efa->mat_nr + 1, &ima, NULL, NULL);
+ ED_object_get_active_image(ob, efa->mat_nr + 1, &ima, NULL, NULL, NULL);
}
else {
MTexPoly *tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
@@ -938,7 +938,7 @@ static void uv_map_rotation_matrix(float result[4][4], RegionView3D *rv3d, Objec
rotup[0][0] = 1.0f / radius;
/* calculate transforms*/
- mul_serie_m4(result, rotup, rotside, viewmatrix, rotobj, NULL, NULL, NULL, NULL);
+ mul_m4_series(result, rotup, rotside, viewmatrix, rotobj);
}
static void uv_map_transform(bContext *C, wmOperator *op, float center[3], float rotmat[4][4])
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp
index dbbc4f77c26..57882cbce0c 100644
--- a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp
+++ b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp
@@ -449,7 +449,7 @@ void BlenderFileLoader::insertShapeNode(ObjectInstanceRen *obi, int id)
return;
// We allocate memory for the meshes to be imported
- NodeTransform *currentMesh = new NodeTransform;
+ NodeGroup *currentMesh = new NodeGroup;
NodeShape *shape = new NodeShape;
unsigned vSize = 3 * 3 * numFaces;
@@ -799,10 +799,6 @@ void BlenderFileLoader::insertShapeNode(ObjectInstanceRen *obi, int id)
rep->setBBox(bbox);
shape->AddRep(rep);
- Matrix44r meshMat = Matrix44r::identity();
- currentMesh->setMatrix(meshMat);
- currentMesh->Translate(0, 0, 0);
-
currentMesh->AddChild(shape);
_Scene->AddChild(currentMesh);
}
diff --git a/source/blender/freestyle/intern/geometry/Grid.h b/source/blender/freestyle/intern/geometry/Grid.h
index c0cab2a05db..c1d04f6b4cc 100644
--- a/source/blender/freestyle/intern/geometry/Grid.h
+++ b/source/blender/freestyle/intern/geometry/Grid.h
@@ -30,9 +30,7 @@
#include <cstring> // for memset
#include <float.h>
-#if !defined(_MSC_VER) || _MSC_VER >= 1700
#include <stdint.h> // For SET_UINT_IN_POINTER, i.e. uintptr_t.
-#endif
#include <vector>
#include "Geom.h"
diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp b/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp
index 36cdb1b92ff..1ef29792d56 100644
--- a/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp
+++ b/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp
@@ -178,6 +178,19 @@ static int CurvePoint_second_svertex_set(BPy_CurvePoint *self, PyObject *value,
return 0;
}
+PyDoc_STRVAR(CurvePoint_fedge_doc,
+"Gets the FEdge for the two SVertices that given CurvePoints consists out of.\n"
+"A shortcut for CurvePoint.first_svertex.get_fedge(CurvePoint.second_svertex).\n"
+"\n"
+":type: :class:`FEdge`");
+
+static PyObject *CurvePoint_fedge_get(BPy_CurvePoint *self, void *UNUSED(closure))
+{
+ SVertex *A = self->cp->A();
+ Interface0D *B = (Interface0D *)self->cp->B();
+ return Any_BPy_Interface1D_from_Interface1D(*(A->getFEdge(*B)));
+}
+
PyDoc_STRVAR(CurvePoint_t2d_doc,
"The 2D interpolation parameter.\n"
"\n"
@@ -204,6 +217,8 @@ static PyGetSetDef BPy_CurvePoint_getseters[] = {
(char *)CurvePoint_first_svertex_doc, NULL},
{(char *)"second_svertex", (getter)CurvePoint_second_svertex_get, (setter)CurvePoint_second_svertex_set,
(char *)CurvePoint_second_svertex_doc, NULL},
+ {(char *)"fedge", (getter)CurvePoint_fedge_get, NULL,
+ CurvePoint_fedge_doc, NULL},
{(char *)"t2d", (getter)CurvePoint_t2d_get, (setter)CurvePoint_t2d_set, (char *)CurvePoint_t2d_doc, NULL},
{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
};
diff --git a/source/blender/freestyle/intern/stroke/StrokeRep.h b/source/blender/freestyle/intern/stroke/StrokeRep.h
index 61a456cdf42..50615e0c571 100644
--- a/source/blender/freestyle/intern/stroke/StrokeRep.h
+++ b/source/blender/freestyle/intern/stroke/StrokeRep.h
@@ -37,7 +37,7 @@
#endif
extern "C" {
-#include "DNA_material_types.h"
+#include "DNA_material_types.h" // for MAX_MTEX
}
namespace Freestyle {
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index 739deffa519..13e46bc7de8 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -51,12 +51,14 @@ set(SRC
intern/gpu_extensions.c
intern/gpu_material.c
intern/gpu_simple_shader.c
+ intern/gpu_select.c
GPU_buffers.h
GPU_draw.h
GPU_extensions.h
GPU_material.h
GPU_simple_shader.h
+ GPU_select.h
intern/gpu_codegen.h
)
diff --git a/source/blender/gpu/GPU_buffers.h b/source/blender/gpu/GPU_buffers.h
index 096b2080b2b..461995e37b5 100644
--- a/source/blender/gpu/GPU_buffers.h
+++ b/source/blender/gpu/GPU_buffers.h
@@ -139,6 +139,7 @@ void GPU_drawobject_free(struct DerivedMesh *dm);
void GPU_vertex_setup(struct DerivedMesh *dm);
void GPU_normal_setup(struct DerivedMesh *dm);
void GPU_uv_setup(struct DerivedMesh *dm);
+void GPU_texpaint_uv_setup(struct DerivedMesh *dm);
/* colType is the cddata MCol type to use! */
void GPU_color_setup(struct DerivedMesh *dm, int colType);
void GPU_edge_setup(struct DerivedMesh *dm); /* does not mix with other data */
diff --git a/source/blender/gpu/GPU_draw.h b/source/blender/gpu/GPU_draw.h
index bdd70a49e7a..3ddec157c49 100644
--- a/source/blender/gpu/GPU_draw.h
+++ b/source/blender/gpu/GPU_draw.h
@@ -87,7 +87,7 @@ int GPU_get_material_alpha_blend(void);
* - passing NULL clears the state again */
int GPU_set_tpage(struct MTFace *tface, int mipmap, int transp);
-
+void GPU_clear_tpage(bool force);
/* Lights
* - returns how many lights were enabled
* - this affects fixed functions materials and texface, not glsl */
diff --git a/source/blender/gpu/GPU_select.h b/source/blender/gpu/GPU_select.h
new file mode 100644
index 00000000000..1a274e0ad9d
--- /dev/null
+++ b/source/blender/gpu/GPU_select.h
@@ -0,0 +1,61 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Antony Riakiotakis.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file GPU_select.h
+ * \ingroup gpu
+ */
+
+#ifndef __GPU_SELECT__
+#define __GPU_SELECT__
+
+#include "DNA_vec_types.h" /* rcft */
+#include "BLI_sys_types.h"
+
+/* flags for mode of operation */
+enum {
+ GPU_SELECT_ALL = 1,
+ GPU_SELECT_NEAREST_FIRST_PASS = 2,
+ GPU_SELECT_NEAREST_SECOND_PASS = 3,
+};
+
+/* initialize and provide buffer for results */
+void GPU_select_begin(unsigned int *buffer, unsigned int bufsize, rctf *input, char mode, int oldhits);
+
+/* loads a new selection id and ends previous query, if any. In second pass of selection it also returns
+ * if id has been hit on the first pass already. Thus we can skip drawing un-hit objects IMPORTANT: We rely on the order of object rendering on passes to be
+ * the same for this to work */
+bool GPU_select_load_id(unsigned int id);
+
+/* cleanup and flush selection results to buffer. Return number of hits and hits in buffer.
+ * if dopass is true, we will do a second pass with occlusion queries to get the closest hit */
+unsigned int GPU_select_end(void);
+
+/* does the GPU support occlusion queries? */
+bool GPU_select_query_check_support(void);
+
+/* is occlusion query supported and user activated? */
+bool GPU_select_query_check_active(void);
+
+#endif
diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c
index f5256f18897..91eb2a43132 100644
--- a/source/blender/gpu/intern/gpu_buffers.c
+++ b/source/blender/gpu/intern/gpu_buffers.c
@@ -46,11 +46,13 @@
#include "BLI_ghash.h"
#include "BLI_threads.h"
+#include "DNA_material_types.h"
#include "DNA_meshdata_types.h"
#include "BKE_ccg.h"
#include "BKE_DerivedMesh.h"
#include "BKE_paint.h"
+#include "BKE_material.h"
#include "BKE_pbvh.h"
#include "DNA_userdef_types.h"
@@ -63,13 +65,16 @@
typedef enum {
GPU_BUFFER_VERTEX_STATE = 1,
GPU_BUFFER_NORMAL_STATE = 2,
- GPU_BUFFER_TEXCOORD_STATE = 4,
- GPU_BUFFER_COLOR_STATE = 8,
- GPU_BUFFER_ELEMENT_STATE = 16,
+ GPU_BUFFER_TEXCOORD_UNIT_0_STATE = 4,
+ GPU_BUFFER_TEXCOORD_UNIT_1_STATE = 8,
+ GPU_BUFFER_COLOR_STATE = 16,
+ GPU_BUFFER_ELEMENT_STATE = 32,
} GPUBufferState;
#define MAX_GPU_ATTRIB_DATA 32
+#define BUFFER_OFFSET(n) ((GLubyte *)NULL + (n))
+
/* -1 - undefined, 0 - vertex arrays, 1 - VBOs */
static int useVBOs = -1;
static GPUBufferState GLStates = 0;
@@ -611,7 +616,7 @@ static GPUBuffer *gpu_buffer_setup(DerivedMesh *dm, GPUDrawObject *object,
}
mat_orig_to_new = MEM_mallocN(sizeof(*mat_orig_to_new) * dm->totmat,
- "GPU_buffer_setup.mat_orig_to_new");
+ "GPU_buffer_setup.mat_orig_to_new");
cur_index_per_mat = MEM_mallocN(sizeof(int) * object->totmaterial,
"GPU_buffer_setup.cur_index_per_mat");
for (i = 0; i < object->totmaterial; i++) {
@@ -836,6 +841,61 @@ static void GPU_buffer_copy_uv(DerivedMesh *dm, float *varray, int *index, int *
}
}
+
+static void GPU_buffer_copy_uv_texpaint(DerivedMesh *dm, float *varray, int *index, int *mat_orig_to_new, void *UNUSED(user))
+{
+ int start;
+ int i, totface;
+
+ int totmaterial = dm->totmat;
+ MTFace **mtface_base;
+ MTFace *stencil_base;
+ int stencil;
+ MFace *mf;
+
+ /* should have been checked for before, reassert */
+ BLI_assert(DM_get_tessface_data_layer(dm, CD_MTFACE));
+ mf = dm->getTessFaceArray(dm);
+ mtface_base = MEM_mallocN(totmaterial * sizeof(*mtface_base), "texslots");
+
+ for (i = 0; i < totmaterial; i++) {
+ mtface_base[i] = DM_paint_uvlayer_active_get(dm, i);
+ }
+
+ stencil = CustomData_get_stencil_layer(&dm->faceData, CD_MTFACE);
+ stencil_base = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, stencil);
+
+ totface = dm->getNumTessFaces(dm);
+
+ for (i = 0; i < totface; i++, mf++) {
+ int mat_i = mf->mat_nr;
+ start = index[mat_orig_to_new[mat_i]];
+
+ /* v1 v2 v3 */
+ copy_v2_v2(&varray[start], mtface_base[mat_i][i].uv[0]);
+ copy_v2_v2(&varray[start + 2], stencil_base[i].uv[0]);
+ copy_v2_v2(&varray[start + 4], mtface_base[mat_i][i].uv[1]);
+ copy_v2_v2(&varray[start + 6], stencil_base[i].uv[1]);
+ copy_v2_v2(&varray[start + 8], mtface_base[mat_i][i].uv[2]);
+ copy_v2_v2(&varray[start + 10], stencil_base[i].uv[2]);
+ index[mat_orig_to_new[mat_i]] += 12;
+
+ if (mf->v4) {
+ /* v3 v4 v1 */
+ copy_v2_v2(&varray[start + 12], mtface_base[mat_i][i].uv[2]);
+ copy_v2_v2(&varray[start + 14], stencil_base[i].uv[2]);
+ copy_v2_v2(&varray[start + 16], mtface_base[mat_i][i].uv[3]);
+ copy_v2_v2(&varray[start + 18], stencil_base[i].uv[3]);
+ copy_v2_v2(&varray[start + 20], mtface_base[mat_i][i].uv[0]);
+ copy_v2_v2(&varray[start + 22], stencil_base[i].uv[0]);
+ index[mat_orig_to_new[mat_i]] += 12;
+ }
+ }
+
+ MEM_freeN(mtface_base);
+}
+
+
static void copy_mcol_uc3(unsigned char *v, unsigned char *col)
{
v[0] = col[3];
@@ -925,6 +985,7 @@ typedef enum {
GPU_BUFFER_NORMAL,
GPU_BUFFER_COLOR,
GPU_BUFFER_UV,
+ GPU_BUFFER_UV_TEXPAINT,
GPU_BUFFER_EDGE,
GPU_BUFFER_UVEDGE,
} GPUBufferType;
@@ -940,6 +1001,7 @@ const GPUBufferTypeSettings gpu_buffer_type_settings[] = {
{GPU_buffer_copy_normal, GL_ARRAY_BUFFER_ARB, 3},
{GPU_buffer_copy_mcol, GL_ARRAY_BUFFER_ARB, 3},
{GPU_buffer_copy_uv, GL_ARRAY_BUFFER_ARB, 2},
+ {GPU_buffer_copy_uv_texpaint, GL_ARRAY_BUFFER_ARB, 4},
{GPU_buffer_copy_edge, GL_ELEMENT_ARRAY_BUFFER_ARB, 2},
{GPU_buffer_copy_uvedge, GL_ELEMENT_ARRAY_BUFFER_ARB, 4}
};
@@ -956,6 +1018,8 @@ static GPUBuffer **gpu_drawobject_buffer_from_type(GPUDrawObject *gdo, GPUBuffer
return &gdo->colors;
case GPU_BUFFER_UV:
return &gdo->uv;
+ case GPU_BUFFER_UV_TEXPAINT:
+ return &gdo->uv;
case GPU_BUFFER_EDGE:
return &gdo->edges;
case GPU_BUFFER_UVEDGE:
@@ -977,6 +1041,8 @@ static int gpu_buffer_size_from_type(DerivedMesh *dm, GPUBufferType type)
return sizeof(char) * 3 * dm->drawObject->tot_triangle_point;
case GPU_BUFFER_UV:
return sizeof(float) * 2 * dm->drawObject->tot_triangle_point;
+ case GPU_BUFFER_UV_TEXPAINT:
+ return sizeof(float) * 4 * dm->drawObject->tot_triangle_point;
case GPU_BUFFER_EDGE:
return sizeof(int) * 2 * dm->drawObject->totedge;
case GPU_BUFFER_UVEDGE:
@@ -1005,7 +1071,7 @@ static GPUBuffer *gpu_buffer_setup_type(DerivedMesh *dm, GPUBufferType type)
if (!(user_data = DM_get_tessface_data_layer(dm, dm->drawObject->colType)))
return NULL;
}
- else if (type == GPU_BUFFER_UV) {
+ else if (ELEM(type, GPU_BUFFER_UV, GPU_BUFFER_UV_TEXPAINT)) {
if (!DM_get_tessface_data_layer(dm, CD_MTFACE))
return NULL;
}
@@ -1081,9 +1147,35 @@ void GPU_uv_setup(DerivedMesh *dm)
glTexCoordPointer(2, GL_FLOAT, 0, dm->drawObject->uv->pointer);
}
- GLStates |= GPU_BUFFER_TEXCOORD_STATE;
+ GLStates |= GPU_BUFFER_TEXCOORD_UNIT_0_STATE;
}
+void GPU_texpaint_uv_setup(DerivedMesh *dm)
+{
+ if (!gpu_buffer_setup_common(dm, GPU_BUFFER_UV_TEXPAINT))
+ return;
+
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ if (useVBOs) {
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, dm->drawObject->uv->id);
+ glTexCoordPointer(2, GL_FLOAT, 4 * sizeof(float), 0);
+ glClientActiveTexture(GL_TEXTURE1);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glTexCoordPointer(2, GL_FLOAT, 4 * sizeof(float), BUFFER_OFFSET(2 * sizeof(float)));
+ glClientActiveTexture(GL_TEXTURE0);
+ }
+ else {
+ glTexCoordPointer(2, GL_FLOAT, 4 * sizeof(float), dm->drawObject->uv->pointer);
+ glClientActiveTexture(GL_TEXTURE1);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glTexCoordPointer(2, GL_FLOAT, 4 * sizeof(float), (char *)dm->drawObject->uv->pointer + 2 * sizeof(float));
+ glClientActiveTexture(GL_TEXTURE0);
+ }
+
+ GLStates |= GPU_BUFFER_TEXCOORD_UNIT_0_STATE | GPU_BUFFER_TEXCOORD_UNIT_1_STATE;
+}
+
+
void GPU_color_setup(DerivedMesh *dm, int colType)
{
if (!dm->drawObject) {
@@ -1241,8 +1333,13 @@ void GPU_buffer_unbind(void)
glDisableClientState(GL_VERTEX_ARRAY);
if (GLStates & GPU_BUFFER_NORMAL_STATE)
glDisableClientState(GL_NORMAL_ARRAY);
- if (GLStates & GPU_BUFFER_TEXCOORD_STATE)
+ if (GLStates & GPU_BUFFER_TEXCOORD_UNIT_0_STATE)
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ if (GLStates & GPU_BUFFER_TEXCOORD_UNIT_1_STATE) {
+ glClientActiveTexture(GL_TEXTURE1);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glClientActiveTexture(GL_TEXTURE0);
+ }
if (GLStates & GPU_BUFFER_COLOR_STATE)
glDisableClientState(GL_COLOR_ARRAY);
if (GLStates & GPU_BUFFER_ELEMENT_STATE) {
@@ -1251,8 +1348,8 @@ void GPU_buffer_unbind(void)
}
}
GLStates &= ~(GPU_BUFFER_VERTEX_STATE | GPU_BUFFER_NORMAL_STATE |
- GPU_BUFFER_TEXCOORD_STATE | GPU_BUFFER_COLOR_STATE |
- GPU_BUFFER_ELEMENT_STATE);
+ GPU_BUFFER_TEXCOORD_UNIT_0_STATE | GPU_BUFFER_TEXCOORD_UNIT_1_STATE |
+ GPU_BUFFER_COLOR_STATE | GPU_BUFFER_ELEMENT_STATE);
for (i = 0; i < MAX_GPU_ATTRIB_DATA; i++) {
if (attribData[i].index != -1) {
@@ -2577,11 +2674,14 @@ bool GPU_pbvh_buffers_diffuse_changed(GPU_PBVH_Buffers *buffers, GSet *bm_faces,
}
else if (buffers->use_bmesh) {
/* due to dynamc nature of dyntopo, only get first material */
- GSetIterator gs_iter;
- BMFace *f;
- BLI_gsetIterator_init(&gs_iter, bm_faces);
- f = BLI_gsetIterator_getKey(&gs_iter);
- GPU_material_diffuse_get(f->mat_nr + 1, diffuse_color);
+ if (BLI_gset_size(bm_faces) > 0) {
+ GSetIterator gs_iter;
+ BMFace *f;
+
+ BLI_gsetIterator_init(&gs_iter, bm_faces);
+ f = BLI_gsetIterator_getKey(&gs_iter);
+ GPU_material_diffuse_get(f->mat_nr + 1, diffuse_color);
+ }
}
else {
const DMFlagMat *flags = &buffers->grid_flag_mats[buffers->grid_indices[0]];
diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c
index b3155f0ad50..d60525dd34a 100644
--- a/source/blender/gpu/intern/gpu_codegen.c
+++ b/source/blender/gpu/intern/gpu_codegen.c
@@ -97,7 +97,7 @@ static char *gpu_str_skip_token(char *str, char *token, int max)
/* skip a variable/function name */
while (*str) {
- if (ELEM7(*str, ' ', '(', ')', ',', '\t', '\n', '\r'))
+ if (ELEM(*str, ' ', '(', ')', ',', '\t', '\n', '\r'))
break;
else {
if (token && len < max-1) {
@@ -115,7 +115,7 @@ static char *gpu_str_skip_token(char *str, char *token, int max)
/* skip the next special characters:
* note the missing ')' */
while (*str) {
- if (ELEM6(*str, ' ', '(', ',', '\t', '\n', '\r'))
+ if (ELEM(*str, ' ', '(', ',', '\t', '\n', '\r'))
str++;
else
break;
diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c
index 68b8492926b..fa9bc73dcbe 100644
--- a/source/blender/gpu/intern/gpu_draw.c
+++ b/source/blender/gpu/intern/gpu_draw.c
@@ -370,9 +370,9 @@ static void gpu_make_repbind(Image *ima)
BKE_image_release_ibuf(ima, ibuf, NULL);
}
-static void gpu_clear_tpage(void)
+void GPU_clear_tpage(bool force)
{
- if (GTS.lasttface==NULL)
+ if (GTS.lasttface==NULL && !force)
return;
GTS.lasttface= NULL;
@@ -866,7 +866,7 @@ int GPU_set_tpage(MTFace *tface, int mipmap, int alphablend)
/* check if we need to clear the state */
if (tface==NULL) {
- gpu_clear_tpage();
+ GPU_clear_tpage(false);
return 0;
}
@@ -1548,7 +1548,7 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O
/* setting 'do_alpha_after = true' indicates this object needs to be
* drawn in a second alpha pass for improved blending */
if (do_alpha_after && !GMS.is_alpha_pass)
- if (ELEM3(alphablend, GPU_BLEND_ALPHA, GPU_BLEND_ADD, GPU_BLEND_ALPHA_SORT))
+ if (ELEM(alphablend, GPU_BLEND_ALPHA, GPU_BLEND_ADD, GPU_BLEND_ALPHA_SORT))
*do_alpha_after = true;
GMS.alphablend[a]= alphablend;
diff --git a/source/blender/gpu/intern/gpu_select.c b/source/blender/gpu/intern/gpu_select.c
new file mode 100644
index 00000000000..2df9e603903
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_select.c
@@ -0,0 +1,246 @@
+/*
+ * ***** 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) 2014 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Antony Riakiotakis.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/gpu/intern/gpu_select.c
+ * \ingroup gpu
+ *
+ * Interface for accessing gpu-related methods for selection. The semantics will be
+ * similar to glRenderMode(GL_SELECT) since the goal is to maintain compatibility.
+ */
+#include "GPU_select.h"
+#include "GPU_extensions.h"
+
+#include "BLI_utildefines.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_userdef_types.h"
+
+#include <GL/glew.h>
+
+/* Ad hoc number of queries to allocate to skip doing many glGenQueries */
+#define ALLOC_QUERIES 200
+
+typedef struct GPUQueryState {
+ /* To ignore selection id calls when not initialized */
+ bool select_is_active;
+ /* Tracks whether a query has been issued so that gpu_load_id can end the previous one */
+ bool query_issued;
+ /* array holding the OpenGL query identifiers */
+ unsigned int *queries;
+ /* array holding the id corresponding to each query */
+ unsigned int *id;
+ /* number of queries in *queries and *id */
+ unsigned int num_of_queries;
+ /* index to the next query to start */
+ unsigned int active_query;
+ /* flag to cache user preference for occlusion based selection */
+ bool use_gpu_select;
+ /* cache on initialization */
+ unsigned int *buffer;
+ unsigned int bufsize;
+ /* mode of operation */
+ char mode;
+ unsigned int index;
+ int oldhits;
+} GPUQueryState;
+
+static GPUQueryState g_query_state = {0};
+
+void GPU_select_begin(unsigned int *buffer, unsigned int bufsize, rctf *input, char mode, int oldhits)
+{
+ g_query_state.select_is_active = true;
+ g_query_state.query_issued = false;
+ g_query_state.active_query = 0;
+ g_query_state.use_gpu_select = GPU_select_query_check_active();
+ g_query_state.num_of_queries = 0;
+ g_query_state.bufsize = bufsize;
+ g_query_state.buffer = buffer;
+ g_query_state.mode = mode;
+ g_query_state.index = 0;
+ g_query_state.oldhits = oldhits;
+
+ if (!g_query_state.use_gpu_select) {
+ glSelectBuffer( bufsize, (GLuint *)buffer);
+ glRenderMode(GL_SELECT);
+ glInitNames();
+ glPushName(-1);
+ }
+ else {
+ float viewport[4];
+
+ g_query_state.num_of_queries = ALLOC_QUERIES;
+
+ g_query_state.queries = MEM_mallocN(g_query_state.num_of_queries * sizeof(*g_query_state.queries) , "gpu selection queries");
+ g_query_state.id = MEM_mallocN(g_query_state.num_of_queries * sizeof(*g_query_state.id) , "gpu selection ids");
+ glGenQueriesARB(g_query_state.num_of_queries, g_query_state.queries);
+
+ glPushAttrib(GL_DEPTH_BUFFER_BIT | GL_VIEWPORT_BIT);
+ /* disable writing to the framebuffer */
+ glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+
+ /* In order to save some fill rate we minimize the viewport using rect.
+ * We need to get the region of the scissor so that our geometry doesn't
+ * get rejected before the depth test. Should probably cull rect against
+ * scissor for viewport but this is a rare case I think */
+ glGetFloatv(GL_SCISSOR_BOX, viewport);
+ if (!input || input->xmin == input->xmax) {
+ glViewport(viewport[0], viewport[1], 24, 24);
+ }
+ else {
+ glViewport(viewport[0], viewport[1], (int)(input->xmax - input->xmin), (int)(input->ymax - input->ymin));
+ }
+
+ /* occlusion queries operates on fragments that pass tests and since we are interested on all
+ * objects in the view frustum independently of their order, we need to disable the depth test */
+ if (mode == GPU_SELECT_ALL) {
+ glDisable(GL_DEPTH_TEST);
+ glDepthMask(GL_FALSE);
+ }
+ else if (mode == GPU_SELECT_NEAREST_FIRST_PASS) {
+ glClear(GL_DEPTH_BUFFER_BIT);
+ glEnable(GL_DEPTH_TEST);
+ glDepthMask(GL_TRUE);
+ glDepthFunc(GL_LEQUAL);
+ }
+ else if (mode == GPU_SELECT_NEAREST_SECOND_PASS) {
+ glEnable(GL_DEPTH_TEST);
+ glDepthMask(GL_TRUE);
+ glDepthFunc(GL_EQUAL);
+ }
+ }
+}
+
+bool GPU_select_load_id(unsigned int id)
+{
+ /* if no selection mode active, ignore */
+ if(!g_query_state.select_is_active)
+ return true;
+
+ if (!g_query_state.use_gpu_select) {
+ glLoadName(id);
+ }
+ else {
+ if (g_query_state.query_issued) {
+ glEndQueryARB(GL_SAMPLES_PASSED_ARB);
+ }
+ /* if required, allocate extra queries */
+ if (g_query_state.active_query == g_query_state.num_of_queries) {
+ g_query_state.num_of_queries += ALLOC_QUERIES;
+ g_query_state.queries = MEM_reallocN(g_query_state.queries, g_query_state.num_of_queries * sizeof(*g_query_state.queries));
+ g_query_state.id = MEM_reallocN(g_query_state.id, g_query_state.num_of_queries * sizeof(*g_query_state.id));
+ glGenQueriesARB(ALLOC_QUERIES, &g_query_state.queries[g_query_state.active_query]);
+ }
+
+ glBeginQueryARB(GL_SAMPLES_PASSED_ARB, g_query_state.queries[g_query_state.active_query]);
+ g_query_state.id[g_query_state.active_query] = id;
+ g_query_state.active_query++;
+ g_query_state.query_issued = true;
+
+ if (g_query_state.mode == GPU_SELECT_NEAREST_SECOND_PASS) {
+ if (g_query_state.buffer[g_query_state.index * 4 + 3] == id) {
+ g_query_state.index++;
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+unsigned int GPU_select_end(void)
+{
+ unsigned int hits = 0;
+ if (!g_query_state.use_gpu_select) {
+ glPopName();
+ hits = glRenderMode(GL_RENDER);
+ }
+ else {
+ int i;
+
+ if (g_query_state.query_issued) {
+ glEndQueryARB(GL_SAMPLES_PASSED_ARB);
+ }
+
+ for (i = 0; i < g_query_state.active_query; i++) {
+ unsigned int result;
+ glGetQueryObjectuivARB(g_query_state.queries[i], GL_QUERY_RESULT_ARB, &result);
+ if (result > 0) {
+ if (g_query_state.mode != GPU_SELECT_NEAREST_SECOND_PASS) {
+ if(hits < g_query_state.bufsize) {
+ g_query_state.buffer[hits * 4] = 1;
+ g_query_state.buffer[hits * 4 + 1] = 0xFFFF;
+ g_query_state.buffer[hits * 4 + 2] = 0xFFFF;
+ g_query_state.buffer[hits * 4 + 3] = g_query_state.id[i];
+
+ hits++;
+ }
+ else {
+ hits = -1;
+ break;
+ }
+ }
+ else {
+ int j;
+ /* search in buffer and make selected object first */
+ for (j = 0; j < g_query_state.oldhits; j++) {
+ if (g_query_state.buffer[j * 4 + 3] == g_query_state.id[i]) {
+ g_query_state.buffer[j * 4 + 1] = 0;
+ g_query_state.buffer[j * 4 + 2] = 0;
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ glDeleteQueriesARB(g_query_state.num_of_queries, g_query_state.queries);
+ MEM_freeN(g_query_state.queries);
+ MEM_freeN(g_query_state.id);
+ glPopAttrib();
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ }
+
+ g_query_state.select_is_active = false;
+
+ return hits;
+}
+
+
+bool GPU_select_query_check_support(void)
+{
+ return GLEW_ARB_occlusion_query;
+}
+
+
+bool GPU_select_query_check_active(void)
+{
+ return GLEW_ARB_occlusion_query &&
+ ((U.gpu_select_method == USER_SELECT_USE_OCCLUSION_QUERY) ||
+ ((U.gpu_select_method == USER_SELECT_AUTO) && GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_ANY)));
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl
index d5d0c7ef454..fb364018282 100644
--- a/source/blender/gpu/shaders/gpu_shader_material.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_material.glsl
@@ -2257,6 +2257,11 @@ void node_attribute(vec3 attr_uv, out vec4 outcol, out vec3 outvec, out float ou
outf = (attr_uv.x + attr_uv.y + attr_uv.z)/3.0;
}
+void node_uvmap(vec3 attr_uv, out vec3 outvec)
+{
+ outvec = attr_uv;
+}
+
void node_geometry(vec3 I, vec3 N, mat4 toworld,
out vec3 position, out vec3 normal, out vec3 tangent,
out vec3 true_normal, out vec3 incoming, out vec3 parametric,
diff --git a/source/blender/ikplugin/intern/iksolver_plugin.c b/source/blender/ikplugin/intern/iksolver_plugin.c
index 80c508267f3..cd09b56b262 100644
--- a/source/blender/ikplugin/intern/iksolver_plugin.c
+++ b/source/blender/ikplugin/intern/iksolver_plugin.c
@@ -215,7 +215,7 @@ static void where_is_ik_bone(bPoseChannel *pchan, float ik_mat[3][3]) // nr =
copy_m4_m3(ikmat, ik_mat);
if (pchan->parent)
- mul_serie_m4(pchan->pose_mat, pchan->parent->pose_mat, pchan->chan_mat, ikmat, NULL, NULL, NULL, NULL, NULL);
+ mul_m4_series(pchan->pose_mat, pchan->parent->pose_mat, pchan->chan_mat, ikmat);
else
mul_m4_m4m4(pchan->pose_mat, pchan->chan_mat, ikmat);
@@ -420,7 +420,7 @@ static void execute_posetree(struct Scene *scene, Object *ob, PoseTree *tree)
/* end effector in world space */
copy_m4_m4(end_pose, pchan->pose_mat);
copy_v3_v3(end_pose[3], pchan->pose_tail);
- mul_serie_m4(world_pose, goalinv, ob->obmat, end_pose, NULL, NULL, NULL, NULL, NULL);
+ mul_m4_series(world_pose, goalinv, ob->obmat, end_pose);
/* blend position */
goalpos[0] = fac * goalpos[0] + mfac * world_pose[3][0];
diff --git a/source/blender/ikplugin/intern/itasc_plugin.cpp b/source/blender/ikplugin/intern/itasc_plugin.cpp
index dbc4100e287..5077ccec256 100644
--- a/source/blender/ikplugin/intern/itasc_plugin.cpp
+++ b/source/blender/ikplugin/intern/itasc_plugin.cpp
@@ -566,7 +566,7 @@ static bool target_callback(const iTaSC::Timestamp& timestamp, const iTaSC::Fram
float chanmat[4][4];
copy_m4_m4(chanmat, pchan->pose_mat);
copy_v3_v3(chanmat[3], pchan->pose_tail);
- mul_serie_m4(restmat, target->owner->obmat, chanmat, target->eeRest, NULL, NULL, NULL, NULL, NULL);
+ mul_m4_series(restmat, target->owner->obmat, chanmat, target->eeRest);
}
else {
mul_m4_m4m4(restmat, target->owner->obmat, target->eeRest);
diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h
index 090e7a66d41..ce6a7eb1c47 100644
--- a/source/blender/imbuf/IMB_imbuf.h
+++ b/source/blender/imbuf/IMB_imbuf.h
@@ -163,6 +163,22 @@ typedef enum IMB_BlendMode {
IMB_BLEND_DARKEN = 5,
IMB_BLEND_ERASE_ALPHA = 6,
IMB_BLEND_ADD_ALPHA = 7,
+ IMB_BLEND_OVERLAY = 8,
+ IMB_BLEND_HARDLIGHT = 9,
+ IMB_BLEND_COLORBURN = 10,
+ IMB_BLEND_LINEARBURN = 11,
+ IMB_BLEND_COLORDODGE = 12,
+ IMB_BLEND_SCREEN = 13,
+ IMB_BLEND_SOFTLIGHT = 14,
+ IMB_BLEND_PINLIGHT = 15,
+ IMB_BLEND_VIVIDLIGHT = 16,
+ IMB_BLEND_LINEARLIGHT = 17,
+ IMB_BLEND_DIFFERENCE = 18,
+ IMB_BLEND_EXCLUSION = 19,
+ IMB_BLEND_HUE = 20,
+ IMB_BLEND_SATURATION = 21,
+ IMB_BLEND_LUMINOSITY = 22,
+ IMB_BLEND_COLOR = 23,
IMB_BLEND_COPY = 1000,
IMB_BLEND_COPY_RGB = 1001,
@@ -179,9 +195,9 @@ void IMB_rectclip(struct ImBuf *dbuf, struct ImBuf *sbuf, int *destx,
void IMB_rectcpy(struct ImBuf *drect, struct ImBuf *srect, int destx,
int desty, int srcx, int srcy, int width, int height);
void IMB_rectblend(struct ImBuf *dbuf, struct ImBuf *obuf, struct ImBuf *sbuf,
- unsigned short *dmask, unsigned short *smask, unsigned short mask_max,
+ unsigned short *dmask, unsigned short *curvemask, unsigned short *mmask, float mask_max,
int destx, int desty, int origx, int origy, int srcx, int srcy,
- int width, int height, IMB_BlendMode mode);
+ int width, int height, IMB_BlendMode mode, bool accumulate);
/**
*
diff --git a/source/blender/imbuf/intern/cineon/cineonlib.c b/source/blender/imbuf/intern/cineon/cineonlib.c
index e8cb550fc05..880df0ce5c3 100644
--- a/source/blender/imbuf/intern/cineon/cineonlib.c
+++ b/source/blender/imbuf/intern/cineon/cineonlib.c
@@ -39,10 +39,6 @@
#include "BLI_fileops.h"
#include "BLI_utildefines.h"
-#if defined(_MSC_VER) && (_MSC_VER <= 1500)
-#include "BLI_math_base.h"
-#endif
-
#include "MEM_guardedalloc.h"
/*
diff --git a/source/blender/imbuf/intern/cineon/dpxlib.c b/source/blender/imbuf/intern/cineon/dpxlib.c
index 84f80faeacc..626d05b05c5 100644
--- a/source/blender/imbuf/intern/cineon/dpxlib.c
+++ b/source/blender/imbuf/intern/cineon/dpxlib.c
@@ -39,10 +39,6 @@
#include "BLI_fileops.h"
#include "BLI_utildefines.h"
-#if defined(_MSC_VER) && (_MSC_VER <= 1500)
-#include "BLI_math_base.h"
-#endif
-
#include "MEM_guardedalloc.h"
/*
diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp
index 2dca3114765..b8b7d15bf28 100644
--- a/source/blender/imbuf/intern/openexr/openexr_api.cpp
+++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp
@@ -896,7 +896,7 @@ static int imb_exr_split_channel_name(ExrChannel *echan, char *layname, char *pa
echan->chan_id = name[0];
layname[0] = '\0';
- if (ELEM4(name[0], 'R', 'G', 'B', 'A'))
+ if (ELEM(name[0], 'R', 'G', 'B', 'A'))
strcpy(passname, "Combined");
else if (name[0] == 'Z')
strcpy(passname, "Depth");
@@ -927,9 +927,9 @@ static int imb_exr_split_channel_name(ExrChannel *echan, char *layname, char *pa
*
* Here we do some magic to distinguish such cases.
*/
- if (ELEM3(token[1], 'X', 'Y', 'Z') ||
- ELEM3(token[1], 'R', 'G', 'B') ||
- ELEM3(token[1], 'U', 'V', 'A'))
+ if (ELEM(token[1], 'X', 'Y', 'Z') ||
+ ELEM(token[1], 'R', 'G', 'B') ||
+ ELEM(token[1], 'U', 'V', 'A'))
{
echan->chan_id = token[1];
ok = true;
diff --git a/source/blender/imbuf/intern/rectop.c b/source/blender/imbuf/intern/rectop.c
index 6df7587ee5c..dd2406e234e 100644
--- a/source/blender/imbuf/intern/rectop.c
+++ b/source/blender/imbuf/intern/rectop.c
@@ -65,6 +65,39 @@ void IMB_blend_color_byte(unsigned char dst[4], unsigned char src1[4], unsigned
blend_color_erase_alpha_byte(dst, src1, src2); break;
case IMB_BLEND_ADD_ALPHA:
blend_color_add_alpha_byte(dst, src1, src2); break;
+ case IMB_BLEND_OVERLAY:
+ blend_color_overlay_byte(dst, src1, src2); break;
+ case IMB_BLEND_HARDLIGHT:
+ blend_color_hardlight_byte(dst, src1, src2); break;
+ case IMB_BLEND_COLORBURN:
+ blend_color_burn_byte(dst, src1, src2); break;
+ case IMB_BLEND_LINEARBURN:
+ blend_color_linearburn_byte(dst, src1, src2); break;
+ case IMB_BLEND_COLORDODGE:
+ blend_color_dodge_byte(dst, src1, src2); break;
+ case IMB_BLEND_SCREEN:
+ blend_color_screen_byte(dst, src1, src2); break;
+ case IMB_BLEND_SOFTLIGHT:
+ blend_color_softlight_byte(dst, src1, src2); break;
+ case IMB_BLEND_PINLIGHT:
+ blend_color_pinlight_byte(dst, src1, src2); break;
+ case IMB_BLEND_LINEARLIGHT:
+ blend_color_linearlight_byte(dst, src1, src2); break;
+ case IMB_BLEND_VIVIDLIGHT:
+ blend_color_vividlight_byte(dst, src1, src2); break;
+ case IMB_BLEND_DIFFERENCE:
+ blend_color_difference_byte(dst, src1, src2); break;
+ case IMB_BLEND_EXCLUSION:
+ blend_color_exclusion_byte(dst, src1, src2); break;
+ case IMB_BLEND_COLOR:
+ blend_color_color_byte(dst, src1, src2); break;
+ case IMB_BLEND_HUE:
+ blend_color_hue_byte(dst, src1, src2); break;
+ case IMB_BLEND_SATURATION:
+ blend_color_saturation_byte(dst, src1, src2); break;
+ case IMB_BLEND_LUMINOSITY:
+ blend_color_luminosity_byte(dst, src1, src2); break;
+
default:
dst[0] = src1[0];
dst[1] = src1[1];
@@ -93,6 +126,38 @@ void IMB_blend_color_float(float dst[4], float src1[4], float src2[4], IMB_Blend
blend_color_erase_alpha_float(dst, src1, src2); break;
case IMB_BLEND_ADD_ALPHA:
blend_color_add_alpha_float(dst, src1, src2); break;
+ case IMB_BLEND_OVERLAY:
+ blend_color_overlay_float(dst, src1, src2); break;
+ case IMB_BLEND_HARDLIGHT:
+ blend_color_hardlight_float(dst, src1, src2); break;
+ case IMB_BLEND_COLORBURN:
+ blend_color_burn_float(dst, src1, src2); break;
+ case IMB_BLEND_LINEARBURN:
+ blend_color_linearburn_float(dst, src1, src2); break;
+ case IMB_BLEND_COLORDODGE:
+ blend_color_dodge_float(dst, src1, src2); break;
+ case IMB_BLEND_SCREEN:
+ blend_color_screen_float(dst, src1, src2); break;
+ case IMB_BLEND_SOFTLIGHT:
+ blend_color_softlight_float(dst, src1, src2); break;
+ case IMB_BLEND_PINLIGHT:
+ blend_color_pinlight_float(dst, src1, src2); break;
+ case IMB_BLEND_LINEARLIGHT:
+ blend_color_linearlight_float(dst, src1, src2); break;
+ case IMB_BLEND_VIVIDLIGHT:
+ blend_color_vividlight_float(dst, src1, src2); break;
+ case IMB_BLEND_DIFFERENCE:
+ blend_color_difference_float(dst, src1, src2); break;
+ case IMB_BLEND_EXCLUSION:
+ blend_color_exclusion_float(dst, src1, src2); break;
+ case IMB_BLEND_COLOR:
+ blend_color_color_float(dst, src1, src2); break;
+ case IMB_BLEND_HUE:
+ blend_color_hue_float(dst, src1, src2); break;
+ case IMB_BLEND_SATURATION:
+ blend_color_saturation_float(dst, src1, src2); break;
+ case IMB_BLEND_LUMINOSITY:
+ blend_color_luminosity_float(dst, src1, src2); break;
default:
dst[0] = src1[0];
dst[1] = src1[1];
@@ -226,22 +291,23 @@ static void imb_rectclip3(ImBuf *dbuf, ImBuf *obuf, ImBuf *sbuf, int *destx,
void IMB_rectcpy(ImBuf *dbuf, ImBuf *sbuf, int destx,
int desty, int srcx, int srcy, int width, int height)
{
- IMB_rectblend(dbuf, dbuf, sbuf, NULL, NULL, 0, destx, desty, destx, desty, srcx, srcy, width, height, IMB_BLEND_COPY);
+ IMB_rectblend(dbuf, dbuf, sbuf, NULL, NULL, NULL, 0, destx, desty, destx, desty, srcx, srcy, width, height, IMB_BLEND_COPY, false);
}
typedef void (*IMB_blend_func)(unsigned char *dst, const unsigned char *src1, const unsigned char *src2);
typedef void (*IMB_blend_func_float)(float *dst, const float *src1, const float *src2);
-void IMB_rectblend(ImBuf *dbuf, ImBuf *obuf, ImBuf *sbuf, unsigned short *dmask,
- unsigned short *smask, unsigned short mask_max,
+void IMB_rectblend(ImBuf *dbuf, ImBuf *obuf, ImBuf *sbuf, unsigned short *dmask, unsigned short *curvemask,
+ unsigned short *texmask, float mask_max,
int destx, int desty, int origx, int origy, int srcx, int srcy, int width, int height,
- IMB_BlendMode mode)
+ IMB_BlendMode mode, bool accumulate)
{
unsigned int *drect = NULL, *orect, *srect = NULL, *dr, *or, *sr;
float *drectf = NULL, *orectf, *srectf = NULL, *drf, *orf, *srf;
- unsigned short *smaskrect = smask, *smr;
+ unsigned short *cmaskrect = curvemask, *cmr;
unsigned short *dmaskrect = dmask, *dmr;
+ unsigned short *texmaskrect = texmask, *tmr;
int do_float, do_char, srcskip, destskip, origskip, x;
IMB_blend_func func = NULL;
IMB_blend_func_float func_float = NULL;
@@ -277,8 +343,11 @@ void IMB_rectblend(ImBuf *dbuf, ImBuf *obuf, ImBuf *sbuf, unsigned short *dmask,
if (do_float) srectf = sbuf->rect_float + (srcy * sbuf->x + srcx) * 4;
srcskip = sbuf->x;
- if (smaskrect)
- smaskrect += srcy * sbuf->x + srcx;
+ if (cmaskrect)
+ cmaskrect += srcy * sbuf->x + srcx;
+
+ if (texmaskrect)
+ texmaskrect += srcy * sbuf->x + srcx;
}
else {
srect = drect;
@@ -388,6 +457,70 @@ void IMB_rectblend(ImBuf *dbuf, ImBuf *obuf, ImBuf *sbuf, unsigned short *dmask,
func = blend_color_add_alpha_byte;
func_float = blend_color_add_alpha_float;
break;
+ case IMB_BLEND_OVERLAY:
+ func = blend_color_overlay_byte;
+ func_float = blend_color_overlay_float;
+ break;
+ case IMB_BLEND_HARDLIGHT:
+ func = blend_color_hardlight_byte;
+ func_float = blend_color_hardlight_float;
+ break;
+ case IMB_BLEND_COLORBURN:
+ func = blend_color_burn_byte;
+ func_float = blend_color_burn_float;
+ break;
+ case IMB_BLEND_LINEARBURN:
+ func = blend_color_linearburn_byte;
+ func_float = blend_color_linearburn_float;
+ break;
+ case IMB_BLEND_COLORDODGE:
+ func = blend_color_dodge_byte;
+ func_float = blend_color_dodge_float;
+ break;
+ case IMB_BLEND_SCREEN:
+ func = blend_color_screen_byte;
+ func_float = blend_color_screen_float;
+ break;
+ case IMB_BLEND_SOFTLIGHT:
+ func = blend_color_softlight_byte;
+ func_float = blend_color_softlight_float;
+ break;
+ case IMB_BLEND_PINLIGHT:
+ func = blend_color_pinlight_byte;
+ func_float = blend_color_pinlight_float;
+ break;
+ case IMB_BLEND_LINEARLIGHT:
+ func = blend_color_linearlight_byte;
+ func_float = blend_color_linearlight_float;
+ break;
+ case IMB_BLEND_VIVIDLIGHT:
+ func = blend_color_vividlight_byte;
+ func_float = blend_color_vividlight_float;
+ break;
+ case IMB_BLEND_DIFFERENCE:
+ func = blend_color_difference_byte;
+ func_float = blend_color_difference_float;
+ break;
+ case IMB_BLEND_EXCLUSION:
+ func = blend_color_exclusion_byte;
+ func_float = blend_color_exclusion_float;
+ break;
+ case IMB_BLEND_COLOR:
+ func = blend_color_color_byte;
+ func_float = blend_color_color_float;
+ break;
+ case IMB_BLEND_HUE:
+ func = blend_color_hue_byte;
+ func_float = blend_color_hue_float;
+ break;
+ case IMB_BLEND_SATURATION:
+ func = blend_color_saturation_byte;
+ func_float = blend_color_saturation_float;
+ break;
+ case IMB_BLEND_LUMINOSITY:
+ func = blend_color_luminosity_byte;
+ func_float = blend_color_luminosity_float;
+ break;
default:
break;
}
@@ -399,21 +532,60 @@ void IMB_rectblend(ImBuf *dbuf, ImBuf *obuf, ImBuf *sbuf, unsigned short *dmask,
or = orect;
sr = srect;
- if (dmaskrect && smaskrect) {
+ if (cmaskrect) {
/* mask accumulation for painting */
- dmr = dmaskrect;
- smr = smaskrect;
+ cmr = cmaskrect;
+ tmr = texmaskrect;
- for (x = width; x > 0; x--, dr++, or++, sr++, dmr++, smr++) {
- unsigned char *src = (unsigned char *)sr;
+ /* destination mask present, do max alpha masking */
+ if (dmaskrect) {
+ dmr = dmaskrect;
+ for (x = width; x > 0; x--, dr++, or++, sr++, dmr++, cmr++) {
+ unsigned char *src = (unsigned char *)sr;
+ float mask_lim = mask_max * (*cmr);
- if (src[3] && *smr) {
- unsigned short mask = *dmr + (((mask_max - *dmr) * (*smr)) / 65535);
+ if (texmaskrect)
+ mask_lim *= ((*tmr++) / 65535.0f);
- if (mask > *dmr) {
- unsigned char mask_src[4];
+ if (src[3] && mask_lim) {
+ float mask;
+
+ if (accumulate)
+ mask = *dmr + mask_lim;
+ else
+ mask = *dmr + mask_lim - (*dmr * (*cmr / 65535.0f));
+
+ mask = min_ff(mask, 65535.0);
+
+ if (mask > *dmr) {
+ unsigned char mask_src[4];
+
+ *dmr = mask;
- *dmr = mask;
+ mask_src[0] = src[0];
+ mask_src[1] = src[1];
+ mask_src[2] = src[2];
+ mask_src[3] = divide_round_i(src[3] * mask, 65535);
+
+ func((unsigned char *)dr, (unsigned char *)or, mask_src);
+ }
+ }
+ }
+ dmaskrect += origskip;
+ }
+ /* no destination mask buffer, do regular blend with masktexture if present */
+ else {
+ for (x = width; x > 0; x--, dr++, or++, sr++, cmr++) {
+ unsigned char *src = (unsigned char *)sr;
+ float mask = (float)mask_max * ((float)(*cmr));
+
+ if (texmaskrect)
+ mask *= ((float)(*tmr++) / 65535.0f);
+
+ mask = min_ff(mask, 65535.0);
+
+ if (src[3] && (mask > 0.0f)) {
+ unsigned char mask_src[4];
mask_src[0] = src[0];
mask_src[1] = src[1];
@@ -425,8 +597,9 @@ void IMB_rectblend(ImBuf *dbuf, ImBuf *obuf, ImBuf *sbuf, unsigned short *dmask,
}
}
- dmaskrect += origskip;
- smaskrect += srcskip;
+ cmaskrect += srcskip;
+ if (texmaskrect)
+ texmaskrect += srcskip;
}
else {
/* regular blending */
@@ -446,28 +619,65 @@ void IMB_rectblend(ImBuf *dbuf, ImBuf *obuf, ImBuf *sbuf, unsigned short *dmask,
orf = orectf;
srf = srectf;
- if (dmaskrect && smaskrect) {
+ if (cmaskrect) {
/* mask accumulation for painting */
- dmr = dmaskrect;
- smr = smaskrect;
+ cmr = cmaskrect;
+ tmr = texmaskrect;
+
+ /* destination mask present, do max alpha masking */
+ if (dmaskrect) {
+ dmr = dmaskrect;
+ for (x = width; x > 0; x--, drf += 4, orf += 4, srf += 4, dmr++, cmr++) {
+ float mask_lim = mask_max * (*cmr);
+
+ if (texmaskrect)
+ mask_lim *= ((*tmr++) / 65535.0f);
+
+ if (srf[3] && mask_lim) {
+ float mask;
+
+ if (accumulate)
+ mask = min_ff(*dmr + mask_lim, 65535.0);
+ else
+ mask = *dmr + mask_lim - (*dmr * (*cmr / 65535.0f));
+
+ mask = min_ff(mask, 65535.0);
+
+ if (mask > *dmr) {
+ float mask_srf[4];
+
+ *dmr = mask;
+ mul_v4_v4fl(mask_srf, srf, mask / 65535.0f);
+
+ func_float(drf, orf, mask_srf);
+ }
+ }
+ }
+ dmaskrect += origskip;
+ }
+ /* no destination mask buffer, do regular blend with masktexture if present */
+ else {
+ for (x = width; x > 0; x--, drf += 4, orf += 4, srf += 4, cmr++) {
+ float mask = (float)mask_max * ((float)(*cmr));
+
+ if (texmaskrect)
+ mask *= ((float)(*tmr++) / 65535.0f);
- for (x = width; x > 0; x--, drf += 4, orf += 4, srf += 4, dmr++, smr++) {
- if (srf[3] != 0 && *smr) {
- unsigned short mask = *dmr + (((mask_max - *dmr) * (*smr)) / 65535);
+ mask = min_ff(mask, 65535.0);
- if (mask > *dmr) {
+ if (srf[3] && (mask > 0.0f)) {
float mask_srf[4];
- *dmr = mask;
- mul_v4_v4fl(mask_srf, srf, mask * (1.0f / 65535.0f));
+ mul_v4_v4fl(mask_srf, srf, mask / 65535.0f);
func_float(drf, orf, mask_srf);
}
}
}
- dmaskrect += origskip;
- smaskrect += srcskip;
+ cmaskrect += srcskip;
+ if (texmaskrect)
+ texmaskrect += srcskip;
}
else {
/* regular blending */
diff --git a/source/blender/imbuf/intern/scaling.c b/source/blender/imbuf/intern/scaling.c
index c98b39c826b..e066443769d 100644
--- a/source/blender/imbuf/intern/scaling.c
+++ b/source/blender/imbuf/intern/scaling.c
@@ -1353,7 +1353,7 @@ static ImBuf *scaleupy(struct ImBuf *ibuf, int newy)
val_g += 0.5f;
val_r = rect[3];
- nval_r = rect[skipx + 4];
+ nval_r = rect[skipx + 3];
diff_r = nval_r - val_r;
val_r += 0.5f;
diff --git a/source/blender/imbuf/intern/util.c b/source/blender/imbuf/intern/util.c
index b912c3e229a..32100aa2288 100644
--- a/source/blender/imbuf/intern/util.c
+++ b/source/blender/imbuf/intern/util.c
@@ -254,10 +254,6 @@ static int isqtime(const char *name)
#ifdef WITH_FFMPEG
-#if defined(_MSC_VER) && _MSC_VER < 1800
-#define va_copy(dst, src) ((dst) = (src))
-#endif
-
/* BLI_vsnprintf in ffmpeg_log_callback() causes invalid warning */
#ifdef __GNUC__
# pragma GCC diagnostic push
diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h
index f429360e1cf..8483e5f08f9 100644
--- a/source/blender/makesdna/DNA_ID.h
+++ b/source/blender/makesdna/DNA_ID.h
@@ -168,14 +168,10 @@ typedef struct PreviewImage {
#ifdef __BIG_ENDIAN__
/* big endian */
-# define MAKE_ID2(c, d) ( (c)<<8 | (d) )
-# define MOST_SIG_BYTE 0
-# define BBIG_ENDIAN
+# define MAKE_ID2(c, d) ((c) << 8 | (d))
#else
/* little endian */
-# define MAKE_ID2(c, d) ( (d)<<8 | (c) )
-# define MOST_SIG_BYTE 1
-# define BLITTLE_ENDIAN
+# define MAKE_ID2(c, d) ((d) << 8 | (c))
#endif
/* ID from database */
@@ -213,6 +209,8 @@ typedef struct PreviewImage {
#define ID_MC MAKE_ID2('M', 'C') /* MovieClip */
#define ID_MSK MAKE_ID2('M', 'S') /* Mask */
#define ID_LS MAKE_ID2('L', 'S') /* FreestyleLineStyle */
+#define ID_PAL MAKE_ID2('P', 'L') /* Palette */
+#define ID_PC MAKE_ID2('P', 'C') /* Paint Curve */
/* NOTE! Fake IDs, needed for g.sipo->blocktype or outliner */
#define ID_SEQ MAKE_ID2('S', 'Q')
@@ -235,7 +233,7 @@ typedef struct PreviewImage {
# undef GS
#endif
// #define GS(a) (*((short *)(a)))
-#define GS(a) (CHECK_TYPE_INLINE(a, const char *), (*((short *)(a))))
+#define GS(a) (CHECK_TYPE_INLINE(a, char *), (*((short *)(a))))
#define ID_NEW(a) if ( (a) && (a)->id.newid ) (a) = (void *)(a)->id.newid
#define ID_NEW_US(a) if ( (a)->id.newid) { (a) = (void *)(a)->id.newid; (a)->id.us++; }
diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h
index 86fa7058f97..9fbd70419f4 100644
--- a/source/blender/makesdna/DNA_brush_types.h
+++ b/source/blender/makesdna/DNA_brush_types.h
@@ -35,6 +35,7 @@
#include "DNA_ID.h"
#include "DNA_texture_types.h" /* for MTex */
+#include "DNA_curve_types.h"
//#ifndef MAX_MTEX // XXX Not used?
//#define MAX_MTEX 18
@@ -62,6 +63,9 @@ typedef struct Brush {
struct ImBuf *icon_imbuf;
PreviewImage *preview;
+ struct ColorBand *gradient; /* color gradient */
+ struct PaintCurve *paint_curve;
+
char icon_filepath[1024]; /* 1024 = FILE_MAX */
float normal_weight;
@@ -71,6 +75,7 @@ typedef struct Brush {
float weight; /* brush weight */
int size; /* brush diameter */
int flag; /* general purpose flag */
+ int mask_pressure; /* pressure influence for mask */
float jitter; /* jitter the position of the brush */
int jitter_absolute; /* absolute jitter in pixels */
int overlay_flags;
@@ -82,10 +87,17 @@ typedef struct Brush {
float rgb[3]; /* color */
float alpha; /* opacity */
+ float secondary_rgb[3]; /* background color */
+
int sculpt_plane; /* the direction of movement for sculpt vertices */
float plane_offset; /* offset for plane brushes (clay, flatten, fill, scrape) */
+ float pad;
+ int gradient_spacing;
+ int gradient_stroke_mode; /* source for stroke color gradient application */
+ int gradient_fill_mode; /* source for fill tool color gradient application */
+
char sculpt_tool; /* active sculpt tool */
char vertexpaint_tool; /* active vertex/weight paint blend mode (poorly named) */
char imagepaint_tool; /* active image paint tool */
@@ -100,12 +112,21 @@ typedef struct Brush {
float texture_sample_bias;
+ /* overlay */
int texture_overlay_alpha;
int mask_overlay_alpha;
int cursor_overlay_alpha;
float unprojected_radius;
+ /* soften/sharpen */
+ float sharp_threshold;
+ int blur_kernel_radius;
+ int blur_mode;
+
+ /* fill tool */
+ float fill_threshold;
+
float add_col[3];
float sub_col[3];
@@ -116,6 +137,52 @@ typedef struct Brush {
float mask_stencil_dimension[2];
} Brush;
+typedef struct PaletteColor
+{
+ struct PaletteColor *next, *prev;
+ /* two values, one to store rgb, other to store values for sculpt/weight */
+ float rgb[3];
+ float value;
+} PaletteColor;
+
+typedef struct Palette
+{
+ ID id;
+
+ /* pointer to individual colours */
+ ListBase colors;
+ ListBase deleted;
+
+ int num_of_colours;
+ int active_color;
+} Palette;
+
+typedef struct PaintCurvePoint
+{
+ BezTriple bez; /* bezier handle */
+ float pressure; /* pressure on that point */
+} PaintCurvePoint;
+
+typedef struct PaintCurve
+{
+ ID id;
+ PaintCurvePoint *points; /* points of curve */
+ int tot_points;
+ int add_index; /* index where next point will be added */
+} PaintCurve;
+
+/* Brush.gradient_source */
+typedef enum BrushGradientSourceStroke {
+ BRUSH_GRADIENT_PRESSURE = 0, /* gradient from pressure */
+ BRUSH_GRADIENT_SPACING_REPEAT = 1, /* gradient from spacing */
+ BRUSH_GRADIENT_SPACING_CLAMP = 2 /* gradient from spacing */
+} BrushGradientSourceStroke;
+
+typedef enum BrushGradientSourceFill {
+ BRUSH_GRADIENT_LINEAR = 0, /* gradient from pressure */
+ BRUSH_GRADIENT_RADIAL = 1 /* gradient from spacing */
+} BrushGradientSourceFill;
+
/* Brush.flag */
typedef enum BrushFlags {
BRUSH_AIRBRUSH = (1 << 0),
@@ -124,7 +191,7 @@ typedef enum BrushFlags {
BRUSH_SIZE_PRESSURE = (1 << 3),
BRUSH_JITTER_PRESSURE = (1 << 4),
BRUSH_SPACING_PRESSURE = (1 << 5),
- // BRUSH_FIXED_TEX = (1 << 6), /* obsolete, use mtex->brush_map_mode = MTEX_MAP_MODE_TILED instead */
+ BRUSH_UNUSED = (1 << 6),
BRUSH_RAKE = (1 << 7),
BRUSH_ANCHORED = (1 << 8),
BRUSH_DIR_IN = (1 << 9),
@@ -138,7 +205,7 @@ typedef enum BrushFlags {
BRUSH_SPACE_ATTEN = (1 << 18),
BRUSH_ADAPTIVE_SPACE = (1 << 19),
BRUSH_LOCK_SIZE = (1 << 20),
-// BRUSH_TEXTURE_OVERLAY = (1 << 21), /* obsolete, use overlay_flags |= BRUSH_OVERLAY_PRIMARY instead */
+ BRUSH_USE_GRADIENT = (1 << 21),
BRUSH_EDGE_TO_EDGE = (1 << 22),
BRUSH_DRAG_DOT = (1 << 23),
BRUSH_INVERSE_SMOOTH_PRESSURE = (1 << 24),
@@ -146,13 +213,16 @@ typedef enum BrushFlags {
BRUSH_PLANE_TRIM = (1 << 26),
BRUSH_FRONTFACE = (1 << 27),
BRUSH_CUSTOM_ICON = (1 << 28),
-
- /* temporary flag which sets up automatically for correct brush
- * drawing when inverted modal operator is running */
- BRUSH_INVERTED = (1 << 29),
- BRUSH_ABSOLUTE_JITTER = (1 << 30)
+ BRUSH_LINE = (1 << 29),
+ BRUSH_ABSOLUTE_JITTER = (1 << 30),
+ BRUSH_CURVE = (1 << 31)
} BrushFlags;
+typedef enum {
+ BRUSH_MASK_PRESSURE_RAMP = (1 << 1),
+ BRUSH_MASK_PRESSURE_CUTOFF = (1 << 2)
+} BrushMaskPressureFlags;
+
/* Brush.overlay_flags */
typedef enum OverlayFlags {
BRUSH_OVERLAY_CURSOR = (1),
@@ -195,7 +265,9 @@ typedef enum BrushImagePaintTool {
PAINT_TOOL_DRAW = 0,
PAINT_TOOL_SOFTEN = 1,
PAINT_TOOL_SMEAR = 2,
- PAINT_TOOL_CLONE = 3
+ PAINT_TOOL_CLONE = 3,
+ PAINT_TOOL_FILL = 4,
+ PAINT_TOOL_MASK = 5
} BrushImagePaintTool;
/* direction that the brush displaces along */
@@ -222,6 +294,12 @@ typedef enum {
BRUSH_MASK_SMOOTH = 1
} BrushMaskTool;
+/* blur kernel types, Brush.blur_mode */
+typedef enum BlurKernelType {
+ KERNEL_GAUSSIAN,
+ KERNEL_BOX
+} BlurKernelType;
+
#define MAX_BRUSH_PIXEL_RADIUS 200
#endif
diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h
index e35e4673684..0277956cac5 100644
--- a/source/blender/makesdna/DNA_constraint_types.h
+++ b/source/blender/makesdna/DNA_constraint_types.h
@@ -796,7 +796,8 @@ typedef enum ePivotConstraint_Flag {
typedef enum eFollowTrack_Flags {
FOLLOWTRACK_ACTIVECLIP = (1<<0),
- FOLLOWTRACK_USE_3D_POSITION = (1<<1)
+ FOLLOWTRACK_USE_3D_POSITION = (1<<1),
+ FOLLOWTRACK_USE_UNDISTORTION = (1<<2)
} eFollowTrack_Flags;
typedef enum eFollowTrack_FrameMethod {
diff --git a/source/blender/makesdna/DNA_material_types.h b/source/blender/makesdna/DNA_material_types.h
index 5fda38f52a1..ba617baa4e0 100644
--- a/source/blender/makesdna/DNA_material_types.h
+++ b/source/blender/makesdna/DNA_material_types.h
@@ -41,6 +41,7 @@
#endif
struct MTex;
+struct Image;
struct ColorBand;
struct Group;
struct bNodeTree;
@@ -82,6 +83,11 @@ typedef struct GameSettings {
int pad1;
} GameSettings;
+typedef struct TexPaintSlot {
+ struct Image *ima; /* image to be painted on */
+ char *uvname; /* customdata index for uv layer, MAX_NAME*/
+} TexPaintSlot;
+
typedef struct Material {
ID id;
struct AnimData *adt; /* animation data (must be immediately after id for utilities to use it) */
@@ -182,8 +188,15 @@ typedef struct Material {
float line_col[4];
short line_priority;
short vcol_alpha;
- int pad4;
+ /* texture painting */
+ short paint_active_slot;
+ short paint_clone_slot;
+ short tot_slots;
+ short pad4[3];
+
+ struct TexPaintSlot *texpaintslot; /* cached slot for painting. Make sure to recalculate before use
+ * with refresh_texpaint_image_cache */
ListBase gpumaterial; /* runtime */
} Material;
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index b13353609c6..e0d25e763d4 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -852,6 +852,12 @@ typedef struct NodeShaderUVMap {
char uv_map[64];
} NodeShaderUVMap;
+typedef struct NodeSunBeams {
+ float source[2];
+
+ float ray_length;
+} NodeSunBeams;
+
/* script node mode */
#define NODE_SCRIPT_INTERNAL 0
#define NODE_SCRIPT_EXTERNAL 1
diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h
index 2e3cd878900..e576cbc018f 100644
--- a/source/blender/makesdna/DNA_object_types.h
+++ b/source/blender/makesdna/DNA_object_types.h
@@ -361,13 +361,13 @@ enum {
#define OB_TYPE_SUPPORT_VGROUP(_type) \
(ELEM(_type, OB_MESH, OB_LATTICE))
#define OB_TYPE_SUPPORT_EDITMODE(_type) \
- (ELEM7(_type, OB_MESH, OB_FONT, OB_CURVE, OB_SURF, OB_MBALL, OB_LATTICE, OB_ARMATURE))
+ (ELEM(_type, OB_MESH, OB_FONT, OB_CURVE, OB_SURF, OB_MBALL, OB_LATTICE, OB_ARMATURE))
#define OB_TYPE_SUPPORT_PARVERT(_type) \
- (ELEM4(_type, OB_MESH, OB_SURF, OB_CURVE, OB_LATTICE))
+ (ELEM(_type, OB_MESH, OB_SURF, OB_CURVE, OB_LATTICE))
/* is this ID type used as object data */
#define OB_DATA_SUPPORT_ID(_id_type) \
- (ELEM8(_id_type, ID_ME, ID_CU, ID_MB, ID_LA, ID_SPK, ID_CA, ID_LT, ID_AR))
+ (ELEM(_id_type, ID_ME, ID_CU, ID_MB, ID_LA, ID_SPK, ID_CA, ID_LT, ID_AR))
#define OB_DATA_SUPPORT_ID_CASE \
ID_ME: case ID_CU: case ID_MB: case ID_LA: case ID_SPK: case ID_CA: case ID_LT: case ID_AR
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index 5f2aefdb53f..8a7ddb88f59 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -811,7 +811,8 @@ typedef struct TimeMarker {
/* Paint Tool Base */
typedef struct Paint {
struct Brush *brush;
-
+ struct Palette *palette;
+
/* WM Paint cursor */
void *paint_cursor;
unsigned char paint_cursor_col[4];
@@ -843,6 +844,9 @@ typedef struct ImagePaintSettings {
int pad1;
void *paintcursor; /* wm handle */
+ struct Image *stencil; /* workaround until we support true layer masks */
+ float stencil_col[3];
+ float pad2;
} ImagePaintSettings;
/* ------------------------------------------- */
@@ -966,6 +970,11 @@ typedef struct UnifiedPaintSettings {
/* unified brush weight, [0, 1] */
float weight;
+ /* unified brush color */
+ float rgb[3];
+ /* unified brush secondary color */
+ float secondary_rgb[3];
+
/* user preferences for sculpt and paint */
int flag;
@@ -973,7 +982,6 @@ typedef struct UnifiedPaintSettings {
/* record movement of mouse so that rake can start at an intuitive angle */
float last_rake[2];
- int pad;
float brush_rotation;
@@ -981,7 +989,14 @@ typedef struct UnifiedPaintSettings {
* all data below are used to communicate with cursor drawing and tex sampling *
*********************************************************************************/
int draw_anchored;
- int anchored_size;
+ int anchored_size;
+
+ char draw_inverted;
+ char pad3[7];
+
+ float overlap_factor; /* normalization factor due to accumulated value of curve along spacing.
+ * Calculated when brush spacing changes to dampen strength of stroke
+ * if space attenuation is used*/
float anchored_initial_mouse[2];
/* check is there an ongoing stroke right now */
@@ -1001,15 +1016,16 @@ typedef struct UnifiedPaintSettings {
struct ColorSpace *colorspace;
/* radius of brush, premultiplied with pressure.
- * In case of anchored brushes contains that radius */
+ * In case of anchored brushes contains the anchored radius */
float pixel_radius;
- int pad2;
+ int pad4;
} UnifiedPaintSettings;
typedef enum {
UNIFIED_PAINT_SIZE = (1 << 0),
UNIFIED_PAINT_ALPHA = (1 << 1),
UNIFIED_PAINT_WEIGHT = (1 << 5),
+ UNIFIED_PAINT_COLOR = (1 << 6),
/* only used if unified size is enabled, mirrors the brush flags
* BRUSH_LOCK_SIZE and BRUSH_SIZE_PRESSURE */
@@ -1627,8 +1643,8 @@ typedef enum eVGroupSelect {
#define SCE_FRAME_DROP (1<<3)
- /* return flag BKE_scene_base_iter_next function */
-#define F_ERROR -1
+ /* return flag BKE_scene_base_iter_next functions */
+/* #define F_ERROR -1 */ /* UNUSED */
#define F_START 0
#define F_SCENE 1
#define F_DUPLI 3
@@ -1654,7 +1670,7 @@ enum {
typedef enum {
PAINT_SHOW_BRUSH = (1 << 0),
PAINT_FAST_NAVIGATE = (1 << 1),
- PAINT_SHOW_BRUSH_ON_SURFACE = (1 << 2),
+ PAINT_SHOW_BRUSH_ON_SURFACE = (1 << 2)
} PaintFlags;
/* Paint.symmetry_flags
diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h
index 38d3c2786ce..556923cea54 100644
--- a/source/blender/makesdna/DNA_screen_types.h
+++ b/source/blender/makesdna/DNA_screen_types.h
@@ -271,12 +271,12 @@ typedef struct ARegion {
// #define WIN_EQUAL 3 // UNUSED
/* area->flag */
-#define HEADER_NO_PULLDOWN 1
-#define AREA_FLAG_DRAWJOINTO 2
-#define AREA_FLAG_DRAWJOINFROM 4
-#define AREA_TEMP_INFO 8
-#define AREA_FLAG_DRAWSPLIT_H 16
-#define AREA_FLAG_DRAWSPLIT_V 32
+#define HEADER_NO_PULLDOWN (1 << 0)
+#define AREA_FLAG_DRAWJOINTO (1 << 1)
+#define AREA_FLAG_DRAWJOINFROM (1 << 2)
+#define AREA_TEMP_INFO (1 << 3)
+#define AREA_FLAG_DRAWSPLIT_H (1 << 4)
+#define AREA_FLAG_DRAWSPLIT_V (1 << 5)
#define EDGEWIDTH 1
#define AREAGRID 4
diff --git a/source/blender/makesdna/DNA_sequence_types.h b/source/blender/makesdna/DNA_sequence_types.h
index 69d4693ab05..4795048d346 100644
--- a/source/blender/makesdna/DNA_sequence_types.h
+++ b/source/blender/makesdna/DNA_sequence_types.h
@@ -249,6 +249,11 @@ typedef struct SpeedControlVars {
int lastValidFrame;
} SpeedControlVars;
+typedef struct GaussianBlurVars {
+ float size_x;
+ float size_y;
+} GaussianBlurVars;
+
/* ***************** Sequence modifiers ****************** */
typedef struct SequenceModifierData {
@@ -421,7 +426,8 @@ enum {
SEQ_TYPE_SPEED = 29,
SEQ_TYPE_MULTICAM = 30,
SEQ_TYPE_ADJUSTMENT = 31,
- SEQ_TYPE_EFFECT_MAX = 31
+ SEQ_TYPE_GAUSSIAN_BLUR = 40,
+ SEQ_TYPE_EFFECT_MAX = 40
};
#define SEQ_MOVIECLIP_RENDER_UNDISTORTED (1 << 0)
@@ -434,7 +440,7 @@ enum {
*/
-#define SEQ_HAS_PATH(_seq) (ELEM4((_seq)->type, SEQ_TYPE_MOVIE, SEQ_TYPE_IMAGE, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SOUND_HD))
+#define SEQ_HAS_PATH(_seq) (ELEM((_seq)->type, SEQ_TYPE_MOVIE, SEQ_TYPE_IMAGE, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SOUND_HD))
/* modifiers */
diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h
index c7a6d4809a5..e7a98246ecc 100644
--- a/source/blender/makesdna/DNA_space_types.h
+++ b/source/blender/makesdna/DNA_space_types.h
@@ -809,6 +809,8 @@ typedef enum eSpaceImage_Flag {
SI_DRAW_OTHER = (1 << 23),
SI_COLOR_CORRECTION = (1 << 24),
+
+ SI_NO_DRAW_TEXPAINT = (1 << 25)
} eSpaceImage_Flag;
/* Text Editor ============================================ */
diff --git a/source/blender/makesdna/DNA_texture_types.h b/source/blender/makesdna/DNA_texture_types.h
index 1906f71a230..dc891f8d971 100644
--- a/source/blender/makesdna/DNA_texture_types.h
+++ b/source/blender/makesdna/DNA_texture_types.h
@@ -585,7 +585,7 @@ typedef struct ColorMapping {
#define TEX_VD_IMAGE_SEQUENCE 3
#define TEX_VD_SMOKE 4
/* for voxels which use VoxelData->source_path */
-#define TEX_VD_IS_SOURCE_PATH(_format) (ELEM3(_format, TEX_VD_BLENDERVOXEL, TEX_VD_RAW_8BIT, TEX_VD_RAW_16BIT))
+#define TEX_VD_IS_SOURCE_PATH(_format) (ELEM(_format, TEX_VD_BLENDERVOXEL, TEX_VD_RAW_8BIT, TEX_VD_RAW_16BIT))
/* smoke data types */
#define TEX_VD_SMOKEDENSITY 0
diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h
index 9229505d714..31b06220bc8 100644
--- a/source/blender/makesdna/DNA_userdef_types.h
+++ b/source/blender/makesdna/DNA_userdef_types.h
@@ -154,7 +154,6 @@ typedef struct uiGradientColors {
char high_gradient[4];
int show_grad;
int pad2;
-
} uiGradientColors;
typedef struct ThemeUI {
@@ -328,6 +327,9 @@ typedef struct ThemeSpace {
char info_warning[4], info_warning_text[4];
char info_info[4], info_info_text[4];
char info_debug[4], info_debug_text[4];
+
+ char paint_curve_pivot[4];
+ char paint_curve_handle[4];
} ThemeSpace;
@@ -489,7 +491,8 @@ typedef struct UserDef {
short color_picker_type;
char ipo_new; /* interpolation mode for newly added F-Curves */
char keyhandles_new; /* handle types for newly added keyframes */
- char pad1[2];
+ char gpu_select_method;
+ char pad1;
short scrcastfps; /* frame rate for screencast to be played back */
short scrcastwait; /* milliseconds between screencast snapshots */
@@ -717,6 +720,13 @@ typedef enum eOpenGL_RenderingOptions {
/* USER_DISABLE_AA = (1 << 4), */ /* DEPRECATED */
} eOpenGL_RenderingOptions;
+/* selection method for opengl gpu_select_method */
+typedef enum eOpenGL_SelectOptions {
+ USER_SELECT_AUTO = 0,
+ USER_SELECT_USE_OCCLUSION_QUERY = 1,
+ USER_SELECT_USE_SELECT_RENDERMODE = 2
+} eOpenGL_SelectOptions;
+
/* wm draw method */
typedef enum eWM_DrawMethod {
USER_DRAW_TRIPLE = 0,
diff --git a/source/blender/makesdna/DNA_vfont_types.h b/source/blender/makesdna/DNA_vfont_types.h
index 14ec6c9b312..7025a5767c4 100644
--- a/source/blender/makesdna/DNA_vfont_types.h
+++ b/source/blender/makesdna/DNA_vfont_types.h
@@ -66,7 +66,7 @@ typedef struct VFont {
#define FO_SELCHANGE 10
/* BKE_vfont_to_curve will move the cursor in these cases */
-#define FO_CURS_IS_MOTION(mode) (ELEM4(mode, FO_CURSUP, FO_CURSDOWN, FO_PAGEUP, FO_PAGEDOWN))
+#define FO_CURS_IS_MOTION(mode) (ELEM(mode, FO_CURSUP, FO_CURSDOWN, FO_PAGEUP, FO_PAGEDOWN))
#define FO_BUILTIN_NAME "<builtin>"
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index add59bafc3f..ba2dd8b5d69 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -427,6 +427,9 @@ extern StructRNA RNA_OrController;
extern StructRNA RNA_OutflowFluidSettings;
extern StructRNA RNA_PackedFile;
extern StructRNA RNA_Paint;
+extern StructRNA RNA_PaintCurve;
+extern StructRNA RNA_Palette;
+extern StructRNA RNA_PaletteColor;
extern StructRNA RNA_Panel;
extern StructRNA RNA_Particle;
extern StructRNA RNA_ParticleBrush;
@@ -924,9 +927,22 @@ bool RNA_path_resolve_property(PointerRNA *ptr, const char *path,
bool RNA_path_resolve_property_full(PointerRNA *ptr, const char *path,
PointerRNA *r_ptr, PropertyRNA **r_prop, int *r_index);
+typedef struct PropertyElemRNA PropertyElemRNA;
+struct PropertyElemRNA {
+ PropertyElemRNA *next, *prev;
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ int index;
+};
+bool RNA_path_resolve_elements(PointerRNA *ptr, const char *path, struct ListBase *r_elements);
+
char *RNA_path_from_ID_to_struct(PointerRNA *ptr);
char *RNA_path_from_ID_to_property(PointerRNA *ptr, PropertyRNA *prop);
+char *RNA_path_resolve_from_type_to_property(
+ struct PointerRNA *ptr, struct PropertyRNA *prop,
+ const struct StructRNA *type);
+
char *RNA_path_full_ID_py(struct ID *id);
char *RNA_path_full_struct_py(struct PointerRNA *ptr);
char *RNA_path_full_property_py(struct PointerRNA *ptr, struct PropertyRNA *prop, int index);
diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c
index 7f1f04cdb6a..9023f25e3d5 100644
--- a/source/blender/makesrna/intern/makesrna.c
+++ b/source/blender/makesrna/intern/makesrna.c
@@ -745,6 +745,24 @@ static void rna_clamp_value_range(FILE *f, PropertyRNA *prop)
}
}
+#ifdef USE_RNA_RANGE_CHECK
+static void rna_clamp_value_range_check(
+ FILE *f, PropertyRNA *prop,
+ const char *dnaname_prefix, const char *dnaname)
+{
+ if (prop->type == PROP_INT) {
+ IntPropertyRNA *iprop = (IntPropertyRNA *)prop;
+ fprintf(f,
+ " { BLI_STATIC_ASSERT("
+ "(TYPEOF_MAX(%s%s) >= %d) && "
+ "(TYPEOF_MIN(%s%s) <= %d), "
+ "\"invalid limits\"); }\n",
+ dnaname_prefix, dnaname, iprop->hardmax,
+ dnaname_prefix, dnaname, iprop->hardmin);
+ }
+}
+#endif /* USE_RNA_RANGE_CHECK */
+
static void rna_clamp_value(FILE *f, PropertyRNA *prop, int array)
{
if (prop->type == PROP_INT) {
@@ -944,6 +962,18 @@ static char *rna_def_property_set_func(FILE *f, StructRNA *srna, PropertyRNA *pr
}
fprintf(f, " }\n");
}
+
+#ifdef USE_RNA_RANGE_CHECK
+ if (dp->dnaname && manualfunc == NULL) {
+ if (dp->dnaarraylength == 1) {
+ rna_clamp_value_range_check(f, prop, "data->", dp->dnaname);
+ }
+ else {
+ rna_clamp_value_range_check(f, prop, "*data->", dp->dnaname);
+ }
+ }
+#endif
+
fprintf(f, "}\n\n");
}
else {
@@ -975,6 +1005,13 @@ static char *rna_def_property_set_func(FILE *f, StructRNA *srna, PropertyRNA *pr
rna_clamp_value(f, prop, 0);
}
}
+
+#ifdef USE_RNA_RANGE_CHECK
+ if (dp->dnaname && manualfunc == NULL) {
+ rna_clamp_value_range_check(f, prop, "data->", dp->dnaname);
+ }
+#endif
+
fprintf(f, "}\n\n");
}
break;
diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c
index 7959e60da33..83fe56102ac 100644
--- a/source/blender/makesrna/intern/rna_ID.c
+++ b/source/blender/makesrna/intern/rna_ID.c
@@ -153,6 +153,8 @@ short RNA_type_to_ID_code(StructRNA *type)
if (RNA_struct_is_a(type, &RNA_WindowManager)) return ID_WM;
if (RNA_struct_is_a(type, &RNA_MovieClip)) return ID_MC;
if (RNA_struct_is_a(type, &RNA_Mask)) return ID_MSK;
+ if (RNA_struct_is_a(type, &RNA_Palette)) return ID_PAL;
+ if (RNA_struct_is_a(type, &RNA_PaintCurve)) return ID_PC;
return 0;
}
@@ -190,6 +192,9 @@ StructRNA *ID_code_to_RNA_type(short idcode)
case ID_WM: return &RNA_WindowManager;
case ID_MC: return &RNA_MovieClip;
case ID_MSK: return &RNA_Mask;
+ case ID_PAL: return &RNA_Palette;
+ case ID_PC: return &RNA_PaintCurve;
+
default: return &RNA_ID;
}
}
@@ -620,6 +625,10 @@ static void rna_def_library(BlenderRNA *brna)
prop = RNA_def_property(srna, "parent", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "Library");
RNA_def_property_ui_text(prop, "Parent", "");
+
+ prop = RNA_def_property(srna, "packed_file", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "packedfile");
+ RNA_def_property_ui_text(prop, "Packed File", "");
}
void RNA_def_ID(BlenderRNA *brna)
{
diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c
index ded0278b44d..8c76edd2f17 100644
--- a/source/blender/makesrna/intern/rna_access.c
+++ b/source/blender/makesrna/intern/rna_access.c
@@ -359,12 +359,12 @@ static bool rna_idproperty_verify_valid(PointerRNA *ptr, PropertyRNA *prop, IDPr
if (idprop->subtype == IDP_FLOAT && prop->type != PROP_FLOAT)
return false;
- if (idprop->subtype == IDP_INT && !ELEM3(prop->type, PROP_BOOLEAN, PROP_INT, PROP_ENUM))
+ if (idprop->subtype == IDP_INT && !ELEM(prop->type, PROP_BOOLEAN, PROP_INT, PROP_ENUM))
return false;
break;
case IDP_INT:
- if (!ELEM3(prop->type, PROP_BOOLEAN, PROP_INT, PROP_ENUM))
+ if (!ELEM(prop->type, PROP_BOOLEAN, PROP_INT, PROP_ENUM))
return false;
break;
case IDP_FLOAT:
@@ -872,8 +872,8 @@ char RNA_property_array_item_char(PropertyRNA *prop, int index)
if ((index < 4) && ELEM(subtype, PROP_QUATERNION, PROP_AXISANGLE)) {
return quatitem[index];
}
- else if ((index < 4) && ELEM8(subtype, PROP_TRANSLATION, PROP_DIRECTION, PROP_XYZ, PROP_XYZ_LENGTH,
- PROP_EULER, PROP_VELOCITY, PROP_ACCELERATION, PROP_COORDS))
+ else if ((index < 4) && ELEM(subtype, PROP_TRANSLATION, PROP_DIRECTION, PROP_XYZ, PROP_XYZ_LENGTH,
+ PROP_EULER, PROP_VELOCITY, PROP_ACCELERATION, PROP_COORDS))
{
return vectoritem[index];
}
@@ -902,7 +902,7 @@ int RNA_property_array_item_index(PropertyRNA *prop, char name)
return 3;
}
}
- else if (ELEM6(subtype, PROP_TRANSLATION, PROP_DIRECTION, PROP_XYZ,
+ else if (ELEM(subtype, PROP_TRANSLATION, PROP_DIRECTION, PROP_XYZ,
PROP_EULER, PROP_VELOCITY, PROP_ACCELERATION))
{
switch (name) {
@@ -3329,7 +3329,7 @@ static int rna_raw_access(ReportList *reports, PointerRNA *ptr, PropertyRNA *pro
/* check type */
itemtype = RNA_property_type(itemprop);
- if (!ELEM3(itemtype, PROP_BOOLEAN, PROP_INT, PROP_FLOAT)) {
+ if (!ELEM(itemtype, PROP_BOOLEAN, PROP_INT, PROP_FLOAT)) {
BKE_report(reports, RPT_ERROR, "Only boolean, int and float properties supported");
return 0;
}
@@ -3409,7 +3409,7 @@ static int rna_raw_access(ReportList *reports, PointerRNA *ptr, PropertyRNA *pro
break;
}
- if (!ELEM3(itemtype, PROP_BOOLEAN, PROP_INT, PROP_FLOAT)) {
+ if (!ELEM(itemtype, PROP_BOOLEAN, PROP_INT, PROP_FLOAT)) {
BKE_report(reports, RPT_ERROR, "Only boolean, int and float properties supported");
err = 1;
break;
@@ -4015,11 +4015,14 @@ static bool rna_path_parse_array_index(const char **path, PointerRNA *ptr, Prope
}
static bool rna_path_parse(PointerRNA *ptr, const char *path,
- PointerRNA *r_ptr, PropertyRNA **r_prop, int *index,
+ PointerRNA *r_ptr, PropertyRNA **r_prop, int *r_index,
+ ListBase *r_elements,
const bool eval_pointer)
{
PropertyRNA *prop;
PointerRNA curptr;
+ PropertyElemRNA *prop_elem = NULL;
+ int index = -1;
char fixedbuf[256];
int type;
@@ -4061,6 +4064,14 @@ static bool rna_path_parse(PointerRNA *ptr, const char *path,
if (!prop)
return false;
+ if (r_elements) {
+ prop_elem = MEM_mallocN(sizeof(PropertyElemRNA), __func__);
+ prop_elem->ptr = curptr;
+ prop_elem->prop = prop;
+ prop_elem->index = -1; /* index will be added later, if needed. */
+ BLI_addtail(r_elements, prop_elem);
+ }
+
type = RNA_property_type(prop);
/* now look up the value of this property if it is a pointer or
@@ -4076,7 +4087,7 @@ static bool rna_path_parse(PointerRNA *ptr, const char *path,
curptr = nextptr;
prop = NULL; /* now we have a PointerRNA, the prop is our parent so forget it */
- if (index) *index = -1;
+ index = -1;
}
break;
}
@@ -4093,21 +4104,38 @@ static bool rna_path_parse(PointerRNA *ptr, const char *path,
curptr = nextptr;
prop = NULL; /* now we have a PointerRNA, the prop is our parent so forget it */
- if (index) *index = -1;
+ index = -1;
}
break;
}
default:
- if (index) {
- if (!rna_path_parse_array_index(&path, &curptr, prop, index))
+ if (r_index || prop_elem) {
+ if (!rna_path_parse_array_index(&path, &curptr, prop, &index)) {
return false;
+ }
+
+ if (prop_elem) {
+ prop_elem->index = index;
+ }
}
break;
}
}
- *r_ptr = curptr;
- *r_prop = prop;
+ if (r_ptr)
+ *r_ptr = curptr;
+ if (r_prop)
+ *r_prop = prop;
+ if (r_index)
+ *r_index = index;
+
+ if (prop_elem && (prop_elem->ptr.data != curptr.data || prop_elem->prop != prop || prop_elem->index != index)) {
+ PropertyElemRNA *prop_elem = MEM_mallocN(sizeof(PropertyElemRNA), __func__);
+ prop_elem->ptr = curptr;
+ prop_elem->prop = prop;
+ prop_elem->index = index;
+ BLI_addtail(r_elements, prop_elem);
+ }
return true;
}
@@ -4120,7 +4148,7 @@ static bool rna_path_parse(PointerRNA *ptr, const char *path,
*/
bool RNA_path_resolve(PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop)
{
- if (!rna_path_parse(ptr, path, r_ptr, r_prop, NULL, true))
+ if (!rna_path_parse(ptr, path, r_ptr, r_prop, NULL, NULL, true))
return false;
return r_ptr->data != NULL;
@@ -4134,7 +4162,7 @@ bool RNA_path_resolve(PointerRNA *ptr, const char *path, PointerRNA *r_ptr, Prop
*/
bool RNA_path_resolve_full(PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop, int *r_index)
{
- if (!rna_path_parse(ptr, path, r_ptr, r_prop, r_index, true))
+ if (!rna_path_parse(ptr, path, r_ptr, r_prop, r_index, NULL, true))
return false;
return r_ptr->data != NULL;
@@ -4149,7 +4177,7 @@ bool RNA_path_resolve_full(PointerRNA *ptr, const char *path, PointerRNA *r_ptr,
*/
bool RNA_path_resolve_property(PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop)
{
- if (!rna_path_parse(ptr, path, r_ptr, r_prop, NULL, false))
+ if (!rna_path_parse(ptr, path, r_ptr, r_prop, NULL, NULL, false))
return false;
return r_ptr->data != NULL && *r_prop != NULL;
@@ -4165,12 +4193,25 @@ bool RNA_path_resolve_property(PointerRNA *ptr, const char *path, PointerRNA *r_
*/
bool RNA_path_resolve_property_full(PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop, int *r_index)
{
- if (!rna_path_parse(ptr, path, r_ptr, r_prop, r_index, false))
+ if (!rna_path_parse(ptr, path, r_ptr, r_prop, r_index, NULL, false))
return false;
return r_ptr->data != NULL && *r_prop != NULL;
}
+/**
+ * Resolve the given RNA Path into a linked list of PropertyElemRNA's.
+ *
+ * To be used when complex operations over path are needed, like e.g. get relative paths, to avoid too much
+ * string operations.
+ *
+ * \return True if there was no error while resolving the path
+ * \note Assumes all pointers provided are valid
+ */
+bool RNA_path_resolve_elements(PointerRNA *ptr, const char *path, ListBase *r_elements)
+{
+ return rna_path_parse(ptr, path, NULL, NULL, NULL, r_elements, false);
+}
char *RNA_path_append(const char *path, PointerRNA *UNUSED(ptr), PropertyRNA *prop, int intkey, const char *strkey)
{
@@ -4498,6 +4539,47 @@ char *RNA_path_from_ID_to_property(PointerRNA *ptr, PropertyRNA *prop)
}
/**
+ * \return the path to given ptr/prop from the closest ancestor of given type, if any (else return NULL).
+ */
+char *RNA_path_resolve_from_type_to_property(
+ PointerRNA *ptr, PropertyRNA *prop,
+ const StructRNA *type)
+{
+ /* Try to recursively find an "type"'d ancestor,
+ * to handle situations where path from ID is not enough. */
+ PointerRNA idptr;
+ ListBase path_elems = {NULL};
+ char *path = NULL;
+ char *full_path = RNA_path_from_ID_to_property(ptr, prop);
+
+ if (full_path == NULL) {
+ return NULL;
+ }
+
+ RNA_id_pointer_create(ptr->id.data, &idptr);
+
+ if (RNA_path_resolve_elements(&idptr, full_path, &path_elems)) {
+ PropertyElemRNA *prop_elem;
+
+ for (prop_elem = path_elems.last; prop_elem; prop_elem = prop_elem->prev) {
+ if (RNA_struct_is_a(prop_elem->ptr.type, type)) {
+ char *ref_path = RNA_path_from_ID_to_struct(&prop_elem->ptr);
+ if (ref_path) {
+ path = BLI_strdup(full_path + strlen(ref_path) + 1); /* +1 for the linking '.' */
+ MEM_freeN(ref_path);
+ }
+ break;
+ }
+ }
+
+ BLI_freelistN(&path_elems);
+ }
+
+ MEM_freeN(full_path);
+ return path;
+}
+
+/**
* Get the ID as a python representation, eg:
* bpy.data.foo["bar"]
*/
diff --git a/source/blender/makesrna/intern/rna_actuator.c b/source/blender/makesrna/intern/rna_actuator.c
index 956077055a9..0114ffa35c0 100644
--- a/source/blender/makesrna/intern/rna_actuator.c
+++ b/source/blender/makesrna/intern/rna_actuator.c
@@ -150,7 +150,7 @@ static void rna_ConstraintActuator_type_set(struct PointerRNA *ptr, int value)
switch (ca->type) {
case ACT_CONST_TYPE_ORI:
/* negative axis not supported in the orientation mode */
- if (ELEM3(ca->mode, ACT_CONST_DIRNX, ACT_CONST_DIRNY, ACT_CONST_DIRNZ))
+ if (ELEM(ca->mode, ACT_CONST_DIRNX, ACT_CONST_DIRNY, ACT_CONST_DIRNZ))
ca->mode = ACT_CONST_NONE;
break;
diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c
index 893cad2b76a..1ff99271146 100644
--- a/source/blender/makesrna/intern/rna_brush.c
+++ b/source/blender/makesrna/intern/rna_brush.c
@@ -55,6 +55,9 @@ static EnumPropertyItem sculpt_stroke_method_items[] = {
{BRUSH_SPACE, "SPACE", 0, "Space", "Limit brush application to the distance specified by spacing"},
{BRUSH_AIRBRUSH, "AIRBRUSH", 0, "Airbrush", "Keep applying paint effect while holding mouse (spray)"},
{BRUSH_ANCHORED, "ANCHORED", 0, "Anchored", "Keep the brush anchored to the initial location"},
+ {BRUSH_LINE, "LINE", 0, "Line", "Draw a line with dabs separated according to spacing"},
+ {BRUSH_CURVE, "CURVE", 0, "Curve",
+ "Define the stroke curve with a bezier curve (dabs are separated according to spacing)"},
{0, NULL, 0, NULL, NULL}
};
@@ -99,6 +102,8 @@ EnumPropertyItem brush_image_tool_items[] = {
{PAINT_TOOL_SOFTEN, "SOFTEN", ICON_BRUSH_SOFTEN, "Soften", ""},
{PAINT_TOOL_SMEAR, "SMEAR", ICON_BRUSH_SMEAR, "Smear", ""},
{PAINT_TOOL_CLONE, "CLONE", ICON_BRUSH_CLONE, "Clone", ""},
+ {PAINT_TOOL_FILL, "FILL", ICON_BRUSH_TEXFILL, "Fill", ""},
+ {PAINT_TOOL_MASK, "MASK", ICON_BRUSH_TEXMASK, "Mask", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -120,9 +125,9 @@ EnumPropertyItem brush_image_tool_items[] = {
static int rna_SculptToolCapabilities_has_accumulate_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
- return ELEM6(br->sculpt_tool,
- SCULPT_TOOL_BLOB, SCULPT_TOOL_CLAY, SCULPT_TOOL_CREASE,
- SCULPT_TOOL_DRAW, SCULPT_TOOL_INFLATE, SCULPT_TOOL_LAYER);
+ return ELEM(br->sculpt_tool,
+ SCULPT_TOOL_BLOB, SCULPT_TOOL_CLAY, SCULPT_TOOL_CREASE,
+ SCULPT_TOOL_DRAW, SCULPT_TOOL_INFLATE, SCULPT_TOOL_LAYER);
}
static int rna_SculptToolCapabilities_has_auto_smooth_get(PointerRNA *ptr)
@@ -142,9 +147,9 @@ static int rna_SculptToolCapabilities_has_jitter_get(PointerRNA *ptr)
Brush *br = (Brush *)ptr->data;
return (!(br->flag & BRUSH_ANCHORED) &&
!(br->flag & BRUSH_DRAG_DOT) &&
- !ELEM4(br->sculpt_tool,
- SCULPT_TOOL_GRAB, SCULPT_TOOL_ROTATE,
- SCULPT_TOOL_SNAKE_HOOK, SCULPT_TOOL_THUMB));
+ !ELEM(br->sculpt_tool,
+ SCULPT_TOOL_GRAB, SCULPT_TOOL_ROTATE,
+ SCULPT_TOOL_SNAKE_HOOK, SCULPT_TOOL_THUMB));
}
static int rna_SculptToolCapabilities_has_normal_weight_get(PointerRNA *ptr)
@@ -156,7 +161,7 @@ static int rna_SculptToolCapabilities_has_normal_weight_get(PointerRNA *ptr)
static int rna_BrushCapabilities_has_overlay_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
- return ELEM3(br->mtex.brush_map_mode,
+ return ELEM(br->mtex.brush_map_mode,
MTEX_MAP_MODE_VIEW,
MTEX_MAP_MODE_TILED,
MTEX_MAP_MODE_STENCIL);
@@ -177,22 +182,22 @@ static int rna_SculptToolCapabilities_has_pinch_factor_get(PointerRNA *ptr)
static int rna_SculptToolCapabilities_has_plane_offset_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
- return ELEM5(br->sculpt_tool, SCULPT_TOOL_CLAY, SCULPT_TOOL_CLAY_STRIPS,
- SCULPT_TOOL_FILL, SCULPT_TOOL_FLATTEN, SCULPT_TOOL_SCRAPE);
+ return ELEM(br->sculpt_tool, SCULPT_TOOL_CLAY, SCULPT_TOOL_CLAY_STRIPS,
+ SCULPT_TOOL_FILL, SCULPT_TOOL_FLATTEN, SCULPT_TOOL_SCRAPE);
}
static int rna_SculptToolCapabilities_has_random_texture_angle_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
- return (!ELEM4(br->sculpt_tool,
- SCULPT_TOOL_GRAB, SCULPT_TOOL_ROTATE,
- SCULPT_TOOL_SNAKE_HOOK, SCULPT_TOOL_THUMB));
+ return (!ELEM(br->sculpt_tool,
+ SCULPT_TOOL_GRAB, SCULPT_TOOL_ROTATE,
+ SCULPT_TOOL_SNAKE_HOOK, SCULPT_TOOL_THUMB));
}
static int rna_BrushCapabilities_has_random_texture_angle_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
- return (ELEM3(br->mtex.brush_map_mode,
+ return (ELEM(br->mtex.brush_map_mode,
MTEX_MAP_MODE_VIEW,
MTEX_MAP_MODE_AREA,
MTEX_MAP_MODE_RANDOM) &&
@@ -202,19 +207,19 @@ static int rna_BrushCapabilities_has_random_texture_angle_get(PointerRNA *ptr)
static int rna_SculptToolCapabilities_has_sculpt_plane_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
- return !ELEM4(br->sculpt_tool, SCULPT_TOOL_INFLATE,
- SCULPT_TOOL_MASK, SCULPT_TOOL_PINCH,
- SCULPT_TOOL_SMOOTH);
+ return !ELEM(br->sculpt_tool, SCULPT_TOOL_INFLATE,
+ SCULPT_TOOL_MASK, SCULPT_TOOL_PINCH,
+ SCULPT_TOOL_SMOOTH);
}
static int rna_SculptToolCapabilities_has_secondary_color_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
- return ELEM10(br->sculpt_tool,
- SCULPT_TOOL_BLOB, SCULPT_TOOL_CLAY, SCULPT_TOOL_CLAY_STRIPS,
- SCULPT_TOOL_CREASE, SCULPT_TOOL_DRAW, SCULPT_TOOL_FILL,
- SCULPT_TOOL_FLATTEN, SCULPT_TOOL_INFLATE, SCULPT_TOOL_PINCH,
- SCULPT_TOOL_SCRAPE);
+ return ELEM(br->sculpt_tool,
+ SCULPT_TOOL_BLOB, SCULPT_TOOL_CLAY, SCULPT_TOOL_CLAY_STRIPS,
+ SCULPT_TOOL_CREASE, SCULPT_TOOL_DRAW, SCULPT_TOOL_FILL,
+ SCULPT_TOOL_FLATTEN, SCULPT_TOOL_INFLATE, SCULPT_TOOL_PINCH,
+ SCULPT_TOOL_SCRAPE);
}
static int rna_SculptToolCapabilities_has_smooth_stroke_get(PointerRNA *ptr)
@@ -222,19 +227,37 @@ static int rna_SculptToolCapabilities_has_smooth_stroke_get(PointerRNA *ptr)
Brush *br = (Brush *)ptr->data;
return (!(br->flag & BRUSH_ANCHORED) &&
!(br->flag & BRUSH_DRAG_DOT) &&
- !ELEM4(br->sculpt_tool,
+ !(br->flag & BRUSH_LINE) &&
+ !(br->flag & BRUSH_CURVE) &&
+ !ELEM(br->sculpt_tool,
SCULPT_TOOL_GRAB, SCULPT_TOOL_ROTATE,
SCULPT_TOOL_SNAKE_HOOK, SCULPT_TOOL_THUMB));
}
+static int rna_BrushCapabilities_has_smooth_stroke_get(PointerRNA *ptr)
+{
+ Brush *br = (Brush *)ptr->data;
+ return (!(br->flag & BRUSH_ANCHORED) &&
+ !(br->flag & BRUSH_DRAG_DOT) &&
+ !(br->flag & BRUSH_LINE) &&
+ !(br->flag & BRUSH_CURVE));
+}
+
static int rna_SculptToolCapabilities_has_space_attenuation_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
- return ((br->flag & BRUSH_SPACE) &&
- !ELEM4(br->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_ROTATE,
+ return ((br->flag & (BRUSH_SPACE | BRUSH_LINE | BRUSH_CURVE)) &&
+ !ELEM(br->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_ROTATE,
SCULPT_TOOL_SMOOTH, SCULPT_TOOL_SNAKE_HOOK));
}
+static int rna_ImapaintToolCapabilities_has_space_attenuation_get(PointerRNA *ptr)
+{
+ Brush *br = (Brush *)ptr->data;
+ return (br->flag & (BRUSH_SPACE | BRUSH_LINE | BRUSH_CURVE)) &&
+ br->imagepaint_tool != PAINT_TOOL_FILL;
+}
+
static int rna_BrushCapabilities_has_spacing_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
@@ -250,12 +273,12 @@ static int rna_SculptToolCapabilities_has_strength_get(PointerRNA *ptr)
static int rna_BrushCapabilities_has_texture_angle_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
- return ELEM5(br->mtex.brush_map_mode,
- MTEX_MAP_MODE_VIEW,
- MTEX_MAP_MODE_AREA,
- MTEX_MAP_MODE_TILED,
- MTEX_MAP_MODE_STENCIL,
- MTEX_MAP_MODE_RANDOM);
+ return ELEM(br->mtex.brush_map_mode,
+ MTEX_MAP_MODE_VIEW,
+ MTEX_MAP_MODE_AREA,
+ MTEX_MAP_MODE_TILED,
+ MTEX_MAP_MODE_STENCIL,
+ MTEX_MAP_MODE_RANDOM);
}
static int rna_SculptToolCapabilities_has_gravity_get(PointerRNA *ptr)
@@ -267,17 +290,46 @@ static int rna_SculptToolCapabilities_has_gravity_get(PointerRNA *ptr)
static int rna_BrushCapabilities_has_texture_angle_source_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
- return ELEM3(br->mtex.brush_map_mode,
+ return ELEM(br->mtex.brush_map_mode,
MTEX_MAP_MODE_VIEW,
MTEX_MAP_MODE_AREA,
MTEX_MAP_MODE_RANDOM);
}
-static PointerRNA rna_Sculpt_sculpt_tool_capabilities_get(PointerRNA *ptr)
+static int rna_ImapaintToolCapabilities_has_accumulate_get(PointerRNA *ptr)
+{
+ /* only support for draw tool */
+ Brush *br = (Brush *)ptr->data;
+
+ return ((br->flag & BRUSH_AIRBRUSH) ||
+ (br->flag & BRUSH_DRAG_DOT) ||
+ (br->flag & BRUSH_ANCHORED) ||
+ (br->imagepaint_tool == PAINT_TOOL_SOFTEN) ||
+ (br->imagepaint_tool == PAINT_TOOL_SMEAR) ||
+ (br->imagepaint_tool == PAINT_TOOL_FILL) ||
+ (br->mtex.tex && !ELEM(br->mtex.brush_map_mode, MTEX_MAP_MODE_TILED, MTEX_MAP_MODE_STENCIL, MTEX_MAP_MODE_3D))
+ ) ? false : true;
+}
+
+static int rna_ImapaintToolCapabilities_has_radius_get(PointerRNA *ptr)
+{
+ /* only support for draw tool */
+ Brush *br = (Brush *)ptr->data;
+
+ return (br->imagepaint_tool != PAINT_TOOL_FILL);
+}
+
+
+static PointerRNA rna_Sculpt_tool_capabilities_get(PointerRNA *ptr)
{
return rna_pointer_inherit_refine(ptr, &RNA_SculptToolCapabilities, ptr->id.data);
}
+static PointerRNA rna_Imapaint_tool_capabilities_get(PointerRNA *ptr)
+{
+ return rna_pointer_inherit_refine(ptr, &RNA_ImapaintToolCapabilities, ptr->id.data);
+}
+
static PointerRNA rna_Brush_capabilities_get(PointerRNA *ptr)
{
return rna_pointer_inherit_refine(ptr, &RNA_BrushCapabilities, ptr->id.data);
@@ -328,7 +380,6 @@ static void rna_Brush_size_update(Main *bmain, Scene *scene, PointerRNA *ptr)
static void rna_Brush_sculpt_tool_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
- BKE_paint_invalidate_overlay_all();
rna_Brush_reset_icon(br, "sculpt");
rna_Brush_update(bmain, scene, ptr);
}
@@ -336,7 +387,6 @@ static void rna_Brush_sculpt_tool_update(Main *bmain, Scene *scene, PointerRNA *
static void rna_Brush_vertex_tool_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
- BKE_paint_invalidate_overlay_all();
rna_Brush_reset_icon(br, "vertex_paint");
rna_Brush_update(bmain, scene, ptr);
}
@@ -344,11 +394,16 @@ static void rna_Brush_vertex_tool_update(Main *bmain, Scene *scene, PointerRNA *
static void rna_Brush_imagepaint_tool_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
- BKE_paint_invalidate_overlay_all();
rna_Brush_reset_icon(br, "image_paint");
rna_Brush_update(bmain, scene, ptr);
}
+static void rna_Brush_stroke_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ WM_main_add_notifier(NC_SCENE | ND_TOOLSETTINGS, scene);
+ rna_Brush_update(bmain, scene, ptr);
+}
+
static void rna_Brush_icon_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
@@ -388,6 +443,17 @@ static void rna_Brush_set_size(PointerRNA *ptr, int value)
brush->size = value;
}
+static void rna_Brush_use_gradient_set(PointerRNA *ptr, int value)
+{
+ Brush *br = (Brush *)ptr->data;
+
+ if (value) br->flag |= BRUSH_USE_GRADIENT;
+ else br->flag &= ~BRUSH_USE_GRADIENT;
+
+ if ((br->flag & BRUSH_USE_GRADIENT) && br->gradient == NULL)
+ br->gradient = add_colorband(true);
+}
+
static void rna_Brush_set_unprojected_radius(PointerRNA *ptr, float value)
{
Brush *brush = ptr->data;
@@ -397,13 +463,16 @@ static void rna_Brush_set_unprojected_radius(PointerRNA *ptr, float value)
brush->unprojected_radius = value;
}
-static EnumPropertyItem *rna_Brush_direction_itemf(bContext *UNUSED(C), PointerRNA *ptr,
+static EnumPropertyItem *rna_Brush_direction_itemf(bContext *C, PointerRNA *ptr,
PropertyRNA *UNUSED(prop), bool *UNUSED(r_free))
{
+ PaintMode mode = BKE_paintmode_get_active_from_context(C);
+
static EnumPropertyItem prop_default_items[] = {
{0, NULL, 0, NULL, NULL}
};
+ /* sculpt mode */
static EnumPropertyItem prop_flatten_contrast_items[] = {
{0, "FLATTEN", 0, "Flatten", "Add effect of brush"},
{BRUSH_DIR_IN, "CONTRAST", 0, "Contrast", "Subtract effect of brush"},
@@ -434,41 +503,66 @@ static EnumPropertyItem *rna_Brush_direction_itemf(bContext *UNUSED(C), PointerR
{0, NULL, 0, NULL, NULL}
};
+ /* texture paint mode */
+ static EnumPropertyItem prop_soften_sharpen_items[] = {
+ {0, "SOFTEN", 0, "Soften", "Blur effect of brush"},
+ {BRUSH_DIR_IN, "SHARPEN", 0, "Sharpen", "Sharpen effect of brush"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
Brush *me = (Brush *)(ptr->data);
- switch (me->sculpt_tool) {
- case SCULPT_TOOL_DRAW:
- case SCULPT_TOOL_CREASE:
- case SCULPT_TOOL_BLOB:
- case SCULPT_TOOL_LAYER:
- case SCULPT_TOOL_CLAY:
- case SCULPT_TOOL_CLAY_STRIPS:
- return prop_direction_items;
-
- case SCULPT_TOOL_MASK:
- switch ((BrushMaskTool)me->mask_tool) {
- case BRUSH_MASK_DRAW:
+ switch (mode) {
+ case PAINT_SCULPT:
+ switch (me->sculpt_tool) {
+ case SCULPT_TOOL_DRAW:
+ case SCULPT_TOOL_CREASE:
+ case SCULPT_TOOL_BLOB:
+ case SCULPT_TOOL_LAYER:
+ case SCULPT_TOOL_CLAY:
+ case SCULPT_TOOL_CLAY_STRIPS:
return prop_direction_items;
- break;
- case BRUSH_MASK_SMOOTH:
- return prop_default_items;
- break;
- }
- case SCULPT_TOOL_FLATTEN:
- return prop_flatten_contrast_items;
+ case SCULPT_TOOL_MASK:
+ switch ((BrushMaskTool)me->mask_tool) {
+ case BRUSH_MASK_DRAW:
+ return prop_direction_items;
+ break;
+ case BRUSH_MASK_SMOOTH:
+ return prop_default_items;
+ break;
+ }
- case SCULPT_TOOL_FILL:
- return prop_fill_deepen_items;
+ case SCULPT_TOOL_FLATTEN:
+ return prop_flatten_contrast_items;
- case SCULPT_TOOL_SCRAPE:
- return prop_scrape_peaks_items;
+ case SCULPT_TOOL_FILL:
+ return prop_fill_deepen_items;
- case SCULPT_TOOL_PINCH:
- return prop_pinch_magnify_items;
+ case SCULPT_TOOL_SCRAPE:
+ return prop_scrape_peaks_items;
- case SCULPT_TOOL_INFLATE:
- return prop_inflate_deflate_items;
+ case SCULPT_TOOL_PINCH:
+ return prop_pinch_magnify_items;
+
+ case SCULPT_TOOL_INFLATE:
+ return prop_inflate_deflate_items;
+
+ default:
+ return prop_default_items;
+ }
+ break;
+
+ case PAINT_TEXTURE_2D:
+ case PAINT_TEXTURE_PROJECTIVE:
+ switch (me->imagepaint_tool) {
+ case PAINT_TOOL_SOFTEN:
+ return prop_soften_sharpen_items;
+
+ default:
+ return prop_default_items;
+ }
+ break;
default:
return prop_default_items;
@@ -484,11 +578,15 @@ static EnumPropertyItem *rna_Brush_stroke_itemf(bContext *C, PointerRNA *UNUSED(
{0, "DOTS", 0, "Dots", "Apply paint on each mouse move step"},
{BRUSH_SPACE, "SPACE", 0, "Space", "Limit brush application to the distance specified by spacing"},
{BRUSH_AIRBRUSH, "AIRBRUSH", 0, "Airbrush", "Keep applying paint effect while holding mouse (spray)"},
+ {BRUSH_LINE, "LINE", 0, "Line", "Drag a line with dabs separated according to spacing"},
+ {BRUSH_CURVE, "CURVE", 0, "Curve", "Define the stroke curve with a bezier curve. Dabs are separated according to spacing"},
{0, NULL, 0, NULL, NULL}
};
switch (mode) {
case PAINT_SCULPT:
+ case PAINT_TEXTURE_2D:
+ case PAINT_TEXTURE_PROJECTIVE:
return sculpt_stroke_method_items;
default:
@@ -622,10 +720,39 @@ static void rna_def_brush_capabilities(BlenderRNA *brna)
BRUSH_CAPABILITY(has_texture_angle, "Has Texture Angle");
BRUSH_CAPABILITY(has_texture_angle_source, "Has Texture Angle Source");
BRUSH_CAPABILITY(has_spacing, "Has Spacing");
+ BRUSH_CAPABILITY(has_smooth_stroke, "Has Smooth Stroke");
+
#undef BRUSH_CAPABILITY
}
+static void rna_def_image_paint_capabilities(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "ImapaintToolCapabilities", NULL);
+ RNA_def_struct_sdna(srna, "Brush");
+ RNA_def_struct_nested(brna, srna, "Brush");
+ RNA_def_struct_ui_text(srna, "Image Paint Capabilities",
+ "Read-only indications of which brush operations "
+ "are supported by the current image paint brush");
+
+#define IMAPAINT_TOOL_CAPABILITY(prop_name_, ui_name_) \
+ prop = RNA_def_property(srna, #prop_name_, \
+ PROP_BOOLEAN, PROP_NONE); \
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE); \
+ RNA_def_property_boolean_funcs(prop, "rna_ImapaintToolCapabilities_" \
+ #prop_name_ "_get", NULL); \
+ RNA_def_property_ui_text(prop, ui_name_, NULL)
+
+ IMAPAINT_TOOL_CAPABILITY(has_accumulate, "Has Accumulate");
+ IMAPAINT_TOOL_CAPABILITY(has_space_attenuation, "Has Space Attenuation");
+ IMAPAINT_TOOL_CAPABILITY(has_radius, "Has Radius");
+
+#undef IMAPAINT_TOOL_CAPABILITY
+}
+
static void rna_def_brush(BlenderRNA *brna)
{
StructRNA *srna;
@@ -640,6 +767,22 @@ static void rna_def_brush(BlenderRNA *brna)
{IMB_BLEND_DARKEN, "DARKEN", 0, "Darken", "Use darken blending mode while painting"},
{IMB_BLEND_ERASE_ALPHA, "ERASE_ALPHA", 0, "Erase Alpha", "Erase alpha while painting"},
{IMB_BLEND_ADD_ALPHA, "ADD_ALPHA", 0, "Add Alpha", "Add alpha while painting"},
+ {IMB_BLEND_OVERLAY, "OVERLAY", 0, "Overlay", "Use overlay blending mode while painting"},
+ {IMB_BLEND_HARDLIGHT, "HARDLIGHT", 0, "Hard light", "Use hard light blending mode while painting"},
+ {IMB_BLEND_COLORBURN, "COLORBURN", 0, "Color burn", "Use color burn blending mode while painting"},
+ {IMB_BLEND_LINEARBURN, "LINEARBURN", 0, "Linear burn", "Use linear burn blending mode while painting"},
+ {IMB_BLEND_COLORDODGE, "COLORDODGE", 0, "Color dodge", "Use color dodge blending mode while painting"},
+ {IMB_BLEND_SCREEN, "SCREEN", 0, "Screen", "Use screen blending mode while painting"},
+ {IMB_BLEND_SOFTLIGHT, "SOFTLIGHT", 0, "Soft light", "Use softlight blending mode while painting"},
+ {IMB_BLEND_PINLIGHT, "PINLIGHT", 0, "Pin light", "Use pinlight blending mode while painting"},
+ {IMB_BLEND_VIVIDLIGHT, "VIVIDLIGHT", 0, "Vivid light", "Use vividlight blending mode while painting"},
+ {IMB_BLEND_LINEARLIGHT, "LINEARLIGHT", 0, "Linear light", "Use linearlight blending mode while painting"},
+ {IMB_BLEND_DIFFERENCE, "DIFFERENCE", 0, "Difference", "Use difference blending mode while painting"},
+ {IMB_BLEND_EXCLUSION, "EXCLUSION", 0, "Exclusion", "Use exclusion blending mode while painting"},
+ {IMB_BLEND_HUE, "HUE", 0, "Hue", "Use hue blending mode while painting"},
+ {IMB_BLEND_SATURATION, "SATURATION", 0, "Saturation", "Use saturation blending mode while painting"},
+ {IMB_BLEND_LUMINOSITY, "LUMINOSITY", 0, "Luminosity", "Use luminosity blending mode while painting"},
+ {IMB_BLEND_COLOR, "COLOR", 0, "Color", "Use color blending mode while painting"},
{0, NULL, 0, NULL, NULL}
};
@@ -671,6 +814,32 @@ static void rna_def_brush(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
+ static EnumPropertyItem brush_blur_mode_items[] = {
+ {KERNEL_BOX, "BOX", 0, "Box", ""},
+ {KERNEL_GAUSSIAN, "GAUSSIAN", 0, "Gaussian", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ static EnumPropertyItem brush_gradient_items[] = {
+ {BRUSH_GRADIENT_PRESSURE, "PRESSURE", 0, "Pressure", ""},
+ {BRUSH_GRADIENT_SPACING_REPEAT, "SPACING_REPEAT", 0, "Repeat", ""},
+ {BRUSH_GRADIENT_SPACING_CLAMP, "SPACING_CLAMP", 0, "Clamp", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ static EnumPropertyItem brush_gradient_fill_items[] = {
+ {BRUSH_GRADIENT_LINEAR, "LINEAR", 0, "Linear", ""},
+ {BRUSH_GRADIENT_RADIAL, "RADIAL", 0, "Radial", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ static EnumPropertyItem brush_mask_pressure_items[] = {
+ {0, "NONE", 0, "Off", ""},
+ {BRUSH_MASK_PRESSURE_RAMP, "RAMP", ICON_STYLUS_PRESSURE, "Ramp", ""},
+ {BRUSH_MASK_PRESSURE_CUTOFF, "CUTOFF", ICON_STYLUS_PRESSURE, "Cutoff", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
srna = RNA_def_struct(brna, "Brush", "ID");
RNA_def_struct_ui_text(srna, "Brush", "Brush datablock for storing brush settings for painting and sculpting");
RNA_def_struct_ui_icon(srna, ICON_BRUSH_DATA);
@@ -710,7 +879,7 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_enum_items(prop, sculpt_stroke_method_items);
RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_Brush_stroke_itemf");
RNA_def_property_ui_text(prop, "Stroke Method", "");
- RNA_def_property_update(prop, 0, "rna_Brush_update");
+ RNA_def_property_update(prop, 0, "rna_Brush_stroke_update");
prop = RNA_def_property(srna, "texture_angle_source_random", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
@@ -769,6 +938,13 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Spacing", "Spacing between brush daubs as a percentage of brush diameter");
RNA_def_property_update(prop, 0, "rna_Brush_update");
+ prop = RNA_def_property(srna, "grad_spacing", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "gradient_spacing");
+ RNA_def_property_range(prop, 1, 10000);
+ RNA_def_property_ui_range(prop, 1, 10000, 5, -1);
+ RNA_def_property_ui_text(prop, "Gradient Spacing", "Spacing before brush gradient goes full circle");
+ RNA_def_property_update(prop, 0, "rna_Brush_update");
+
prop = RNA_def_property(srna, "smooth_stroke_radius", PROP_INT, PROP_NONE);
RNA_def_property_range(prop, 10, 200);
RNA_def_property_ui_text(prop, "Smooth Stroke Radius", "Minimum distance from last point before stroke continues");
@@ -791,7 +967,13 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "rgb");
RNA_def_property_ui_text(prop, "Color", "");
RNA_def_property_update(prop, 0, "rna_Brush_update");
-
+
+ prop = RNA_def_property(srna, "secondary_color", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_range(prop, 0.0, 1.0);
+ RNA_def_property_float_sdna(prop, NULL, "secondary_rgb");
+ RNA_def_property_ui_text(prop, "Secondary Color", "");
+ RNA_def_property_update(prop, 0, "rna_Brush_update");
+
prop = RNA_def_property(srna, "weight", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_default(prop, 1.0f);
RNA_def_property_range(prop, 0.0f, 1.0f);
@@ -884,6 +1066,32 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Mask Stencil Dimensions", "Dimensions of mask stencil in viewport");
RNA_def_property_update(prop, 0, "rna_Brush_update");
+ prop = RNA_def_property(srna, "sharp_threshold", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.0, 100.0);
+ RNA_def_property_ui_range(prop, 0.0, 1.0, 1, 3);
+ RNA_def_property_float_sdna(prop, NULL, "sharp_threshold");
+ RNA_def_property_ui_text(prop, "Sharp Threshold", "Threshold below which, no sharpening is done");
+ RNA_def_property_update(prop, 0, "rna_Brush_update");
+
+ prop = RNA_def_property(srna, "fill_threshold", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.0, 100.0);
+ RNA_def_property_ui_range(prop, 0.0, 1.0, 1, 3);
+ RNA_def_property_float_sdna(prop, NULL, "fill_threshold");
+ RNA_def_property_ui_text(prop, "Fill Threshold", "Threshold above which filling is not propagated");
+ RNA_def_property_update(prop, 0, "rna_Brush_update");
+
+ prop = RNA_def_property(srna, "blur_kernel_radius", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "blur_kernel_radius");
+ RNA_def_property_range(prop, 1, 10000);
+ RNA_def_property_ui_range(prop, 1, 50, 1, -1);
+ RNA_def_property_ui_text(prop, "Kernel Radius", "Radius of kernel used for soften and sharpen in pixels");
+ RNA_def_property_update(prop, 0, "rna_Brush_update");
+
+ prop = RNA_def_property(srna, "blur_mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, brush_blur_mode_items);
+ RNA_def_property_ui_text(prop, "Blur Mode", "");
+ RNA_def_property_update(prop, 0, "rna_Brush_update");
+
/* flag */
prop = RNA_def_property(srna, "use_airbrush", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_AIRBRUSH);
@@ -919,7 +1127,13 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0);
RNA_def_property_ui_text(prop, "Size Pressure", "Enable tablet pressure sensitivity for size");
RNA_def_property_update(prop, 0, "rna_Brush_update");
-
+
+ prop = RNA_def_property(srna, "use_gradient", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_USE_GRADIENT);
+ RNA_def_property_boolean_funcs(prop, NULL, "rna_Brush_use_gradient_set");
+ RNA_def_property_ui_text(prop, "Use Gradient", "Use Gradient by utilizing a sampling method");
+ RNA_def_property_update(prop, 0, "rna_Brush_update");
+
prop = RNA_def_property(srna, "use_pressure_jitter", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_JITTER_PRESSURE);
RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0);
@@ -932,6 +1146,12 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Spacing Pressure", "Enable tablet pressure sensitivity for spacing");
RNA_def_property_update(prop, 0, "rna_Brush_update");
+ prop = RNA_def_property(srna, "use_pressure_masking", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "mask_pressure");
+ RNA_def_property_enum_items(prop, brush_mask_pressure_items);
+ RNA_def_property_ui_text(prop, "Mask Pressure Mode", "Pen pressure makes texture influence smaller");
+ RNA_def_property_update(prop, 0, "rna_Brush_update");
+
prop = RNA_def_property(srna, "use_inverse_smooth_pressure", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_INVERSE_SMOOTH_PRESSURE);
RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0);
@@ -974,6 +1194,16 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Space", "Limit brush application to the distance specified by spacing");
RNA_def_property_update(prop, 0, "rna_Brush_update");
+ prop = RNA_def_property(srna, "use_line", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_LINE);
+ RNA_def_property_ui_text(prop, "Line", "Draw a line with dabs separated according to spacing");
+ RNA_def_property_update(prop, 0, "rna_Brush_update");
+
+ prop = RNA_def_property(srna, "use_curve", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_CURVE);
+ RNA_def_property_ui_text(prop, "Curve", "Define the stroke curve with a bezier curve. Dabs are separated according to spacing");
+ RNA_def_property_update(prop, 0, "rna_Brush_update");
+
prop = RNA_def_property(srna, "use_smooth_stroke", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_SMOOTH_STROKE);
RNA_def_property_ui_text(prop, "Smooth Stroke", "Brush lags behind mouse and follows a smoother path");
@@ -1015,7 +1245,7 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Edge-to-edge", "Drag anchor brush from edge-to-edge");
RNA_def_property_update(prop, 0, "rna_Brush_update");
- prop = RNA_def_property(srna, "use_drag_dot", PROP_BOOLEAN, PROP_NONE);
+ prop = RNA_def_property(srna, "use_restore_mesh", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_DRAG_DOT);
RNA_def_property_ui_text(prop, "Restore Mesh", "Allow a single dot to be carefully positioned");
RNA_def_property_update(prop, 0, "rna_Brush_update");
@@ -1031,6 +1261,28 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Curve", "Editable falloff curve");
RNA_def_property_update(prop, 0, "rna_Brush_update");
+ prop = RNA_def_property(srna, "paint_curve", PROP_POINTER, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Paint Curve", "Active Paint Curve");
+ RNA_def_property_update(prop, 0, "rna_Brush_update");
+
+ prop = RNA_def_property(srna, "gradient", PROP_POINTER, PROP_NEVER_NULL);
+ RNA_def_property_pointer_sdna(prop, NULL, "gradient");
+ RNA_def_property_struct_type(prop, "ColorRamp");
+ RNA_def_property_ui_text(prop, "Gradient", "");
+ RNA_def_property_update(prop, 0, "rna_Brush_update");
+
+ /* gradient source */
+ prop = RNA_def_property(srna, "gradient_stroke_mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, brush_gradient_items);
+ RNA_def_property_ui_text(prop, "Gradient Stroke Mode", "");
+ RNA_def_property_update(prop, 0, "rna_Brush_update");
+
+ prop = RNA_def_property(srna, "gradient_fill_mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, brush_gradient_fill_items);
+ RNA_def_property_ui_text(prop, "Gradient Fill Mode", "");
+ RNA_def_property_update(prop, 0, "rna_Brush_update");
+
/* overlay flags */
prop = RNA_def_property(srna, "use_primary_overlay", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "overlay_flags", BRUSH_OVERLAY_PRIMARY);
@@ -1173,8 +1425,14 @@ static void rna_def_brush(BlenderRNA *brna)
prop = RNA_def_property(srna, "sculpt_capabilities", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_NEVER_NULL);
RNA_def_property_struct_type(prop, "SculptToolCapabilities");
- RNA_def_property_pointer_funcs(prop, "rna_Sculpt_sculpt_tool_capabilities_get", NULL, NULL, NULL);
+ RNA_def_property_pointer_funcs(prop, "rna_Sculpt_tool_capabilities_get", NULL, NULL, NULL);
RNA_def_property_ui_text(prop, "Sculpt Capabilities", "Brush's capabilities in sculpt mode");
+
+ prop = RNA_def_property(srna, "image_paint_capabilities", PROP_POINTER, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_NEVER_NULL);
+ RNA_def_property_struct_type(prop, "ImapaintToolCapabilities");
+ RNA_def_property_pointer_funcs(prop, "rna_Imapaint_tool_capabilities_get", NULL, NULL, NULL);
+ RNA_def_property_ui_text(prop, "Image Painting Capabilities", "Brush's capabilities in image paint mode");
}
@@ -1211,6 +1469,11 @@ static void rna_def_operator_stroke_element(BlenderRNA *brna)
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Pressure", "Tablet pressure");
+ prop = RNA_def_property(srna, "size", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_IDPROPERTY);
+ RNA_def_property_range(prop, 0.0f, FLT_MAX);
+ RNA_def_property_ui_text(prop, "Brush Size", "Brush Size in screen space");
+
prop = RNA_def_property(srna, "pen_flip", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_flag(prop, PROP_IDPROPERTY);
RNA_def_property_ui_text(prop, "Flip", "");
@@ -1237,6 +1500,7 @@ void RNA_def_brush(BlenderRNA *brna)
rna_def_brush(brna);
rna_def_brush_capabilities(brna);
rna_def_sculpt_capabilities(brna);
+ rna_def_image_paint_capabilities(brna);
rna_def_brush_texture_slot(brna);
rna_def_operator_stroke_element(brna);
}
diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c
index fdba76e9aa2..4db873423f6 100644
--- a/source/blender/makesrna/intern/rna_color.c
+++ b/source/blender/makesrna/intern/rna_color.c
@@ -176,7 +176,7 @@ static char *rna_ColorRamp_path(PointerRNA *ptr)
char *node_path;
for (node = ntree->nodes.first; node; node = node->next) {
- if (ELEM3(node->type, SH_NODE_VALTORGB, CMP_NODE_VALTORGB, TEX_NODE_VALTORGB)) {
+ if (ELEM(node->type, SH_NODE_VALTORGB, CMP_NODE_VALTORGB, TEX_NODE_VALTORGB)) {
if (node->storage == ptr->data) {
/* all node color ramp properties called 'color_ramp'
* prepend path from ID to the node
@@ -265,7 +265,7 @@ static char *rna_ColorRampElement_path(PointerRNA *ptr)
bNode *node;
for (node = ntree->nodes.first; node; node = node->next) {
- if (ELEM3(node->type, SH_NODE_VALTORGB, CMP_NODE_VALTORGB, TEX_NODE_VALTORGB)) {
+ if (ELEM(node->type, SH_NODE_VALTORGB, CMP_NODE_VALTORGB, TEX_NODE_VALTORGB)) {
RNA_pointer_create(id, &RNA_ColorRamp, node->storage, &ramp_ptr);
COLRAMP_GETPATH;
}
@@ -324,7 +324,7 @@ static void rna_ColorRamp_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *
bNode *node;
for (node = ntree->nodes.first; node; node = node->next) {
- if (ELEM3(node->type, SH_NODE_VALTORGB, CMP_NODE_VALTORGB, TEX_NODE_VALTORGB)) {
+ if (ELEM(node->type, SH_NODE_VALTORGB, CMP_NODE_VALTORGB, TEX_NODE_VALTORGB)) {
ED_node_tag_update_nodetree(bmain, ntree);
}
}
diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c
index 120992cffe8..5519b192ca4 100644
--- a/source/blender/makesrna/intern/rna_constraint.c
+++ b/source/blender/makesrna/intern/rna_constraint.c
@@ -351,7 +351,7 @@ static void rna_ActionConstraint_minmax_range(PointerRNA *ptr, float *min, float
bActionConstraint *acon = (bActionConstraint *)con->data;
/* 0, 1, 2 = magic numbers for rotX, rotY, rotZ */
- if (ELEM3(acon->type, 0, 1, 2)) {
+ if (ELEM(acon->type, 0, 1, 2)) {
*min = -180.0f;
*max = 180.0f;
}
@@ -2452,6 +2452,12 @@ static void rna_def_constraint_follow_track(BlenderRNA *brna)
RNA_def_property_enum_items(prop, frame_method_items);
RNA_def_property_ui_text(prop, "Frame Method", "How the footage fits in the camera frame");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_dependency_update");
+
+ /* use undistortion */
+ prop = RNA_def_property(srna, "use_undistorted_position", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", FOLLOWTRACK_USE_UNDISTORTION);
+ RNA_def_property_ui_text(prop, "Undistort", "Parent to undistorted position of 2D track");
+ RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
}
static void rna_def_constraint_camera_solver(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h
index be275058957..83b7a81c649 100644
--- a/source/blender/makesrna/intern/rna_internal.h
+++ b/source/blender/makesrna/intern/rna_internal.h
@@ -202,6 +202,7 @@ void rna_def_texmat_common(struct StructRNA *srna, const char *texspace_editable
void rna_def_mtex_common(struct BlenderRNA *brna, struct StructRNA *srna, const char *begin, const char *activeget,
const char *activeset, const char *activeeditable, const char *structname,
const char *structname_slots, const char *update, const char *update_index);
+void rna_def_texpaint_slots(struct BlenderRNA *brna, struct StructRNA *srna);
void rna_def_render_layer_common(struct StructRNA *srna, int scene);
void rna_def_actionbone_group_common(struct StructRNA *srna, int update_flag, const char *update_cb);
@@ -412,4 +413,24 @@ void rna_RenderPass_rect_set(PointerRNA *ptr, const float *values);
# endif
#endif
+/* C11 for compile time range checks */
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
+# define USE_RNA_RANGE_CHECK
+# define TYPEOF_MAX(x) \
+ _Generic((x), \
+ bool: 1, \
+ char: CHAR_MAX, signed char: SCHAR_MAX, unsigned char: UCHAR_MAX, \
+ signed short: SHRT_MAX, unsigned short: USHRT_MAX, \
+ signed int: INT_MAX, unsigned int: UINT_MAX, \
+ float: FLT_MAX, double: DBL_MAX)
+
+# define TYPEOF_MIN(x) \
+ _Generic((x), \
+ bool: 0, \
+ char: CHAR_MIN, signed char: SCHAR_MIN, unsigned char: 0, \
+ signed short: SHRT_MIN, unsigned short: 0, \
+ signed int: INT_MIN, unsigned int: 0, \
+ float: -FLT_MAX, double: -DBL_MAX)
+#endif
+
#endif /* __RNA_INTERNAL_H__ */
diff --git a/source/blender/makesrna/intern/rna_linestyle.c b/source/blender/makesrna/intern/rna_linestyle.c
index 3ede815b5b1..50b888b0247 100644
--- a/source/blender/makesrna/intern/rna_linestyle.c
+++ b/source/blender/makesrna/intern/rna_linestyle.c
@@ -500,7 +500,7 @@ static void rna_def_linestyle_mtex(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_tips", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "texflag", MTEX_TIPS);
- RNA_def_property_ui_text(prop, "Use tips", "Lower half of the texture is for tips of the stroke");
+ RNA_def_property_ui_text(prop, "Use Tips", "Lower half of the texture is for tips of the stroke");
RNA_def_property_update(prop, 0, "rna_LineStyle_update");
prop = RNA_def_property(srna, "texture_coords", PROP_ENUM, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_material.c b/source/blender/makesrna/intern/rna_material.c
index 7ae15b0b06c..70da4ab0fa0 100644
--- a/source/blender/makesrna/intern/rna_material.c
+++ b/source/blender/makesrna/intern/rna_material.c
@@ -82,6 +82,8 @@ EnumPropertyItem ramp_blend_items[] = {
#include "DNA_node_types.h"
#include "DNA_object_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
#include "BKE_context.h"
#include "BKE_depsgraph.h"
@@ -92,6 +94,8 @@ EnumPropertyItem ramp_blend_items[] = {
#include "BKE_paint.h"
#include "ED_node.h"
+#include "ED_image.h"
+#include "BKE_scene.h"
static void rna_Material_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
@@ -165,6 +169,50 @@ static void rna_Material_mtex_begin(CollectionPropertyIterator *iter, PointerRNA
rna_iterator_array_begin(iter, (void *)ma->mtex, sizeof(MTex *), MAX_MTEX, 0, NULL);
}
+static void rna_Material_texpaint_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
+{
+ Material *ma = (Material *)ptr->data;
+ rna_iterator_array_begin(iter, (void *)ma->texpaintslot, sizeof(TexPaintSlot), ma->tot_slots, 0, NULL);
+}
+
+
+static void rna_Material_active_paint_texture_index_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ bScreen *sc;
+ Material *ma = ptr->id.data;
+
+
+ if (ma->use_nodes && ma->nodetree && BKE_scene_use_new_shading_nodes(scene)) {
+ struct bNode *node;
+ int index = 0;
+ for (node = ma->nodetree->nodes.first; node; node = node->next) {
+ if (node->typeinfo->nclass == NODE_CLASS_TEXTURE && node->typeinfo->type == SH_NODE_TEX_IMAGE && node->id) {
+ if (index++ == ma->paint_active_slot) {
+ break;
+ }
+ }
+ }
+ if (node)
+ nodeSetActive(ma->nodetree, node);
+ }
+
+ 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) {
+ if (sl->spacetype == SPACE_IMAGE) {
+ SpaceImage *sima = (SpaceImage *)sl;
+ ED_space_image_set(sima, scene, scene->obedit, ma->texpaintslot[ma->paint_active_slot].ima);
+ }
+ }
+ }
+ }
+
+ DAG_id_tag_update(&ma->id, 0);
+ WM_main_add_notifier(NC_MATERIAL | ND_SHADING, ma);
+}
+
static PointerRNA rna_Material_active_texture_get(PointerRNA *ptr)
{
Material *ma = (Material *)ptr->data;
@@ -307,7 +355,7 @@ static EnumPropertyItem *rna_Material_texture_coordinates_itemf(bContext *UNUSED
if (ma->material_type == MA_TYPE_VOLUME) {
}
- else if (ELEM3(ma->material_type, MA_TYPE_SURFACE, MA_TYPE_HALO, MA_TYPE_WIRE)) {
+ else if (ELEM(ma->material_type, MA_TYPE_SURFACE, MA_TYPE_HALO, MA_TYPE_WIRE)) {
RNA_enum_items_add_value(&item, &totitem, prop_texture_coordinates_items, TEXCO_UV);
RNA_enum_items_add_value(&item, &totitem, prop_texture_coordinates_items, TEXCO_STRAND);
RNA_enum_items_add_value(&item, &totitem, prop_texture_coordinates_items, TEXCO_WINDOW);
@@ -2059,6 +2107,8 @@ void RNA_def_material(BlenderRNA *brna)
"rna_Material_active_texture_set", "rna_Material_active_texture_editable",
"MaterialTextureSlot", "MaterialTextureSlots", "rna_Material_update", "rna_Material_update");
+ rna_def_texpaint_slots(brna, srna);
+
/* only material has this one */
prop = RNA_def_property(srna, "use_textures", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "septex", 1);
@@ -2147,4 +2197,53 @@ void rna_def_mtex_common(BlenderRNA *brna, StructRNA *srna, const char *begin,
RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING_LINKS, update_index);
}
+static void rna_def_tex_slot(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "TexPaintSlot", NULL);
+ RNA_def_struct_ui_text(srna, "Texture Paint Slot",
+ "Slot that contains information about texture painting");
+
+ prop = RNA_def_property(srna, "uv_layer", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_maxlength(prop, 64); /* else it uses the pointer size! */
+ RNA_def_property_string_sdna(prop, NULL, "uvname");
+ RNA_def_property_ui_text(prop, "UV Map", "Name of UV map");
+ RNA_def_property_update(prop, NC_GEOM | ND_DATA, "rna_Material_update");
+
+}
+
+
+void rna_def_texpaint_slots(BlenderRNA *brna, StructRNA *srna)
+{
+ PropertyRNA *prop;
+
+ rna_def_tex_slot(brna);
+
+ /* mtex */
+ prop = RNA_def_property(srna, "texture_paint_images", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "texpaintslot", NULL);
+ RNA_def_property_collection_funcs(prop, "rna_Material_texpaint_begin", "rna_iterator_array_next", "rna_iterator_array_end",
+ "rna_iterator_array_dereference_get", NULL, NULL, NULL, NULL);
+ RNA_def_property_struct_type(prop, "Image");
+ RNA_def_property_ui_text(prop, "Texture Slot Images", "Texture images used for texture painting");
+
+ prop = RNA_def_property(srna, "texture_paint_slots", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_funcs(prop, "rna_Material_texpaint_begin", "rna_iterator_array_next", "rna_iterator_array_end",
+ "rna_iterator_array_get", NULL, NULL, NULL, NULL);
+ RNA_def_property_struct_type(prop, "TexPaintSlot");
+ RNA_def_property_ui_text(prop, "Texture Slots", "Texture slots defining the mapping and influence of textures");
+
+ prop = RNA_def_property(srna, "paint_active_slot", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_range(prop, 0, SHRT_MAX);
+ RNA_def_property_ui_text(prop, "Active Paint Texture Index", "Index of active texture paint slot");
+ RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING_LINKS, "rna_Material_active_paint_texture_index_update");
+
+ prop = RNA_def_property(srna, "paint_clone_slot", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_range(prop, 0, SHRT_MAX);
+ RNA_def_property_ui_text(prop, "Clone Paint Texture Index", "Index of clone texture paint slot");
+ RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING_LINKS, NULL);
+}
+
#endif
diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c
index 8c0f9980108..b0b99dcd2ca 100644
--- a/source/blender/makesrna/intern/rna_mesh.c
+++ b/source/blender/makesrna/intern/rna_mesh.c
@@ -3121,11 +3121,13 @@ static void rna_def_mesh(BlenderRNA *brna)
"rna_Mesh_uv_texture_stencil_set", NULL, NULL);
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Mask UV Map", "UV map to mask the painted area");
+ RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
prop = RNA_def_property(srna, "uv_texture_stencil_index", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_funcs(prop, "rna_Mesh_uv_texture_stencil_index_get",
"rna_Mesh_uv_texture_stencil_index_set", "rna_Mesh_uv_texture_index_range");
RNA_def_property_ui_text(prop, "Mask UV Map Index", "Mask UV map index");
+ RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
/* Tessellated face colors - used by renderers */
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index 065b6f787b6..8a177c6e2f9 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -6187,6 +6187,27 @@ static void def_cmp_planetrackdeform(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
+static void def_cmp_sunbeams(StructRNA *srna)
+{
+ PropertyRNA *prop;
+
+ RNA_def_struct_sdna_from(srna, "NodeSunBeams", "storage");
+
+ prop = RNA_def_property(srna, "source", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "source");
+ RNA_def_property_range(prop, -100.0f, 100.0f);
+ RNA_def_property_ui_range(prop, -10.0f, 10.0f, 10, 3);
+ RNA_def_property_ui_text(prop, "Source", "Source point of rays as a factor of the image width & height");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+
+ prop = RNA_def_property(srna, "ray_length", PROP_FLOAT, PROP_UNSIGNED);
+ RNA_def_property_float_sdna(prop, NULL, "ray_length");
+ RNA_def_property_range(prop, 0.0f, 100.0f);
+ RNA_def_property_ui_range(prop, 0.0f, 1.0f, 10, 3);
+ RNA_def_property_ui_text(prop, "Ray Length", "Length of rays as a factor of the image size");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+}
+
/* -- Texture Nodes --------------------------------------------------------- */
static void def_tex_output(StructRNA *srna)
diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c
index 0f37575146b..925672071bb 100644
--- a/source/blender/makesrna/intern/rna_object_force.c
+++ b/source/blender/makesrna/intern/rna_object_force.c
@@ -598,9 +598,11 @@ static char *rna_FieldSettings_path(PointerRNA *ptr)
static void rna_EffectorWeight_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- DAG_id_tag_update((ID *)ptr->id.data, OB_RECALC_DATA | PSYS_RECALC_RESET);
+ Scene *scene = (Scene *)ptr->id.data;
+ Base *base;
- WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL);
+ for (base = scene->base.first; base; base = base->next)
+ BKE_ptcache_object_reset(scene, base->object, PTCACHE_RESET_DEPSGRAPH);
}
static void rna_EffectorWeight_dependency_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
@@ -733,7 +735,7 @@ static EnumPropertyItem *rna_Effector_shape_itemf(bContext *UNUSED(C), PointerRN
return curve_shape_items;
}
- else if (ELEM3(ob->type, OB_MESH, OB_SURF, OB_FONT)) {
+ else if (ELEM(ob->type, OB_MESH, OB_SURF, OB_FONT)) {
if (ob->pd->forcefield == PFIELD_VORTEX)
return vortex_shape_items;
diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c
index 674ea92fcbe..0e56b184990 100644
--- a/source/blender/makesrna/intern/rna_particle.c
+++ b/source/blender/makesrna/intern/rna_particle.c
@@ -432,25 +432,24 @@ static EnumPropertyItem *rna_Particle_Material_itemf(bContext *C, PointerRNA *UN
return item;
}
-static void rna_ParticleSystem_uv_on_emitter(ParticleSystem *particlesystem, ReportList *reports,
- ParticleSystemModifierData *modifier, ParticleData *particle,
- int particle_no, int uv_no,
- float r_uv[2])
+/* return < 0 means invalid (no matching tessellated face could be found). */
+static int rna_ParticleSystem_tessfaceidx_on_emitter(ParticleSystem *particlesystem,
+ ParticleSystemModifierData *modifier, ParticleData *particle,
+ int particle_no, float (**r_fuv)[4])
{
ParticleSettings *part = 0;
int totpart;
int totchild = 0;
- int num;
+ int totface;
+ int num = -1;
- if (!CustomData_has_layer(&modifier->dm->loopData, CD_MLOOPUV)) {
- BKE_report(reports, RPT_ERROR, "Mesh has no UV data");
- return;
- }
DM_ensure_tessface(modifier->dm); /* BMESH - UNTIL MODIFIER IS UPDATED FOR MPoly */
+ totface = modifier->dm->getNumTessFaces(modifier->dm);
/* 1. check that everything is ok & updated */
- if (particlesystem == NULL)
- return;
+ if (!particlesystem || !totface) {
+ return num;
+ }
part = particlesystem->part;
@@ -468,52 +467,31 @@ static void rna_ParticleSystem_uv_on_emitter(ParticleSystem *particlesystem, Rep
totpart = particlesystem->totpart;
if (particle_no >= totpart + totchild)
- return;
+ return num;
-/* 3. start creating renderable things */
- /* setup per particle individual stuff */
+ /* 2. get matching face index. */
if (particle_no < totpart) {
-
- /* get uvco & mcol */
- num = (ELEM(particle->num_dmcache, DMCACHE_ISCHILD, DMCACHE_NOTFOUND)) ?
- particle->num : particle->num_dmcache;
+ num = (ELEM(particle->num_dmcache, DMCACHE_ISCHILD, DMCACHE_NOTFOUND)) ? particle->num : particle->num_dmcache;
if (num == DMCACHE_NOTFOUND)
- if (particle->num < modifier->dm->getNumTessFaces(modifier->dm))
- num = particle->num;
+ num = particle->num;
- if (r_uv && ELEM(part->from, PART_FROM_FACE, PART_FROM_VOLUME)) {
- if (num != DMCACHE_NOTFOUND) {
- MFace *mface = modifier->dm->getTessFaceData(modifier->dm, num, CD_MFACE);
- MTFace *mtface = (MTFace *)CustomData_get_layer_n(&modifier->dm->faceData, CD_MTFACE, uv_no);
- mtface += num;
-
- psys_interpolate_uvs(mtface, mface->v4, particle->fuv, r_uv);
- }
- else {
- r_uv[0] = 0.0f;
- r_uv[1] = 0.0f;
+ if (ELEM(part->from, PART_FROM_FACE, PART_FROM_VOLUME)) {
+ if (num != DMCACHE_NOTFOUND && num < totface) {
+ *r_fuv = &particle->fuv;
+ return num;
}
}
}
else {
ChildParticle *cpa = particlesystem->child + particle_no - totpart;
-
num = cpa->num;
- /* get uvco & mcol */
if (part->childtype == PART_CHILD_FACES) {
- if (r_uv && ELEM(PART_FROM_FACE, PART_FROM_FACE, PART_FROM_VOLUME)) {
- if (cpa->num != DMCACHE_NOTFOUND) {
- MFace *mface = modifier->dm->getTessFaceData(modifier->dm, cpa->num, CD_MFACE);
- MTFace *mtface = (MTFace *)CustomData_get_layer_n(&modifier->dm->faceData, CD_MTFACE, uv_no);
- mtface += cpa->num;
-
- psys_interpolate_uvs(mtface, mface->v4, cpa->fuv, r_uv);
- }
- else {
- r_uv[0] = 0.0f;
- r_uv[1] = 0.0f;
+ if (ELEM(PART_FROM_FACE, PART_FROM_FACE, PART_FROM_VOLUME)) {
+ if (num != DMCACHE_NOTFOUND && num < totface) {
+ *r_fuv = &cpa->fuv;
+ return num;
}
}
}
@@ -522,137 +500,78 @@ static void rna_ParticleSystem_uv_on_emitter(ParticleSystem *particlesystem, Rep
num = parent->num_dmcache;
if (num == DMCACHE_NOTFOUND)
- if (parent->num < modifier->dm->getNumTessFaces(modifier->dm))
- num = parent->num;
-
- if (r_uv && ELEM(part->from, PART_FROM_FACE, PART_FROM_VOLUME)) {
- if (num != DMCACHE_NOTFOUND) {
- MFace *mface = modifier->dm->getTessFaceData(modifier->dm, num, CD_MFACE);
- MTFace *mtface = (MTFace *)CustomData_get_layer_n(&modifier->dm->faceData, CD_MTFACE, uv_no);
- mtface += num;
-
- psys_interpolate_uvs(mtface, mface->v4, parent->fuv, r_uv);
- }
- else {
- r_uv[0] = 0.0f;
- r_uv[1] = 0.0f;
+ num = parent->num;
+
+ if (ELEM(part->from, PART_FROM_FACE, PART_FROM_VOLUME)) {
+ if (num != DMCACHE_NOTFOUND && num < totface) {
+ *r_fuv = &parent->fuv;
+ return num;
}
}
}
}
+
+ return -1;
}
-static void rna_ParticleSystem_mcol_on_emitter(ParticleSystem *particlesystem, ParticleSystemModifierData *modifier,
- ParticleData *particle, int particle_no, int vcol_no,
- float n_mcol[3])
+static void rna_ParticleSystem_uv_on_emitter(ParticleSystem *particlesystem, ReportList *reports,
+ ParticleSystemModifierData *modifier, ParticleData *particle,
+ int particle_no, int uv_no, float r_uv[2])
{
- ParticleSettings *part;
- int totpart;
- int totchild = 0;
- int num;
- MCol mcol = {255, 255, 255, 255};
-
- /* 1. check that everything is ok & updated */
- if (particlesystem == NULL)
+ if (!CustomData_has_layer(&modifier->dm->loopData, CD_MLOOPUV)) {
+ BKE_report(reports, RPT_ERROR, "Mesh has no UV data");
+ zero_v2(r_uv);
return;
-
- part = particlesystem->part;
-
- if (particlesystem->renderdata) {
- totchild = particlesystem->totchild;
- }
- else {
- totchild = (int)((float)particlesystem->totchild * (float)(part->disp) / 100.0f);
}
- /* can happen for disconnected/global hair */
- if (part->type == PART_HAIR && !particlesystem->childcache)
- totchild = 0;
-
- totpart = particlesystem->totpart;
-
- if (particle_no >= totpart + totchild)
- return;
-
- /* 3. start creating renderable things */
- /* setup per particle individual stuff */
- if (particle_no < totpart) {
+ {
+ float (*fuv)[4];
+ /* Note all sanity checks are done in this helper func. */
+ const int num = rna_ParticleSystem_tessfaceidx_on_emitter(particlesystem, modifier, particle,
+ particle_no, &fuv);
- /* get uvco & mcol */
- num = particle->num_dmcache;
+ if (num < 0) {
+ /* No matching face found. */
+ zero_v2(r_uv);
+ }
+ else {
+ MFace *mface = modifier->dm->getTessFaceData(modifier->dm, num, CD_MFACE);
+ MTFace *mtface = (MTFace *)CustomData_get_layer_n(&modifier->dm->faceData, CD_MTFACE, uv_no);
- if (num == DMCACHE_NOTFOUND)
- if (particle->num < modifier->dm->getNumTessFaces(modifier->dm))
- num = particle->num;
-
- if (n_mcol && ELEM(part->from, PART_FROM_FACE, PART_FROM_VOLUME)) {
- if (num != DMCACHE_NOTFOUND) {
- MFace *mface = modifier->dm->getTessFaceData(modifier->dm, num, CD_MFACE);
- MCol *mc = (MCol *)CustomData_get_layer_n(&modifier->dm->faceData, CD_MCOL, vcol_no);
- mc += num * 4;
-
- psys_interpolate_mcol(mc, mface->v4, particle->fuv, &mcol);
- n_mcol[0] = (float)mcol.b / 255.0f;
- n_mcol[1] = (float)mcol.g / 255.0f;
- n_mcol[2] = (float)mcol.r / 255.0f;
- }
- else {
- n_mcol[0] = 0.0f;
- n_mcol[1] = 0.0f;
- n_mcol[2] = 0.0f;
- }
+ psys_interpolate_uvs(&mtface[num], mface->v4, *fuv, r_uv);
}
}
- else {
- ChildParticle *cpa = particlesystem->child + particle_no - totpart;
+}
- num = cpa->num;
+static void rna_ParticleSystem_mcol_on_emitter(ParticleSystem *particlesystem, ReportList *reports,
+ ParticleSystemModifierData *modifier, ParticleData *particle,
+ int particle_no, int vcol_no, float r_mcol[3])
+{
+ if (!CustomData_has_layer(&modifier->dm->loopData, CD_MLOOPCOL)) {
+ BKE_report(reports, RPT_ERROR, "Mesh has no VCol data");
+ zero_v3(r_mcol);
+ return;
+ }
- /* get uvco & mcol */
- if (part->childtype == PART_CHILD_FACES) {
- if (n_mcol && ELEM(PART_FROM_FACE, PART_FROM_FACE, PART_FROM_VOLUME)) {
- if (cpa->num != DMCACHE_NOTFOUND) {
- MFace *mface = modifier->dm->getTessFaceData(modifier->dm, cpa->num, CD_MFACE);
- MCol *mc = (MCol *)CustomData_get_layer_n(&modifier->dm->faceData, CD_MCOL, vcol_no);
- mc += cpa->num * 4;
-
- psys_interpolate_mcol(mc, mface->v4, cpa->fuv, &mcol);
- n_mcol[0] = (float)mcol.b / 255.0f;
- n_mcol[1] = (float)mcol.g / 255.0f;
- n_mcol[2] = (float)mcol.r / 255.0f;
- }
- else {
- n_mcol[0] = 0.0f;
- n_mcol[1] = 0.0f;
- n_mcol[2] = 0.0f;
- }
- }
+ {
+ float (*fuv)[4];
+ /* Note all sanity checks are done in this helper func. */
+ const int num = rna_ParticleSystem_tessfaceidx_on_emitter(particlesystem, modifier, particle,
+ particle_no, &fuv);
+
+ if (num < 0) {
+ /* No matching face found. */
+ zero_v3(r_mcol);
}
else {
- ParticleData *parent = particlesystem->particles + cpa->parent;
- num = parent->num_dmcache;
-
- if (num == DMCACHE_NOTFOUND)
- if (parent->num < modifier->dm->getNumTessFaces(modifier->dm))
- num = parent->num;
-
- if (n_mcol && ELEM(part->from, PART_FROM_FACE, PART_FROM_VOLUME)) {
- if (num != DMCACHE_NOTFOUND) {
- MFace *mface = modifier->dm->getTessFaceData(modifier->dm, num, CD_MFACE);
- MCol *mc = (MCol *)CustomData_get_layer_n(&modifier->dm->faceData, CD_MCOL, vcol_no);
- mc += num * 4;
-
- psys_interpolate_mcol(mc, mface->v4, parent->fuv, &mcol);
- n_mcol[0] = (float)mcol.b / 255.0f;
- n_mcol[1] = (float)mcol.g / 255.0f;
- n_mcol[2] = (float)mcol.r / 255.0f;
- }
- else {
- n_mcol[0] = 0.0f;
- n_mcol[1] = 0.0f;
- n_mcol[2] = 0.0f;
- }
- }
+ MFace *mface = modifier->dm->getTessFaceData(modifier->dm, num, CD_MFACE);
+ MCol *mc = (MCol *)CustomData_get_layer_n(&modifier->dm->faceData, CD_MCOL, vcol_no);
+ MCol mcol;
+
+ psys_interpolate_mcol(&mc[num * 4], mface->v4, *fuv, &mcol);
+ r_mcol[0] = (float)mcol.b / 255.0f;
+ r_mcol[1] = (float)mcol.g / 255.0f;
+ r_mcol[2] = (float)mcol.r / 255.0f;
}
}
}
@@ -2520,7 +2439,7 @@ static void rna_def_particle_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "simplify_refsize", PROP_INT, PROP_PIXEL);
RNA_def_property_int_sdna(prop, NULL, "simplify_refsize");
- RNA_def_property_range(prop, 1, 32768);
+ RNA_def_property_range(prop, 1, SHRT_MAX);
RNA_def_property_ui_text(prop, "Reference Size", "Reference size in pixels, after which simplification begins");
prop = RNA_def_property(srna, "simplify_rate", PROP_FLOAT, PROP_NONE);
@@ -3496,6 +3415,7 @@ static void rna_def_particle_system(BlenderRNA *brna)
/* extract hair mcols */
func = RNA_def_function(srna, "mcol_on_emitter", "rna_ParticleSystem_mcol_on_emitter");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
RNA_def_function_ui_description(func, "Obtain mcol for all particles");
prop = RNA_def_pointer(func, "modifier", "ParticleSystemModifier", "", "Particle modifier");
RNA_def_property_flag(prop, PROP_REQUIRED | PROP_NEVER_NULL);
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 06c39938f30..3dafd00d3f5 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -880,7 +880,7 @@ static EnumPropertyItem *rna_ImageFormatSettings_color_depth_itemf(bContext *UNU
}
else {
const int depth_ok = BKE_imtype_valid_depths(imf->imtype);
- const int is_float = ELEM3(imf->imtype, R_IMF_IMTYPE_RADHDR, R_IMF_IMTYPE_OPENEXR, R_IMF_IMTYPE_MULTILAYER);
+ const int is_float = ELEM(imf->imtype, R_IMF_IMTYPE_RADHDR, R_IMF_IMTYPE_OPENEXR, R_IMF_IMTYPE_MULTILAYER);
EnumPropertyItem *item_8bit = &image_color_depth_items[0];
EnumPropertyItem *item_10bit = &image_color_depth_items[1];
@@ -1316,7 +1316,7 @@ static void object_simplify_update(Object *ob)
ob->id.flag &= ~LIB_DOIT;
for (md = ob->modifiers.first; md; md = md->next) {
- if (ELEM3(md->type, eModifierType_Subsurf, eModifierType_Multires, eModifierType_ParticleSystem)) {
+ if (ELEM(md->type, eModifierType_Subsurf, eModifierType_Multires, eModifierType_ParticleSystem)) {
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
}
@@ -2121,6 +2121,11 @@ static void rna_def_unified_paint_settings(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Use Unified Weight",
"Instead of per-brush weight, the weight is shared across brushes");
+ prop = RNA_def_property(srna, "use_unified_color", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", UNIFIED_PAINT_COLOR);
+ RNA_def_property_ui_text(prop, "Use Unified Color",
+ "Instead of per-brush color, the color is shared across brushes");
+
/* unified paint settings that override the equivalent settings
* from the active brush */
prop = RNA_def_property(srna, "size", PROP_INT, PROP_PIXEL);
@@ -2153,6 +2158,18 @@ static void rna_def_unified_paint_settings(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Weight", "Weight to assign in vertex groups");
RNA_def_property_update(prop, 0, "rna_UnifiedPaintSettings_update");
+ prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_range(prop, 0.0, 1.0);
+ RNA_def_property_float_sdna(prop, NULL, "rgb");
+ RNA_def_property_ui_text(prop, "Color", "");
+ RNA_def_property_update(prop, 0, "rna_UnifiedPaintSettings_update");
+
+ prop = RNA_def_property(srna, "secondary_color", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_range(prop, 0.0, 1.0);
+ RNA_def_property_float_sdna(prop, NULL, "secondary_rgb");
+ RNA_def_property_ui_text(prop, "Secondary Color", "");
+ RNA_def_property_update(prop, 0, "rna_UnifiedPaintSettings_update");
+
prop = RNA_def_property(srna, "use_pressure_size", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", UNIFIED_PAINT_BRUSH_SIZE_PRESSURE);
RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0);
@@ -5622,7 +5639,7 @@ void RNA_def_scene(BlenderRNA *brna)
prop = RNA_def_property(srna, "gravity", PROP_FLOAT, PROP_ACCELERATION);
RNA_def_property_float_sdna(prop, NULL, "physics_settings.gravity");
RNA_def_property_array(prop, 3);
- RNA_def_property_range(prop, -200.0f, 200.0f);
+ RNA_def_property_ui_range(prop, -200.0f, 200.0f, 1, 2);
RNA_def_property_ui_text(prop, "Gravity", "Constant acceleration in a given direction");
RNA_def_property_update(prop, 0, "rna_Physics_update");
diff --git a/source/blender/makesrna/intern/rna_sculpt_paint.c b/source/blender/makesrna/intern/rna_sculpt_paint.c
index a3a06893522..af6cf493f1e 100644
--- a/source/blender/makesrna/intern/rna_sculpt_paint.c
+++ b/source/blender/makesrna/intern/rna_sculpt_paint.c
@@ -285,8 +285,67 @@ static void rna_Paint_brush_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Po
BKE_paint_invalidate_overlay_all();
WM_main_add_notifier(NC_BRUSH | NA_EDITED, br);
}
+
+static void rna_ImaPaint_stencil_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
+{
+ /* not the best solution maybe, but will refresh the 3D viewport */
+ WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL);
+}
#else
+static void rna_def_palettecolor(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "PaletteColor", NULL);
+ RNA_def_struct_ui_text(srna, "Palette Color", "");
+
+ prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_range(prop, 0.0, 1.0);
+ RNA_def_property_float_sdna(prop, NULL, "rgb");
+ RNA_def_property_ui_text(prop, "Color", "");
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
+
+ prop = RNA_def_property(srna, "strength", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.0, 1.0);
+ RNA_def_property_float_sdna(prop, NULL, "value");
+ RNA_def_property_ui_text(prop, "Value", "");
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
+
+ prop = RNA_def_property(srna, "weight", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.0, 1.0);
+ RNA_def_property_float_sdna(prop, NULL, "value");
+ RNA_def_property_ui_text(prop, "Weight", "");
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
+}
+
+
+static void rna_def_palette(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "Palette", "ID");
+ RNA_def_struct_ui_text(srna, "Palette", "");
+ RNA_def_struct_ui_icon(srna, ICON_COLOR);
+
+ prop = RNA_def_property(srna, "colors", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_struct_type(prop, "PaletteColor");
+ RNA_def_property_ui_text(prop, "Palette Color", "Colors that are part of this palette");
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
+}
+
+static void rna_def_paint_curve(BlenderRNA *brna)
+{
+ StructRNA *srna;
+
+ srna = RNA_def_struct(brna, "PaintCurve", "ID");
+ RNA_def_struct_ui_text(srna, "Paint Curve", "");
+ RNA_def_struct_ui_icon(srna, ICON_CURVE_BEZCURVE);
+}
+
+
static void rna_def_paint(BlenderRNA *brna)
{
StructRNA *srna;
@@ -302,6 +361,11 @@ static void rna_def_paint(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Brush", "Active Brush");
RNA_def_property_update(prop, 0, "rna_Paint_brush_update");
+ prop = RNA_def_property(srna, "palette", PROP_POINTER, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, NULL);
+ RNA_def_property_ui_text(prop, "Palette", "Active Palette");
+
prop = RNA_def_property(srna, "show_brush", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", PAINT_SHOW_BRUSH);
RNA_def_property_ui_text(prop, "Show Brush", "");
@@ -532,12 +596,24 @@ static void rna_def_image_paint(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_stencil_layer", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", IMAGEPAINT_PROJECT_LAYER_STENCIL);
RNA_def_property_ui_text(prop, "Stencil Layer", "Set the mask layer from the UV map buttons");
- RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_ImaPaint_stencil_update");
prop = RNA_def_property(srna, "invert_stencil", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", IMAGEPAINT_PROJECT_LAYER_STENCIL_INV);
RNA_def_property_ui_text(prop, "Invert", "Invert the stencil layer");
- RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_ImaPaint_stencil_update");
+
+ prop = RNA_def_property(srna, "stencil_image", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "stencil");
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Stencil Image", "Image used as stencil");
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_ImaPaint_stencil_update");
+
+ prop = RNA_def_property(srna, "stencil_color", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_range(prop, 0.0, 1.0);
+ RNA_def_property_float_sdna(prop, NULL, "stencil_col");
+ RNA_def_property_ui_text(prop, "Stencil Color", "Stencil color in the viewport");
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_ImaPaint_stencil_update");
prop = RNA_def_property(srna, "use_clone_layer", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", IMAGEPAINT_PROJECT_LAYER_CLONE);
@@ -741,6 +817,9 @@ void RNA_def_sculpt_paint(BlenderRNA *brna)
{
/* *** Non-Animated *** */
RNA_define_animate_sdna(false);
+ rna_def_palettecolor(brna);
+ rna_def_palette(brna);
+ rna_def_paint_curve(brna);
rna_def_paint(brna);
rna_def_sculpt(brna);
rna_def_uv_sculpt(brna);
diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c
index ddae8b2a01a..00f0a6ff487 100644
--- a/source/blender/makesrna/intern/rna_sequencer.c
+++ b/source/blender/makesrna/intern/rna_sequencer.c
@@ -539,6 +539,8 @@ static StructRNA *rna_Sequence_refine(struct PointerRNA *ptr)
return &RNA_ColorSequence;
case SEQ_TYPE_SPEED:
return &RNA_SpeedControlSequence;
+ case SEQ_TYPE_GAUSSIAN_BLUR:
+ return &RNA_GaussianBlurSequence;
default:
return &RNA_Sequence;
}
@@ -1374,6 +1376,7 @@ static void rna_def_sequence(BlenderRNA *brna)
{SEQ_TYPE_SPEED, "SPEED", 0, "Speed", ""},
{SEQ_TYPE_MULTICAM, "MULTICAM", 0, "Multicam Selector", ""},
{SEQ_TYPE_ADJUSTMENT, "ADJUSTMENT", 0, "Adjustment Layer", ""},
+ {SEQ_TYPE_GAUSSIAN_BLUR, "GAUSSIAN_BLUR", 0, "Gaussian Blur", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -2203,6 +2206,23 @@ static void rna_def_speed_control(StructRNA *srna)
RNA_def_property_boolean_sdna(prop, NULL, "flags", SEQ_SPEED_COMPRESS_IPO_Y);
RNA_def_property_ui_text(prop, "Scale to length", "Scale values from 0.0 to 1.0 to target sequence length");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+
+}
+
+static void rna_def_gaussian_blur(StructRNA *srna)
+{
+ PropertyRNA *prop;
+
+ RNA_def_struct_sdna_from(srna, "GaussianBlurVars", "effectdata");
+ prop = RNA_def_property(srna, "size_x", PROP_FLOAT, PROP_UNSIGNED);
+ RNA_def_property_ui_text(prop, "Size X", "Size of the blur along X axis");
+ RNA_def_property_ui_range(prop, 0.0f, FLT_MAX, 1, -1);
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+
+ prop = RNA_def_property(srna, "size_y", PROP_FLOAT, PROP_UNSIGNED);
+ RNA_def_property_ui_text(prop, "Size Y", "Size of the blur along Y axis");
+ RNA_def_property_ui_range(prop, 0.0f, FLT_MAX, 1, -1);
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
}
static EffectInfo def_effects[] = {
@@ -2227,6 +2247,8 @@ static EffectInfo def_effects[] = {
"Sequence strip applying affine transformations to other strips", rna_def_transform, 1},
{"WipeSequence", "Wipe Sequence", "Sequence strip creating a wipe transition",
rna_def_wipe, 1},
+ {"GaussianBlurSequence", "Gaussian Blur Sequence", "Sequence strip creating a gaussian blur",
+ rna_def_gaussian_blur, 1},
{"", "", "", NULL, 0}
};
diff --git a/source/blender/makesrna/intern/rna_sequencer_api.c b/source/blender/makesrna/intern/rna_sequencer_api.c
index 30fcb63169b..70370f1ae36 100644
--- a/source/blender/makesrna/intern/rna_sequencer_api.c
+++ b/source/blender/makesrna/intern/rna_sequencer_api.c
@@ -468,6 +468,7 @@ void RNA_api_sequences(BlenderRNA *brna, PropertyRNA *cprop)
{SEQ_TYPE_SPEED, "SPEED", 0, "Speed", ""},
{SEQ_TYPE_MULTICAM, "MULTICAM", 0, "Multicam Selector", ""},
{SEQ_TYPE_ADJUSTMENT, "ADJUSTMENT", 0, "Adjustment Layer", ""},
+ {SEQ_TYPE_GAUSSIAN_BLUR, "GAUSSIAN_BLUR", 0, "Gaussian Blur", ""},
{0, NULL, 0, NULL, NULL}
};
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index 39d6e665077..0ddc63e57cf 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -87,6 +87,18 @@ EnumPropertyItem space_type_items[] = {
{0, NULL, 0, NULL, NULL}
};
+static EnumPropertyItem pivot_items_full[] = {
+ {V3D_CENTER, "BOUNDING_BOX_CENTER", ICON_ROTATE, "Bounding Box Center",
+ "Pivot around bounding box center of selected object(s)"},
+ {V3D_CURSOR, "CURSOR", ICON_CURSOR, "3D Cursor", "Pivot around the 3D cursor"},
+ {V3D_LOCAL, "INDIVIDUAL_ORIGINS", ICON_ROTATECOLLECTION,
+ "Individual Origins", "Pivot around each object's own origin"},
+ {V3D_CENTROID, "MEDIAN_POINT", ICON_ROTATECENTER, "Median Point",
+ "Pivot around the median point of selected objects"},
+ {V3D_ACTIVE, "ACTIVE_ELEMENT", ICON_ROTACTIVE, "Active Element", "Pivot around active object"},
+ {0, NULL, 0, NULL, NULL}
+};
+
static EnumPropertyItem draw_channels_items[] = {
{SI_USE_ALPHA, "COLOR_ALPHA", ICON_IMAGE_RGB_ALPHA, "Color and Alpha",
"Draw image with RGB colors and alpha transparency"},
@@ -454,12 +466,12 @@ static void rna_SpaceView3D_layer_update(Main *bmain, Scene *UNUSED(scene), Poin
DAG_on_visible_update(bmain, false);
}
-static void rna_SpaceView3D_viewport_shade_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
+static void rna_SpaceView3D_viewport_shade_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
View3D *v3d = (View3D *)(ptr->data);
ScrArea *sa = rna_area_from_space(ptr);
- ED_view3d_shade_update(bmain, v3d, sa);
+ ED_view3d_shade_update(bmain, scene, v3d, sa);
}
static void rna_SpaceView3D_matcap_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
@@ -616,9 +628,7 @@ static int rna_SpaceView3D_viewport_shade_get(PointerRNA *ptr)
View3D *v3d = (View3D *)ptr->data;
int drawtype = v3d->drawtype;
- if (drawtype == OB_MATERIAL && !BKE_scene_use_new_shading_nodes(scene))
- return OB_SOLID;
- else if (drawtype == OB_RENDER && !(type && type->view_draw))
+ if (drawtype == OB_RENDER && !(type && type->view_draw))
return OB_SOLID;
return drawtype;
@@ -637,9 +647,7 @@ static EnumPropertyItem *rna_SpaceView3D_viewport_shade_itemf(bContext *UNUSED(C
RNA_enum_items_add_value(&item, &totitem, viewport_shade_items, OB_WIRE);
RNA_enum_items_add_value(&item, &totitem, viewport_shade_items, OB_SOLID);
RNA_enum_items_add_value(&item, &totitem, viewport_shade_items, OB_TEXTURE);
-
- if (BKE_scene_use_new_shading_nodes(scene))
- RNA_enum_items_add_value(&item, &totitem, viewport_shade_items, OB_MATERIAL);
+ RNA_enum_items_add_value(&item, &totitem, viewport_shade_items, OB_MATERIAL);
if (type && type->view_draw)
RNA_enum_items_add_value(&item, &totitem, viewport_shade_items, OB_RENDER);
@@ -803,6 +811,24 @@ static void rna_SpaceImageEditor_scopes_update(Main *UNUSED(bmain), Scene *scene
ED_space_image_release_buffer(sima, ibuf, lock);
}
+static EnumPropertyItem *rna_SpaceImageEditor_pivot_itemf(bContext *UNUSED(C), PointerRNA *ptr,
+ PropertyRNA *UNUSED(prop), bool *UNUSED(r_free))
+{
+ static EnumPropertyItem pivot_items[] = {
+ {V3D_CENTER, "CENTER", ICON_ROTATE, "Bounding Box Center", ""},
+ {V3D_CENTROID, "MEDIAN", ICON_ROTATECENTER, "Median Point", ""},
+ {V3D_CURSOR, "CURSOR", ICON_CURSOR, "2D Cursor", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ SpaceImage *sima = (SpaceImage *)ptr->data;
+
+ if (sima->mode == SI_MODE_PAINT)
+ return pivot_items_full;
+ else
+ return pivot_items;
+}
+
/* Space Text Editor */
static void rna_SpaceTextEditor_word_wrap_set(PointerRNA *ptr, int value)
@@ -1492,6 +1518,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_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");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, NULL);
+
prop = RNA_def_property(srna, "show_normalized_coords", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SI_COORDFLOATS);
RNA_def_property_ui_text(prop, "Normalized Coordinates",
@@ -1752,18 +1783,6 @@ static void rna_def_space_view3d(BlenderRNA *brna)
StructRNA *srna;
PropertyRNA *prop;
- static EnumPropertyItem pivot_items[] = {
- {V3D_CENTER, "BOUNDING_BOX_CENTER", ICON_ROTATE, "Bounding Box Center",
- "Pivot around bounding box center of selected object(s)"},
- {V3D_CURSOR, "CURSOR", ICON_CURSOR, "3D Cursor", "Pivot around the 3D cursor"},
- {V3D_LOCAL, "INDIVIDUAL_ORIGINS", ICON_ROTATECOLLECTION,
- "Individual Origins", "Pivot around each object's own origin"},
- {V3D_CENTROID, "MEDIAN_POINT", ICON_ROTATECENTER, "Median Point",
- "Pivot around the median point of selected objects"},
- {V3D_ACTIVE, "ACTIVE_ELEMENT", ICON_ROTACTIVE, "Active Element", "Pivot around active object"},
- {0, NULL, 0, NULL, NULL}
- };
-
static EnumPropertyItem manipulators_items[] = {
{V3D_MANIP_TRANSLATE, "TRANSLATE", ICON_MAN_TRANS, "Manipulator Translate",
"Use the manipulator for movement transformations"},
@@ -2042,7 +2061,7 @@ static void rna_def_space_view3d(BlenderRNA *brna)
prop = RNA_def_property(srna, "pivot_point", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "around");
- RNA_def_property_enum_items(prop, pivot_items);
+ RNA_def_property_enum_items(prop, pivot_items_full);
RNA_def_property_ui_text(prop, "Pivot Point", "Pivot center for rotation/scaling");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_SpaceView3D_pivot_update");
@@ -2310,13 +2329,6 @@ static void rna_def_space_image(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
- static EnumPropertyItem pivot_items[] = {
- {V3D_CENTER, "CENTER", ICON_ROTATE, "Bounding Box Center", ""},
- {V3D_CENTROID, "MEDIAN", ICON_ROTATECENTER, "Median Point", ""},
- {V3D_CURSOR, "CURSOR", ICON_CURSOR, "2D Cursor", ""},
- {0, NULL, 0, NULL, NULL}
- };
-
StructRNA *srna;
PropertyRNA *prop;
@@ -2404,7 +2416,8 @@ static void rna_def_space_image(BlenderRNA *brna)
prop = RNA_def_property(srna, "pivot_point", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "around");
- RNA_def_property_enum_items(prop, pivot_items);
+ RNA_def_property_enum_items(prop, pivot_items_full);
+ RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_SpaceImageEditor_pivot_itemf");
RNA_def_property_ui_text(prop, "Pivot", "Rotation/Scaling Pivot");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, NULL);
diff --git a/source/blender/makesrna/intern/rna_tracking.c b/source/blender/makesrna/intern/rna_tracking.c
index 537ffe630a2..899da62d9d3 100644
--- a/source/blender/makesrna/intern/rna_tracking.c
+++ b/source/blender/makesrna/intern/rna_tracking.c
@@ -393,6 +393,7 @@ static void rna_tracking_flushUpdate(Main *UNUSED(bmain), Scene *scene, PointerR
nodeUpdateID(scene->nodetree, &clip->id);
WM_main_add_notifier(NC_SCENE | ND_NODES, NULL);
+ WM_main_add_notifier(NC_SCENE, NULL);
DAG_id_tag_update(&clip->id, 0);
}
diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c
index d3d17a90f99..da3d7b029ed 100644
--- a/source/blender/makesrna/intern/rna_ui_api.c
+++ b/source/blender/makesrna/intern/rna_ui_api.c
@@ -740,6 +740,11 @@ void RNA_api_ui_layout(StructRNA *srna)
RNA_def_boolean(func, "lock_luminosity", false, "", "Keep the color at its original vector length");
RNA_def_boolean(func, "cubic", false, "", "Cubic saturation for picking values close to white");
+ func = RNA_def_function(srna, "template_palette", "uiTemplatePalette");
+ RNA_def_function_ui_description(func, "Item. A palette used to pick colors");
+ api_ui_item_rna_common(func);
+ RNA_def_boolean(func, "color", 0, "", "Display the colors as colors or values");
+
func = RNA_def_function(srna, "template_image_layers", "uiTemplateImageLayers");
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
parm = RNA_def_pointer(func, "image", "Image", "", "");
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index 3a9b3e539d1..850e68d3d90 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -91,6 +91,7 @@ EnumPropertyItem navigation_mode_items[] = {
#include "BKE_idprop.h"
#include "GPU_draw.h"
+#include "GPU_select.h"
#include "BLF_api.h"
@@ -332,6 +333,11 @@ static void rna_UserDef_viewport_lights_update(Main *bmain, Scene *scene, Pointe
rna_userdef_update(bmain, scene, ptr);
}
+static int rna_Scene_GPU_selection_supported(UserDef *UNUSED(U))
+{
+ return GPU_select_query_check_support();
+}
+
static void rna_userdef_autosave_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
wmWindowManager *wm = bmain->wm.first;
@@ -1292,7 +1298,23 @@ static void rna_def_userdef_theme_spaces_face(StructRNA *srna)
RNA_def_property_update(prop, 0, "rna_userdef_update");
}
-static void rna_def_userdef_theme_spaces_curves(StructRNA *srna, bool incl_nurbs, bool incl_lastsel, bool incl_vector)
+static void rna_def_userdef_theme_spaces_paint_curves(StructRNA *srna)
+{
+ PropertyRNA *prop;
+
+ prop = RNA_def_property(srna, "paint_curve_handle", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_array(prop, 4);
+ RNA_def_property_ui_text(prop, "Paint Curve Handle", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "paint_curve_pivot", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_array(prop, 4);
+ RNA_def_property_ui_text(prop, "Paint Curve Pivot", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+}
+
+static void rna_def_userdef_theme_spaces_curves(StructRNA *srna, bool incl_nurbs, bool incl_lastsel,
+ bool incl_vector, bool incl_verthandle)
{
PropertyRNA *prop;
@@ -1377,8 +1399,8 @@ static void rna_def_userdef_theme_spaces_curves(StructRNA *srna, bool incl_nurbs
RNA_def_property_array(prop, 3);
RNA_def_property_ui_text(prop, "Align handle selected color", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
-
- if (incl_nurbs == false) {
+
+ if (!incl_nurbs) {
/* assume that when nurbs are off, this is for 2D (i.e. anim) editors */
prop = RNA_def_property(srna, "handle_auto_clamped", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "handle_auto_clamped");
@@ -1400,6 +1422,23 @@ static void rna_def_userdef_theme_spaces_curves(StructRNA *srna, bool incl_nurbs
RNA_def_property_ui_text(prop, "Last selected point", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
}
+
+ if (incl_verthandle) {
+ prop = RNA_def_property(srna, "handle_vertex", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Handle Vertex", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "handle_vertex_select", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Handle Vertex Select", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ prop = RNA_def_property(srna, "handle_vertex_size", PROP_INT, PROP_NONE);
+ RNA_def_property_range(prop, 0, 255);
+ RNA_def_property_ui_text(prop, "Handle Vertex Size", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+ }
}
static void rna_def_userdef_theme_space_view3d(BlenderRNA *brna)
@@ -1488,7 +1527,7 @@ static void rna_def_userdef_theme_space_view3d(BlenderRNA *brna)
rna_def_userdef_theme_spaces_vertex(srna);
rna_def_userdef_theme_spaces_edge(srna);
rna_def_userdef_theme_spaces_face(srna);
- rna_def_userdef_theme_spaces_curves(srna, true, true, true);
+ rna_def_userdef_theme_spaces_curves(srna, true, true, true, false);
prop = RNA_def_property(srna, "extra_edge_len", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_array(prop, 3);
@@ -1567,6 +1606,8 @@ static void rna_def_userdef_theme_space_view3d(BlenderRNA *brna)
RNA_def_property_array(prop, 3);
RNA_def_property_ui_text(prop, "Skin Root", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
+
+ rna_def_userdef_theme_spaces_paint_curves(srna);
}
@@ -1632,22 +1673,7 @@ static void rna_def_userdef_theme_space_graph(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_userdef_update");
rna_def_userdef_theme_spaces_vertex(srna);
- rna_def_userdef_theme_spaces_curves(srna, false, true, true);
-
- prop = RNA_def_property(srna, "handle_vertex", PROP_FLOAT, PROP_COLOR_GAMMA);
- RNA_def_property_array(prop, 3);
- RNA_def_property_ui_text(prop, "Handle Vertex", "");
- RNA_def_property_update(prop, 0, "rna_userdef_update");
-
- prop = RNA_def_property(srna, "handle_vertex_select", PROP_FLOAT, PROP_COLOR_GAMMA);
- RNA_def_property_array(prop, 3);
- RNA_def_property_ui_text(prop, "Handle Vertex Select", "");
- RNA_def_property_update(prop, 0, "rna_userdef_update");
-
- prop = RNA_def_property(srna, "handle_vertex_size", PROP_INT, PROP_NONE);
- RNA_def_property_range(prop, 0, 255);
- RNA_def_property_ui_text(prop, "Handle Vertex Size", "");
- RNA_def_property_update(prop, 0, "rna_userdef_update");
+ rna_def_userdef_theme_spaces_curves(srna, false, true, true, true);
}
static void rna_def_userdef_theme_space_file(BlenderRNA *brna)
@@ -2258,7 +2284,9 @@ 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");
- rna_def_userdef_theme_spaces_curves(srna, false, false, false);
+ rna_def_userdef_theme_spaces_curves(srna, false, false, false, true);
+
+ rna_def_userdef_theme_spaces_paint_curves(srna);
}
static void rna_def_userdef_theme_space_seq(BlenderRNA *brna)
@@ -2745,21 +2773,6 @@ static void rna_def_userdef_theme_space_clip(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Current Frame", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
- prop = RNA_def_property(srna, "handle_vertex", PROP_FLOAT, PROP_COLOR_GAMMA);
- RNA_def_property_array(prop, 3);
- RNA_def_property_ui_text(prop, "Handle Vertex", "");
- RNA_def_property_update(prop, 0, "rna_userdef_update");
-
- prop = RNA_def_property(srna, "handle_vertex_select", PROP_FLOAT, PROP_COLOR_GAMMA);
- RNA_def_property_array(prop, 3);
- RNA_def_property_ui_text(prop, "Handle Vertex Select", "");
- RNA_def_property_update(prop, 0, "rna_userdef_update");
-
- prop = RNA_def_property(srna, "handle_vertex_size", PROP_INT, PROP_NONE);
- RNA_def_property_range(prop, 0, 255);
- RNA_def_property_ui_text(prop, "Handle Vertex Size", "");
- RNA_def_property_update(prop, 0, "rna_userdef_update");
-
prop = RNA_def_property(srna, "strips", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "strip");
RNA_def_property_array(prop, 3);
@@ -2772,7 +2785,7 @@ static void rna_def_userdef_theme_space_clip(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Strips Selected", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
- rna_def_userdef_theme_spaces_curves(srna, false, false, false);
+ rna_def_userdef_theme_spaces_curves(srna, false, false, false, true);
}
static void rna_def_userdef_themes(BlenderRNA *brna)
@@ -3141,7 +3154,7 @@ static void rna_def_userdef_view(BlenderRNA *brna)
/* display */
prop = RNA_def_property(srna, "show_tooltips", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_TOOLTIPS);
- RNA_def_property_ui_text(prop, "Tooltips", "Display tooltips");
+ RNA_def_property_ui_text(prop, "Tooltips", "Display tooltips (when off hold Alt to force display)");
prop = RNA_def_property(srna, "show_tooltips_python", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", USER_TOOLTIPS_PYTHON);
@@ -3569,7 +3582,9 @@ static void rna_def_userdef_edit(BlenderRNA *brna)
static void rna_def_userdef_system(BlenderRNA *brna)
{
+ FunctionRNA *func;
PropertyRNA *prop;
+ PropertyRNA *parm;
StructRNA *srna;
static EnumPropertyItem gl_texture_clamp_items[] = {
@@ -3689,6 +3704,13 @@ static void rna_def_userdef_system(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
+ static EnumPropertyItem gpu_select_method_items[] = {
+ {USER_SELECT_AUTO, "AUTO", 0, "Automatic", ""},
+ {USER_SELECT_USE_SELECT_RENDERMODE, "GL_SELECT", 0, "OpenGL Select", ""},
+ {USER_SELECT_USE_OCCLUSION_QUERY, "GL_QUERY", 0, "OpenGL Occlusion Queries", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
srna = RNA_def_struct(brna, "UserPreferencesSystem", NULL);
RNA_def_struct_sdna(srna, "UserDef");
RNA_def_struct_nested(brna, srna, "UserPreferences");
@@ -3931,12 +3953,24 @@ static void rna_def_userdef_system(BlenderRNA *brna)
RNA_def_property_boolean_negative_sdna(prop, NULL, "text_render", USER_TEXT_DISABLE_AA);
RNA_def_property_ui_text(prop, "Text Anti-aliasing", "Draw user interface text anti-aliased");
RNA_def_property_update(prop, 0, "rna_userdef_text_update");
-
+
+ func = RNA_def_function(srna, "is_occlusion_query_supported", "rna_Scene_GPU_selection_supported");
+ parm = RNA_def_boolean(func, "is_supported", 0, "Occlusion Query Support",
+ "Check if GPU supports Occlusion Queries");
+ RNA_def_function_return(func, parm);
+
+ prop = RNA_def_property(srna, "select_method", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "gpu_select_method");
+ RNA_def_property_enum_items(prop, gpu_select_method_items);
+ RNA_def_property_ui_text(prop, "Selection Method",
+ "Use OpenGL occlusion queries or selection render mode to accelerate selection");
+
/* Full scene anti-aliasing */
prop = RNA_def_property(srna, "multi_sample", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "ogl_multisamples");
RNA_def_property_enum_items(prop, multi_sample_levels);
- RNA_def_property_ui_text(prop, "MultiSample", "Enable OpenGL multi-sampling, only for systems that support it, requires restart");
+ RNA_def_property_ui_text(prop, "MultiSample",
+ "Enable OpenGL multi-sampling, only for systems that support it, requires restart");
prop = RNA_def_property(srna, "use_region_overlap", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "uiflag2", USER_REGION_OVERLAP);
diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c
index 0a4a6140c02..085834de602 100644
--- a/source/blender/modifiers/intern/MOD_array.c
+++ b/source/blender/modifiers/intern/MOD_array.c
@@ -370,9 +370,8 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd,
else
unit_m4(obinv);
- mul_serie_m4(result_mat, offset,
- obinv, amd->offset_ob->obmat,
- NULL, NULL, NULL, NULL, NULL);
+ mul_m4_series(result_mat, offset,
+ obinv, amd->offset_ob->obmat);
copy_m4_m4(offset, result_mat);
}
diff --git a/source/blender/modifiers/intern/MOD_hook.c b/source/blender/modifiers/intern/MOD_hook.c
index c89bc8c1d41..f6d7c03df32 100644
--- a/source/blender/modifiers/intern/MOD_hook.c
+++ b/source/blender/modifiers/intern/MOD_hook.c
@@ -156,8 +156,7 @@ static void deformVerts_do(HookModifierData *hmd, Object *ob, DerivedMesh *dm,
copy_m4_m4(dmat, hmd->object->obmat);
}
invert_m4_m4(ob->imat, ob->obmat);
- mul_serie_m4(mat, ob->imat, dmat, hmd->parentinv,
- NULL, NULL, NULL, NULL, NULL);
+ mul_m4_series(mat, ob->imat, dmat, hmd->parentinv);
modifier_get_vgroup(ob, dm, hmd->name, &dvert, &defgrp_index);
max_dvert = (dvert) ? numVerts : 0;
diff --git a/source/blender/modifiers/intern/MOD_mask.c b/source/blender/modifiers/intern/MOD_mask.c
index 7f21376ef48..838336a8f8a 100644
--- a/source/blender/modifiers/intern/MOD_mask.c
+++ b/source/blender/modifiers/intern/MOD_mask.c
@@ -153,7 +153,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
const int defbase_tot = BLI_countlist(&ob->defbase);
/* check that there is armature object with bones to use, otherwise return original mesh */
- if (ELEM3(NULL, oba, oba->pose, ob->defbase.first))
+ if (ELEM(NULL, oba, oba->pose, ob->defbase.first))
return dm;
/* determine whether each vertexgroup is associated with a selected bone or not
diff --git a/source/blender/modifiers/intern/MOD_meshcache_mdd.c b/source/blender/modifiers/intern/MOD_meshcache_mdd.c
index 0cbf07ca907..90fc750de3b 100644
--- a/source/blender/modifiers/intern/MOD_meshcache_mdd.c
+++ b/source/blender/modifiers/intern/MOD_meshcache_mdd.c
@@ -30,9 +30,11 @@
#include "BLI_sys_types.h"
#include "BLI_utildefines.h"
-#include "BLI_endian_switch.h"
#include "BLI_fileops.h"
#include "BLI_math.h"
+#ifdef __LITTLE_ENDIAN__
+# include "BLI_endian_switch.h"
+#endif
#include "MOD_meshcache_util.h" /* own include */
diff --git a/source/blender/modifiers/intern/MOD_meshcache_pc2.c b/source/blender/modifiers/intern/MOD_meshcache_pc2.c
index ac0363f8673..3ef0ee54886 100644
--- a/source/blender/modifiers/intern/MOD_meshcache_pc2.c
+++ b/source/blender/modifiers/intern/MOD_meshcache_pc2.c
@@ -32,6 +32,9 @@
#include "BLI_utildefines.h"
#include "BLI_fileops.h"
#include "BLI_math.h"
+#ifdef __BIG_ENDIAN__
+# include "BLI_endian_switch.h"
+#endif
#include "MOD_meshcache_util.h" /* own include */
diff --git a/source/blender/modifiers/intern/MOD_shrinkwrap.c b/source/blender/modifiers/intern/MOD_shrinkwrap.c
index eebb687aa8d..229f4911ab4 100644
--- a/source/blender/modifiers/intern/MOD_shrinkwrap.c
+++ b/source/blender/modifiers/intern/MOD_shrinkwrap.c
@@ -37,6 +37,7 @@
#include "DNA_object_types.h"
+#include "BLI_math.h"
#include "BLI_string.h"
#include "BLI_utildefines.h"
diff --git a/source/blender/modifiers/intern/MOD_simpledeform.c b/source/blender/modifiers/intern/MOD_simpledeform.c
index ccba2097264..3314196b776 100644
--- a/source/blender/modifiers/intern/MOD_simpledeform.c
+++ b/source/blender/modifiers/intern/MOD_simpledeform.c
@@ -42,7 +42,6 @@
#include "BKE_cdderivedmesh.h"
#include "BKE_modifier.h"
#include "BKE_deform.h"
-#include "BKE_shrinkwrap.h"
#include "depsgraph_private.h"
@@ -166,7 +165,7 @@ static void SimpleDeformModifier_do(SimpleDeformModifierData *smd, struct Object
/* Calculate matrixs do convert between coordinate spaces */
if (smd->origin) {
transf = &tmp_transf;
- space_transform_from_matrixs(transf, ob->obmat, smd->origin->obmat);
+ BLI_SPACE_TRANSFORM_SETUP(transf, ob, smd->origin);
}
/* Setup vars,
@@ -182,7 +181,9 @@ static void SimpleDeformModifier_do(SimpleDeformModifierData *smd, struct Object
float tmp[3];
copy_v3_v3(tmp, vertexCos[i]);
- if (transf) space_transform_apply(transf, tmp);
+ if (transf) {
+ BLI_space_transform_apply(transf, tmp);
+ }
lower = min_ff(lower, tmp[limit_axis]);
upper = max_ff(upper, tmp[limit_axis]);
@@ -220,7 +221,7 @@ static void SimpleDeformModifier_do(SimpleDeformModifierData *smd, struct Object
float co[3], dcut[3] = {0.0f, 0.0f, 0.0f};
if (transf) {
- space_transform_apply(transf, vertexCos[i]);
+ BLI_space_transform_apply(transf, vertexCos[i]);
}
copy_v3_v3(co, vertexCos[i]);
@@ -236,7 +237,7 @@ static void SimpleDeformModifier_do(SimpleDeformModifierData *smd, struct Object
interp_v3_v3v3(vertexCos[i], vertexCos[i], co, weight); /* Use vertex weight has coef of linear interpolation */
if (transf) {
- space_transform_invert(transf, vertexCos[i]);
+ BLI_space_transform_invert(transf, vertexCos[i]);
}
}
}
diff --git a/source/blender/modifiers/intern/MOD_util.c b/source/blender/modifiers/intern/MOD_util.c
index 386d6d985fb..829c2b88995 100644
--- a/source/blender/modifiers/intern/MOD_util.c
+++ b/source/blender/modifiers/intern/MOD_util.c
@@ -198,7 +198,7 @@ DerivedMesh *get_dm(Object *ob, struct BMEditMesh *em, DerivedMesh *dm,
DM_add_vert_layer(dm, CD_ORCO, CD_ASSIGN, BKE_mesh_orco_verts_get(ob));
}
}
- else if (ELEM3(ob->type, OB_FONT, OB_CURVE, OB_SURF)) {
+ else if (ELEM(ob->type, OB_FONT, OB_CURVE, OB_SURF)) {
dm = CDDM_from_curve(ob);
}
diff --git a/source/blender/modifiers/intern/MOD_weightvg_util.c b/source/blender/modifiers/intern/MOD_weightvg_util.c
index 12ecae8ad4f..744b6b62c2a 100644
--- a/source/blender/modifiers/intern/MOD_weightvg_util.c
+++ b/source/blender/modifiers/intern/MOD_weightvg_util.c
@@ -66,9 +66,9 @@ void weightvg_do_map(int num, float *new_w, short falloff_type, CurveMapping *cm
/* Return immediately, if we have nothing to do! */
/* Also security checks... */
if (((falloff_type == MOD_WVG_MAPPING_CURVE) && (cmap == NULL)) ||
- !ELEM7(falloff_type, MOD_WVG_MAPPING_CURVE, MOD_WVG_MAPPING_SHARP, MOD_WVG_MAPPING_SMOOTH,
- MOD_WVG_MAPPING_ROOT, MOD_WVG_MAPPING_SPHERE, MOD_WVG_MAPPING_RANDOM,
- MOD_WVG_MAPPING_STEP))
+ !ELEM(falloff_type, MOD_WVG_MAPPING_CURVE, MOD_WVG_MAPPING_SHARP, MOD_WVG_MAPPING_SMOOTH,
+ MOD_WVG_MAPPING_ROOT, MOD_WVG_MAPPING_SPHERE, MOD_WVG_MAPPING_RANDOM,
+ MOD_WVG_MAPPING_STEP))
{
return;
}
diff --git a/source/blender/modifiers/intern/MOD_weightvgproximity.c b/source/blender/modifiers/intern/MOD_weightvgproximity.c
index f5ae8561300..010fe1d5a29 100644
--- a/source/blender/modifiers/intern/MOD_weightvgproximity.c
+++ b/source/blender/modifiers/intern/MOD_weightvgproximity.c
@@ -43,7 +43,6 @@
#include "BKE_deform.h"
#include "BKE_library.h"
#include "BKE_modifier.h"
-#include "BKE_shrinkwrap.h" /* For SpaceTransform stuff. */
#include "BKE_texture.h" /* Texture masking. */
#include "depsgraph_private.h"
@@ -73,12 +72,12 @@ static void get_vert2geom_distance(int numVerts, float (*v_cos)[3],
DerivedMesh *target, const SpaceTransform *loc2trgt)
{
int i;
- BVHTreeFromMesh treeData_v = NULL_BVHTreeFromMesh;
- BVHTreeFromMesh treeData_e = NULL_BVHTreeFromMesh;
- BVHTreeFromMesh treeData_f = NULL_BVHTreeFromMesh;
- BVHTreeNearest nearest_v = NULL_BVHTreeNearest;
- BVHTreeNearest nearest_e = NULL_BVHTreeNearest;
- BVHTreeNearest nearest_f = NULL_BVHTreeNearest;
+ BVHTreeFromMesh treeData_v = {0};
+ BVHTreeFromMesh treeData_e = {0};
+ BVHTreeFromMesh treeData_f = {0};
+ BVHTreeNearest nearest_v = {0};
+ BVHTreeNearest nearest_e = {0};
+ BVHTreeNearest nearest_f = {0};
if (dist_v) {
/* Create a bvh-tree of the given target's verts. */
@@ -120,7 +119,7 @@ static void get_vert2geom_distance(int numVerts, float (*v_cos)[3],
/* Convert the vertex to tree coordinates. */
copy_v3_v3(tmp_co, v_cos[i]);
- space_transform_apply(loc2trgt, tmp_co);
+ BLI_space_transform_apply(loc2trgt, tmp_co);
/* Use local proximity heuristics (to reduce the nearest search).
*
@@ -465,7 +464,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der
DerivedMesh *target_dm = obr->derivedFinal;
bool free_target_dm = false;
if (!target_dm) {
- if (ELEM3(obr->type, OB_CURVE, OB_SURF, OB_FONT))
+ if (ELEM(obr->type, OB_CURVE, OB_SURF, OB_FONT))
target_dm = CDDM_from_curve(obr);
else if (obr->type == OB_MESH) {
Mesh *me = (Mesh *)obr->data;
@@ -484,7 +483,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der
float *dists_e = use_trgt_edges ? MEM_mallocN(sizeof(float) * numIdx, "dists_e") : NULL;
float *dists_f = use_trgt_faces ? MEM_mallocN(sizeof(float) * numIdx, "dists_f") : NULL;
- SPACE_TRANSFORM_SETUP(&loc2trgt, ob, obr);
+ BLI_SPACE_TRANSFORM_SETUP(&loc2trgt, ob, obr);
get_vert2geom_distance(numIdx, v_cos, dists_v, dists_e, dists_f,
target_dm, &loc2trgt);
for (i = 0; i < numIdx; i++) {
diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt
index 6fed0d16848..e09a0892370 100644
--- a/source/blender/nodes/CMakeLists.txt
+++ b/source/blender/nodes/CMakeLists.txt
@@ -105,6 +105,7 @@ set(SRC
composite/nodes/node_composite_setalpha.c
composite/nodes/node_composite_splitViewer.c
composite/nodes/node_composite_stabilize2d.c
+ composite/nodes/node_composite_sunbeams.c
composite/nodes/node_composite_texture.c
composite/nodes/node_composite_tonemap.c
composite/nodes/node_composite_trackpos.c
diff --git a/source/blender/nodes/NOD_composite.h b/source/blender/nodes/NOD_composite.h
index ad5f35b8faa..961fdbfc0fb 100644
--- a/source/blender/nodes/NOD_composite.h
+++ b/source/blender/nodes/NOD_composite.h
@@ -125,7 +125,7 @@ void register_node_type_cmp_mask(void);
void register_node_type_cmp_glare(void);
void register_node_type_cmp_tonemap(void);
void register_node_type_cmp_lensdist(void);
-
+void register_node_type_cmp_sunbeams(void);
void register_node_type_cmp_colorcorrection(void);
void register_node_type_cmp_boxmask(void);
diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h
index 8d6c4abaef6..be87abd7b7e 100644
--- a/source/blender/nodes/NOD_static_types.h
+++ b/source/blender/nodes/NOD_static_types.h
@@ -208,6 +208,7 @@ DefNode( CompositorNode, CMP_NODE_TRACKPOS, def_cmp_trackpos, "TRACK
DefNode( CompositorNode, CMP_NODE_PIXELATE, 0, "PIXELATE", Pixelate, "Pixelate", "" )
DefNode( CompositorNode, CMP_NODE_PLANETRACKDEFORM,def_cmp_planetrackdeform,"PLANETRACKDEFORM",PlaneTrackDeform,"Plane Track Deform","" )
DefNode( CompositorNode, CMP_NODE_CORNERPIN, 0, "CORNERPIN", CornerPin, "Corner Pin", "" )
+DefNode( CompositorNode, CMP_NODE_SUNBEAMS, def_cmp_sunbeams, "SUNBEAMS", SunBeams, "Sun Beams", "" )
DefNode( TextureNode, TEX_NODE_OUTPUT, def_tex_output, "OUTPUT", Output, "Output", "" )
DefNode( TextureNode, TEX_NODE_CHECKER, 0, "CHECKER", Checker, "Checker", "" )
diff --git a/source/blender/nodes/composite/nodes/node_composite_sunbeams.c b/source/blender/nodes/composite/nodes/node_composite_sunbeams.c
new file mode 100644
index 00000000000..4d937d63b75
--- /dev/null
+++ b/source/blender/nodes/composite/nodes/node_composite_sunbeams.c
@@ -0,0 +1,63 @@
+/*
+ * ***** 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) 2014 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Lukas Toenne
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/nodes/composite/nodes/node_composite_sunbeams.c
+ * \ingroup cmpnodes
+ */
+
+#include "node_composite_util.h"
+
+static bNodeSocketTemplate inputs[] = {
+ { SOCK_RGBA, 1, N_("Image"), 1.0f, 1.0f, 1.0f, 1.0f},
+ { -1, 0, "" }
+};
+static bNodeSocketTemplate outputs[] = {
+ { SOCK_RGBA, 0, N_("Image")},
+ { -1, 0, "" }
+};
+
+static void init(bNodeTree *UNUSED(ntree), bNode *node)
+{
+ NodeSunBeams *data = MEM_callocN(sizeof(NodeSunBeams), "sun beams node");
+
+ data->source[0] = 0.5f;
+ data->source[1] = 0.5f;
+
+ node->storage = data;
+}
+
+void register_node_type_cmp_sunbeams(void)
+{
+ static bNodeType ntype;
+
+ cmp_node_type_base(&ntype, CMP_NODE_SUNBEAMS, "Sun Beams", NODE_CLASS_OP_FILTER, 0);
+ node_type_socket_templates(&ntype, inputs, outputs);
+ node_type_init(&ntype, init);
+ node_type_storage(&ntype, "NodeSunBeams", node_free_standard_storage, node_copy_standard_storage);
+
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/intern/node_common.c b/source/blender/nodes/intern/node_common.c
index ae834f9e7cc..c58c9c902ec 100644
--- a/source/blender/nodes/intern/node_common.c
+++ b/source/blender/nodes/intern/node_common.c
@@ -336,6 +336,40 @@ void ntree_update_reroute_nodes(bNodeTree *ntree)
node_reroute_inherit_type_recursive(ntree, node);
}
+static bool node_is_connected_to_output_recursive(bNodeTree *ntree, bNode *node)
+{
+ bNodeLink *link;
+
+ /* avoid redundant checks, and infinite loops in case of cyclic node links */
+ if (node->done)
+ return false;
+ node->done = 1;
+
+ /* main test, done before child loop so it catches output nodes themselves as well */
+ if (node->typeinfo->nclass == NODE_CLASS_OUTPUT && node->flag & NODE_DO_OUTPUT)
+ return true;
+
+ /* test all connected nodes, first positive find is sufficient to return true */
+ for (link = ntree->links.first; link; link = link->next) {
+ if (link->fromnode == node) {
+ if (node_is_connected_to_output_recursive(ntree, link->tonode))
+ return true;
+ }
+ }
+ return false;
+}
+
+bool BKE_node_is_connected_to_output(bNodeTree *ntree, bNode *node)
+{
+ bNode *tnode;
+
+ /* clear flags */
+ for (tnode = ntree->nodes.first; tnode; tnode = tnode->next)
+ tnode->done = 0;
+
+ return node_is_connected_to_output_recursive(ntree, node);
+}
+
void BKE_node_tree_unlink_id(ID *id, struct bNodeTree *ntree)
{
bNode *node;
diff --git a/source/blender/nodes/intern/node_exec.c b/source/blender/nodes/intern/node_exec.c
index 0e5f72c831b..ec481839a16 100644
--- a/source/blender/nodes/intern/node_exec.c
+++ b/source/blender/nodes/intern/node_exec.c
@@ -47,7 +47,7 @@
/* supported socket types in old nodes */
int node_exec_socket_use_stack(bNodeSocket *sock)
{
- return ELEM4(sock->type, SOCK_FLOAT, SOCK_VECTOR, SOCK_RGBA, SOCK_SHADER);
+ return ELEM(sock->type, SOCK_FLOAT, SOCK_VECTOR, SOCK_RGBA, SOCK_SHADER);
}
/* for a given socket, find the actual stack entry */
diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_glass.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_glass.c
index 55dafaeca35..75ca4b87f09 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bsdf_glass.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_glass.c
@@ -30,7 +30,7 @@
/* **************** OUTPUT ******************** */
static bNodeSocketTemplate sh_node_bsdf_glass_in[] = {
- { SOCK_RGBA, 1, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+ { SOCK_RGBA, 1, N_("Color"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 1, N_("Roughness"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
{ SOCK_FLOAT, 1, N_("IOR"), 1.45f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f},
{ SOCK_VECTOR, 1, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
diff --git a/source/blender/nodes/shader/nodes/node_shader_uvmap.c b/source/blender/nodes/shader/nodes/node_shader_uvmap.c
index fff1bc1df95..0f96cb45fe0 100644
--- a/source/blender/nodes/shader/nodes/node_shader_uvmap.c
+++ b/source/blender/nodes/shader/nodes/node_shader_uvmap.c
@@ -42,6 +42,14 @@ static void node_shader_init_uvmap(bNodeTree *UNUSED(ntree), bNode *node)
node->storage = attr;
}
+static int node_shader_gpu_uvmap(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+{
+ NodeShaderUVMap *attr = node->storage;
+ GPUNodeLink *mtface = GPU_attribute(CD_MTFACE, attr->uv_map);
+
+ return GPU_stack_link(mat, "node_uvmap", in, out, mtface);
+}
+
/* node type definition */
void register_node_type_sh_uvmap(void)
{
@@ -53,6 +61,7 @@ void register_node_type_sh_uvmap(void)
node_type_size_preset(&ntype, NODE_SIZE_MIDDLE);
node_type_init(&ntype, node_shader_init_uvmap);
node_type_storage(&ntype, "NodeShaderUVMap", node_free_standard_storage, node_copy_standard_storage);
+ node_type_gpu(&ntype, node_shader_gpu_uvmap);
nodeRegisterType(&ntype);
}
diff --git a/source/blender/python/bmesh/bmesh_py_utils.c b/source/blender/python/bmesh/bmesh_py_utils.c
index 3c412cf2a08..88e369af8bb 100644
--- a/source/blender/python/bmesh/bmesh_py_utils.c
+++ b/source/blender/python/bmesh/bmesh_py_utils.c
@@ -595,7 +595,9 @@ static PyObject *bpy_bm_utils_face_split_edgenet(PyObject *UNUSED(self), PyObjec
if (ok) {
PyObject *ret = BPy_BMFace_Array_As_Tuple(bm, face_arr, face_arr_len);
- MEM_freeN(face_arr);
+ if (face_arr) {
+ MEM_freeN(face_arr);
+ }
return ret;
}
else {
diff --git a/source/blender/python/generic/bgl.c b/source/blender/python/generic/bgl.c
index 9b819977345..e77a528bb09 100644
--- a/source/blender/python/generic/bgl.c
+++ b/source/blender/python/generic/bgl.c
@@ -301,7 +301,7 @@ static PyObject *Buffer_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject
if (!PyArg_ParseTuple(args, "iO|O: bgl.Buffer", &type, &length_ob, &init)) {
return NULL;
}
- if (!ELEM5(type, GL_BYTE, GL_SHORT, GL_INT, GL_FLOAT, GL_DOUBLE)) {
+ if (!ELEM(type, GL_BYTE, GL_SHORT, GL_INT, GL_FLOAT, GL_DOUBLE)) {
PyErr_SetString(PyExc_AttributeError,
"invalid first argument type, should be one of "
"GL_BYTE, GL_SHORT, GL_INT, GL_FLOAT or GL_DOUBLE");
diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c
index 440af035bcd..3fdc3641173 100644
--- a/source/blender/python/intern/bpy_rna.c
+++ b/source/blender/python/intern/bpy_rna.c
@@ -1363,7 +1363,7 @@ PyObject *pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop)
if (subtype == PROP_BYTESTRING) {
ret = PyBytes_FromStringAndSize(buf, buf_len);
}
- else if (ELEM3(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME)) {
+ else if (ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME)) {
ret = PyC_UnicodeFromByteAndSize(buf, buf_len);
}
else {
@@ -1629,7 +1629,7 @@ static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyOb
/* Unicode String */
#ifdef USE_STRING_COERCE
PyObject *value_coerce = NULL;
- if (ELEM3(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME)) {
+ if (ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME)) {
/* TODO, get size */
param = PyC_UnicodeAsByte(value, &value_coerce);
}
@@ -4894,7 +4894,7 @@ static PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *dat
if (subtype == PROP_BYTESTRING) {
ret = PyBytes_FromString(data_ch);
}
- else if (ELEM3(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME)) {
+ else if (ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME)) {
ret = PyC_UnicodeFromByte(data_ch);
}
else {
diff --git a/source/blender/python/mathutils/mathutils_Euler.c b/source/blender/python/mathutils/mathutils_Euler.c
index 5d8252d3c72..f6d124938a4 100644
--- a/source/blender/python/mathutils/mathutils_Euler.c
+++ b/source/blender/python/mathutils/mathutils_Euler.c
@@ -83,14 +83,23 @@ static const char *euler_order_str(EulerObject *self)
short euler_order_from_string(const char *str, const char *error_prefix)
{
if ((str[0] && str[1] && str[2] && str[3] == '\0')) {
+
+#ifdef __LITTLE_ENDIAN__
+# define MAKE_ID3(a, b, c) (((a)) | ((b) << 8) | ((c) << 16))
+#else
+# define MAKE_ID3(a, b, c) (((a) << 24) | ((b) << 16) | ((c) << 8))
+#endif
+
switch (*((PY_INT32_T *)str)) {
- case 'X' | 'Y' << 8 | 'Z' << 16: return EULER_ORDER_XYZ;
- case 'X' | 'Z' << 8 | 'Y' << 16: return EULER_ORDER_XZY;
- case 'Y' | 'X' << 8 | 'Z' << 16: return EULER_ORDER_YXZ;
- case 'Y' | 'Z' << 8 | 'X' << 16: return EULER_ORDER_YZX;
- case 'Z' | 'X' << 8 | 'Y' << 16: return EULER_ORDER_ZXY;
- case 'Z' | 'Y' << 8 | 'X' << 16: return EULER_ORDER_ZYX;
+ case MAKE_ID3('X', 'Y', 'Z'): return EULER_ORDER_XYZ;
+ case MAKE_ID3('X', 'Z', 'Y'): return EULER_ORDER_XZY;
+ case MAKE_ID3('Y', 'X', 'Z'): return EULER_ORDER_YXZ;
+ case MAKE_ID3('Y', 'Z', 'X'): return EULER_ORDER_YZX;
+ case MAKE_ID3('Z', 'X', 'Y'): return EULER_ORDER_ZXY;
+ case MAKE_ID3('Z', 'Y', 'X'): return EULER_ORDER_ZYX;
}
+
+#undef MAKE_ID3
}
PyErr_Format(PyExc_ValueError,
@@ -203,7 +212,7 @@ static PyObject *Euler_rotate_axis(EulerObject *self, PyObject *args)
return NULL;
}
- if (!(ELEM3(axis, 'X', 'Y', 'Z'))) {
+ if (!(ELEM(axis, 'X', 'Y', 'Z'))) {
PyErr_SetString(PyExc_ValueError,
"Euler.rotate_axis(): "
"expected axis to be 'X', 'Y' or 'Z'");
diff --git a/source/blender/python/mathutils/mathutils_Vector.c b/source/blender/python/mathutils/mathutils_Vector.c
index a719691d5d4..15a9860be0a 100644
--- a/source/blender/python/mathutils/mathutils_Vector.c
+++ b/source/blender/python/mathutils/mathutils_Vector.c
@@ -814,17 +814,20 @@ static PyObject *Vector_orthogonal(VectorObject *self)
{
float vec[3];
- if (self->size != 3) {
+ if (self->size > 3) {
PyErr_SetString(PyExc_TypeError,
"Vector.orthogonal(): "
- "Vector must be 3D");
+ "Vector must be 3D or 2D");
return NULL;
}
if (BaseMath_ReadCallback(self) == -1)
return NULL;
- ortho_v3_v3(vec, self->vec);
+ if (self->size == 3)
+ ortho_v3_v3(vec, self->vec);
+ else
+ ortho_v2_v2(vec, self->vec);
return Vector_CreatePyObject(vec, self->size, Py_NEW, Py_TYPE(self));
}
diff --git a/source/blender/python/mathutils/mathutils_geometry.c b/source/blender/python/mathutils/mathutils_geometry.c
index 139764abb00..20d69caf02d 100644
--- a/source/blender/python/mathutils/mathutils_geometry.c
+++ b/source/blender/python/mathutils/mathutils_geometry.c
@@ -229,6 +229,11 @@ static PyObject *M_Geometry_intersect_line_line(PyObject *UNUSED(self), PyObject
}
result = isect_line_line_v3(v1, v2, v3, v4, i1, i2);
+ /* The return-code isnt exposed,
+ * this way we can check know how close the lines are. */
+ if (result == 1) {
+ closest_to_line_v3(i2, i1, v3, v4);
+ }
if (result == 0) {
/* colinear */
@@ -597,7 +602,7 @@ static PyObject *M_Geometry_intersect_line_plane(PyObject *UNUSED(self), PyObjec
return NULL;
}
- if (ELEM4(2, line_a->size, line_b->size, plane_co->size, plane_no->size)) {
+ if (ELEM(2, line_a->size, line_b->size, plane_co->size, plane_no->size)) {
PyErr_SetString(PyExc_ValueError,
"geometry.intersect_line_plane(...): "
" can't use 2D Vectors");
@@ -654,7 +659,7 @@ static PyObject *M_Geometry_intersect_plane_plane(PyObject *UNUSED(self), PyObje
return NULL;
}
- if (ELEM4(2, plane_a_co->size, plane_a_no->size, plane_b_co->size, plane_b_no->size)) {
+ if (ELEM(2, plane_a_co->size, plane_a_no->size, plane_b_co->size, plane_b_no->size)) {
PyErr_SetString(PyExc_ValueError,
"geometry.intersect_plane_plane(...): "
" can't use 2D Vectors");
@@ -726,7 +731,7 @@ static PyObject *M_Geometry_intersect_line_sphere(PyObject *UNUSED(self), PyObje
return NULL;
}
- if (ELEM3(2, line_a->size, line_b->size, sphere_co->size)) {
+ if (ELEM(2, line_a->size, line_b->size, sphere_co->size)) {
PyErr_SetString(PyExc_ValueError,
"geometry.intersect_line_sphere(...): "
" can't use 2D Vectors");
@@ -893,13 +898,69 @@ static PyObject *M_Geometry_intersect_point_line(PyObject *UNUSED(self), PyObjec
return ret;
}
+PyDoc_STRVAR(M_Geometry_intersect_point_tri_doc,
+".. function:: intersect_point_tri(pt, tri_p1, tri_p2, tri_p3)\n"
+"\n"
+" Takes 4 vectors: one is the point and the next 3 define the triangle.\n"
+"\n"
+" :arg pt: Point\n"
+" :type pt: :class:`mathutils.Vector`\n"
+" :arg tri_p1: First point of the triangle\n"
+" :type tri_p1: :class:`mathutils.Vector`\n"
+" :arg tri_p2: Second point of the triangle\n"
+" :type tri_p2: :class:`mathutils.Vector`\n"
+" :arg tri_p3: Third point of the triangle\n"
+" :type tri_p3: :class:`mathutils.Vector`\n"
+" :return: Point on the triangles plane or None if its outside the triangle\n"
+" :rtype: :class:`mathutils.Vector` or None\n"
+);
+static PyObject *M_Geometry_intersect_point_tri(PyObject *UNUSED(self), PyObject *args)
+{
+ VectorObject *pt_vec, *tri_p1, *tri_p2, *tri_p3;
+ float vi[3];
+
+ if (!PyArg_ParseTuple(args, "O!O!O!O!:intersect_point_tri",
+ &vector_Type, &pt_vec,
+ &vector_Type, &tri_p1,
+ &vector_Type, &tri_p2,
+ &vector_Type, &tri_p3))
+ {
+ return NULL;
+ }
+
+ if (BaseMath_ReadCallback(pt_vec) == -1 ||
+ BaseMath_ReadCallback(tri_p1) == -1 ||
+ BaseMath_ReadCallback(tri_p2) == -1 ||
+ BaseMath_ReadCallback(tri_p3) == -1)
+ {
+ return NULL;
+ }
+
+ if (pt_vec->size < 3 ||
+ tri_p1->size < 3 ||
+ tri_p2->size < 3 ||
+ tri_p3->size < 3)
+ {
+ PyErr_SetString(PyExc_ValueError,
+ "One of more of the vector arguments wasn't a 3D vector");
+ return NULL;
+ }
+
+ if (isect_point_tri_v3(pt_vec->vec, tri_p1->vec, tri_p2->vec, tri_p3->vec, vi)) {
+ return Vector_CreatePyObject(vi, 3, Py_NEW, NULL);
+ }
+ else {
+ Py_RETURN_NONE;
+ }
+}
+
PyDoc_STRVAR(M_Geometry_intersect_point_tri_2d_doc,
".. function:: intersect_point_tri_2d(pt, tri_p1, tri_p2, tri_p3)\n"
"\n"
" Takes 4 vectors (using only the x and y coordinates): one is the point and the next 3 define the triangle. Returns 1 if the point is within the triangle, otherwise 0.\n"
"\n"
" :arg pt: Point\n"
-" :type v1: :class:`mathutils.Vector`\n"
+" :type pt: :class:`mathutils.Vector`\n"
" :arg tri_p1: First point of the triangle\n"
" :type tri_p1: :class:`mathutils.Vector`\n"
" :arg tri_p2: Second point of the triangle\n"
@@ -1606,6 +1667,7 @@ static PyObject *M_Geometry_convex_hull_2d(PyObject *UNUSED(self), PyObject *poi
static PyMethodDef M_Geometry_methods[] = {
{"intersect_ray_tri", (PyCFunction) M_Geometry_intersect_ray_tri, METH_VARARGS, M_Geometry_intersect_ray_tri_doc},
{"intersect_point_line", (PyCFunction) M_Geometry_intersect_point_line, METH_VARARGS, M_Geometry_intersect_point_line_doc},
+ {"intersect_point_tri", (PyCFunction) M_Geometry_intersect_point_tri, METH_VARARGS, M_Geometry_intersect_point_tri_doc},
{"intersect_point_tri_2d", (PyCFunction) M_Geometry_intersect_point_tri_2d, METH_VARARGS, M_Geometry_intersect_point_tri_2d_doc},
{"intersect_point_quad_2d", (PyCFunction) M_Geometry_intersect_point_quad_2d, METH_VARARGS, M_Geometry_intersect_point_quad_2d_doc},
{"intersect_line_line", (PyCFunction) M_Geometry_intersect_line_line, METH_VARARGS, M_Geometry_intersect_line_line_doc},
diff --git a/source/blender/render/extern/include/RE_bake.h b/source/blender/render/extern/include/RE_bake.h
index 8f2a0e382a4..481da452529 100644
--- a/source/blender/render/extern/include/RE_bake.h
+++ b/source/blender/render/extern/include/RE_bake.h
@@ -39,7 +39,7 @@ typedef struct BakeImage {
struct Image *image;
int width;
int height;
- int offset;
+ size_t offset;
} BakeImage;
typedef struct BakeImages {
@@ -72,35 +72,35 @@ bool RE_bake_has_engine(struct Render *re);
bool RE_bake_engine(
struct Render *re, struct Object *object, const BakePixel pixel_array[],
- const int num_pixels, const int depth, const ScenePassType pass_type, float result[]);
+ const size_t num_pixels, const int depth, const ScenePassType pass_type, float result[]);
/* bake.c */
int RE_pass_depth(const ScenePassType pass_type);
bool RE_bake_internal(
struct Render *re, struct Object *object, const BakePixel pixel_array[],
- const int num_pixels, const int depth, const ScenePassType pass_type, float result[]);
+ const size_t num_pixels, const int depth, const ScenePassType pass_type, float result[]);
bool RE_bake_pixels_populate_from_objects(
struct Mesh *me_low, BakePixel pixel_array_from[],
- BakeHighPolyData highpoly[], const int tot_highpoly, const int num_pixels, const bool is_custom_cage,
+ BakeHighPolyData highpoly[], const int tot_highpoly, const size_t num_pixels, const bool is_custom_cage,
const float cage_extrusion, float mat_low[4][4], float mat_cage[4][4], struct Mesh *me_cage);
void RE_bake_pixels_populate(
struct Mesh *me, struct BakePixel *pixel_array,
- const int num_pixels, const struct BakeImages *bake_images, const char *uv_layer);
+ const size_t num_pixels, const struct BakeImages *bake_images, const char *uv_layer);
-void RE_bake_mask_fill(const BakePixel pixel_array[], const int num_pixels, char *mask);
+void RE_bake_mask_fill(const BakePixel pixel_array[], const size_t num_pixels, char *mask);
void RE_bake_margin(struct ImBuf *ibuf, char *mask, const int margin);
void RE_bake_normal_world_to_object(
- const BakePixel pixel_array[], const int num_pixels, const int depth, float result[],
+ const BakePixel pixel_array[], const size_t num_pixels, const int depth, float result[],
struct Object *ob, const BakeNormalSwizzle normal_swizzle[3]);
void RE_bake_normal_world_to_tangent(
- const BakePixel pixel_array[], const int num_pixels, const int depth, float result[],
+ const BakePixel pixel_array[], const size_t num_pixels, const int depth, float result[],
struct Mesh *me, const BakeNormalSwizzle normal_swizzle[3], float mat[4][4]);
void RE_bake_normal_world_to_world(
- const BakePixel pixel_array[], const int num_pixels, const int depth, float result[],
+ const BakePixel pixel_array[], const size_t num_pixels, const int depth, float result[],
const BakeNormalSwizzle normal_swizzle[3]);
void RE_bake_ibuf_clear(struct Image *image, const bool is_tangent);
diff --git a/source/blender/render/intern/source/bake.c b/source/blender/render/intern/source/bake.c
index f2793a9bc5b..15634c93491 100644
--- a/source/blender/render/intern/source/bake.c
+++ b/source/blender/render/intern/source/bake.c
@@ -174,7 +174,7 @@ static void bake_shade(void *handle, Object *ob, ShadeInput *shi, int UNUSED(qua
/* only do AO for a full bake (and obviously AO bakes)
* AO for light bakes is a leftover and might not be needed */
- if (ELEM3(bs->type, RE_BAKE_ALL, RE_BAKE_AO, RE_BAKE_LIGHT))
+ if (ELEM(bs->type, RE_BAKE_ALL, RE_BAKE_AO, RE_BAKE_LIGHT))
shade_samples_do_AO(ssamp);
if (shi->mat->nodetree && shi->mat->use_nodes) {
@@ -303,7 +303,7 @@ static void bake_shade(void *handle, Object *ob, ShadeInput *shi, int UNUSED(qua
rgb_float_to_uchar(col, shr.combined);
}
- if (ELEM3(bs->type, RE_BAKE_ALL, RE_BAKE_TEXTURE, RE_BAKE_VERTEX_COLORS)) {
+ if (ELEM(bs->type, RE_BAKE_ALL, RE_BAKE_TEXTURE, RE_BAKE_VERTEX_COLORS)) {
col[3] = FTOCHAR(shr.alpha);
}
else {
diff --git a/source/blender/render/intern/source/bake_api.c b/source/blender/render/intern/source/bake_api.c
index 15ad6051f4c..08fea632cd4 100644
--- a/source/blender/render/intern/source/bake_api.c
+++ b/source/blender/render/intern/source/bake_api.c
@@ -120,7 +120,7 @@ static void store_bake_pixel(void *handle, int x, int y, float u, float v)
BakePixel *pixel;
const int width = bd->bk_image->width;
- const int offset = bd->bk_image->offset;
+ const size_t offset = bd->bk_image->offset;
const int i = offset + y * width + x;
pixel = &bd->pixel_array[i];
@@ -134,9 +134,9 @@ static void store_bake_pixel(void *handle, int x, int y, float u, float v)
pixel->dv_dy = bd->dv_dy;
}
-void RE_bake_mask_fill(const BakePixel pixel_array[], const int num_pixels, char *mask)
+void RE_bake_mask_fill(const BakePixel pixel_array[], const size_t num_pixels, char *mask)
{
- int i;
+ size_t i;
if (!mask)
return;
@@ -438,10 +438,10 @@ static void mesh_calc_tri_tessface(
bool RE_bake_pixels_populate_from_objects(
struct Mesh *me_low, BakePixel pixel_array_from[],
- BakeHighPolyData highpoly[], const int tot_highpoly, const int num_pixels, const bool is_custom_cage,
+ BakeHighPolyData highpoly[], const int tot_highpoly, const size_t num_pixels, const bool is_custom_cage,
const float cage_extrusion, float mat_low[4][4], float mat_cage[4][4], struct Mesh *me_cage)
{
- int i;
+ size_t i;
int primitive_id;
float u, v;
float imat_low [4][4];
@@ -594,11 +594,11 @@ static void bake_differentials(BakeDataZSpan *bd, const float *uv1, const float
void RE_bake_pixels_populate(
Mesh *me, BakePixel pixel_array[],
- const int num_pixels, const BakeImages *bake_images, const char *uv_layer)
+ const size_t num_pixels, const BakeImages *bake_images, const char *uv_layer)
{
BakeDataZSpan bd;
- int i, a;
- int p_id;
+ size_t i;
+ int a, p_id;
MTFace *mtface;
MFace *mface;
@@ -725,11 +725,11 @@ static void normal_compress(float out[3], const float in[3], const BakeNormalSwi
* This function converts an object space normal map to a tangent space normal map for a given low poly mesh
*/
void RE_bake_normal_world_to_tangent(
- const BakePixel pixel_array[], const int num_pixels, const int depth,
+ const BakePixel pixel_array[], const size_t num_pixels, const int depth,
float result[], Mesh *me, const BakeNormalSwizzle normal_swizzle[3],
float mat[4][4])
{
- int i;
+ size_t i;
TriTessFace *triangles;
@@ -756,7 +756,7 @@ void RE_bake_normal_world_to_tangent(
float tsm[3][3]; /* tangent space matrix */
float itsm[3][3];
- int offset;
+ size_t offset;
float nor[3]; /* texture normal */
bool is_smooth;
@@ -834,16 +834,16 @@ void RE_bake_normal_world_to_tangent(
}
void RE_bake_normal_world_to_object(
- const BakePixel pixel_array[], const int num_pixels, const int depth,
+ const BakePixel pixel_array[], const size_t num_pixels, const int depth,
float result[], struct Object *ob, const BakeNormalSwizzle normal_swizzle[3])
{
- int i;
+ size_t i;
float iobmat[4][4];
invert_m4_m4(iobmat, ob->obmat);
for (i = 0; i < num_pixels; i++) {
- int offset;
+ size_t offset;
float nor[3];
if (pixel_array[i].primitive_id == -1)
@@ -862,13 +862,13 @@ void RE_bake_normal_world_to_object(
}
void RE_bake_normal_world_to_world(
- const BakePixel pixel_array[], const int num_pixels, const int depth,
+ const BakePixel pixel_array[], const size_t num_pixels, const int depth,
float result[], const BakeNormalSwizzle normal_swizzle[3])
{
- int i;
+ size_t i;
for (i = 0; i < num_pixels; i++) {
- int offset;
+ size_t offset;
float nor[3];
if (pixel_array[i].primitive_id == -1)
@@ -908,12 +908,12 @@ void RE_bake_ibuf_clear(Image *image, const bool is_tangent)
/**
* not the real UV, but the internal per-face UV instead
* I'm using it to test if everything is correct */
-static bool bake_uv(const BakePixel pixel_array[], const int num_pixels, const int depth, float result[])
+static bool bake_uv(const BakePixel pixel_array[], const size_t num_pixels, const int depth, float result[])
{
- int i;
+ size_t i;
for (i=0; i < num_pixels; i++) {
- int offset = i * depth;
+ size_t offset = i * depth;
copy_v2_v2(&result[offset], pixel_array[i].uv);
}
@@ -922,7 +922,7 @@ static bool bake_uv(const BakePixel pixel_array[], const int num_pixels, const i
bool RE_bake_internal(
Render *UNUSED(re), Object *UNUSED(object), const BakePixel pixel_array[],
- const int num_pixels, const int depth, const ScenePassType pass_type, float result[])
+ const size_t num_pixels, const int depth, const ScenePassType pass_type, float result[])
{
switch (pass_type) {
case SCE_PASS_UV:
diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c
index 5c44f1cd0c1..c6ebe44c5da 100644
--- a/source/blender/render/intern/source/convertblender.c
+++ b/source/blender/render/intern/source/convertblender.c
@@ -3704,8 +3704,8 @@ static GroupObject *add_render_lamp(Render *re, Object *ob)
/* Annoying, lamp UI does this, but the UI might not have been used? - add here too.
* make sure this matches buttons_shading.c's logic */
- if (ELEM4(la->type, LA_AREA, LA_SPOT, LA_SUN, LA_LOCAL) && (la->mode & LA_SHAD_RAY))
- if (ELEM3(la->type, LA_SPOT, LA_SUN, LA_LOCAL))
+ if (ELEM(la->type, LA_AREA, LA_SPOT, LA_SUN, LA_LOCAL) && (la->mode & LA_SHAD_RAY))
+ if (ELEM(la->type, LA_SPOT, LA_SUN, LA_LOCAL))
if (la->ray_samp_method == LA_SAMP_CONSTANT) la->ray_samp_method = LA_SAMP_HALTON;
lar->ray_samp_method= la->ray_samp_method;
@@ -4546,8 +4546,7 @@ static void set_dupli_tex_mat(Render *re, ObjectInstanceRen *obi, DupliObject *d
obi->duplitexmat= BLI_memarena_alloc(re->memArena, sizeof(float)*4*4);
invert_m4_m4(imat, dob->mat);
- mul_serie_m4(obi->duplitexmat, re->viewmat, omat, imat, re->viewinv,
- NULL, NULL, NULL, NULL);
+ mul_m4_series(obi->duplitexmat, re->viewmat, omat, imat, re->viewinv);
}
copy_v3_v3(obi->dupliorco, dob->orco);
@@ -4831,7 +4830,7 @@ static int allow_render_dupli_instance(Render *UNUSED(re), DupliObject *dob, Obj
}
for (psys=obd->particlesystem.first; psys; psys=psys->next)
- if (!ELEM5(psys->part->ren_as, PART_DRAW_BB, PART_DRAW_LINE, PART_DRAW_PATH, PART_DRAW_OB, PART_DRAW_GR))
+ if (!ELEM(psys->part->ren_as, PART_DRAW_BB, PART_DRAW_LINE, PART_DRAW_PATH, PART_DRAW_OB, PART_DRAW_GR))
return 0;
/* don't allow lamp, animated duplis, or radio render */
@@ -5833,8 +5832,8 @@ void RE_Database_Baking(Render *re, Main *bmain, Scene *scene, unsigned int lay,
Object *camera;
float mat[4][4];
float amb[3];
- const short onlyselected= !ELEM5(type, RE_BAKE_LIGHT, RE_BAKE_ALL, RE_BAKE_SHADOW, RE_BAKE_AO, RE_BAKE_VERTEX_COLORS);
- const short nolamps= ELEM5(type, RE_BAKE_NORMALS, RE_BAKE_TEXTURE, RE_BAKE_DISPLACEMENT, RE_BAKE_DERIVATIVE, RE_BAKE_VERTEX_COLORS);
+ const short onlyselected= !ELEM(type, RE_BAKE_LIGHT, RE_BAKE_ALL, RE_BAKE_SHADOW, RE_BAKE_AO, RE_BAKE_VERTEX_COLORS);
+ const short nolamps= ELEM(type, RE_BAKE_NORMALS, RE_BAKE_TEXTURE, RE_BAKE_DISPLACEMENT, RE_BAKE_DERIVATIVE, RE_BAKE_VERTEX_COLORS);
re->main= bmain;
re->scene= scene;
@@ -5858,7 +5857,7 @@ void RE_Database_Baking(Render *re, Main *bmain, Scene *scene, unsigned int lay,
if (type==RE_BAKE_VERTEX_COLORS)
re->flag |= R_NEED_VCOL;
- if (!actob && ELEM6(type, RE_BAKE_LIGHT, RE_BAKE_NORMALS, RE_BAKE_TEXTURE, RE_BAKE_DISPLACEMENT, RE_BAKE_DERIVATIVE, RE_BAKE_VERTEX_COLORS)) {
+ if (!actob && ELEM(type, RE_BAKE_LIGHT, RE_BAKE_NORMALS, RE_BAKE_TEXTURE, RE_BAKE_DISPLACEMENT, RE_BAKE_DERIVATIVE, RE_BAKE_VERTEX_COLORS)) {
re->r.mode &= ~R_SHADOW;
re->r.mode &= ~R_RAYTRACE;
}
diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c
index 58e3038682c..3c35d500948 100644
--- a/source/blender/render/intern/source/external_engine.c
+++ b/source/blender/render/intern/source/external_engine.c
@@ -425,7 +425,7 @@ bool RE_bake_has_engine(Render *re)
bool RE_bake_engine(
Render *re, Object *object, const BakePixel pixel_array[],
- const int num_pixels, const int depth,
+ const size_t num_pixels, const int depth,
const ScenePassType pass_type, float result[])
{
RenderEngineType *type = RE_engines_find(re->r.engine);
diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c
index 2131b820bd4..9e14645a732 100644
--- a/source/blender/render/intern/source/pipeline.c
+++ b/source/blender/render/intern/source/pipeline.c
@@ -1935,6 +1935,8 @@ static void add_freestyle(Render *re, int render)
{
SceneRenderLayer *srl, *actsrl;
LinkData *link;
+ Render *r;
+ const bool do_link = (re->r.mode & R_MBLUR) == 0 || re->i.curblur == re->r.mblur_samples;
actsrl = BLI_findlink(&re->r.layers, re->r.actlay);
@@ -1951,15 +1953,17 @@ static void add_freestyle(Render *re, int render)
FRS_init_stroke_rendering(re);
- for (srl= (SceneRenderLayer *)re->r.layers.first; srl; srl= srl->next) {
-
- link = (LinkData *)MEM_callocN(sizeof(LinkData), "LinkData to Freestyle render");
- BLI_addtail(&re->freestyle_renders, link);
-
+ for (srl = (SceneRenderLayer *)re->r.layers.first; srl; srl = srl->next) {
+ if (do_link) {
+ link = (LinkData *)MEM_callocN(sizeof(LinkData), "LinkData to Freestyle render");
+ BLI_addtail(&re->freestyle_renders, link);
+ }
if ((re->r.scemode & R_SINGLE_LAYER) && srl != actsrl)
continue;
if (FRS_is_freestyle_enabled(srl)) {
- link->data = (void *)FRS_do_stroke_rendering(re, srl, render);
+ r = FRS_do_stroke_rendering(re, srl, render);
+ if (do_link)
+ link->data = (void *)r;
}
}
diff --git a/source/blender/render/intern/source/render_texture.c b/source/blender/render/intern/source/render_texture.c
index 253f8a1383f..dd14c2495e8 100644
--- a/source/blender/render/intern/source/render_texture.c
+++ b/source/blender/render/intern/source/render_texture.c
@@ -3564,7 +3564,7 @@ Material *RE_init_sample_material(Material *orig_mat, Scene *scene)
/* depending of material type, strip non-compatible mapping modes */
if (mat->material_type == MA_TYPE_SURFACE) {
- if (!ELEM4(mtex->texco, TEXCO_ORCO, TEXCO_OBJECT, TEXCO_GLOB, TEXCO_UV)) {
+ if (!ELEM(mtex->texco, TEXCO_ORCO, TEXCO_OBJECT, TEXCO_GLOB, TEXCO_UV)) {
/* ignore this texture */
mtex->texco = 0;
continue;
@@ -3573,7 +3573,7 @@ Material *RE_init_sample_material(Material *orig_mat, Scene *scene)
mtex->mapto = (mtex->mapto & MAP_COL) | (mtex->mapto & MAP_ALPHA);
}
else if (mat->material_type == MA_TYPE_VOLUME) {
- if (!ELEM3(mtex->texco, TEXCO_OBJECT, TEXCO_ORCO, TEXCO_GLOB)) {
+ if (!ELEM(mtex->texco, TEXCO_OBJECT, TEXCO_ORCO, TEXCO_GLOB)) {
/* ignore */
mtex->texco = 0;
continue;
diff --git a/source/blender/render/intern/source/shadbuf.c b/source/blender/render/intern/source/shadbuf.c
index 9d337e542a1..aa420d7e7c8 100644
--- a/source/blender/render/intern/source/shadbuf.c
+++ b/source/blender/render/intern/source/shadbuf.c
@@ -784,7 +784,7 @@ void makeshadowbuf(Render *re, LampRen *lar)
perspective_m4(shb->winmat, -wsize, wsize, -wsize, wsize, shb->d, shb->clipend);
mul_m4_m4m4(shb->persmat, shb->winmat, shb->viewmat);
- if (ELEM3(lar->buftype, LA_SHADBUF_REGULAR, LA_SHADBUF_HALFWAY, LA_SHADBUF_DEEP)) {
+ if (ELEM(lar->buftype, LA_SHADBUF_REGULAR, LA_SHADBUF_HALFWAY, LA_SHADBUF_DEEP)) {
shb->totbuf= lar->buffers;
/* jitter, weights - not threadsafe! */
diff --git a/source/blender/render/intern/source/volumetric.c b/source/blender/render/intern/source/volumetric.c
index fe3af5b840e..d5c4c407bf6 100644
--- a/source/blender/render/intern/source/volumetric.c
+++ b/source/blender/render/intern/source/volumetric.c
@@ -499,7 +499,7 @@ static void vol_shade_one_lamp(struct ShadeInput *shi, const float co[3], const
if (shi->mat->vol.shade_type == MA_VOL_SHADE_SHADOWED) {
mul_v3_fl(lacol, vol_get_shadow(shi, lar, co));
}
- else if (ELEM3(shi->mat->vol.shade_type, MA_VOL_SHADE_SHADED, MA_VOL_SHADE_MULTIPLE, MA_VOL_SHADE_SHADEDPLUSMULTIPLE)) {
+ else if (ELEM(shi->mat->vol.shade_type, MA_VOL_SHADE_SHADED, MA_VOL_SHADE_MULTIPLE, MA_VOL_SHADE_SHADEDPLUSMULTIPLE)) {
Isect is;
if (shi->mat->vol.shadeflag & MA_VOL_RECV_EXT_SHADOW) {
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index cfa795cb3b7..253976052fd 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -344,8 +344,10 @@ void WM_event_print(const struct wmEvent *event);
void WM_operator_region_active_win_set(struct bContext *C);
/* drag and drop */
-struct wmDrag *WM_event_start_drag(struct bContext *C, int icon, int type, void *poin, double value);
+struct wmDrag *WM_event_start_drag(struct bContext *C, int icon, int type, void *poin, double value, unsigned int flags);
void WM_event_drag_image(struct wmDrag *, struct ImBuf *, float scale, int sx, int sy);
+void WM_drag_free(struct wmDrag *drag);
+void WM_drag_free_list(struct ListBase *lb);
struct wmDropBox *WM_dropbox_add(ListBase *lb, const char *idname, int (*poll)(struct bContext *, struct wmDrag *, const struct wmEvent *event),
void (*copy)(struct wmDrag *, struct wmDropBox *));
diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h
index 9ad1bc97f4d..123a07d281c 100644
--- a/source/blender/windowmanager/WM_types.h
+++ b/source/blender/windowmanager/WM_types.h
@@ -597,6 +597,12 @@ typedef struct wmReport {
#define WM_DRAG_PATH 2
#define WM_DRAG_NAME 3
#define WM_DRAG_VALUE 4
+#define WM_DRAG_COLOR 5
+
+typedef enum wmDragFlags {
+ WM_DRAG_NOP = 0,
+ WM_DRAG_FREE_DATA = 1,
+} wmDragFlags;
/* note: structs need not exported? */
@@ -613,6 +619,7 @@ typedef struct wmDrag {
int sx, sy;
char opname[200]; /* if set, draws operator name*/
+ unsigned int flags;
} wmDrag;
/* dropboxes are like keymaps, part of the screen/area/region definition */
diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c
index 28bddb47778..d05cc572c45 100644
--- a/source/blender/windowmanager/intern/wm.c
+++ b/source/blender/windowmanager/intern/wm.c
@@ -462,7 +462,8 @@ void wm_close_and_free(bContext *C, wmWindowManager *wm)
BLI_freelistN(&wm->queue);
BLI_freelistN(&wm->paintcursors);
- BLI_freelistN(&wm->drags);
+
+ WM_drag_free_list(&wm->drags);
wm_reports_free(wm);
diff --git a/source/blender/windowmanager/intern/wm_dragdrop.c b/source/blender/windowmanager/intern/wm_dragdrop.c
index 2aa177602cb..e5bba9285b4 100644
--- a/source/blender/windowmanager/intern/wm_dragdrop.c
+++ b/source/blender/windowmanager/intern/wm_dragdrop.c
@@ -143,7 +143,7 @@ void wm_dropbox_free(void)
/* *********************************** */
/* note that the pointer should be valid allocated and not on stack */
-wmDrag *WM_event_start_drag(struct bContext *C, int icon, int type, void *poin, double value)
+wmDrag *WM_event_start_drag(struct bContext *C, int icon, int type, void *poin, double value, unsigned int flags)
{
wmWindowManager *wm = CTX_wm_manager(C);
wmDrag *drag = MEM_callocN(sizeof(struct wmDrag), "new drag");
@@ -152,6 +152,7 @@ wmDrag *WM_event_start_drag(struct bContext *C, int icon, int type, void *poin,
/* if multiple drags are added, they're drawn as list */
BLI_addtail(&wm->drags, drag);
+ drag->flags = flags;
drag->icon = icon;
drag->type = type;
if (type == WM_DRAG_PATH)
@@ -171,6 +172,22 @@ void WM_event_drag_image(wmDrag *drag, ImBuf *imb, float scale, int sx, int sy)
drag->sy = sy;
}
+void WM_drag_free(wmDrag *drag)
+{
+ if ((drag->flags & WM_DRAG_FREE_DATA) && drag->poin) {
+ MEM_freeN(drag->poin);
+ }
+
+ MEM_freeN(drag);
+}
+
+void WM_drag_free_list(struct ListBase *lb)
+{
+ wmDrag *drag;
+ while ((drag = BLI_pophead(lb))) {
+ WM_drag_free(drag);
+ }
+}
static const char *dropbox_active(bContext *C, ListBase *handlers, wmDrag *drag, wmEvent *event)
{
diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c
index 96824eca578..2f20e8c234f 100644
--- a/source/blender/windowmanager/intern/wm_draw.c
+++ b/source/blender/windowmanager/intern/wm_draw.c
@@ -592,7 +592,7 @@ static void wm_method_draw_triple(bContext *C, wmWindow *win)
bScreen *screen = win->screen;
ScrArea *sa;
ARegion *ar;
- int copytex = 0, paintcursor = 1;
+ int copytex = 0;
if (win->drawdata) {
glClearColor(0, 0, 0, 0);
@@ -639,7 +639,7 @@ static void wm_method_draw_triple(bContext *C, wmWindow *win)
wm_triple_copy_textures(win, triple);
}
- if (paintcursor && wm->paintcursors.first) {
+ if (wm->paintcursors.first) {
for (sa = screen->areabase.first; sa; sa = sa->next) {
for (ar = sa->regionbase.first; ar; ar = ar->next) {
if (ar->swinid && ar->swinid == screen->subwinactive) {
@@ -685,8 +685,6 @@ static void wm_method_draw_triple(bContext *C, wmWindow *win)
CTX_wm_menu_set(C, ar);
ED_region_do_draw(C, ar);
CTX_wm_menu_set(C, NULL);
- /* when a menu is being drawn, don't do the paint cursors */
- paintcursor = 0;
}
}
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index 9f1359dfb9b..7e2b7f2eb65 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -111,10 +111,13 @@ void wm_event_free(wmEvent *event)
if (event->customdata) {
if (event->customdatafree) {
/* note: pointer to listbase struct elsewhere */
- if (event->custom == EVT_DATA_LISTBASE)
- BLI_freelistN(event->customdata);
- else
+ if (event->custom == EVT_DATA_DRAGDROP) {
+ ListBase *lb = event->customdata;
+ WM_drag_free_list(lb);
+ }
+ else {
MEM_freeN(event->customdata);
+ }
}
}
@@ -289,7 +292,7 @@ void wm_event_do_notifiers(bContext *C)
do_anim = true;
}
}
- if (ELEM5(note->category, NC_SCENE, NC_OBJECT, NC_GEOM, NC_SCENE, NC_WM)) {
+ if (ELEM(note->category, NC_SCENE, NC_OBJECT, NC_GEOM, NC_SCENE, NC_WM)) {
ED_info_stats_clear(win->screen->scene);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_INFO, NULL);
}
@@ -393,7 +396,7 @@ static int wm_handler_ui_call(bContext *C, wmEventHandler *handler, wmEvent *eve
ARegion *region = CTX_wm_region(C);
ARegion *menu = CTX_wm_menu(C);
static bool do_wheel_ui = true;
- const bool is_wheel = ELEM3(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE, MOUSEPAN);
+ const bool is_wheel = ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE, MOUSEPAN);
int retval;
/* UI code doesn't handle return values - it just always returns break.
@@ -1934,17 +1937,17 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers
wmDropBox *drop = handler->dropboxes->first;
for (; drop; drop = drop->next) {
/* other drop custom types allowed */
- if (event->custom == EVT_DATA_LISTBASE) {
+ if (event->custom == EVT_DATA_DRAGDROP) {
ListBase *lb = (ListBase *)event->customdata;
wmDrag *drag;
for (drag = lb->first; drag; drag = drag->next) {
if (drop->poll(C, drag, event)) {
-
drop->copy(drag, drop);
/* free the drags before calling operator */
- BLI_freelistN(event->customdata);
+ WM_drag_free_list(lb);
+
event->customdata = NULL;
event->custom = 0;
@@ -2010,7 +2013,7 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers)
if (CTX_wm_window(C) == NULL)
return action;
- if (!ELEM3(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE, EVENT_NONE) && !ISTIMER(event->type)) {
+ if (!ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE, EVENT_NONE) && !ISTIMER(event->type)) {
/* test for CLICK events */
if (wm_action_not_handled(action)) {
@@ -2146,10 +2149,12 @@ static void wm_event_drag_test(wmWindowManager *wm, wmWindow *win, wmEvent *even
return;
}
- if (event->type == MOUSEMOVE || ISKEYMODIFIER(event->type))
+ if (event->type == MOUSEMOVE || ISKEYMODIFIER(event->type)) {
win->screen->do_draw_drag = true;
+ }
else if (event->type == ESCKEY) {
- BLI_freelistN(&wm->drags);
+ WM_drag_free_list(&wm->drags);
+
win->screen->do_draw_drag = true;
}
else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
@@ -2161,7 +2166,7 @@ static void wm_event_drag_test(wmWindowManager *wm, wmWindow *win, wmEvent *even
MEM_freeN(event->customdata);
}
- event->custom = EVT_DATA_LISTBASE;
+ event->custom = EVT_DATA_DRAGDROP;
event->customdata = &wm->drags;
event->customdatafree = 1;
@@ -2694,7 +2699,7 @@ bool WM_modal_tweak_exit(const wmEvent *event, int tweak_event)
else {
/* if the initial event wasn't a tweak event then
* ignore USER_RELEASECONFIRM setting: see [#26756] */
- if (ELEM3(tweak_event, EVT_TWEAK_L, EVT_TWEAK_M, EVT_TWEAK_R) == 0) {
+ if (ELEM(tweak_event, EVT_TWEAK_L, EVT_TWEAK_M, EVT_TWEAK_R) == 0) {
return 1;
}
}
diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c
index 0bc6442348c..3c28d2b93cd 100644
--- a/source/blender/windowmanager/intern/wm_files.c
+++ b/source/blender/windowmanager/intern/wm_files.c
@@ -278,11 +278,13 @@ static void wm_window_match_do(bContext *C, ListBase *oldwmlist)
/* in case UserDef was read, we re-initialize all, and do versioning */
static void wm_init_userdef(bContext *C, const bool from_memory)
{
+ Main *bmain = CTX_data_main(C);
+
/* versioning is here */
UI_init_userdef();
MEM_CacheLimiter_set_maximum(((size_t)U.memcachelimit) * 1024 * 1024);
- sound_init(CTX_data_main(C));
+ sound_init(bmain);
/* needed so loading a file from the command line respects user-pref [#26156] */
BKE_BIT_TEST_SET(G.fileflags, U.flag & USER_FILENOUI, G_FILE_NO_UI);
@@ -295,7 +297,7 @@ static void wm_init_userdef(bContext *C, const bool from_memory)
/* avoid re-saving for every small change to our prefs, allow overrides */
if (from_memory) {
- UI_init_userdef_factory();
+ BLO_update_defaults_userpref_blend();
}
/* update tempdir from user preferences */
diff --git a/source/blender/windowmanager/intern/wm_gesture.c b/source/blender/windowmanager/intern/wm_gesture.c
index c9ef473a442..3e287a3907b 100644
--- a/source/blender/windowmanager/intern/wm_gesture.c
+++ b/source/blender/windowmanager/intern/wm_gesture.c
@@ -74,7 +74,7 @@ wmGesture *WM_gesture_new(bContext *C, const wmEvent *event, int type)
wm_subwindow_origin_get(window, gesture->swinid, &sx, &sy);
- if (ELEM5(type, WM_GESTURE_RECT, WM_GESTURE_CROSS_RECT, WM_GESTURE_TWEAK,
+ if (ELEM(type, WM_GESTURE_RECT, WM_GESTURE_CROSS_RECT, WM_GESTURE_TWEAK,
WM_GESTURE_CIRCLE, WM_GESTURE_STRAIGHTLINE))
{
rcti *rect = MEM_callocN(sizeof(rcti), "gesture rect new");
diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c
index 0163517545f..a95f2af1a8f 100644
--- a/source/blender/windowmanager/intern/wm_keymap.c
+++ b/source/blender/windowmanager/intern/wm_keymap.c
@@ -1108,9 +1108,9 @@ int WM_keymap_item_compare(wmKeyMapItem *k1, wmKeyMapItem *k2)
if (k1->val != KM_ANY && k2->val != KM_ANY) {
/* take click, press, release conflict into account */
- if (k1->val == KM_CLICK && ELEM3(k2->val, KM_PRESS, KM_RELEASE, KM_CLICK) == 0)
+ if (k1->val == KM_CLICK && ELEM(k2->val, KM_PRESS, KM_RELEASE, KM_CLICK) == 0)
return 0;
- if (k2->val == KM_CLICK && ELEM3(k1->val, KM_PRESS, KM_RELEASE, KM_CLICK) == 0)
+ if (k2->val == KM_CLICK && ELEM(k1->val, KM_PRESS, KM_RELEASE, KM_CLICK) == 0)
return 0;
if (k1->val != k2->val)
return 0;
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index ba454bb1818..0239175835e 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -501,7 +501,7 @@ void WM_operator_py_idname(char *to, const char *from)
int ofs = (sep - from);
/* note, we use ascii tolower instead of system tolower, because the
- * latter depends on the locale, and can lead to idname mistmatch */
+ * latter depends on the locale, and can lead to idname mismatch */
memcpy(to, from, sizeof(char) * ofs);
BLI_ascii_strtolower(to, ofs);
@@ -3291,7 +3291,7 @@ void wm_tweakevent_test(bContext *C, wmEvent *event, int action)
if (win->tweak == NULL) {
if (CTX_wm_region(C)) {
if (event->val == KM_PRESS) {
- if (ELEM3(event->type, LEFTMOUSE, MIDDLEMOUSE, RIGHTMOUSE)) {
+ if (ELEM(event->type, LEFTMOUSE, MIDDLEMOUSE, RIGHTMOUSE)) {
win->tweak = WM_gesture_new(C, event, WM_GESTURE_TWEAK);
}
}
@@ -4032,7 +4032,7 @@ static int radial_control_invoke(bContext *C, wmOperator *op, const wmEvent *eve
/* get subtype of property */
rc->subtype = RNA_property_subtype(rc->prop);
- if (!ELEM5(rc->subtype, PROP_NONE, PROP_DISTANCE, PROP_FACTOR, PROP_ANGLE, PROP_PIXEL)) {
+ if (!ELEM(rc->subtype, PROP_NONE, PROP_DISTANCE, PROP_FACTOR, PROP_ANGLE, PROP_PIXEL)) {
BKE_report(op->reports, RPT_ERROR, "Property must be a none, distance, a factor, or an angle");
MEM_freeN(rc);
return OPERATOR_CANCELLED;
@@ -4165,8 +4165,6 @@ static int radial_control_modal(bContext *C, wmOperator *op, const wmEvent *even
static void WM_OT_radial_control(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
ot->name = "Radial Control";
ot->idname = "WM_OT_radial_control";
ot->description = "Set some size property (like e.g. brush size) with mouse wheel";
@@ -4178,32 +4176,23 @@ static void WM_OT_radial_control(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
/* all paths relative to the context */
- prop = RNA_def_string(ot->srna, "data_path_primary", NULL, 0, "Primary Data Path", "Primary path of property to be set by the radial control");
- RNA_def_property_flag(prop, PROP_HIDDEN);
+ RNA_def_string(ot->srna, "data_path_primary", NULL, 0, "Primary Data Path", "Primary path of property to be set by the radial control");
- prop = RNA_def_string(ot->srna, "data_path_secondary", NULL, 0, "Secondary Data Path", "Secondary path of property to be set by the radial control");
- RNA_def_property_flag(prop, PROP_HIDDEN);
+ RNA_def_string(ot->srna, "data_path_secondary", NULL, 0, "Secondary Data Path", "Secondary path of property to be set by the radial control");
- prop = RNA_def_string(ot->srna, "use_secondary", NULL, 0, "Use Secondary", "Path of property to select between the primary and secondary data paths");
- RNA_def_property_flag(prop, PROP_HIDDEN);
+ RNA_def_string(ot->srna, "use_secondary", NULL, 0, "Use Secondary", "Path of property to select between the primary and secondary data paths");
- prop = RNA_def_string(ot->srna, "rotation_path", NULL, 0, "Rotation Path", "Path of property used to rotate the texture display");
- RNA_def_property_flag(prop, PROP_HIDDEN);
+ RNA_def_string(ot->srna, "rotation_path", NULL, 0, "Rotation Path", "Path of property used to rotate the texture display");
- prop = RNA_def_string(ot->srna, "color_path", NULL, 0, "Color Path", "Path of property used to set the color of the control");
- RNA_def_property_flag(prop, PROP_HIDDEN);
+ RNA_def_string(ot->srna, "color_path", NULL, 0, "Color Path", "Path of property used to set the color of the control");
- prop = RNA_def_string(ot->srna, "fill_color_path", NULL, 0, "Fill Color Path", "Path of property used to set the fill color of the control");
- RNA_def_property_flag(prop, PROP_HIDDEN);
+ RNA_def_string(ot->srna, "fill_color_path", NULL, 0, "Fill Color Path", "Path of property used to set the fill color of the control");
- prop = RNA_def_string(ot->srna, "zoom_path", NULL, 0, "Zoom Path", "Path of property used to set the zoom level for the control");
- RNA_def_property_flag(prop, PROP_HIDDEN);
+ RNA_def_string(ot->srna, "zoom_path", NULL, 0, "Zoom Path", "Path of property used to set the zoom level for the control");
- prop = RNA_def_string(ot->srna, "image_id", NULL, 0, "Image ID", "Path of ID that is used to generate an image for the control");
- RNA_def_property_flag(prop, PROP_HIDDEN);
+ RNA_def_string(ot->srna, "image_id", NULL, 0, "Image ID", "Path of ID that is used to generate an image for the control");
- prop = RNA_def_boolean(ot->srna, "secondary_tex", 0, "Secondary Texture", "Tweak brush secondary/mask texture");
- RNA_def_property_flag(prop, PROP_HIDDEN);
+ RNA_def_boolean(ot->srna, "secondary_tex", 0, "Secondary Texture", "Tweak brush secondary/mask texture");
}
/* ************************** timer for testing ***************** */
diff --git a/source/blender/windowmanager/intern/wm_subwindow.c b/source/blender/windowmanager/intern/wm_subwindow.c
index 1792ea40a1a..db4459b1799 100644
--- a/source/blender/windowmanager/intern/wm_subwindow.c
+++ b/source/blender/windowmanager/intern/wm_subwindow.c
@@ -308,7 +308,7 @@ void wmSubWindowScissorSet(wmWindow *win, int swinid, const rcti *srct, bool src
int scissor_height = BLI_rcti_size_y(srct);
/* typically a single pixel doesn't matter,
- * but one pixel offset is noticable with viewport border render */
+ * but one pixel offset is noticeable with viewport border render */
if (srct_pad) {
scissor_width += 1;
scissor_height += 1;
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c
index b30fadd46e6..56e094891f5 100644
--- a/source/blender/windowmanager/intern/wm_window.c
+++ b/source/blender/windowmanager/intern/wm_window.c
@@ -1016,7 +1016,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr
/* make blender drop event with custom data pointing to wm drags */
event.type = EVT_DROP;
event.val = KM_RELEASE;
- event.custom = EVT_DATA_LISTBASE;
+ event.custom = EVT_DATA_DRAGDROP;
event.customdata = &wm->drags;
event.customdatafree = 1;
@@ -1035,7 +1035,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr
/* try to get icon type from extension */
icon = ED_file_extension_icon((char *)stra->strings[a]);
- WM_event_start_drag(C, icon, WM_DRAG_PATH, stra->strings[a], 0.0);
+ WM_event_start_drag(C, icon, WM_DRAG_PATH, stra->strings[a], 0.0, WM_DRAG_NOP);
/* void poin should point to string, it makes a copy */
break; /* only one drop element supported now */
}
diff --git a/source/blender/windowmanager/wm_event_types.h b/source/blender/windowmanager/wm_event_types.h
index 4a274d25170..6d3cdf6a270 100644
--- a/source/blender/windowmanager/wm_event_types.h
+++ b/source/blender/windowmanager/wm_event_types.h
@@ -38,7 +38,7 @@
/* customdata type */
#define EVT_DATA_GESTURE 1
#define EVT_DATA_TIMER 2
-#define EVT_DATA_LISTBASE 3
+#define EVT_DATA_DRAGDROP 3
#define EVT_DATA_NDOF_MOTION 4
/* tablet active, matches GHOST_TTabletMode */
diff --git a/source/blenderplayer/CMakeLists.txt b/source/blenderplayer/CMakeLists.txt
index e0365f9ea6c..188fb01d23d 100644
--- a/source/blenderplayer/CMakeLists.txt
+++ b/source/blenderplayer/CMakeLists.txt
@@ -228,3 +228,9 @@ if(WITH_PLAYER)
endif()
setup_liblinks(blenderplayer)
+
+# We put CLEW and CUEW here because OPENSUBDIV_LIBRARIES dpeends on them..
+if(WITH_CYCLES OR WITH_COMPOSITOR OR WITH_OPENSUBDIV)
+ target_link_libraries(blenderplayer "extern_clew")
+ target_link_libraries(blenderplayer "extern_cuew")
+endif()
diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c
index 5fa8a119488..318f10b8baa 100644
--- a/source/blenderplayer/bad_level_call_stubs/stubs.c
+++ b/source/blenderplayer/bad_level_call_stubs/stubs.c
@@ -414,7 +414,7 @@ void ED_view3D_background_image_remove(struct View3D *v3d, struct BGpic *bgpic)
void ED_view3D_background_image_clear(struct View3D *v3d) RET_NONE
void ED_view3d_update_viewmat(struct Scene *scene, struct View3D *v3d, struct ARegion *ar, float viewmat[4][4], float winmat[4][4]) RET_NONE
float ED_view3d_grid_scale(struct Scene *scene, struct View3D *v3d, const char **grid_unit) RET_ZERO
-void ED_view3d_shade_update(struct Main *bmain, struct View3D *v3d, struct ScrArea *sa) RET_NONE
+void ED_view3d_shade_update(struct Main *bmain, struct Scene *scene, struct View3D *v3d, struct ScrArea *sa) RET_NONE
void ED_node_shader_default(const struct bContext *C, struct ID *id) RET_NONE
void ED_screen_animation_timer_update(struct bScreen *screen, int redraws, int refresh) RET_NONE
struct bScreen *ED_screen_animation_playing(const struct wmWindowManager *wm) RET_NULL
@@ -564,6 +564,7 @@ void uiTemplateColorspaceSettings(struct uiLayout *layout, struct PointerRNA *pt
void uiTemplateColormanagedViewSettings(struct uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, const char *propname) RET_NONE
void uiTemplateComponentMenu(struct uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *name) RET_NONE
void uiTemplateNodeSocket(struct uiLayout *layout, struct bContext *C, float *color) RET_NONE
+void uiTemplatePalette(struct uiLayout *layout, struct PointerRNA *ptr, const char *propname, int color) RET_NONE
/* rna render */
struct RenderResult *RE_engine_begin_result(RenderEngine *engine, int x, int y, int w, int h, const char *layername) RET_NULL
diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt
index 8deadb9c7b7..fbda69225b3 100644
--- a/source/creator/CMakeLists.txt
+++ b/source/creator/CMakeLists.txt
@@ -274,7 +274,7 @@ elseif(APPLE)
if(WITH_PYTHON_MODULE)
set(TARGETDIR_VER ${TARGETDIR}/${BLENDER_VERSION})
else()
- set(TARGETDIR_VER ${TARGETDIR}/blender.app/Contents/MacOS/${BLENDER_VERSION})
+ set(TARGETDIR_VER ${TARGETDIR}/blender.app/Contents/Resources/${BLENDER_VERSION})
endif()
endif()
@@ -511,16 +511,22 @@ if(UNIX AND NOT APPLE)
PATTERN "idlelib" EXCLUDE # ./idlelib
PATTERN "test" EXCLUDE # ./test
PATTERN "turtledemo" EXCLUDE # ./turtledemo
- PATTERN "turtle.py" EXCLUDE # ./turtle.py
+ PATTERN "turtle.py" EXCLUDE # ./turtle.py
)
# # doesnt work, todo
# install(CODE "execute_process(COMMAND find ${TARGETDIR}/${BLENDER_VERSION}/python/lib/ -name '*.so' -exec strip -s {} '\;')")
-
+
if(WITH_PYTHON_INSTALL_NUMPY)
+ # Install to the same directory as the source, so debian-like
+ # distros are happy with their policy.
+ set(_suffix "site-packages")
+ if(${PYTHON_NUMPY_PATH} MATCHES "dist-packages")
+ set(_suffix "dist-packages")
+ endif()
install(
DIRECTORY ${PYTHON_NUMPY_PATH}/numpy
- DESTINATION ${TARGETDIR_VER}/python/${_target_LIB}/python${PYTHON_VERSION}/site-packages
+ DESTINATION ${TARGETDIR_VER}/python/${_target_LIB}/python${PYTHON_VERSION}/${_suffix}
PATTERN ".svn" EXCLUDE
PATTERN "__pycache__" EXCLUDE # * any cache *
PATTERN "*.pyc" EXCLUDE # * any cache *
@@ -534,19 +540,47 @@ if(UNIX AND NOT APPLE)
PATTERN "*.h" EXCLUDE # some includes are not in include dirs
PATTERN "*.a" EXCLUDE # ./core/lib/libnpymath.a - for linking, we dont need.
)
+ unset(_suffix)
endif()
# Copy requests, we need to generalize site-packages
if(WITH_PYTHON_INSTALL_REQUESTS)
+ set(_suffix "site-packages")
+ if(${PYTHON_REQUESTS_PATH} MATCHES "dist-packages")
+ set(_suffix "dist-packages")
+ endif()
install(
- DIRECTORY ${PYTHON_LIBPATH}/python${PYTHON_VERSION}/site-packages/requests
- DESTINATION ${TARGETDIR_VER}/python/${_target_LIB}/python${PYTHON_VERSION}/site-packages
+ DIRECTORY ${PYTHON_REQUESTS_PATH}/requests
+ DESTINATION ${TARGETDIR_VER}/python/${_target_LIB}/python${PYTHON_VERSION}/${_suffix}
PATTERN ".svn" EXCLUDE
PATTERN "__pycache__" EXCLUDE # * any cache *
PATTERN "*.pyc" EXCLUDE # * any cache *
PATTERN "*.pyo" EXCLUDE # * any cache *
PATTERN "cacert.pem" EXCLUDE # for now we don't deal with security
)
+ # On some platforms requests does have extra dependencies.
+ set(_requests_deps "chardet" "urllib3")
+ foreach(_requests_dep ${_requests_deps})
+ if(EXISTS ${PYTHON_REQUESTS_PATH}/${_requests_dep})
+ install(
+ DIRECTORY ${PYTHON_REQUESTS_PATH}/${_requests_dep}
+ DESTINATION ${TARGETDIR_VER}/python/${_target_LIB}/python${PYTHON_VERSION}/${_suffix}
+ PATTERN ".svn" EXCLUDE
+ PATTERN "__pycache__" EXCLUDE # * any cache *
+ PATTERN "*.pyc" EXCLUDE # * any cache *
+ PATTERN "*.pyo" EXCLUDE # * any cache *
+ )
+ endif()
+ endforeach()
+ if(EXISTS ${PYTHON_REQUESTS_PATH}/six.py)
+ install(
+ FILES ${PYTHON_REQUESTS_PATH}/six.py
+ DESTINATION ${TARGETDIR_VER}/python/${_target_LIB}/python${PYTHON_VERSION}/${_suffix}
+ )
+ endif()
+ unset(_requests_dep)
+ unset(_requests_deps)
+ unset(_suffix)
endif()
unset(_target_LIB)
@@ -703,12 +737,10 @@ elseif(WIN32)
endif()
if(WITH_SDL)
- if(NOT CMAKE_CL_64)
- install(
- FILES ${LIBDIR}/sdl/lib/SDL.dll
- DESTINATION ${TARGETDIR}
- )
- endif()
+ install(
+ FILES ${LIBDIR}/sdl/lib/SDL.dll
+ DESTINATION ${TARGETDIR}
+ )
endif()
if(NOT CMAKE_CL_64)
@@ -794,6 +826,13 @@ elseif(APPLE)
)
endif()
+ if(WITH_LLVM AND NOT LLVM_STATIC)
+ install(
+ FILES ${LIBDIR}/llvm/lib/libLLVM-3.4.dylib
+ DESTINATION ${TARGETDIR}/blender.app/Contents/MacOS
+ )
+ endif()
+
# python
if(WITH_PYTHON AND NOT WITH_PYTHON_MODULE AND NOT WITH_PYTHON_FRAMEWORK)
# the python zip is first extract as part of the build process,
@@ -893,3 +932,18 @@ setup_blender_sorted_libs()
target_link_libraries(blender ${BLENDER_SORTED_LIBS})
setup_liblinks(blender)
+
+# -----------------------------------------------------------------------------
+# Setup launcher
+
+if(WIN32 AND NOT WITH_PYTHON_MODULE)
+ set(LAUNCHER_SRC
+ creator_launch_win.c
+ ../icons/winblender.rc
+ )
+ add_executable(blender-launcher ${LAUNCHER_SRC})
+ target_link_libraries(blender-launcher ${PLATFORM_LINKLIBS})
+
+ set_target_properties(blender PROPERTIES OUTPUT_NAME blender-app)
+ set_target_properties(blender-launcher PROPERTIES OUTPUT_NAME blender)
+endif()
diff --git a/source/creator/creator_launch_win.c b/source/creator/creator_launch_win.c
new file mode 100644
index 00000000000..e998343c876
--- /dev/null
+++ b/source/creator/creator_launch_win.c
@@ -0,0 +1,69 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 by Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Sergey Sharybin.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/* Binary name to launch. */
+#define BLENDER_BINARY "blender-app.exe"
+
+#define WIN32_LEAN_AND_MEAN
+#include <stdio.h>
+#include <stdlib.h>
+#include <windows.h>
+
+int main(int argc, char **argv)
+{
+ PROCESS_INFORMATION processInformation = {0};
+ STARTUPINFOA startupInfo = {0};
+ BOOL result;
+ char command[65536];
+ int i, len = sizeof(command);
+
+ _putenv_s("OMP_WAIT_POLICY", "PASSIVE");
+
+ startupInfo.cb = sizeof(startupInfo);
+
+ strncpy(command, BLENDER_BINARY, len - 1);
+ len -= strlen(BLENDER_BINARY);
+ for (i = 1; i < argc; ++i) {
+ strncat(command, " ", len - 1);
+ strncat(command, argv[i], len - 2);
+ len -= strlen(argv[i]) + 1;
+ }
+
+ result = CreateProcessA(NULL, command, NULL, NULL, TRUE,
+ 0, NULL, NULL,
+ &startupInfo, &processInformation);
+
+ if (!result) {
+ fprintf(stderr, "Error launching " BLENDER_BINARY "\n");
+ return EXIT_FAILURE;
+ }
+
+ WaitForSingleObject(processInformation.hProcess, INFINITE);
+
+ CloseHandle(processInformation.hProcess);
+ CloseHandle(processInformation.hThread);
+
+ return EXIT_SUCCESS;
+}
diff --git a/source/creator/osx_locals.map b/source/creator/osx_locals.map
index c3dd8b62792..a1d7e7fed57 100644
--- a/source/creator/osx_locals.map
+++ b/source/creator/osx_locals.map
@@ -1,3 +1,5 @@
## The symbols will be treated as if they were marked as __private_extern__
## (aka visibility=hidden) and will not be global in the output file
*boost*
+*__ZNSt6vector*
+
diff --git a/source/gameengine/Converter/BL_ArmatureObject.cpp b/source/gameengine/Converter/BL_ArmatureObject.cpp
index e11bc84a0da..8d73e591113 100644
--- a/source/gameengine/Converter/BL_ArmatureObject.cpp
+++ b/source/gameengine/Converter/BL_ArmatureObject.cpp
@@ -101,7 +101,7 @@ static void game_copy_pose(bPose **dst, bPose *src, int copy_constraint)
out->chanhash = NULL;
out->agroups.first= out->agroups.last= NULL;
out->ikdata = NULL;
- out->ikparam = MEM_dupallocN(out->ikparam);
+ out->ikparam = MEM_dupallocN(src->ikparam);
out->flag |= POSE_GAME_ENGINE;
BLI_duplicatelist(&out->chanbase, &src->chanbase);
@@ -231,6 +231,8 @@ BL_ArmatureObject::BL_ArmatureObject(
m_objArma = BKE_object_copy(armature);
m_objArma->data = BKE_armature_copy((bArmature *)armature->data);
m_pose = m_objArma->pose;
+ // need this to get iTaSC working ok in the BGE
+ m_pose->flag |= POSE_GAME_ENGINE;
memcpy(m_obmat, m_objArma->obmat, sizeof(m_obmat));
}
diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
index e511f01e9c6..87b64582e11 100644
--- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp
+++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
@@ -876,7 +876,7 @@ static bool ConvertMaterial(
material->alphablend = GEMAT_ALPHA;
// always zsort alpha + add
- if ((ELEM3(material->alphablend, GEMAT_ALPHA, GEMAT_ALPHA_SORT, GEMAT_ADD) || texalpha) && (material->alphablend != GEMAT_CLIP )) {
+ if ((ELEM(material->alphablend, GEMAT_ALPHA, GEMAT_ALPHA_SORT, GEMAT_ADD) || texalpha) && (material->alphablend != GEMAT_CLIP )) {
material->ras_mode |= ALPHA;
material->ras_mode |= (mat && (mat->game.alpha_blend & GEMAT_ALPHA_SORT))? ZSORT: 0;
}
diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp
index 68a71218b8c..9ebdfea6156 100644
--- a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp
+++ b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp
@@ -616,7 +616,7 @@ void KX_BlenderMaterial::ActivateMeshSlot(const RAS_MeshSlot & ms, RAS_IRasteriz
/* we do blend modes here, because they can change per object
* with the same material due to obcolor/obalpha */
alphablend = mBlenderShader->GetAlphaBlend();
- if (ELEM3(alphablend, GEMAT_SOLID, GEMAT_ALPHA, GEMAT_ALPHA_SORT) && mMaterial->alphablend != GEMAT_SOLID)
+ if (ELEM(alphablend, GEMAT_SOLID, GEMAT_ALPHA, GEMAT_ALPHA_SORT) && mMaterial->alphablend != GEMAT_SOLID)
alphablend = mMaterial->alphablend;
rasty->SetAlphaBlend(alphablend);
diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp
index 639cd98bb47..c681e0842c4 100644
--- a/source/gameengine/Ketsji/KX_GameObject.cpp
+++ b/source/gameengine/Ketsji/KX_GameObject.cpp
@@ -51,6 +51,7 @@ typedef unsigned long uint_ptr;
#include "KX_Light.h" // only for their ::Type
#include "KX_FontObject.h" // only for their ::Type
#include "RAS_MeshObject.h"
+#include "KX_NavMeshObject.h"
#include "KX_MeshProxy.h"
#include "KX_PolyProxy.h"
#include <stdio.h> // printf
@@ -3795,7 +3796,8 @@ bool ConvertPythonToGameObject(PyObject *value, KX_GameObject **object, bool py_
if ( PyObject_TypeCheck(value, &KX_GameObject::Type) ||
PyObject_TypeCheck(value, &KX_LightObject::Type) ||
PyObject_TypeCheck(value, &KX_Camera::Type) ||
- PyObject_TypeCheck(value, &KX_FontObject::Type))
+ PyObject_TypeCheck(value, &KX_FontObject::Type) ||
+ PyObject_TypeCheck(value, &KX_NavMeshObject::Type))
{
*object = static_cast<KX_GameObject*>BGE_PROXY_REF(value);
diff --git a/source/gameengine/Ketsji/KX_Light.cpp b/source/gameengine/Ketsji/KX_Light.cpp
index 37c36da0db3..5b5981f930b 100644
--- a/source/gameengine/Ketsji/KX_Light.cpp
+++ b/source/gameengine/Ketsji/KX_Light.cpp
@@ -231,7 +231,7 @@ int KX_LightObject::pyattr_set_distance(void *self_v, const KX_PYATTRIBUTE_DEF *
else if (val > 5000.f)
val = 5000.f;
- self->m_lightobj->m_energy = val;
+ self->m_lightobj->m_distance = val;
return PY_SET_ATTR_SUCCESS;
}
diff --git a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp
index e21ac386bc8..a9f6bb0d2ff 100644
--- a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp
+++ b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp
@@ -72,9 +72,9 @@ KX_MouseFocusSensor::KX_MouseFocusSensor(SCA_MouseManager* eventmgr,
: SCA_MouseSensor(eventmgr, startx, starty, mousemode, gameobj),
m_focusmode(focusmode),
m_bTouchPulse(bTouchPulse),
- m_propertyname(propname),
- m_bFindMaterial(bFindMaterial),
m_bXRay(bXRay),
+ m_bFindMaterial(bFindMaterial),
+ m_propertyname(propname),
m_kxscene(kxscene),
m_kxengine(kxengine)
{
diff --git a/source/gameengine/Ketsji/KX_MouseFocusSensor.h b/source/gameengine/Ketsji/KX_MouseFocusSensor.h
index 903c3c03571..0c7c8ab676a 100644
--- a/source/gameengine/Ketsji/KX_MouseFocusSensor.h
+++ b/source/gameengine/Ketsji/KX_MouseFocusSensor.h
@@ -137,7 +137,7 @@ class KX_MouseFocusSensor : public SCA_MouseSensor
bool m_bTouchPulse;
/**
- * Flags get trought other objects
+ * Flags get through other objects
*/
bool m_bXRay;
diff --git a/source/gameengine/Ketsji/KX_NavMeshObject.cpp b/source/gameengine/Ketsji/KX_NavMeshObject.cpp
index 998b856497e..8360681759a 100644
--- a/source/gameengine/Ketsji/KX_NavMeshObject.cpp
+++ b/source/gameengine/Ketsji/KX_NavMeshObject.cpp
@@ -111,7 +111,7 @@ bool KX_NavMeshObject::BuildVertIndArrays(float *&vertices, int& nverts,
float *&dvertices, int &ndvertsuniq, unsigned short *&dtris,
int& ndtris, int &vertsPerPoly)
{
- DerivedMesh* dm = mesh_create_derived_no_virtual(KX_GetActiveScene()->GetBlenderScene(), GetBlenderObject(),
+ DerivedMesh* dm = mesh_create_derived_no_virtual(GetScene()->GetBlenderScene(), GetBlenderObject(),
NULL, CD_MASK_MESH);
CustomData *pdata = dm->getPolyDataLayout(dm);
int* recastData = (int*) CustomData_get_layer(pdata, CD_RECAST);
diff --git a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp
index e9843b0af5b..ebf1b9ec577 100644
--- a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp
+++ b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp
@@ -740,6 +740,7 @@ PyObject *initPythonConstraintBinding()
KX_MACRO_addTypesToDict(d, ANGULAR_CONSTRAINT, PHY_ANGULAR_CONSTRAINT);
KX_MACRO_addTypesToDict(d, CONETWIST_CONSTRAINT, PHY_CONE_TWIST_CONSTRAINT);
KX_MACRO_addTypesToDict(d, VEHICLE_CONSTRAINT, PHY_VEHICLE_CONSTRAINT);
+ KX_MACRO_addTypesToDict(d, GENERIC_6DOF_CONSTRAINT, PHY_GENERIC_6DOF_CONSTRAINT);
// Check for errors
if (PyErr_Occurred()) {
diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp
index bbf9f427a6c..dc603319df4 100644
--- a/source/gameengine/Ketsji/KX_PythonInit.cpp
+++ b/source/gameengine/Ketsji/KX_PythonInit.cpp
@@ -201,7 +201,16 @@ static PyObject *gp_OrigPythonSysModules= NULL;
//#define KX_MACRO_addToDict(dict, name) PyDict_SetItemString(dict, #name, PyLong_FromLong(SCA_IInputDevice::KX_##name))
//#define KX_MACRO_addToDict(dict, name) PyDict_SetItemString(dict, #name, item=PyLong_FromLong(name)); Py_DECREF(item)
/* For the defines for types from logic bricks, we do stuff explicitly... */
-#define KX_MACRO_addTypesToDict(dict, name, name2) PyDict_SetItemString(dict, #name, item=PyLong_FromLong(name2)); Py_DECREF(item)
+#define KX_MACRO_addTypesToDict(dict, name, value) KX_MACRO_addTypesToDict_fn(dict, #name, value)
+static void KX_MACRO_addTypesToDict_fn(PyObject *dict, const char *name, long value)
+{
+ PyObject *item;
+
+ item = PyLong_FromLong(value);
+ PyDict_SetItemString(dict, name, item);
+ Py_DECREF(item);
+}
+
// temporarily python stuff, will be put in another place later !
@@ -2270,7 +2279,6 @@ PyObject *initRasterizer(RAS_IRasterizer* rasty,RAS_ICanvas* canvas)
PyObject *m;
PyObject *d;
- PyObject *item;
/* Use existing module where possible
* be careful not to init any runtime vars after this */
@@ -2400,7 +2408,6 @@ PyObject *initGameKeys()
{
PyObject *m;
PyObject *d;
- PyObject *item;
/* Use existing module where possible */
m = PyImport_ImportModule( "GameKeys" );
diff --git a/source/gameengine/Ketsji/KX_SteeringActuator.cpp b/source/gameengine/Ketsji/KX_SteeringActuator.cpp
index 2fa72c04a20..ff192299702 100644
--- a/source/gameengine/Ketsji/KX_SteeringActuator.cpp
+++ b/source/gameengine/Ketsji/KX_SteeringActuator.cpp
@@ -602,7 +602,7 @@ int KX_SteeringActuator::pyattr_set_navmesh(void *self, const struct KX_PYATTRIB
if (!ConvertPythonToGameObject(value, &gameobj, true, "actuator.object = value: KX_SteeringActuator"))
return PY_SET_ATTR_FAIL; // ConvertPythonToGameObject sets the error
- if (!PyObject_TypeCheck(value, &KX_NavMeshObject::Type))
+ if (dynamic_cast<KX_NavMeshObject *>(gameobj) == NULL)
{
PyErr_Format(PyExc_TypeError, "KX_NavMeshObject is expected");
return PY_SET_ATTR_FAIL;
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
index db2c21226d8..e17d4402556 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
@@ -84,7 +84,7 @@ void DrawRasterizerLine(const float* from,const float* to,int color);
// This was copied from the old KX_ConvertPhysicsObjects
#ifdef WIN32
-#if defined(_MSC_VER) && (_MSC_VER >= 1310)
+#ifdef _MSC_VER
//only use SIMD Hull code under Win32
//#define TEST_HULL 1
#ifdef TEST_HULL
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageIM.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageIM.cpp
index b138f84ea97..c8975c245cb 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageIM.cpp
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageIM.cpp
@@ -247,7 +247,7 @@ void RAS_StorageIM::IndexPrimitivesInternal(RAS_MeshSlot& ms, bool multi)
//ms.m_pDerivedMesh->drawMappedFacesTex(ms.m_pDerivedMesh, CheckTexfaceDM, mcol);
current_blmat_nr = current_polymat->GetMaterialIndex();
current_image = current_polymat->GetBlenderImage();
- ms.m_pDerivedMesh->drawFacesTex(ms.m_pDerivedMesh, CheckTexDM, NULL, NULL);
+ ms.m_pDerivedMesh->drawFacesTex(ms.m_pDerivedMesh, CheckTexDM, NULL, NULL, DM_DRAW_USE_ACTIVE_UV);
}
return;
}
diff --git a/source/gameengine/VideoTexture/ImageBuff.cpp b/source/gameengine/VideoTexture/ImageBuff.cpp
index 6cc8d287e66..705d9136cbe 100644
--- a/source/gameengine/VideoTexture/ImageBuff.cpp
+++ b/source/gameengine/VideoTexture/ImageBuff.cpp
@@ -163,7 +163,7 @@ void ImageBuff::plot(unsigned char *img, short width, short height, short x, sho
// assign temporarily our buffer to the ImBuf buffer, we use the same format
tmpbuf->rect = (unsigned int*)img;
m_imbuf->rect = m_image;
- IMB_rectblend(m_imbuf, m_imbuf, tmpbuf, NULL, NULL, 0, x, y, x, y, 0, 0, width, height, (IMB_BlendMode)mode);
+ IMB_rectblend(m_imbuf, m_imbuf, tmpbuf, NULL, NULL, NULL, 0, x, y, x, y, 0, 0, width, height, (IMB_BlendMode)mode, false);
// remove so that MB_freeImBuf will free our buffer
m_imbuf->rect = NULL;
tmpbuf->rect = NULL;
@@ -186,7 +186,7 @@ void ImageBuff::plot(ImageBuff *img, short x, short y, short mode)
// assign temporarily our buffer to the ImBuf buffer, we use the same format
img->m_imbuf->rect = img->m_image;
m_imbuf->rect = m_image;
- IMB_rectblend(m_imbuf, m_imbuf, img->m_imbuf, NULL, NULL, 0, x, y, x, y, 0, 0, img->m_imbuf->x, img->m_imbuf->y, (IMB_BlendMode)mode);
+ IMB_rectblend(m_imbuf, m_imbuf, img->m_imbuf, NULL, NULL, NULL, 0, x, y, x, y, 0, 0, img->m_imbuf->x, img->m_imbuf->y, (IMB_BlendMode)mode, false);
// remove so that MB_freeImBuf will free our buffer
m_imbuf->rect = NULL;
img->m_imbuf->rect = NULL;