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
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/blenfont/BLF_api.h33
-rw-r--r--source/blender/blenfont/intern/blf.c175
-rw-r--r--source/blender/blenfont/intern/blf_font.c279
-rw-r--r--source/blender/blenfont/intern/blf_internal.h21
-rw-r--r--source/blender/blenfont/intern/blf_internal_types.h9
-rw-r--r--source/blender/blenfont/intern/blf_thumbs.c9
-rw-r--r--source/blender/blenkernel/BKE_DerivedMesh.h5
-rw-r--r--source/blender/blenkernel/BKE_armature.h4
-rw-r--r--source/blender/blenkernel/BKE_blender.h4
-rw-r--r--source/blender/blenkernel/BKE_brush.h4
-rw-r--r--source/blender/blenkernel/BKE_bvhutils.h10
-rw-r--r--source/blender/blenkernel/BKE_camera.h1
-rw-r--r--source/blender/blenkernel/BKE_cdderivedmesh.h12
-rw-r--r--source/blender/blenkernel/BKE_curve.h1
-rw-r--r--source/blender/blenkernel/BKE_customdata.h6
-rw-r--r--source/blender/blenkernel/BKE_depsgraph.h5
-rw-r--r--source/blender/blenkernel/BKE_font.h5
-rw-r--r--source/blender/blenkernel/BKE_idcode.h18
-rw-r--r--source/blender/blenkernel/BKE_image.h2
-rw-r--r--source/blender/blenkernel/BKE_key.h4
-rw-r--r--source/blender/blenkernel/BKE_lamp.h1
-rw-r--r--source/blender/blenkernel/BKE_lattice.h1
-rw-r--r--source/blender/blenkernel/BKE_library.h9
-rw-r--r--source/blender/blenkernel/BKE_library_query.h11
-rw-r--r--source/blender/blenkernel/BKE_linestyle.h1
-rw-r--r--source/blender/blenkernel/BKE_main.h14
-rw-r--r--source/blender/blenkernel/BKE_material.h2
-rw-r--r--source/blender/blenkernel/BKE_mball.h1
-rw-r--r--source/blender/blenkernel/BKE_mesh.h7
-rw-r--r--source/blender/blenkernel/BKE_modifier.h5
-rw-r--r--source/blender/blenkernel/BKE_movieclip.h2
-rw-r--r--source/blender/blenkernel/BKE_node.h1
-rw-r--r--source/blender/blenkernel/BKE_object.h5
-rw-r--r--source/blender/blenkernel/BKE_paint.h18
-rw-r--r--source/blender/blenkernel/BKE_particle.h6
-rw-r--r--source/blender/blenkernel/BKE_rigidbody.h5
-rw-r--r--source/blender/blenkernel/BKE_sca.h10
-rw-r--r--source/blender/blenkernel/BKE_scene.h1
-rw-r--r--source/blender/blenkernel/BKE_sequencer.h13
-rw-r--r--source/blender/blenkernel/BKE_sound.h4
-rw-r--r--source/blender/blenkernel/BKE_speaker.h2
-rw-r--r--source/blender/blenkernel/BKE_text.h1
-rw-r--r--source/blender/blenkernel/BKE_world.h1
-rw-r--r--source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c14
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c52
-rw-r--r--source/blender/blenkernel/intern/action.c3
-rw-r--r--source/blender/blenkernel/intern/appdir.c10
-rw-r--r--source/blender/blenkernel/intern/armature.c60
-rw-r--r--source/blender/blenkernel/intern/blender.c7
-rw-r--r--source/blender/blenkernel/intern/boids.c11
-rw-r--r--source/blender/blenkernel/intern/brush.c28
-rw-r--r--source/blender/blenkernel/intern/bvhutils.c47
-rw-r--r--source/blender/blenkernel/intern/camera.c58
-rw-r--r--source/blender/blenkernel/intern/cdderivedmesh.c69
-rw-r--r--source/blender/blenkernel/intern/colortools.c69
-rw-r--r--source/blender/blenkernel/intern/constraint.c7
-rw-r--r--source/blender/blenkernel/intern/curve.c22
-rw-r--r--source/blender/blenkernel/intern/customdata.c92
-rw-r--r--source/blender/blenkernel/intern/data_transfer.c72
-rw-r--r--source/blender/blenkernel/intern/data_transfer_intern.h8
-rw-r--r--source/blender/blenkernel/intern/deform.c6
-rw-r--r--source/blender/blenkernel/intern/depsgraph.c91
-rw-r--r--source/blender/blenkernel/intern/displist.c4
-rw-r--r--source/blender/blenkernel/intern/dynamicpaint.c8
-rw-r--r--source/blender/blenkernel/intern/editderivedmesh.c22
-rw-r--r--source/blender/blenkernel/intern/effect.c10
-rw-r--r--source/blender/blenkernel/intern/fmodifier.c6
-rw-r--r--source/blender/blenkernel/intern/font.c67
-rw-r--r--source/blender/blenkernel/intern/idcode.c32
-rw-r--r--source/blender/blenkernel/intern/image.c327
-rw-r--r--source/blender/blenkernel/intern/image_gen.c18
-rw-r--r--source/blender/blenkernel/intern/key.c114
-rw-r--r--source/blender/blenkernel/intern/lamp.c18
-rw-r--r--source/blender/blenkernel/intern/lattice.c19
-rw-r--r--source/blender/blenkernel/intern/library.c224
-rw-r--r--source/blender/blenkernel/intern/library_query.c355
-rw-r--r--source/blender/blenkernel/intern/linestyle.c6
-rw-r--r--source/blender/blenkernel/intern/material.c16
-rw-r--r--source/blender/blenkernel/intern/mball.c19
-rw-r--r--source/blender/blenkernel/intern/mesh.c35
-rw-r--r--source/blender/blenkernel/intern/mesh_evaluate.c113
-rw-r--r--source/blender/blenkernel/intern/mesh_mapping.c6
-rw-r--r--source/blender/blenkernel/intern/mesh_remap.c51
-rw-r--r--source/blender/blenkernel/intern/mesh_validate.c3
-rw-r--r--source/blender/blenkernel/intern/modifier.c3
-rw-r--r--source/blender/blenkernel/intern/movieclip.c59
-rw-r--r--source/blender/blenkernel/intern/multires.c4
-rw-r--r--source/blender/blenkernel/intern/nla.c80
-rw-r--r--source/blender/blenkernel/intern/node.c9
-rw-r--r--source/blender/blenkernel/intern/object.c182
-rw-r--r--source/blender/blenkernel/intern/packedFile.c6
-rw-r--r--source/blender/blenkernel/intern/paint.c96
-rw-r--r--source/blender/blenkernel/intern/particle_system.c27
-rw-r--r--source/blender/blenkernel/intern/pbvh_bmesh.c2
-rw-r--r--source/blender/blenkernel/intern/property.c2
-rw-r--r--source/blender/blenkernel/intern/rigidbody.c16
-rw-r--r--source/blender/blenkernel/intern/sca.c174
-rw-r--r--source/blender/blenkernel/intern/scene.c32
-rw-r--r--source/blender/blenkernel/intern/screen.c11
-rw-r--r--source/blender/blenkernel/intern/seqeffects.c77
-rw-r--r--source/blender/blenkernel/intern/sequencer.c91
-rw-r--r--source/blender/blenkernel/intern/shrinkwrap.c11
-rw-r--r--source/blender/blenkernel/intern/softbody.c4
-rw-r--r--source/blender/blenkernel/intern/sound.c48
-rw-r--r--source/blender/blenkernel/intern/speaker.c15
-rw-r--r--source/blender/blenkernel/intern/subsurf_ccg.c490
-rw-r--r--source/blender/blenkernel/intern/text.c245
-rw-r--r--source/blender/blenkernel/intern/texture.c2
-rw-r--r--source/blender/blenkernel/intern/unit.c3
-rw-r--r--source/blender/blenkernel/intern/world.c16
-rw-r--r--source/blender/blenkernel/intern/writeavi.c10
-rw-r--r--source/blender/blenkernel/intern/writeffmpeg.c15
-rw-r--r--source/blender/blenlib/BLI_alloca.h5
-rw-r--r--source/blender/blenlib/BLI_buffer.h29
-rw-r--r--source/blender/blenlib/BLI_fileops.h2
-rw-r--r--source/blender/blenlib/BLI_math_geom.h26
-rw-r--r--source/blender/blenlib/BLI_math_inline.h4
-rw-r--r--source/blender/blenlib/BLI_math_matrix.h17
-rw-r--r--source/blender/blenlib/BLI_math_solvers.h1
-rw-r--r--source/blender/blenlib/BLI_math_vector.h7
-rw-r--r--source/blender/blenlib/BLI_memory_utils.h34
-rw-r--r--source/blender/blenlib/BLI_path_util.h29
-rw-r--r--source/blender/blenlib/BLI_rect.h2
-rw-r--r--source/blender/blenlib/BLI_utildefines.h15
-rw-r--r--source/blender/blenlib/CMakeLists.txt2
-rw-r--r--source/blender/blenlib/intern/BLI_filelist.c3
-rw-r--r--source/blender/blenlib/intern/BLI_ghash.c2
-rw-r--r--source/blender/blenlib/intern/array_utils.c2
-rw-r--r--source/blender/blenlib/intern/buffer.c74
-rw-r--r--source/blender/blenlib/intern/fileops.c2
-rw-r--r--source/blender/blenlib/intern/math_color_blend_inline.c52
-rw-r--r--source/blender/blenlib/intern/math_geom.c270
-rw-r--r--source/blender/blenlib/intern/math_matrix.c174
-rw-r--r--source/blender/blenlib/intern/math_rotation.c2
-rw-r--r--source/blender/blenlib/intern/math_solvers.c13
-rw-r--r--source/blender/blenlib/intern/math_statistics.c2
-rw-r--r--source/blender/blenlib/intern/math_vector.c2
-rw-r--r--source/blender/blenlib/intern/math_vector_inline.c24
-rw-r--r--source/blender/blenlib/intern/memory_utils.c50
-rw-r--r--source/blender/blenlib/intern/noise.c2
-rw-r--r--source/blender/blenlib/intern/path_util.c151
-rw-r--r--source/blender/blenlib/intern/polyfill2d.c2
-rw-r--r--source/blender/blenlib/intern/rct.c97
-rw-r--r--source/blender/blenlib/intern/storage.c10
-rw-r--r--source/blender/blenlib/intern/string.c2
-rw-r--r--source/blender/blenlib/intern/task.c1
-rw-r--r--source/blender/blenlib/intern/timecode.c20
-rw-r--r--source/blender/blenlib/intern/winstuff.c4
-rw-r--r--source/blender/blenloader/BLO_blend_defs.h2
-rw-r--r--source/blender/blenloader/BLO_readfile.h197
-rw-r--r--source/blender/blenloader/BLO_writefile.h6
-rw-r--r--source/blender/blenloader/intern/readblenentry.c126
-rw-r--r--source/blender/blenloader/intern/readfile.c669
-rw-r--r--source/blender/blenloader/intern/readfile.h5
-rw-r--r--source/blender/blenloader/intern/versioning_260.c2
-rw-r--r--source/blender/blenloader/intern/versioning_270.c15
-rw-r--r--source/blender/blenloader/intern/versioning_defaults.c2
-rw-r--r--source/blender/blenloader/intern/writefile.c17
-rw-r--r--source/blender/blentranslation/BLT_translation.h7
-rw-r--r--source/blender/blentranslation/intern/blt_lang.c2
-rw-r--r--source/blender/bmesh/bmesh.h23
-rw-r--r--source/blender/bmesh/intern/bmesh_core.c10
-rw-r--r--source/blender/bmesh/intern/bmesh_marking.c17
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh.c116
-rw-r--r--source/blender/bmesh/intern/bmesh_opdefines.c46
-rw-r--r--source/blender/bmesh/intern/bmesh_queries.c2
-rw-r--r--source/blender/bmesh/operators/bmo_extrude.c6
-rw-r--r--source/blender/bmesh/operators/bmo_inset.c9
-rw-r--r--source/blender/bmesh/operators/bmo_planar_faces.c4
-rw-r--r--source/blender/bmesh/operators/bmo_subdivide.c153
-rw-r--r--source/blender/bmesh/tools/bmesh_bevel.c8
-rw-r--r--source/blender/bmesh/tools/bmesh_intersect.c3
-rw-r--r--source/blender/collada/AnimationImporter.cpp33
-rw-r--r--source/blender/collada/AnimationImporter.h3
-rw-r--r--source/blender/collada/ArmatureImporter.cpp10
-rw-r--r--source/blender/collada/DocumentImporter.cpp36
-rw-r--r--source/blender/compositor/intern/COM_CompositorContext.h1
-rw-r--r--source/blender/compositor/intern/COM_ExecutionGroup.cpp1
-rw-r--r--source/blender/compositor/intern/COM_ExecutionSystem.cpp2
-rw-r--r--source/blender/compositor/intern/COM_MemoryBuffer.cpp47
-rw-r--r--source/blender/compositor/intern/COM_MemoryBuffer.h2
-rw-r--r--source/blender/compositor/intern/COM_Node.h1
-rw-r--r--source/blender/compositor/intern/COM_SocketReader.h7
-rw-r--r--source/blender/compositor/intern/COM_WorkScheduler.h2
-rw-r--r--source/blender/compositor/intern/COM_compositor.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_ChannelMatteNode.cpp37
-rw-r--r--source/blender/compositor/nodes/COM_DistanceMatteNode.cpp20
-rw-r--r--source/blender/compositor/nodes/COM_ImageNode.cpp15
-rw-r--r--source/blender/compositor/operations/COM_CurveBaseOperation.cpp15
-rw-r--r--source/blender/compositor/operations/COM_CurveBaseOperation.h1
-rw-r--r--source/blender/compositor/operations/COM_DisplaceOperation.cpp2
-rw-r--r--source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp2
-rw-r--r--source/blender/compositor/operations/COM_IDMaskOperation.cpp4
-rw-r--r--source/blender/compositor/operations/COM_MapUVOperation.cpp2
-rw-r--r--source/blender/compositor/operations/COM_MovieDistortionOperation.h14
-rw-r--r--source/blender/compositor/operations/COM_MultilayerImageOperation.cpp6
-rw-r--r--source/blender/compositor/operations/COM_MultilayerImageOperation.h10
-rw-r--r--source/blender/compositor/operations/COM_PlaneDistortCommonOperation.cpp6
-rw-r--r--source/blender/compositor/operations/COM_ReadBufferOperation.cpp4
-rw-r--r--source/blender/compositor/operations/COM_ReadBufferOperation.h2
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersProg.cpp1
-rw-r--r--source/blender/depsgraph/DEG_depsgraph.h10
-rw-r--r--source/blender/depsgraph/intern/depsgraph.cc27
-rw-r--r--source/blender/depsgraph/intern/depsgraph_build.h2
-rw-r--r--source/blender/depsgraph/intern/depsgraph_build_nodes.cc6
-rw-r--r--source/blender/depsgraph/intern/depsgraph_build_relations.cc4
-rw-r--r--source/blender/depsgraph/intern/depsgraph_debug.cc27
-rw-r--r--source/blender/depsgraph/intern/depsgraph_eval.cc5
-rw-r--r--source/blender/editors/animation/anim_filter.c2
-rw-r--r--source/blender/editors/animation/keyframes_general.c1
-rw-r--r--source/blender/editors/armature/armature_select.c2
-rw-r--r--source/blender/editors/armature/armature_utils.c135
-rw-r--r--source/blender/editors/armature/editarmature_sketch.c8
-rw-r--r--source/blender/editors/curve/editcurve_select.c19
-rw-r--r--source/blender/editors/gpencil/drawgpencil.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_paint.c10
-rw-r--r--source/blender/editors/include/BIF_gl.h20
-rw-r--r--source/blender/editors/include/ED_image.h4
-rw-r--r--source/blender/editors/include/ED_render.h1
-rw-r--r--source/blender/editors/include/ED_screen.h2
-rw-r--r--source/blender/editors/include/ED_transform.h2
-rw-r--r--source/blender/editors/include/ED_view3d.h21
-rw-r--r--source/blender/editors/include/UI_icons.h8
-rw-r--r--source/blender/editors/include/UI_interface.h2
-rw-r--r--source/blender/editors/include/UI_view2d.h2
-rw-r--r--source/blender/editors/interface/interface.c91
-rw-r--r--source/blender/editors/interface/interface_draw.c12
-rw-r--r--source/blender/editors/interface/interface_handlers.c155
-rw-r--r--source/blender/editors/interface/interface_intern.h11
-rw-r--r--source/blender/editors/interface/interface_layout.c4
-rw-r--r--source/blender/editors/interface/interface_panel.c30
-rw-r--r--source/blender/editors/interface/interface_regions.c134
-rw-r--r--source/blender/editors/interface/interface_style.c44
-rw-r--r--source/blender/editors/interface/interface_templates.c3
-rw-r--r--source/blender/editors/interface/interface_widgets.c15
-rw-r--r--source/blender/editors/interface/resources.c23
-rw-r--r--source/blender/editors/interface/view2d.c14
-rw-r--r--source/blender/editors/interface/view2d_ops.c11
-rw-r--r--source/blender/editors/mask/mask_add.c2
-rw-r--r--source/blender/editors/mask/mask_ops.c4
-rw-r--r--source/blender/editors/mesh/editmesh_knife.c258
-rw-r--r--source/blender/editors/mesh/editmesh_loopcut.c7
-rw-r--r--source/blender/editors/mesh/editmesh_select.c32
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c4
-rw-r--r--source/blender/editors/mesh/editmesh_utils.c4
-rw-r--r--source/blender/editors/mesh/mesh_navmesh.c1
-rw-r--r--source/blender/editors/metaball/mball_edit.c15
-rw-r--r--source/blender/editors/object/object_add.c88
-rw-r--r--source/blender/editors/object/object_bake.c24
-rw-r--r--source/blender/editors/object/object_bake_api.c9
-rw-r--r--source/blender/editors/object/object_data_transfer.c29
-rw-r--r--source/blender/editors/object/object_edit.c4
-rw-r--r--source/blender/editors/object/object_lattice.c12
-rw-r--r--source/blender/editors/object/object_relations.c2
-rw-r--r--source/blender/editors/object/object_select.c42
-rw-r--r--source/blender/editors/object/object_transform.c27
-rw-r--r--source/blender/editors/object/object_vgroup.c6
-rw-r--r--source/blender/editors/physics/particle_edit.c17
-rw-r--r--source/blender/editors/physics/particle_object.c1
-rw-r--r--source/blender/editors/render/render_intern.h2
-rw-r--r--source/blender/editors/render/render_internal.c6
-rw-r--r--source/blender/editors/render/render_opengl.c94
-rw-r--r--source/blender/editors/render/render_update.c18
-rw-r--r--source/blender/editors/render/render_view.c12
-rw-r--r--source/blender/editors/screen/area.c77
-rw-r--r--source/blender/editors/screen/screen_edit.c9
-rw-r--r--source/blender/editors/screen/screen_ops.c32
-rw-r--r--source/blender/editors/screen/screendump.c4
-rw-r--r--source/blender/editors/sculpt_paint/paint_cursor.c16
-rw-r--r--source/blender/editors/sculpt_paint/paint_curve.c18
-rw-r--r--source/blender/editors/sculpt_paint/paint_image.c15
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_2d.c2
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_proj.c136
-rw-r--r--source/blender/editors/sculpt_paint/paint_ops.c10
-rw-r--r--source/blender/editors/sculpt_paint/paint_stroke.c36
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex.c6
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c11
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_uv.c5
-rw-r--r--source/blender/editors/space_action/action_edit.c12
-rw-r--r--source/blender/editors/space_buttons/buttons_texture.c3
-rw-r--r--source/blender/editors/space_clip/clip_draw.c19
-rw-r--r--source/blender/editors/space_clip/clip_ops.c2
-rw-r--r--source/blender/editors/space_file/file_draw.c14
-rw-r--r--source/blender/editors/space_file/file_ops.c109
-rw-r--r--source/blender/editors/space_file/file_utils.c3
-rw-r--r--source/blender/editors/space_file/filelist.c66
-rw-r--r--source/blender/editors/space_file/filesel.c1
-rw-r--r--source/blender/editors/space_file/fsmenu.c53
-rw-r--r--source/blender/editors/space_image/image_buttons.c73
-rw-r--r--source/blender/editors/space_image/image_draw.c4
-rw-r--r--source/blender/editors/space_image/image_ops.c10
-rw-r--r--source/blender/editors/space_image/space_image.c4
-rw-r--r--source/blender/editors/space_logic/logic_window.c2
-rw-r--r--source/blender/editors/space_nla/nla_draw.c26
-rw-r--r--source/blender/editors/space_node/drawnode.c34
-rw-r--r--source/blender/editors/space_node/node_relationships.c39
-rw-r--r--source/blender/editors/space_node/node_templates.c7
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c20
-rw-r--r--source/blender/editors/space_outliner/outliner_edit.c2
-rw-r--r--source/blender/editors/space_outliner/outliner_intern.h45
-rw-r--r--source/blender/editors/space_sequencer/sequencer_draw.c48
-rw-r--r--source/blender/editors/space_sequencer/sequencer_edit.c51
-rw-r--r--source/blender/editors/space_text/text_ops.c256
-rw-r--r--source/blender/editors/space_view3d/CMakeLists.txt4
-rw-r--r--source/blender/editors/space_view3d/SConscript3
-rw-r--r--source/blender/editors/space_view3d/drawarmature.c6
-rw-r--r--source/blender/editors/space_view3d/drawmesh.c5
-rw-r--r--source/blender/editors/space_view3d/drawobject.c116
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c118
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c57
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c31
-rw-r--r--source/blender/editors/space_view3d/view3d_view.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_walk.c13
-rw-r--r--source/blender/editors/transform/transform.c168
-rw-r--r--source/blender/editors/transform/transform.h13
-rw-r--r--source/blender/editors/transform/transform_constraints.c12
-rw-r--r--source/blender/editors/transform/transform_conversions.c17
-rw-r--r--source/blender/editors/transform/transform_generics.c25
-rw-r--r--source/blender/editors/transform/transform_manipulator.c7
-rw-r--r--source/blender/editors/transform/transform_ops.c22
-rw-r--r--source/blender/editors/transform/transform_orientations.c44
-rw-r--r--source/blender/editors/transform/transform_snap.c87
-rw-r--r--source/blender/editors/util/ed_util.c2
-rw-r--r--source/blender/editors/uvedit/uvedit_draw.c22
-rw-r--r--source/blender/editors/uvedit/uvedit_ops.c8
-rw-r--r--source/blender/editors/uvedit/uvedit_unwrap_ops.c51
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp47
-rw-r--r--source/blender/freestyle/intern/geometry/GeomUtils.h2
-rw-r--r--source/blender/freestyle/intern/geometry/Noise.cpp4
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp4
-rw-r--r--source/blender/freestyle/intern/stroke/Stroke.cpp7
-rw-r--r--source/blender/freestyle/intern/winged_edge/WEdge.h2
-rw-r--r--source/blender/gpu/GPU_extensions.h18
-rw-r--r--source/blender/gpu/GPU_material.h5
-rw-r--r--source/blender/gpu/intern/gpu_buffers.c2
-rw-r--r--source/blender/gpu/intern/gpu_codegen.c13
-rw-r--r--source/blender/gpu/intern/gpu_compositing.c13
-rw-r--r--source/blender/gpu/intern/gpu_debug.c30
-rw-r--r--source/blender/gpu/intern/gpu_extensions.c270
-rw-r--r--source/blender/gpu/intern/gpu_init_exit.c2
-rw-r--r--source/blender/gpu/intern/gpu_material.c40
-rw-r--r--source/blender/gpu/shaders/gpu_shader_material.glsl22
-rw-r--r--source/blender/imbuf/CMakeLists.txt2
-rw-r--r--source/blender/imbuf/IMB_imbuf_types.h34
-rw-r--r--source/blender/imbuf/IMB_thumbs.h2
-rw-r--r--source/blender/imbuf/intern/IMB_allocimbuf.h12
-rw-r--r--source/blender/imbuf/intern/allocimbuf.c45
-rw-r--r--source/blender/imbuf/intern/dds/ColorBlock.cpp18
-rw-r--r--source/blender/imbuf/intern/dds/Common.h12
-rw-r--r--source/blender/imbuf/intern/dds/DirectDrawSurface.cpp40
-rw-r--r--source/blender/imbuf/intern/dds/FlipDXT.cpp4
-rw-r--r--source/blender/imbuf/intern/jpeg.c184
-rw-r--r--source/blender/imbuf/intern/module.c2
-rw-r--r--source/blender/imbuf/intern/radiance_hdr.c39
-rw-r--r--source/blender/imbuf/intern/readimage.c11
-rw-r--r--source/blender/imbuf/intern/scaling.c2
-rw-r--r--source/blender/imbuf/intern/stereoimbuf.c16
-rw-r--r--source/blender/imbuf/intern/thumbs.c17
-rw-r--r--source/blender/imbuf/intern/thumbs_blend.c109
-rw-r--r--source/blender/makesdna/DNA_ID.h4
-rw-r--r--source/blender/makesdna/DNA_action_types.h14
-rw-r--r--source/blender/makesdna/DNA_actuator_types.h1
-rw-r--r--source/blender/makesdna/DNA_image_types.h7
-rw-r--r--source/blender/makesdna/DNA_meshdata_types.h14
-rw-r--r--source/blender/makesdna/DNA_node_types.h2
-rw-r--r--source/blender/makesdna/DNA_object_fluidsim.h5
-rw-r--r--source/blender/makesdna/DNA_object_types.h6
-rw-r--r--source/blender/makesdna/DNA_outliner_types.h50
-rw-r--r--source/blender/makesdna/DNA_sequence_types.h20
-rw-r--r--source/blender/makesdna/DNA_userdef_types.h25
-rw-r--r--source/blender/makesdna/intern/CMakeLists.txt2
-rw-r--r--source/blender/makesdna/intern/dna_genfile.c18
-rw-r--r--source/blender/makesrna/SConscript3
-rw-r--r--source/blender/makesrna/intern/CMakeLists.txt2
-rw-r--r--source/blender/makesrna/intern/SConscript3
-rw-r--r--source/blender/makesrna/intern/makesrna.c13
-rw-r--r--source/blender/makesrna/intern/rna_ID.c116
-rw-r--r--source/blender/makesrna/intern/rna_access.c15
-rw-r--r--source/blender/makesrna/intern/rna_actuator.c5
-rw-r--r--source/blender/makesrna/intern/rna_animation.c4
-rw-r--r--source/blender/makesrna/intern/rna_armature.c2
-rw-r--r--source/blender/makesrna/intern/rna_brush.c12
-rw-r--r--source/blender/makesrna/intern/rna_constraint.c3
-rw-r--r--source/blender/makesrna/intern/rna_curve.c10
-rw-r--r--source/blender/makesrna/intern/rna_define.c10
-rw-r--r--source/blender/makesrna/intern/rna_fluidsim.c8
-rw-r--r--source/blender/makesrna/intern/rna_gpencil.c2
-rw-r--r--source/blender/makesrna/intern/rna_image.c23
-rw-r--r--source/blender/makesrna/intern/rna_image_api.c30
-rw-r--r--source/blender/makesrna/intern/rna_internal.h1
-rw-r--r--source/blender/makesrna/intern/rna_key.c139
-rw-r--r--source/blender/makesrna/intern/rna_lattice.c2
-rw-r--r--source/blender/makesrna/intern/rna_main_api.c54
-rw-r--r--source/blender/makesrna/intern/rna_material.c2
-rw-r--r--source/blender/makesrna/intern/rna_mesh_api.c5
-rw-r--r--source/blender/makesrna/intern/rna_modifier.c24
-rw-r--r--source/blender/makesrna/intern/rna_nla.c4
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c84
-rw-r--r--source/blender/makesrna/intern/rna_object.c29
-rw-r--r--source/blender/makesrna/intern/rna_object_force.c2
-rw-r--r--source/blender/makesrna/intern/rna_pose.c11
-rw-r--r--source/blender/makesrna/intern/rna_rigidbody.c2
-rw-r--r--source/blender/makesrna/intern/rna_scene.c22
-rw-r--r--source/blender/makesrna/intern/rna_sensor.c8
-rw-r--r--source/blender/makesrna/intern/rna_sequencer.c35
-rw-r--r--source/blender/makesrna/intern/rna_space.c19
-rw-r--r--source/blender/makesrna/intern/rna_vfont.c4
-rw-r--r--source/blender/makesrna/intern/rna_wm.c3
-rw-r--r--source/blender/modifiers/intern/MOD_armature.c6
-rw-r--r--source/blender/modifiers/intern/MOD_array.c12
-rw-r--r--source/blender/modifiers/intern/MOD_boolean.c6
-rw-r--r--source/blender/modifiers/intern/MOD_cast.c6
-rw-r--r--source/blender/modifiers/intern/MOD_cloth.c5
-rw-r--r--source/blender/modifiers/intern/MOD_curve.c10
-rw-r--r--source/blender/modifiers/intern/MOD_datatransfer.c16
-rw-r--r--source/blender/modifiers/intern/MOD_displace.c8
-rw-r--r--source/blender/modifiers/intern/MOD_dynamicpaint.c7
-rw-r--r--source/blender/modifiers/intern/MOD_explode.c2
-rw-r--r--source/blender/modifiers/intern/MOD_hook.c6
-rw-r--r--source/blender/modifiers/intern/MOD_lattice.c6
-rw-r--r--source/blender/modifiers/intern/MOD_mask.c6
-rw-r--r--source/blender/modifiers/intern/MOD_meshdeform.c6
-rw-r--r--source/blender/modifiers/intern/MOD_mirror.c9
-rw-r--r--source/blender/modifiers/intern/MOD_normal_edit.c16
-rw-r--r--source/blender/modifiers/intern/MOD_ocean.c1
-rw-r--r--source/blender/modifiers/intern/MOD_particleinstance.c3
-rw-r--r--source/blender/modifiers/intern/MOD_screw.c8
-rw-r--r--source/blender/modifiers/intern/MOD_shrinkwrap.c5
-rw-r--r--source/blender/modifiers/intern/MOD_simpledeform.c8
-rw-r--r--source/blender/modifiers/intern/MOD_smoke.c11
-rw-r--r--source/blender/modifiers/intern/MOD_solidify.c2
-rw-r--r--source/blender/modifiers/intern/MOD_subsurf.c10
-rw-r--r--source/blender/modifiers/intern/MOD_surface.c4
-rw-r--r--source/blender/modifiers/intern/MOD_uvproject.c8
-rw-r--r--source/blender/modifiers/intern/MOD_uvwarp.c5
-rw-r--r--source/blender/modifiers/intern/MOD_warp.c13
-rw-r--r--source/blender/modifiers/intern/MOD_wave.c7
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgedit.c9
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgmix.c9
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgproximity.c13
-rw-r--r--source/blender/nodes/shader/node_shader_util.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_hair.c4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_math.c10
-rw-r--r--source/blender/python/SConscript4
-rw-r--r--source/blender/python/bmesh/bmesh_py_ops_call.c2
-rw-r--r--source/blender/python/bmesh/bmesh_py_types.c21
-rw-r--r--source/blender/python/bmesh/bmesh_py_types_customdata.c18
-rw-r--r--source/blender/python/generic/bgl.c383
-rw-r--r--source/blender/python/generic/blf_py_api.c25
-rw-r--r--source/blender/python/generic/bpy_threads.c5
-rw-r--r--source/blender/python/generic/py_capi_utils.c4
-rw-r--r--source/blender/python/intern/CMakeLists.txt1
-rw-r--r--source/blender/python/intern/bpy_interface.c12
-rw-r--r--source/blender/python/intern/bpy_library.c6
-rw-r--r--source/blender/python/intern/bpy_rna.c21
-rw-r--r--source/blender/python/intern/bpy_rna_callback.c6
-rw-r--r--source/blender/python/intern/gpu.c60
-rw-r--r--source/blender/python/intern/gpu.h2
-rw-r--r--source/blender/python/intern/gpu_offscreen.c424
-rw-r--r--source/blender/python/mathutils/mathutils.c2
-rw-r--r--source/blender/python/mathutils/mathutils_bvhtree.c6
-rw-r--r--source/blender/python/mathutils/mathutils_geometry.c14
-rw-r--r--source/blender/quicktime/apple/qtkit_export.m3
-rw-r--r--source/blender/quicktime/quicktime_export.h2
-rw-r--r--source/blender/render/extern/include/RE_pipeline.h4
-rw-r--r--source/blender/render/extern/include/RE_render_ext.h6
-rw-r--r--source/blender/render/intern/include/renderdatabase.h4
-rw-r--r--source/blender/render/intern/source/bake.c6
-rw-r--r--source/blender/render/intern/source/bake_api.c91
-rw-r--r--source/blender/render/intern/source/convertblender.c8
-rw-r--r--source/blender/render/intern/source/envmap.c14
-rw-r--r--source/blender/render/intern/source/external_engine.c8
-rw-r--r--source/blender/render/intern/source/multires_bake.c20
-rw-r--r--source/blender/render/intern/source/pipeline.c37
-rw-r--r--source/blender/render/intern/source/pointdensity.c124
-rw-r--r--source/blender/render/intern/source/rayshade.c2
-rw-r--r--source/blender/render/intern/source/rendercore.c6
-rw-r--r--source/blender/render/intern/source/renderdatabase.c53
-rw-r--r--source/blender/render/intern/source/shadeoutput.c8
-rw-r--r--source/blender/windowmanager/WM_api.h15
-rw-r--r--source/blender/windowmanager/intern/wm.c4
-rw-r--r--source/blender/windowmanager/intern/wm_cursors.c18
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c8
-rw-r--r--source/blender/windowmanager/intern/wm_files.c260
-rw-r--r--source/blender/windowmanager/intern/wm_init_exit.c28
-rw-r--r--source/blender/windowmanager/intern/wm_keymap.c35
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c345
-rw-r--r--source/blender/windowmanager/intern/wm_playanim.c142
-rw-r--r--source/blender/windowmanager/intern/wm_window.c180
-rw-r--r--source/blender/windowmanager/wm_files.h1
-rw-r--r--source/blender/windowmanager/wm_window.h8
492 files changed, 10755 insertions, 5099 deletions
diff --git a/source/blender/blenfont/BLF_api.h b/source/blender/blenfont/BLF_api.h
index d8dee7110a5..9527c4edcf0 100644
--- a/source/blender/blenfont/BLF_api.h
+++ b/source/blender/blenfont/BLF_api.h
@@ -36,6 +36,7 @@
struct rctf;
struct ColorManagedDisplay;
+struct ResultBLF;
int BLF_init(int points, int dpi);
void BLF_exit(void);
@@ -79,9 +80,11 @@ void BLF_draw_default(float x, float y, float z, const char *str, size_t len) AT
void BLF_draw_default_ascii(float x, float y, float z, const char *str, size_t len) ATTR_NONNULL();
/* Draw the string using the current font. */
-void BLF_draw(int fontid, const char *str, size_t len);
-void BLF_draw_ascii(int fontid, const char *str, size_t len);
-int BLF_draw_mono(int fontid, const char *str, size_t len, int cwidth);
+void BLF_draw_ex(int fontid, const char *str, size_t len, struct ResultBLF *r_info) ATTR_NONNULL(2);
+void BLF_draw(int fontid, const char *str, size_t len) ATTR_NONNULL(2);
+void BLF_draw_ascii_ex(int fontid, const char *str, size_t len, struct ResultBLF *r_info) ATTR_NONNULL(2);
+void BLF_draw_ascii(int fontid, const char *str, size_t len) ATTR_NONNULL(2);
+int BLF_draw_mono(int fontid, const char *str, size_t len, int cwidth) ATTR_NONNULL(2);
/* Get the string byte offset that fits within a given width */
size_t BLF_width_to_strlen(int fontid, const char *str, size_t len, float width, float *r_width) ATTR_NONNULL(2);
@@ -91,17 +94,20 @@ size_t BLF_width_to_rstrlen(int fontid, const char *str, size_t len, float width
/* This function return the bounding box of the string
* and are not multiplied by the aspect.
*/
+void BLF_boundbox_ex(int fontid, const char *str, size_t len, struct rctf *box, struct ResultBLF *r_info) ATTR_NONNULL(2);
void BLF_boundbox(int fontid, const char *str, size_t len, struct rctf *box) ATTR_NONNULL();
/* The next both function return the width and height
* of the string, using the current font and both value
* are multiplied by the aspect of the font.
*/
+float BLF_width_ex(int fontid, const char *str, size_t len, struct ResultBLF *r_info) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(2);
float BLF_width(int fontid, const char *str, size_t len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+float BLF_height_ex(int fontid, const char *str, size_t len, struct ResultBLF *r_info) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(2);
float BLF_height(int fontid, const char *str, size_t len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
/* Return dimensions of the font without any sample text. */
-float BLF_height_max(int fontid) ATTR_WARN_UNUSED_RESULT;
+int BLF_height_max(int fontid) ATTR_WARN_UNUSED_RESULT;
float BLF_width_max(int fontid) ATTR_WARN_UNUSED_RESULT;
float BLF_descender(int fontid) ATTR_WARN_UNUSED_RESULT;
float BLF_ascender(int fontid) ATTR_WARN_UNUSED_RESULT;
@@ -137,6 +143,7 @@ void BLF_disable_default(int option);
void BLF_rotation(int fontid, float angle);
void BLF_clipping(int fontid, float xmin, float ymin, float xmax, float ymax);
void BLF_clipping_default(float xmin, float ymin, float xmax, float ymax);
+void BLF_wordwrap(int fontid, int wrap_width);
void BLF_blur(int fontid, int size);
void BLF_enable(int fontid, int option);
@@ -172,7 +179,8 @@ void BLF_buffer_col(int fontid, float r, float g, float b, float a);
/* Draw the string into the buffer, this function draw in both buffer, float and unsigned char _BUT_
* it's not necessary set both buffer, NULL is valid here.
*/
-void BLF_draw_buffer(int fontid, const char *str) ATTR_NONNULL();
+void BLF_draw_buffer_ex(int fontid, const char *str, size_t len, struct ResultBLF *r_info) ATTR_NONNULL(2);
+void BLF_draw_buffer(int fontid, const char *str, size_t len) ATTR_NONNULL(2);
/* Add a path to the font dir paths. */
void BLF_dir_add(const char *path) ATTR_NONNULL();
@@ -210,6 +218,7 @@ void BLF_state_print(int fontid);
#define BLF_MATRIX (1 << 4)
#define BLF_ASPECT (1 << 5)
#define BLF_HINTING (1 << 6)
+#define BLF_WORD_WRAP (1 << 7)
#define BLF_DRAW_STR_DUMMY_MAX 1024
@@ -217,4 +226,18 @@ void BLF_state_print(int fontid);
extern int blf_mono_font;
extern int blf_mono_font_render; /* don't mess drawing with render threads. */
+/**
+ * Result of drawing/evaluating the string
+ */
+struct ResultBLF {
+ /**
+ * Number of lines drawn when #BLF_WORD_WRAP is enabled (both wrapped and `\n` newline).
+ */
+ int lines;
+ /**
+ * The 'cursor' position on completion (ignoring character boundbox).
+ */
+ int width;
+};
+
#endif /* __BLF_API_H__ */
diff --git a/source/blender/blenfont/intern/blf.c b/source/blender/blenfont/intern/blf.c
index 127826f98c8..b7d72bb28bb 100644
--- a/source/blender/blenfont/intern/blf.c
+++ b/source/blender/blenfont/intern/blf.c
@@ -53,6 +53,8 @@
#include "BIF_gl.h"
#include "BLF_api.h"
+#include "IMB_colormanagement.h"
+
#include "blf_internal_types.h"
#include "blf_internal.h"
@@ -66,6 +68,11 @@
/* call BLF_default_set first! */
#define ASSERT_DEFAULT_SET BLI_assert(global_font_default != -1)
+#define BLF_RESULT_CHECK_INIT(r_info) \
+if (r_info) { \
+ memset(r_info, 0, sizeof(*(r_info))); \
+} ((void)0)
+
/* Font array. */
static FontBLF *global_font[BLF_MAX_FONT] = {NULL};
@@ -169,9 +176,6 @@ int BLF_load(const char *name)
char *filename;
int i;
- if (!name)
- return -1;
-
/* check if we already load this font. */
i = blf_search(name);
if (i >= 0) {
@@ -209,9 +213,6 @@ int BLF_load_unique(const char *name)
char *filename;
int i;
- if (!name)
- return -1;
-
/* Don't search in the cache!! make a new
* object font, this is for keep fonts threads safe.
*/
@@ -253,9 +254,6 @@ int BLF_load_mem(const char *name, const unsigned char *mem, int mem_size)
FontBLF *font;
int i;
- if (!name)
- return -1;
-
i = blf_search(name);
if (i >= 0) {
/*font = global_font[i];*/ /*UNUSED*/
@@ -268,7 +266,7 @@ int BLF_load_mem(const char *name, const unsigned char *mem, int mem_size)
return -1;
}
- if (!mem || !mem_size) {
+ if (!mem_size) {
printf("Can't load font: %s from memory!!\n", name);
return -1;
}
@@ -288,9 +286,6 @@ int BLF_load_mem_unique(const char *name, const unsigned char *mem, int mem_size
FontBLF *font;
int i;
- if (!name)
- return -1;
-
/*
* Don't search in the cache, make a new object font!
* this is to keep the font thread safe.
@@ -301,7 +296,7 @@ int BLF_load_mem_unique(const char *name, const unsigned char *mem, int mem_size
return -1;
}
- if (!mem || !mem_size) {
+ if (!mem_size) {
printf("Can't load font: %s from memory!!\n", name);
return -1;
}
@@ -491,7 +486,7 @@ void BLF_rotation_default(float angle)
}
}
-static void blf_draw__start(FontBLF *font, GLint *mode, GLint *param)
+static void blf_draw_gl__start(FontBLF *font, GLint *mode, GLint *param)
{
/*
* The pixmap alignment hack is handle
@@ -515,7 +510,7 @@ static void blf_draw__start(FontBLF *font, GLint *mode, GLint *param)
if (font->flags & BLF_MATRIX)
glMultMatrixd((GLdouble *)&font->m);
- glTranslatef(font->pos[0], font->pos[1], font->pos[2]);
+ glTranslate3fv(font->pos);
if (font->flags & BLF_ASPECT)
glScalef(font->aspect[0], font->aspect[1], font->aspect[2]);
@@ -535,7 +530,7 @@ static void blf_draw__start(FontBLF *font, GLint *mode, GLint *param)
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
}
-static void blf_draw__end(GLint mode, GLint param)
+static void blf_draw_gl__end(GLint mode, GLint param)
{
/* and restore the original value. */
if (param != GL_MODULATE)
@@ -554,29 +549,56 @@ static void blf_draw__end(GLint mode, GLint param)
glDisable(GL_TEXTURE_2D);
}
-void BLF_draw(int fontid, const char *str, size_t len)
+void BLF_draw_ex(
+ int fontid, const char *str, size_t len,
+ struct ResultBLF *r_info)
{
FontBLF *font = blf_get(fontid);
GLint mode, param;
+ BLF_RESULT_CHECK_INIT(r_info);
+
if (font && font->glyph_cache) {
- blf_draw__start(font, &mode, &param);
- blf_font_draw(font, str, len);
- blf_draw__end(mode, param);
+ blf_draw_gl__start(font, &mode, &param);
+ if (font->flags & BLF_WORD_WRAP) {
+ blf_font_draw__wrap(font, str, len, r_info);
+ }
+ else {
+ blf_font_draw(font, str, len, r_info);
+ }
+ blf_draw_gl__end(mode, param);
}
}
+void BLF_draw(int fontid, const char *str, size_t len)
+{
+ BLF_draw_ex(fontid, str, len, NULL);
+}
-void BLF_draw_ascii(int fontid, const char *str, size_t len)
+void BLF_draw_ascii_ex(
+ int fontid, const char *str, size_t len,
+ struct ResultBLF *r_info)
{
FontBLF *font = blf_get(fontid);
GLint mode, param;
+ BLF_RESULT_CHECK_INIT(r_info);
+
if (font && font->glyph_cache) {
- blf_draw__start(font, &mode, &param);
- blf_font_draw_ascii(font, str, len);
- blf_draw__end(mode, param);
+ blf_draw_gl__start(font, &mode, &param);
+ if (font->flags & BLF_WORD_WRAP) {
+ /* use non-ascii draw function for word-wrap */
+ blf_font_draw__wrap(font, str, len, r_info);
+ }
+ else {
+ blf_font_draw_ascii(font, str, len, r_info);
+ }
+ blf_draw_gl__end(mode, param);
}
}
+void BLF_draw_ascii(int fontid, const char *str, size_t len)
+{
+ BLF_draw_ascii_ex(fontid, str, len, NULL);
+}
int BLF_draw_mono(int fontid, const char *str, size_t len, int cwidth)
{
@@ -585,9 +607,9 @@ int BLF_draw_mono(int fontid, const char *str, size_t len, int cwidth)
int columns = 0;
if (font && font->glyph_cache) {
- blf_draw__start(font, &mode, &param);
+ blf_draw_gl__start(font, &mode, &param);
columns = blf_font_draw_mono(font, str, len, cwidth);
- blf_draw__end(mode, param);
+ blf_draw_gl__end(mode, param);
}
return columns;
@@ -633,21 +655,34 @@ size_t BLF_width_to_rstrlen(int fontid, const char *str, size_t len, float width
return 0;
}
-void BLF_boundbox(int fontid, const char *str, size_t len, rctf *box)
+void BLF_boundbox_ex(
+ int fontid, const char *str, size_t len, rctf *r_box,
+ struct ResultBLF *r_info)
{
FontBLF *font = blf_get(fontid);
+ BLF_RESULT_CHECK_INIT(r_info);
+
if (font) {
- blf_font_boundbox(font, str, len, box);
+ if (font->flags & BLF_WORD_WRAP) {
+ blf_font_boundbox__wrap(font, str, len, r_box, r_info);
+ }
+ else {
+ blf_font_boundbox(font, str, len, r_box, r_info);
+ }
}
}
+void BLF_boundbox(int fontid, const char *str, size_t len, rctf *r_box)
+{
+ BLF_boundbox_ex(fontid, str, len, r_box, NULL);
+}
void BLF_width_and_height(int fontid, const char *str, size_t len, float *r_width, float *r_height)
{
FontBLF *font = blf_get(fontid);
if (font && font->glyph_cache) {
- blf_font_width_and_height(font, str, len, r_width, r_height);
+ blf_font_width_and_height(font, str, len, r_width, r_height, NULL);
}
else {
*r_width = *r_height = 0.0f;
@@ -662,16 +697,24 @@ void BLF_width_and_height_default(const char *str, size_t len, float *r_width, f
BLF_width_and_height(global_font_default, str, len, r_width, r_height);
}
-float BLF_width(int fontid, const char *str, size_t len)
+float BLF_width_ex(
+ int fontid, const char *str, size_t len,
+ struct ResultBLF *r_info)
{
FontBLF *font = blf_get(fontid);
+ BLF_RESULT_CHECK_INIT(r_info);
+
if (font && font->glyph_cache) {
- return blf_font_width(font, str, len);
+ return blf_font_width(font, str, len, r_info);
}
return 0.0f;
}
+float BLF_width(int fontid, const char *str, size_t len)
+{
+ return BLF_width_ex(fontid, str, len, NULL);
+}
float BLF_fixed_width(int fontid)
{
@@ -692,18 +735,26 @@ float BLF_width_default(const char *str, size_t len)
return BLF_width(global_font_default, str, len);
}
-float BLF_height(int fontid, const char *str, size_t len)
+float BLF_height_ex(
+ int fontid, const char *str, size_t len,
+ struct ResultBLF *r_info)
{
FontBLF *font = blf_get(fontid);
+ BLF_RESULT_CHECK_INIT(r_info);
+
if (font && font->glyph_cache) {
- return blf_font_height(font, str, len);
+ return blf_font_height(font, str, len, r_info);
}
return 0.0f;
}
+float BLF_height(int fontid, const char *str, size_t len)
+{
+ return BLF_height_ex(fontid, str, len, NULL);
+}
-float BLF_height_max(int fontid)
+int BLF_height_max(int fontid)
{
FontBLF *font = blf_get(fontid);
@@ -711,7 +762,7 @@ float BLF_height_max(int fontid)
return font->glyph_cache->max_glyph_height;
}
- return 0.0f;
+ return 0;
}
float BLF_width_max(int fontid)
@@ -789,6 +840,15 @@ void BLF_clipping_default(float xmin, float ymin, float xmax, float ymax)
}
}
+void BLF_wordwrap(int fontid, int wrap_width)
+{
+ FontBLF *font = blf_get(fontid);
+
+ if (font) {
+ font->wrap_width = wrap_width;
+ }
+}
+
void BLF_shadow(int fontid, int level, float r, float g, float b, float a)
{
FontBLF *font = blf_get(fontid);
@@ -831,21 +891,52 @@ void BLF_buffer_col(int fontid, float r, float g, float b, float a)
FontBLF *font = blf_get(fontid);
if (font) {
- font->buf_info.col[0] = r;
- font->buf_info.col[1] = g;
- font->buf_info.col[2] = b;
- font->buf_info.col[3] = a;
+ ARRAY_SET_ITEMS(font->buf_info.col_init, r, g, b, a);
+ }
+}
+
+
+void blf_draw_buffer__start(FontBLF *font)
+{
+ FontBufInfoBLF *buf_info = &font->buf_info;
+
+ buf_info->col_char[0] = buf_info->col_init[0] * 255;
+ buf_info->col_char[1] = buf_info->col_init[1] * 255;
+ buf_info->col_char[2] = buf_info->col_init[2] * 255;
+ buf_info->col_char[3] = buf_info->col_init[3] * 255;
+
+ if (buf_info->display) {
+ copy_v4_v4(buf_info->col_float, buf_info->col_init);
+ IMB_colormanagement_display_to_scene_linear_v3(buf_info->col_float, buf_info->display);
+ }
+ else {
+ srgb_to_linearrgb_v4(buf_info->col_float, buf_info->col_init);
}
}
+void blf_draw_buffer__end(void) {}
-void BLF_draw_buffer(int fontid, const char *str)
+void BLF_draw_buffer_ex(
+ int fontid, const char *str, size_t len,
+ struct ResultBLF *r_info)
{
FontBLF *font = blf_get(fontid);
if (font && font->glyph_cache && (font->buf_info.fbuf || font->buf_info.cbuf)) {
- blf_font_buffer(font, str);
+ blf_draw_buffer__start(font);
+ if (font->flags & BLF_WORD_WRAP) {
+ blf_font_draw_buffer__wrap(font, str, len, r_info);
+ }
+ else {
+ blf_font_draw_buffer(font, str, len, r_info);
+ }
+ blf_draw_buffer__end();
}
}
+void BLF_draw_buffer(
+ int fontid, const char *str, size_t len)
+{
+ BLF_draw_buffer_ex(fontid, str, len, NULL);
+}
#ifdef DEBUG
void BLF_state_print(int fontid)
diff --git a/source/blender/blenfont/intern/blf_font.c b/source/blender/blenfont/intern/blf_font.c
index 2057b0f6bbf..3f3ca78b6cd 100644
--- a/source/blender/blenfont/intern/blf_font.c
+++ b/source/blender/blenfont/intern/blf_font.c
@@ -58,8 +58,6 @@
#include "BIF_gl.h"
#include "BLF_api.h"
-#include "IMB_colormanagement.h"
-
#include "blf_internal_types.h"
#include "blf_internal.h"
@@ -153,7 +151,7 @@ static void blf_font_ensure_ascii_table(FontBLF *font)
#define BLF_KERNING_VARS(_font, _has_kerning, _kern_mode) \
- const bool _has_kerning = FT_HAS_KERNING((_font)->face); \
+ const bool _has_kerning = FT_HAS_KERNING((_font)->face) != 0; \
const FT_UInt _kern_mode = (_has_kerning == 0) ? 0 : \
(((_font)->flags & BLF_KERNING_DEFAULT) ? \
ft_kerning_default : (FT_UInt)FT_KERNING_UNFITTED) \
@@ -174,12 +172,14 @@ static void blf_font_ensure_ascii_table(FontBLF *font)
} \
} (void)0
-void blf_font_draw(FontBLF *font, const char *str, size_t len)
+static void blf_font_draw_ex(
+ FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info,
+ int pen_y)
{
unsigned int c;
GlyphBLF *g, *g_prev = NULL;
FT_Vector delta;
- int pen_x = 0, pen_y = 0;
+ int pen_x = 0;
size_t i = 0;
GlyphBLF **glyph_ascii_table = font->glyph_cache->glyph_ascii_table;
@@ -203,15 +203,26 @@ void blf_font_draw(FontBLF *font, const char *str, size_t len)
pen_x += g->advance_i;
g_prev = g;
}
+
+ if (r_info) {
+ r_info->lines = 1;
+ r_info->width = pen_x;
+ }
+}
+void blf_font_draw(FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info)
+{
+ blf_font_draw_ex(font, str, len, r_info, 0);
}
/* faster version of blf_font_draw, ascii only for view dimensions */
-void blf_font_draw_ascii(FontBLF *font, const char *str, size_t len)
+static void blf_font_draw_ascii_ex(
+ FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info,
+ int pen_y)
{
unsigned char c;
GlyphBLF *g, *g_prev = NULL;
FT_Vector delta;
- int pen_x = 0, pen_y = 0;
+ int pen_x = 0;
GlyphBLF **glyph_ascii_table = font->glyph_cache->glyph_ascii_table;
BLF_KERNING_VARS(font, has_kerning, kern_mode);
@@ -231,6 +242,15 @@ void blf_font_draw_ascii(FontBLF *font, const char *str, size_t len)
pen_x += g->advance_i;
g_prev = g;
}
+
+ if (r_info) {
+ r_info->lines = 1;
+ r_info->width = pen_x;
+ }
+}
+void blf_font_draw_ascii(FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info)
+{
+ blf_font_draw_ascii_ex(font, str, len, r_info, 0);
}
/* use fixed column width, but an utf8 character may occupy multiple columns */
@@ -268,24 +288,22 @@ int blf_font_draw_mono(FontBLF *font, const char *str, size_t len, int cwidth)
}
/* Sanity checks are done by BLF_draw_buffer() */
-void blf_font_buffer(FontBLF *font, const char *str)
+static void blf_font_draw_buffer_ex(
+ FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info,
+ int pen_y)
{
unsigned int c;
GlyphBLF *g, *g_prev = NULL;
FT_Vector delta;
- int pen_x = (int)font->pos[0], pen_y = 0;
+ int pen_x = (int)font->pos[0];
+ int pen_y_basis = (int)font->pos[1] + pen_y;
size_t i = 0;
GlyphBLF **glyph_ascii_table = font->glyph_cache->glyph_ascii_table;
/* buffer specific vars */
FontBufInfoBLF *buf_info = &font->buf_info;
- float b_col_float[4];
- const unsigned char b_col_char[4] = {
- (unsigned char)(buf_info->col[0] * 255),
- (unsigned char)(buf_info->col[1] * 255),
- (unsigned char)(buf_info->col[2] * 255),
- (unsigned char)(buf_info->col[3] * 255)};
-
+ const float *b_col_float = buf_info->col_float;
+ const unsigned char *b_col_char = buf_info->col_char;
int chx, chy;
int y, x;
float a;
@@ -295,15 +313,8 @@ void blf_font_buffer(FontBLF *font, const char *str)
blf_font_ensure_ascii_table(font);
/* another buffer specific call for color conversion */
- if (buf_info->display) {
- copy_v4_v4(b_col_float, buf_info->col);
- IMB_colormanagement_display_to_scene_linear_v3(b_col_float, buf_info->display);
- }
- else {
- srgb_to_linearrgb_v4(b_col_float, buf_info->col);
- }
- while (str[i]) {
+ while ((i < len) && str[i]) {
BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table);
if (UNLIKELY(c == BLI_UTF8_ERR))
@@ -314,13 +325,13 @@ void blf_font_buffer(FontBLF *font, const char *str)
BLF_KERNING_STEP(font, kern_mode, g_prev, g, delta, pen_x);
chx = pen_x + ((int)g->pos_x);
- chy = (int)font->pos[1] + g->height;
+ chy = pen_y_basis + g->height;
if (g->pitch < 0) {
- pen_y = (int)font->pos[1] + (g->height - (int)g->pos_y);
+ pen_y = pen_y_basis + (g->height - (int)g->pos_y);
}
else {
- pen_y = (int)font->pos[1] - (g->height - (int)g->pos_y);
+ pen_y = pen_y_basis - (g->height - (int)g->pos_y);
}
if ((chx + g->width) >= 0 && chx < buf_info->w && (pen_y + g->height) >= 0 && pen_y < buf_info->h) {
@@ -429,6 +440,16 @@ void blf_font_buffer(FontBLF *font, const char *str)
pen_x += g->advance_i;
g_prev = g;
}
+
+ if (r_info) {
+ r_info->lines = 1;
+ r_info->width = pen_x;
+ }
+}
+void blf_font_draw_buffer(
+ FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info)
+{
+ blf_font_draw_buffer_ex(font, str, len, r_info, 0);
}
size_t blf_font_width_to_strlen(FontBLF *font, const char *str, size_t len, float width, float *r_width)
@@ -558,12 +579,14 @@ size_t blf_font_width_to_rstrlen(FontBLF *font, const char *str, size_t len, flo
return i_prev;
}
-void blf_font_boundbox(FontBLF *font, const char *str, size_t len, rctf *box)
+static void blf_font_boundbox_ex(
+ FontBLF *font, const char *str, size_t len, rctf *box, struct ResultBLF *r_info,
+ int pen_y)
{
unsigned int c;
GlyphBLF *g, *g_prev = NULL;
FT_Vector delta;
- int pen_x = 0, pen_y = 0;
+ int pen_x = 0;
size_t i = 0;
GlyphBLF **glyph_ascii_table = font->glyph_cache->glyph_ascii_table;
@@ -609,9 +632,168 @@ void blf_font_boundbox(FontBLF *font, const char *str, size_t len, rctf *box)
box->xmax = 0.0f;
box->ymax = 0.0f;
}
+
+ if (r_info) {
+ r_info->lines = 1;
+ r_info->width = pen_x;
+ }
}
+void blf_font_boundbox(FontBLF *font, const char *str, size_t len, rctf *r_box, struct ResultBLF *r_info)
+{
+ blf_font_boundbox_ex(font, str, len, r_box, r_info, 0);
+}
+
+
+/* -------------------------------------------------------------------- */
+/** \name Word-Wrap Support
+ * \{ */
+
-void blf_font_width_and_height(FontBLF *font, const char *str, size_t len, float *width, float *height)
+/**
+ * Generic function to add word-wrap support for other existing functions.
+ *
+ * Wraps on spaces and respects newlines.
+ * Intentionally ignores non-unix newlines, tabs and more advanced text formatting.
+ *
+ * \note If we want rich text - we better have a higher level API to handle that
+ * (color, bold, switching fonts... etc).
+ */
+static void blf_font_wrap_apply(
+ FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info,
+ void (*callback)(FontBLF *font, const char *str, size_t len, int pen_y, void *userdata),
+ void *userdata)
+{
+ unsigned int c;
+ GlyphBLF *g, *g_prev = NULL;
+ FT_Vector delta;
+ int pen_x = 0, pen_y = 0;
+ size_t i = 0;
+ GlyphBLF **glyph_ascii_table = font->glyph_cache->glyph_ascii_table;
+ int lines = 0;
+ int pen_x_next = 0;
+
+ BLF_KERNING_VARS(font, has_kerning, kern_mode);
+
+ struct WordWrapVars {
+ int wrap_width;
+ size_t start, last[2];
+ } wrap = {font->wrap_width != -1 ? font->wrap_width : INT_MAX, 0, {0, 0}};
+
+ blf_font_ensure_ascii_table(font);
+ // printf("%s wrapping (%d, %d) `%s`:\n", __func__, len, strlen(str), str);
+ while ((i < len) && str[i]) {
+
+ /* wrap vars */
+ size_t i_curr = i;
+ bool do_draw = false;
+
+ BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table);
+
+ if (UNLIKELY(c == BLI_UTF8_ERR))
+ break;
+ if (UNLIKELY(g == NULL))
+ continue;
+ if (has_kerning)
+ BLF_KERNING_STEP(font, kern_mode, g_prev, g, delta, pen_x);
+
+ /**
+ * Implementation Detail (utf8).
+ *
+ * Take care with single byte offsets here,
+ * since this is utf8 we can't be sure a single byte is a single character.
+ *
+ * This is _only_ done when we know for sure the character is ascii (newline or a space).
+ */
+ pen_x_next = pen_x + g->advance_i;
+ if (UNLIKELY((pen_x_next >= wrap.wrap_width) && (wrap.start != wrap.last[0]))) {
+ do_draw = true;
+ }
+ else if (UNLIKELY(((i < len) && str[i]) == 0)) {
+ /* need check here for trailing newline, else we draw it */
+ wrap.last[0] = i + ((g->c != '\n') ? 1 : 0);
+ wrap.last[1] = i;
+ do_draw = true;
+ }
+ else if (UNLIKELY(g->c == '\n')) {
+ wrap.last[0] = i_curr + 1;
+ wrap.last[1] = i;
+ do_draw = true;
+ }
+ else if (UNLIKELY(g->c != ' ' && (g_prev ? g_prev->c == ' ' : false))) {
+ wrap.last[0] = i_curr;
+ wrap.last[1] = i;
+ }
+
+ if (UNLIKELY(do_draw)) {
+ // printf("(%d..%d) `%.*s`\n", wrap.start, wrap.last[0], (wrap.last[0] - wrap.start) - 1, &str[wrap.start]);
+ callback(font, &str[wrap.start], (wrap.last[0] - wrap.start) - 1, pen_y, userdata);
+ wrap.start = wrap.last[0];
+ i = wrap.last[1];
+ pen_x = 0;
+ pen_y -= font->glyph_cache->max_glyph_height;
+ g_prev = NULL;
+ lines += 1;
+ continue;
+ }
+
+ pen_x = pen_x_next;
+ g_prev = g;
+ }
+
+ // printf("done! %d lines\n", lines);
+
+ if (r_info) {
+ r_info->lines = lines;
+ /* width of last line only (with wrapped lines) */
+ r_info->width = pen_x_next;
+ }
+}
+
+/* blf_font_draw__wrap */
+static void blf_font_draw__wrap_cb(FontBLF *font, const char *str, size_t len, int pen_y, void *UNUSED(userdata))
+{
+ blf_font_draw_ex(font, str, len, NULL, pen_y);
+}
+void blf_font_draw__wrap(FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info)
+{
+ blf_font_wrap_apply(font, str, len, r_info, blf_font_draw__wrap_cb, NULL);
+}
+
+/* blf_font_boundbox__wrap */
+static void blf_font_boundbox_wrap_cb(FontBLF *font, const char *str, size_t len, int pen_y, void *userdata)
+{
+ rctf *box = userdata;
+ rctf box_single;
+
+ blf_font_boundbox_ex(font, str, len, &box_single, NULL, pen_y);
+ BLI_rctf_union(box, &box_single);
+}
+void blf_font_boundbox__wrap(FontBLF *font, const char *str, size_t len, rctf *box, struct ResultBLF *r_info)
+{
+ box->xmin = 32000.0f;
+ box->xmax = -32000.0f;
+ box->ymin = 32000.0f;
+ box->ymax = -32000.0f;
+
+ blf_font_wrap_apply(font, str, len, r_info, blf_font_boundbox_wrap_cb, box);
+}
+
+/* blf_font_draw_buffer__wrap */
+static void blf_font_draw_buffer__wrap_cb(FontBLF *font, const char *str, size_t len, int pen_y, void *UNUSED(userdata))
+{
+ blf_font_draw_buffer_ex(font, str, len, NULL, pen_y);
+}
+void blf_font_draw_buffer__wrap(FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info)
+{
+ blf_font_wrap_apply(font, str, len, r_info, blf_font_draw_buffer__wrap_cb, NULL);
+}
+
+/** \} */
+
+
+void blf_font_width_and_height(
+ FontBLF *font, const char *str, size_t len,
+ float *r_width, float *r_height, struct ResultBLF *r_info)
{
float xa, ya;
rctf box;
@@ -625,12 +807,17 @@ void blf_font_width_and_height(FontBLF *font, const char *str, size_t len, float
ya = 1.0f;
}
- blf_font_boundbox(font, str, len, &box);
- *width = (BLI_rctf_size_x(&box) * xa);
- *height = (BLI_rctf_size_y(&box) * ya);
+ if (font->flags & BLF_WORD_WRAP) {
+ blf_font_boundbox__wrap(font, str, len, &box, r_info);
+ }
+ else {
+ blf_font_boundbox(font, str, len, &box, r_info);
+ }
+ *r_width = (BLI_rctf_size_x(&box) * xa);
+ *r_height = (BLI_rctf_size_y(&box) * ya);
}
-float blf_font_width(FontBLF *font, const char *str, size_t len)
+float blf_font_width(FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info)
{
float xa;
rctf box;
@@ -640,11 +827,16 @@ float blf_font_width(FontBLF *font, const char *str, size_t len)
else
xa = 1.0f;
- blf_font_boundbox(font, str, len, &box);
+ if (font->flags & BLF_WORD_WRAP) {
+ blf_font_boundbox__wrap(font, str, len, &box, r_info);
+ }
+ else {
+ blf_font_boundbox(font, str, len, &box, r_info);
+ }
return BLI_rctf_size_x(&box) * xa;
}
-float blf_font_height(FontBLF *font, const char *str, size_t len)
+float blf_font_height(FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info)
{
float ya;
rctf box;
@@ -654,7 +846,12 @@ float blf_font_height(FontBLF *font, const char *str, size_t len)
else
ya = 1.0f;
- blf_font_boundbox(font, str, len, &box);
+ if (font->flags & BLF_WORD_WRAP) {
+ blf_font_boundbox__wrap(font, str, len, &box, r_info);
+ }
+ else {
+ blf_font_boundbox(font, str, len, &box, r_info);
+ }
return BLI_rctf_size_y(&box) * ya;
}
@@ -744,10 +941,10 @@ static void blf_font_fill(FontBLF *font)
font->buf_info.w = 0;
font->buf_info.h = 0;
font->buf_info.ch = 0;
- font->buf_info.col[0] = 0;
- font->buf_info.col[1] = 0;
- font->buf_info.col[2] = 0;
- font->buf_info.col[3] = 0;
+ font->buf_info.col_init[0] = 0;
+ font->buf_info.col_init[1] = 0;
+ font->buf_info.col_init[2] = 0;
+ font->buf_info.col_init[3] = 0;
font->ft_lib = ft_lib;
font->ft_lib_mutex = &ft_lib_mutex;
diff --git a/source/blender/blenfont/intern/blf_internal.h b/source/blender/blenfont/intern/blf_internal.h
index 85410a4d856..d9d758ce548 100644
--- a/source/blender/blenfont/intern/blf_internal.h
+++ b/source/blender/blenfont/intern/blf_internal.h
@@ -31,6 +31,7 @@
#ifndef __BLF_INTERNAL_H__
#define __BLF_INTERNAL_H__
+struct ResultBLF;
struct FontBLF;
struct GlyphBLF;
struct GlyphCacheBLF;
@@ -46,21 +47,27 @@ char *blf_dir_metrics_search(const char *filename);
int blf_font_init(void);
void blf_font_exit(void);
+void blf_draw_buffer__start(struct FontBLF *font);
+void blf_draw_buffer__end(void);
+
struct FontBLF *blf_font_new(const char *name, const char *filename);
struct FontBLF *blf_font_new_from_mem(const char *name, const unsigned char *mem, int mem_size);
void blf_font_attach_from_mem(struct FontBLF *font, const unsigned char *mem, int mem_size);
void blf_font_size(struct FontBLF *font, unsigned int size, unsigned int dpi);
-void blf_font_draw(struct FontBLF *font, const char *str, size_t len);
-void blf_font_draw_ascii(struct FontBLF *font, const char *str, size_t len);
+void blf_font_draw(struct FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info);
+void blf_font_draw__wrap(struct FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info);
+void blf_font_draw_ascii(struct FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info);
int blf_font_draw_mono(struct FontBLF *font, const char *str, size_t len, int cwidth);
-void blf_font_buffer(struct FontBLF *font, const char *str);
+void blf_font_draw_buffer(struct FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info);
+void blf_font_draw_buffer__wrap(struct FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info);
size_t blf_font_width_to_strlen(struct FontBLF *font, const char *str, size_t len, float width, float *r_width);
size_t blf_font_width_to_rstrlen(struct FontBLF *font, const char *str, size_t len, float width, float *r_width);
-void blf_font_boundbox(struct FontBLF *font, const char *str, size_t len, struct rctf *box);
-void blf_font_width_and_height(struct FontBLF *font, const char *str, size_t len, float *width, float *height);
-float blf_font_width(struct FontBLF *font, const char *str, size_t len);
-float blf_font_height(struct FontBLF *font, const char *str, size_t len);
+void blf_font_boundbox(struct FontBLF *font, const char *str, size_t len, struct rctf *r_box, struct ResultBLF *r_info);
+void blf_font_boundbox__wrap(struct FontBLF *font, const char *str, size_t len, struct rctf *r_box, struct ResultBLF *r_info);
+void blf_font_width_and_height(struct FontBLF *font, const char *str, size_t len, float *r_width, float *r_height, struct ResultBLF *r_info);
+float blf_font_width(struct FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info);
+float blf_font_height(struct FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info);
float blf_font_fixed_width(struct FontBLF *font);
int blf_font_count_missing_chars(struct FontBLF *font, const char *str, const size_t len, int *r_tot_chars);
diff --git a/source/blender/blenfont/intern/blf_internal_types.h b/source/blender/blenfont/intern/blf_internal_types.h
index 1404b9de250..f17401a9991 100644
--- a/source/blender/blenfont/intern/blf_internal_types.h
+++ b/source/blender/blenfont/intern/blf_internal_types.h
@@ -152,7 +152,11 @@ typedef struct FontBufInfoBLF {
/* and the color, the alphas is get from the glyph!
* color is srgb space */
- float col[4];
+ float col_init[4];
+ /* cached conversion from 'col_init' */
+ unsigned char col_char[4];
+ float col_float[4];
+
} FontBufInfoBLF;
typedef struct FontBLF {
@@ -195,6 +199,9 @@ typedef struct FontBLF {
/* clipping rectangle. */
rctf clip_rec;
+ /* the width to wrap the text, see BLF_WORD_WRAP */
+ int wrap_width;
+
/* font dpi (default 72). */
unsigned int dpi;
diff --git a/source/blender/blenfont/intern/blf_thumbs.c b/source/blender/blenfont/intern/blf_thumbs.c
index 4eea5d581d0..133168fccf2 100644
--- a/source/blender/blenfont/intern/blf_thumbs.c
+++ b/source/blender/blenfont/intern/blf_thumbs.c
@@ -84,11 +84,13 @@ void BLF_thumb_preview(
/* Always create the image with a white font,
* the caller can theme how it likes */
- memcpy(font->buf_info.col, font_color, sizeof(font->buf_info.col));
+ memcpy(font->buf_info.col_init, font_color, sizeof(font->buf_info.col_init));
font->pos[1] = (float)h;
font_size_curr = font_size;
+ blf_draw_buffer__start(font);
+
for (i = 0; i < draw_str_lines; i++) {
const char *draw_str_i18n = BLT_translate_do(BLT_I18NCONTEXT_DEFAULT, draw_str[i]);
const size_t draw_str_i18n_len = strlen(draw_str_i18n);
@@ -110,12 +112,13 @@ void BLF_thumb_preview(
if (blf_font_count_missing_chars(
font, draw_str_i18n, draw_str_i18n_len, &draw_str_i18n_nbr) > (draw_str_i18n_nbr / 2))
{
- blf_font_buffer(font, draw_str[i]);
+ blf_font_draw_buffer(font, draw_str[i], strlen(draw_str[i]), NULL);
}
else {
- blf_font_buffer(font, draw_str_i18n);
+ blf_font_draw_buffer(font, draw_str_i18n, draw_str_i18n_len, NULL);
}
}
+ blf_draw_buffer__end();
blf_font_free(font);
}
diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h
index 3883b69c0d4..fad177df978 100644
--- a/source/blender/blenkernel/BKE_DerivedMesh.h
+++ b/source/blender/blenkernel/BKE_DerivedMesh.h
@@ -499,6 +499,11 @@ void DM_init(
DerivedMesh *dm, DerivedMeshType type, int numVerts, int numEdges,
int numFaces, int numLoops, int numPolys);
+void DM_from_template_ex(
+ DerivedMesh *dm, DerivedMesh *source, DerivedMeshType type,
+ int numVerts, int numEdges, int numTessFaces,
+ int numLoops, int numPolys,
+ CustomDataMask mask);
void DM_from_template(
DerivedMesh *dm, DerivedMesh *source,
DerivedMeshType type,
diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h
index a834a83ca00..e1885e46b24 100644
--- a/source/blender/blenkernel/BKE_armature.h
+++ b/source/blender/blenkernel/BKE_armature.h
@@ -80,6 +80,8 @@ struct bArmature *BKE_armature_copy(struct bArmature *arm);
/* Bounding box. */
struct BoundBox *BKE_armature_boundbox_get(struct Object *ob);
+bool BKE_pose_minmax(struct Object *ob, float r_min[3], float r_max[3], bool use_hidden, bool use_select);
+
int bone_autoside_name(char name[64], int strip_number, short axis, float head, float tail);
struct Bone *BKE_armature_find_bone_name(struct bArmature *arm, const char *name);
@@ -89,7 +91,7 @@ bool BKE_armature_bone_flag_test_recursive(const struct Bone *bone, int
float distfactor_to_bone(const float vec[3], const float b1[3], const float b2[3], float r1, float r2, float rdist);
void BKE_armature_where_is(struct bArmature *arm);
-void BKE_armature_where_is_bone(struct Bone *bone, struct Bone *prevbone);
+void BKE_armature_where_is_bone(struct Bone *bone, struct Bone *prevbone, const bool use_recursion);
void BKE_pose_rebuild(struct Object *ob, struct bArmature *arm);
void BKE_pose_where_is(struct Scene *scene, struct Object *ob);
void BKE_pose_where_is_bone(struct Scene *scene, struct Object *ob, struct bPoseChannel *pchan, float ctime, bool do_extra);
diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h
index a13bd0c48ec..607f2a98939 100644
--- a/source/blender/blenkernel/BKE_blender.h
+++ b/source/blender/blenkernel/BKE_blender.h
@@ -41,8 +41,8 @@ extern "C" {
/* these lines are grep'd, watch out for our not-so-awesome regex
* and keep comment above the defines.
* Use STRINGIFY() rather than defining with quotes */
-#define BLENDER_VERSION 275
-#define BLENDER_SUBVERSION 6
+#define BLENDER_VERSION 276
+#define BLENDER_SUBVERSION 2
/* Several breakages with 270, e.g. constraint deg vs rad */
#define BLENDER_MINVERSION 270
#define BLENDER_MINSUBVERSION 5
diff --git a/source/blender/blenkernel/BKE_brush.h b/source/blender/blenkernel/BKE_brush.h
index 042fba7294c..bb3ad0efb63 100644
--- a/source/blender/blenkernel/BKE_brush.h
+++ b/source/blender/blenkernel/BKE_brush.h
@@ -40,7 +40,9 @@ void BKE_brush_system_init(void);
void BKE_brush_system_exit(void);
/* datablock functions */
-struct Brush *BKE_brush_add(struct Main *bmain, const char *name);
+void BKE_brush_init(struct Brush *brush);
+struct Brush *BKE_brush_add(struct Main *bmain, const char *name, short ob_mode);
+struct Brush *BKE_brush_first_search(struct Main *bmain, short ob_mode);
struct Brush *BKE_brush_copy(struct Brush *brush);
void BKE_brush_make_local(struct Brush *brush);
void BKE_brush_free(struct Brush *brush);
diff --git a/source/blender/blenkernel/BKE_bvhutils.h b/source/blender/blenkernel/BKE_bvhutils.h
index 18eda63bcf1..749b0db7c27 100644
--- a/source/blender/blenkernel/BKE_bvhutils.h
+++ b/source/blender/blenkernel/BKE_bvhutils.h
@@ -68,7 +68,8 @@ typedef struct BVHTreeFromMesh {
float sphere_radius;
/* Private data */
- void *em_evil; /* var only for snapping */
+ void *em_evil;
+ bool em_evil_all; /* ignore selection/hidden state, adding all loops to the tree */
bool cached;
} BVHTreeFromMesh;
@@ -141,8 +142,11 @@ enum {
BVHTREE_FROM_VERTS = 0,
BVHTREE_FROM_EDGES = 1,
BVHTREE_FROM_FACES = 2,
- BVHTREE_FROM_FACES_EDITMESH = 3,
- BVHTREE_FROM_LOOPTRI = 4,
+ BVHTREE_FROM_LOOPTRI = 3,
+ /* all faces */
+ BVHTREE_FROM_FACES_EDITMESH_ALL = 4,
+ /* visible unselected, only used for transform snapping */
+ BVHTREE_FROM_FACES_EDITMESH_SNAP = 5,
};
typedef struct LinkNode *BVHCache;
diff --git a/source/blender/blenkernel/BKE_camera.h b/source/blender/blenkernel/BKE_camera.h
index aacb7a4066b..118153a9163 100644
--- a/source/blender/blenkernel/BKE_camera.h
+++ b/source/blender/blenkernel/BKE_camera.h
@@ -50,6 +50,7 @@ struct GPUFXSettings;
/* Camera Datablock */
+void BKE_camera_init(struct Camera *cam);
void *BKE_camera_add(struct Main *bmain, const char *name);
struct Camera *BKE_camera_copy(struct Camera *cam);
void BKE_camera_make_local(struct Camera *cam);
diff --git a/source/blender/blenkernel/BKE_cdderivedmesh.h b/source/blender/blenkernel/BKE_cdderivedmesh.h
index c7ad6419560..9948f21ba90 100644
--- a/source/blender/blenkernel/BKE_cdderivedmesh.h
+++ b/source/blender/blenkernel/BKE_cdderivedmesh.h
@@ -84,9 +84,15 @@ struct DerivedMesh *CDDM_copy_from_tessface(struct DerivedMesh *dm);
* given DerivedMesh and containing the requested numbers of elements.
* elements are initialized to all zeros
*/
-struct DerivedMesh *CDDM_from_template(struct DerivedMesh *source,
- int numVerts, int numEdges, int numFaces,
- int numLoops, int numPolys);
+struct DerivedMesh *CDDM_from_template_ex(
+ struct DerivedMesh *source,
+ int numVerts, int numEdges, int numFaces,
+ int numLoops, int numPolys,
+ CustomDataMask mask);
+struct DerivedMesh *CDDM_from_template(
+ struct DerivedMesh *source,
+ int numVerts, int numEdges, int numFaces,
+ int numLoops, int numPolys);
/* converts mfaces to mpolys. note things may break if there are not valid
* medges surrounding each mface.
diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h
index a03dd287146..061270b8b41 100644
--- a/source/blender/blenkernel/BKE_curve.h
+++ b/source/blender/blenkernel/BKE_curve.h
@@ -69,6 +69,7 @@ typedef struct CurveCache {
void BKE_curve_unlink(struct Curve *cu);
void BKE_curve_free(struct Curve *cu);
void BKE_curve_editfont_free(struct Curve *cu);
+void BKE_curve_init(struct Curve *cu);
struct Curve *BKE_curve_add(struct Main *bmain, const char *name, int type);
struct Curve *BKE_curve_copy(struct Curve *cu);
void BKE_curve_make_local(struct Curve *cu);
diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h
index 6fb27cf7577..a7c5c210061 100644
--- a/source/blender/blenkernel/BKE_customdata.h
+++ b/source/blender/blenkernel/BKE_customdata.h
@@ -381,6 +381,10 @@ void CustomData_bmesh_update_active_layers(struct CustomData *fdata, struct Cust
void CustomData_bmesh_do_versions_update_active_layers(struct CustomData *fdata, struct CustomData *pdata, struct CustomData *ldata);
void CustomData_bmesh_init_pool(struct CustomData *data, int totelem, const char htype);
+#ifndef NDEBUG
+bool CustomData_from_bmeshpoly_test(CustomData *fdata, CustomData *pdata, CustomData *ldata, bool fallback);
+#endif
+
/* External file storage */
void CustomData_external_add(struct CustomData *data,
@@ -468,6 +472,8 @@ typedef struct CustomDataTransferLayerMap {
size_t data_offset; /* Offset of actual data we transfer (in element contained in data_src/dst). */
uint64_t data_flag; /* For bitflag transfer, flag(s) to affect in transfered data. */
+ void *interp_data; /* Opaque pointer, to be used by specific interp callback (e.g. transformspace for normals). */
+
cd_datatransfer_interp interp;
} CustomDataTransferLayerMap;
diff --git a/source/blender/blenkernel/BKE_depsgraph.h b/source/blender/blenkernel/BKE_depsgraph.h
index 7d7db332dd2..40564aeabe9 100644
--- a/source/blender/blenkernel/BKE_depsgraph.h
+++ b/source/blender/blenkernel/BKE_depsgraph.h
@@ -147,7 +147,10 @@ void DAG_pose_sort(struct Object *ob);
/* Editors: callbacks to notify editors of datablock changes */
void DAG_editors_update_cb(void (*id_func)(struct Main *bmain, struct ID *id),
- void (*scene_func)(struct Main *bmain, struct Scene *scene, int updated));
+ void (*scene_func)(struct Main *bmain, struct Scene *scene, int updated),
+ void (*scene_pre_func)(struct Main *bmain, struct Scene *scene, bool time));
+
+void DAG_editors_update_pre(struct Main *bmain, struct Scene *scene, bool time);
/* ** Threaded update ** */
diff --git a/source/blender/blenkernel/BKE_font.h b/source/blender/blenkernel/BKE_font.h
index 137670215cc..5dcc6f8d981 100644
--- a/source/blender/blenkernel/BKE_font.h
+++ b/source/blender/blenkernel/BKE_font.h
@@ -79,8 +79,11 @@ void BKE_vfont_builtin_register(void *mem, int size);
void BKE_vfont_free_data(struct VFont *vfont);
void BKE_vfont_free(struct VFont *sc);
+void BKE_vfont_init(struct VFont *vfont);
struct VFont *BKE_vfont_builtin_get(void);
-struct VFont *BKE_vfont_load(struct Main *bmain, const char *name);
+struct VFont *BKE_vfont_load(struct Main *bmain, const char *filepath);
+struct VFont *BKE_vfont_load_exists_ex(struct Main *bmain, const char *filepath, bool *r_exists);
+struct VFont *BKE_vfont_load_exists(struct Main *bmain, const char *filepath);
bool BKE_vfont_to_curve_ex(struct Main *bmain, struct Object *ob, int mode,
struct ListBase *r_nubase,
diff --git a/source/blender/blenkernel/BKE_idcode.h b/source/blender/blenkernel/BKE_idcode.h
index ebad0d42232..6de0efe2709 100644
--- a/source/blender/blenkernel/BKE_idcode.h
+++ b/source/blender/blenkernel/BKE_idcode.h
@@ -32,15 +32,15 @@
* \ingroup bke
*/
-const char *BKE_idcode_to_name(int code);
-const char *BKE_idcode_to_name_plural(int code);
-const char *BKE_idcode_to_translation_context(int code);
-int BKE_idcode_from_name(const char *name);
-bool BKE_idcode_is_linkable(int code);
-bool BKE_idcode_is_valid(int code);
+const char *BKE_idcode_to_name(short idcode);
+const char *BKE_idcode_to_name_plural(short idcode);
+const char *BKE_idcode_to_translation_context(short idcode);
+short BKE_idcode_from_name(const char *name);
+bool BKE_idcode_is_linkable(short idcode);
+bool BKE_idcode_is_valid(short idcode);
-int BKE_idcode_to_idfilter(const int idcode);
-int BKE_idcode_from_idfilter(const int idfilter);
+int BKE_idcode_to_idfilter(const short idcode);
+short BKE_idcode_from_idfilter(const int idfilter);
/**
* Return an ID code and steps the index forward 1.
@@ -48,6 +48,6 @@ int BKE_idcode_from_idfilter(const int idfilter);
* \param index start as 0.
* \return the code, 0 when all codes have been returned.
*/
-int BKE_idcode_iter_step(int *index);
+short BKE_idcode_iter_step(int *index);
#endif
diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h
index 94afc8a16ea..ea63161e008 100644
--- a/source/blender/blenkernel/BKE_image.h
+++ b/source/blender/blenkernel/BKE_image.h
@@ -212,6 +212,8 @@ void BKE_image_multiview_index(struct Image *ima, struct ImageUser *iuser);
/* for multilayer images as well as for render-viewer */
bool BKE_image_is_multilayer(struct Image *ima);
+bool BKE_image_is_multiview(struct Image *ima);
+bool BKE_image_is_stereo(struct Image *ima);
struct RenderResult *BKE_image_acquire_renderresult(struct Scene *scene, struct Image *ima);
void BKE_image_release_renderresult(struct Scene *scene, struct Image *ima);
diff --git a/source/blender/blenkernel/BKE_key.h b/source/blender/blenkernel/BKE_key.h
index abe12282a1b..1edbb455ca4 100644
--- a/source/blender/blenkernel/BKE_key.h
+++ b/source/blender/blenkernel/BKE_key.h
@@ -65,6 +65,8 @@ float *BKE_key_evaluate_object_ex(
float *BKE_key_evaluate_object(
struct Object *ob, int *r_totelem);
+struct Key **BKE_key_from_id_p(struct ID *id);
+struct Key *BKE_key_from_id(struct ID *id);
struct Key **BKE_key_from_object_p(struct Object *ob);
struct Key *BKE_key_from_object(struct Object *ob);
struct KeyBlock *BKE_keyblock_from_object(struct Object *ob);
@@ -101,6 +103,8 @@ void BKE_keyblock_convert_to_curve(struct KeyBlock *kb, struct Curve *cu, st
void BKE_keyblock_update_from_mesh(struct Mesh *me, struct KeyBlock *kb);
void BKE_keyblock_convert_from_mesh(struct Mesh *me, struct KeyBlock *kb);
void BKE_keyblock_convert_to_mesh(struct KeyBlock *kb, struct Mesh *me);
+void BKE_keyblock_mesh_calc_normals(
+ struct KeyBlock *kb, struct Mesh *mesh, float (*r_vertnors)[3], float (*r_polynors)[3], float (*r_loopnors)[3]);
void BKE_keyblock_update_from_vertcos(struct Object *ob, struct KeyBlock *kb, float (*vertCos)[3]);
void BKE_keyblock_convert_from_vertcos(struct Object *ob, struct KeyBlock *kb, float (*vertCos)[3]);
diff --git a/source/blender/blenkernel/BKE_lamp.h b/source/blender/blenkernel/BKE_lamp.h
index fb2c4da91ea..d830c19651f 100644
--- a/source/blender/blenkernel/BKE_lamp.h
+++ b/source/blender/blenkernel/BKE_lamp.h
@@ -42,6 +42,7 @@ struct Lamp;
struct Main;
struct Scene;
+void BKE_lamp_init(struct Lamp *la);
struct Lamp *BKE_lamp_add(struct Main *bmain, const char *name) ATTR_WARN_UNUSED_RESULT;
struct Lamp *BKE_lamp_copy(struct Lamp *la) ATTR_WARN_UNUSED_RESULT;
struct Lamp *localize_lamp(struct Lamp *la) ATTR_WARN_UNUSED_RESULT;
diff --git a/source/blender/blenkernel/BKE_lattice.h b/source/blender/blenkernel/BKE_lattice.h
index 677d8e34229..828a40de1c9 100644
--- a/source/blender/blenkernel/BKE_lattice.h
+++ b/source/blender/blenkernel/BKE_lattice.h
@@ -45,6 +45,7 @@ struct BPoint;
struct MDeformVert;
void BKE_lattice_resize(struct Lattice *lt, int u, int v, int w, struct Object *ltOb);
+void BKE_lattice_init(struct Lattice *lt);
struct Lattice *BKE_lattice_add(struct Main *bmain, const char *name);
struct Lattice *BKE_lattice_copy(struct Lattice *lt);
void BKE_lattice_free(struct Lattice *lt);
diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h
index 6ecc955e26c..f46ae5617ac 100644
--- a/source/blender/blenkernel/BKE_library.h
+++ b/source/blender/blenkernel/BKE_library.h
@@ -38,8 +38,10 @@ extern "C" {
#include "BLI_compiler_attrs.h"
+struct BlendThumbnail;
struct ListBase;
struct ID;
+struct ImBuf;
struct Main;
struct Library;
struct wmWindowManager;
@@ -47,11 +49,14 @@ struct bContext;
struct PointerRNA;
struct PropertyRNA;
+void *BKE_libblock_alloc_notest(short type);
void *BKE_libblock_alloc(struct Main *bmain, short type, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+void BKE_libblock_init_empty(struct ID *id);
void *BKE_libblock_copy_ex(struct Main *bmain, struct ID *id) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
void *BKE_libblock_copy_nolib(struct ID *id, const bool do_action) ATTR_NONNULL();
void *BKE_libblock_copy(struct ID *id) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
void BKE_libblock_copy_data(struct ID *id, const struct ID *id_from, const bool do_action);
+void BKE_libblock_relink(struct ID *id);
void BKE_id_lib_local_paths(struct Main *bmain, struct Library *lib, struct ID *id);
void id_lib_extern(struct ID *id);
@@ -87,6 +92,10 @@ void BKE_main_free(struct Main *mainvar);
void BKE_main_lock(struct Main *bmain);
void BKE_main_unlock(struct Main *bmain);
+struct BlendThumbnail *BKE_main_thumbnail_from_imbuf(struct Main *bmain, struct ImBuf *img);
+struct ImBuf *BKE_main_thumbnail_to_imbuf(struct Main *bmain, struct BlendThumbnail *data);
+void BKE_main_thumbnail_create(struct Main *bmain);
+
void BKE_main_id_tag_idcode(struct Main *mainvar, const short type, const bool tag);
void BKE_main_id_tag_listbase(struct ListBase *lb, const bool tag);
void BKE_main_id_tag_all(struct Main *mainvar, const bool tag);
diff --git a/source/blender/blenkernel/BKE_library_query.h b/source/blender/blenkernel/BKE_library_query.h
index 50958f8ee80..194b6f0e6b3 100644
--- a/source/blender/blenkernel/BKE_library_query.h
+++ b/source/blender/blenkernel/BKE_library_query.h
@@ -38,6 +38,16 @@ enum {
IDWALK_NOP = 0,
IDWALK_NEVER_NULL = (1 << 0),
IDWALK_NEVER_SELF = (1 << 1),
+
+ /**
+ * Adjusts #ID.us reference-count.
+ * \note keep in sync with 'newlibadr_us' use in readfile.c
+ */
+ IDWALK_USER = (1 << 8),
+ /**
+ * Ensure #ID.us is at least 1 on use.
+ */
+ IDWALK_USER_ONE = (1 << 9),
};
/* Call a callback for each ID link which the given ID uses.
@@ -53,5 +63,6 @@ enum {
/* Loop over all of the ID's this datablock links to. */
void BKE_library_foreach_ID_link(struct ID *id, LibraryIDLinkCallback callback, void *user_data, int flag);
+void BKE_library_update_ID_link_user(struct ID *id_dst, struct ID *id_src, const int cd_flag);
#endif /* __BKE_LIBRARY_QUERY_H__ */
diff --git a/source/blender/blenkernel/BKE_linestyle.h b/source/blender/blenkernel/BKE_linestyle.h
index e77b4f5e8fe..e3eead4102c 100644
--- a/source/blender/blenkernel/BKE_linestyle.h
+++ b/source/blender/blenkernel/BKE_linestyle.h
@@ -49,6 +49,7 @@ struct Object;
struct ColorBand;
struct bContext;
+void BKE_linestyle_init(struct FreestyleLineStyle *linestyle);
FreestyleLineStyle *BKE_linestyle_new(struct Main *bmain, const char *name);
void BKE_linestyle_free(FreestyleLineStyle *linestyle);
FreestyleLineStyle *BKE_linestyle_copy(struct Main *bmain, FreestyleLineStyle *linestyle);
diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h
index ec654ea4b71..6a00961fbb3 100644
--- a/source/blender/blenkernel/BKE_main.h
+++ b/source/blender/blenkernel/BKE_main.h
@@ -50,6 +50,13 @@ struct EvaluationContext;
struct Library;
struct MainLock;
+/* Blender thumbnail, as written on file (width, height, and data as char RGBA). */
+/* We pack pixel data after that struct. */
+typedef struct BlendThumbnail {
+ int width, height;
+ char rect[0];
+} BlendThumbnail;
+
typedef struct Main {
struct Main *next, *prev;
char name[1024]; /* 1024 = FILE_MAX */
@@ -58,6 +65,8 @@ typedef struct Main {
uint64_t build_commit_timestamp; /* commit's timestamp from buildinfo */
char build_hash[16]; /* hash from buildinfo */
short recovered; /* indicate the main->name (file) is the recovered one */
+
+ BlendThumbnail *blen_thumb;
struct Library *curlib;
ListBase scene;
@@ -109,7 +118,10 @@ typedef struct Main {
#define MAIN_VERSION_OLDER(main, ver, subver) \
((main)->versionfile < (ver) || (main->versionfile == (ver) && (main)->subversionfile < (subver)))
-
+#define BLEN_THUMB_SIZE 128
+
+#define BLEN_THUMB_MEMSIZE(_x, _y) (sizeof(BlendThumbnail) + (size_t)((_x) * (_y)) * sizeof(int))
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_material.h b/source/blender/blenkernel/BKE_material.h
index a3c61f44ff2..d32d679e7ed 100644
--- a/source/blender/blenkernel/BKE_material.h
+++ b/source/blender/blenkernel/BKE_material.h
@@ -49,7 +49,7 @@ void BKE_material_free(struct Material *sc);
void BKE_material_free_ex(struct Material *ma, bool do_id_user);
void test_object_materials(struct Main *bmain, struct ID *id);
void BKE_material_resize_object(struct Object *ob, const short totcol, bool do_id_user);
-void init_material(struct Material *ma);
+void BKE_material_init(struct Material *ma);
void BKE_material_remap_object(struct Object *ob, const unsigned int *remap);
struct Material *BKE_material_add(struct Main *bmain, const char *name);
struct Material *BKE_material_copy(struct Material *ma);
diff --git a/source/blender/blenkernel/BKE_mball.h b/source/blender/blenkernel/BKE_mball.h
index 62cd50099fd..0574b88bef3 100644
--- a/source/blender/blenkernel/BKE_mball.h
+++ b/source/blender/blenkernel/BKE_mball.h
@@ -40,6 +40,7 @@ struct MetaElem;
void BKE_mball_unlink(struct MetaBall *mb);
void BKE_mball_free(struct MetaBall *mb);
+void BKE_mball_init(struct MetaBall *mb);
struct MetaBall *BKE_mball_add(struct Main *bmain, const char *name);
struct MetaBall *BKE_mball_copy(struct MetaBall *mb);
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index 41241988f2b..f35613f8bf7 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -82,6 +82,7 @@ int BKE_mesh_edge_other_vert(const struct MEdge *e, int v);
void BKE_mesh_unlink(struct Mesh *me);
void BKE_mesh_free(struct Mesh *me, int unlink);
+void BKE_mesh_init(struct Mesh *me);
struct Mesh *BKE_mesh_add(struct Main *bmain, const char *name);
struct Mesh *BKE_mesh_copy_ex(struct Main *bmain, struct Mesh *me);
struct Mesh *BKE_mesh_copy(struct Mesh *me);
@@ -170,7 +171,7 @@ void BKE_mesh_calc_normals_mapping_ex(
const struct MFace *mfaces, int numFaces, const int *origIndexFace, float (*r_faceNors)[3],
const bool only_face_normals);
void BKE_mesh_calc_normals_poly(
- struct MVert *mverts, int numVerts,
+ struct MVert *mverts, float (*r_vertnors)[3], int numVerts,
const struct MLoop *mloop, const struct MPoly *mpolys,
int numLoops, int numPolys, float (*r_polyNors)[3],
const bool only_face_normals);
@@ -234,11 +235,11 @@ void BKE_mesh_normals_loop_split(
void BKE_mesh_normals_loop_custom_set(
const struct MVert *mverts, const int numVerts, struct MEdge *medges, const int numEdges,
- struct MLoop *mloops, float (*custom_loopnors)[3], const int numLoops,
+ struct MLoop *mloops, float (*r_custom_loopnors)[3], const int numLoops,
struct MPoly *mpolys, const float (*polynors)[3], const int numPolys,
short (*r_clnors_data)[2]);
void BKE_mesh_normals_loop_custom_from_vertices_set(
- const struct MVert *mverts, float (*custom_vertnors)[3], const int numVerts,
+ const struct MVert *mverts, float (*r_custom_vertnors)[3], const int numVerts,
struct MEdge *medges, const int numEdges, struct MLoop *mloops, const int numLoops,
struct MPoly *mpolys, const float (*polynors)[3], const int numPolys,
short (*r_clnors_data)[2]);
diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h
index ded6e13e003..455912ab819 100644
--- a/source/blender/blenkernel/BKE_modifier.h
+++ b/source/blender/blenkernel/BKE_modifier.h
@@ -104,8 +104,9 @@ typedef enum {
eModifierTypeFlag_UsesPreview = (1 << 9)
} ModifierTypeFlag;
-typedef void (*ObjectWalkFunc)(void *userData, struct Object *ob, struct Object **obpoin);
-typedef void (*IDWalkFunc)(void *userData, struct Object *ob, struct ID **idpoin);
+/* IMPORTANT! Keep ObjectWalkFunc and IDWalkFunc signatures compatible. */
+typedef void (*ObjectWalkFunc)(void *userData, struct Object *ob, struct Object **obpoin, int cd_flag);
+typedef void (*IDWalkFunc)(void *userData, struct Object *ob, struct ID **idpoin, int cd_flag);
typedef void (*TexWalkFunc)(void *userData, struct Object *ob, struct ModifierData *md, const char *propname);
typedef enum ModifierApplyFlag {
diff --git a/source/blender/blenkernel/BKE_movieclip.h b/source/blender/blenkernel/BKE_movieclip.h
index 7d7675270de..afca326c727 100644
--- a/source/blender/blenkernel/BKE_movieclip.h
+++ b/source/blender/blenkernel/BKE_movieclip.h
@@ -43,6 +43,8 @@ void BKE_movieclip_free(struct MovieClip *clip);
void BKE_movieclip_unlink(struct Main *bmain, struct MovieClip *clip);
struct MovieClip *BKE_movieclip_file_add(struct Main *bmain, const char *name);
+struct MovieClip *BKE_movieclip_file_add_exists_ex(struct Main *bmain, const char *name, bool *r_exists);
+struct MovieClip *BKE_movieclip_file_add_exists(struct Main *bmain, const char *name);
void BKE_movieclip_reload(struct MovieClip *clip);
void BKE_movieclip_clear_cache(struct MovieClip *clip);
void BKE_movieclip_clear_proxy_cache(struct MovieClip *clip);
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index b97bf203a7c..88e54d0ff2c 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -337,6 +337,7 @@ struct GHashIterator *ntreeTypeGetIterator(void);
void ntreeSetTypes(const struct bContext *C, struct bNodeTree *ntree);
+void ntreeInitDefault(struct bNodeTree *ntree);
struct bNodeTree *ntreeAddTree(struct Main *bmain, const char *name, const char *idname);
/* copy/free funcs, need to manage ID users */
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index 9482ec778d3..45d14a35539 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -85,6 +85,7 @@ bool BKE_object_is_in_editmode(struct Object *ob);
bool BKE_object_is_in_editmode_vgroup(struct Object *ob);
bool BKE_object_is_in_wpaint_select_vert(struct Object *ob);
+void BKE_object_init(struct Object *ob);
struct Object *BKE_object_add_only_object(
struct Main *bmain,
int type, const char *name)
@@ -142,6 +143,9 @@ bool BKE_boundbox_ray_hit_check(
float *r_lambda);
void BKE_boundbox_calc_center_aabb(const struct BoundBox *bb, float r_cent[3]);
void BKE_boundbox_calc_size_aabb(const struct BoundBox *bb, float r_size[3]);
+void BKE_boundbox_minmax(const struct BoundBox *bb, float obmat[4][4], float r_min[3], float r_max[3]);
+struct BoundBox *BKE_boundbox_ensure_minimum_dimensions(
+ struct BoundBox *bb, struct BoundBox *bb_temp, const float epsilon);
struct BoundBox *BKE_object_boundbox_get(struct Object *ob);
void BKE_object_dimensions_get(struct Object *ob, float vec[3]);
@@ -231,6 +235,7 @@ int BKE_object_is_modified(struct Scene *scene, struct Object *ob);
int BKE_object_is_deform_modified(struct Scene *scene, struct Object *ob);
void BKE_object_relink(struct Object *ob);
+void BKE_object_data_relink(struct Object *ob);
struct MovieClip *BKE_object_movieclip_get(struct Scene *scene, struct Object *ob, bool use_default);
diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index c9192fddec6..bf1cfb263eb 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -66,13 +66,13 @@ extern const char PAINT_CURSOR_WEIGHT_PAINT[3];
extern const char PAINT_CURSOR_TEXTURE_PAINT[3];
typedef enum PaintMode {
- PAINT_SCULPT = 0,
- PAINT_VERTEX = 1,
- PAINT_WEIGHT = 2,
- PAINT_TEXTURE_PROJECTIVE = 3,
- PAINT_TEXTURE_2D = 4,
- PAINT_SCULPT_UV = 5,
- PAINT_INVALID = 6
+ ePaintSculpt = 0,
+ ePaintVertex = 1,
+ ePaintWeight = 2,
+ ePaintTextureProjective = 3,
+ ePaintTexture2D = 4,
+ ePaintSculptUV = 5,
+ ePaintInvalid = 6
} PaintMode;
/* overlay invalidation */
@@ -108,12 +108,14 @@ void BKE_palette_clear(struct Palette *palette);
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 UnifiedPaintSettings *ups, struct Paint *p, const char col[3]);
+void BKE_paint_init(struct Scene *sce, PaintMode mode, const char col[3]);
void BKE_paint_free(struct Paint *p);
void BKE_paint_copy(struct Paint *src, struct Paint *tar);
void BKE_paint_cavity_curve_preset(struct Paint *p, int preset);
+short BKE_paint_object_mode_from_paint_mode(PaintMode mode);
+struct Paint *BKE_paint_get_active_from_paintmode(struct Scene *sce, PaintMode mode);
struct Paint *BKE_paint_get_active(struct Scene *sce);
struct Paint *BKE_paint_get_active_from_context(const struct bContext *C);
PaintMode BKE_paintmode_get_active_from_context(const struct bContext *C);
diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h
index 32325707c9a..00cc48cf713 100644
--- a/source/blender/blenkernel/BKE_particle.h
+++ b/source/blender/blenkernel/BKE_particle.h
@@ -378,6 +378,11 @@ void psys_get_birth_coords(struct ParticleSimulationData *sim, struct ParticleDa
void particle_system_update(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys);
+/* Callback format for performing operations on ID-pointers for particle systems */
+typedef void (*ParticleSystemIDFunc)(struct ParticleSystem *psys, struct ID **idpoin, void *userdata, int cd_flag);
+
+void BKE_particlesystem_id_loop(struct ParticleSystem *psys, ParticleSystemIDFunc func, void *userdata);
+
/* ----------- functions needed only inside particlesystem ------------ */
/* particle.c */
void psys_disable_all(struct Object *ob);
@@ -464,6 +469,7 @@ typedef struct ParticleRenderData {
struct EvaluationContext;
void BKE_particle_system_eval(struct EvaluationContext *eval_ctx,
+ struct Scene *scene,
struct Object *ob,
struct ParticleSystem *psys);
diff --git a/source/blender/blenkernel/BKE_rigidbody.h b/source/blender/blenkernel/BKE_rigidbody.h
index a30ce6cda79..272abc42899 100644
--- a/source/blender/blenkernel/BKE_rigidbody.h
+++ b/source/blender/blenkernel/BKE_rigidbody.h
@@ -53,6 +53,11 @@ struct RigidBodyOb *BKE_rigidbody_copy_object(struct Object *ob);
struct RigidBodyCon *BKE_rigidbody_copy_constraint(struct Object *ob);
void BKE_rigidbody_relink_constraint(struct RigidBodyCon *rbc);
+/* Callback format for performing operations on ID-pointers for rigidbody world. */
+typedef void (*RigidbodyWorldIDFunc)(struct RigidBodyWorld *rbw, struct ID **idpoin, void *userdata, int cd_flag);
+
+void BKE_rigidbody_world_id_loop(struct RigidBodyWorld *rbw, RigidbodyWorldIDFunc func, void *userdata);
+
/* -------------- */
/* Setup */
diff --git a/source/blender/blenkernel/BKE_sca.h b/source/blender/blenkernel/BKE_sca.h
index ebdd159b40c..fa448aa97b8 100644
--- a/source/blender/blenkernel/BKE_sca.h
+++ b/source/blender/blenkernel/BKE_sca.h
@@ -73,6 +73,16 @@ void sca_move_sensor(struct bSensor *sens_to_move, struct Object *ob, int move_u
void sca_move_controller(struct bController *cont_to_move, struct Object *ob, int move_up);
void sca_move_actuator(struct bActuator *act_to_move, struct Object *ob, int move_up);
+/* Callback format for performing operations on ID-pointers for sensors/controllers/actuators. */
+typedef void (*SCASensorIDFunc)(struct bSensor *sensor, struct ID **idpoin, void *userdata, int cd_flag);
+typedef void (*SCAControllerIDFunc)(struct bController *controller, struct ID **idpoin, void *userdata, int cd_flag);
+typedef void (*SCAActuatorIDFunc)(struct bActuator *actuator, struct ID **idpoin, void *userdata, int cd_flag);
+
+void BKE_sca_sensors_id_loop(struct ListBase *senslist, SCASensorIDFunc func, void *userdata);
+void BKE_sca_controllers_id_loop(struct ListBase *contlist, SCAControllerIDFunc func, void *userdata);
+void BKE_sca_actuators_id_loop(struct ListBase *atclist, SCAActuatorIDFunc func, void *userdata);
+
+
const char *sca_state_name_get(Object *ob, short bit);
#endif
diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h
index 027bdbbbe58..aa698317e33 100644
--- a/source/blender/blenkernel/BKE_scene.h
+++ b/source/blender/blenkernel/BKE_scene.h
@@ -67,6 +67,7 @@ void free_avicodecdata(struct AviCodecData *acd);
void free_qtcodecdata(struct QuicktimeCodecData *acd);
void BKE_scene_free(struct Scene *sce);
+void BKE_scene_init(struct Scene *sce);
struct Scene *BKE_scene_add(struct Main *bmain, const char *name);
/* base functions */
diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h
index f73548373ef..06f46131c68 100644
--- a/source/blender/blenkernel/BKE_sequencer.h
+++ b/source/blender/blenkernel/BKE_sequencer.h
@@ -35,6 +35,7 @@ struct EvaluationContext;
struct StripColorBalance;
struct Editing;
struct GSet;
+struct GPUOffScreen;
struct ImBuf;
struct Main;
struct Mask;
@@ -101,6 +102,10 @@ typedef struct SeqRenderData {
bool skip_cache;
bool is_proxy_render;
size_t view_id;
+
+ /* special case for OpenGL render */
+ struct GPUOffScreen *gpu_offscreen;
+ int gpu_samples;
} SeqRenderData;
void BKE_sequencer_new_render_data(
@@ -108,6 +113,8 @@ void BKE_sequencer_new_render_data(
int rectx, int recty, int preview_render_size,
SeqRenderData *r_context);
+int BKE_sequencer_cmp_time_startdisp(const void *a, const void *b);
+
/* Wipe effect */
enum {
DO_SINGLE_WIPE,
@@ -406,7 +413,11 @@ struct Sequence *BKE_sequencer_add_sound_strip(struct bContext *C, ListBase *seq
struct Sequence *BKE_sequencer_add_movie_strip(struct bContext *C, ListBase *seqbasep, struct SeqLoadInfo *seq_load);
/* view3d draw callback, run when not in background view */
-typedef struct ImBuf *(*SequencerDrawView)(struct Scene *, struct Object *, int, int, unsigned int, int, bool, bool, bool, int, const char *, char[256]);
+typedef struct ImBuf *(*SequencerDrawView)(
+ struct Scene *, struct Object *, int, int,
+ unsigned int, int, bool, bool, bool,
+ int, int, const char *,
+ struct GPUOffScreen *, char[256]);
extern SequencerDrawView sequencer_view3d_cb;
/* copy/paste */
diff --git a/source/blender/blenkernel/BKE_sound.h b/source/blender/blenkernel/BKE_sound.h
index e68be701b61..67db2537c8f 100644
--- a/source/blender/blenkernel/BKE_sound.h
+++ b/source/blender/blenkernel/BKE_sound.h
@@ -61,7 +61,9 @@ void BKE_sound_exit(void);
void BKE_sound_force_device(const char *device);
-struct bSound *BKE_sound_new_file(struct Main *main, const char *filename);
+struct bSound *BKE_sound_new_file(struct Main *main, const char *filepath);
+struct bSound *BKE_sound_new_file_exists_ex(struct Main *bmain, const char *filepath, bool *r_exists);
+struct bSound *BKE_sound_new_file_exists(struct Main *bmain, const char *filepath);
// XXX unused currently
#if 0
diff --git a/source/blender/blenkernel/BKE_speaker.h b/source/blender/blenkernel/BKE_speaker.h
index 5d93b9844ab..5f30df1d6e3 100644
--- a/source/blender/blenkernel/BKE_speaker.h
+++ b/source/blender/blenkernel/BKE_speaker.h
@@ -29,7 +29,9 @@
*/
struct Main;
+struct Speaker;
+void BKE_speaker_init(struct Speaker *spk);
void *BKE_speaker_add(struct Main *bmain, const char *name);
struct Speaker *BKE_speaker_copy(struct Speaker *spk);
void BKE_speaker_make_local(struct Speaker *spk);
diff --git a/source/blender/blenkernel/BKE_text.h b/source/blender/blenkernel/BKE_text.h
index a5a59d14c92..50e4fa4c41d 100644
--- a/source/blender/blenkernel/BKE_text.h
+++ b/source/blender/blenkernel/BKE_text.h
@@ -44,6 +44,7 @@ struct TextLine;
void BKE_text_free (struct Text *text);
void txt_set_undostate (int u);
int txt_get_undostate (void);
+void BKE_text_init(struct Text *ta);
struct Text *BKE_text_add (struct Main *bmain, const char *name);
int txt_extended_ascii_as_utf8(char **str);
bool BKE_text_reload(struct Text *text);
diff --git a/source/blender/blenkernel/BKE_world.h b/source/blender/blenkernel/BKE_world.h
index 7f4ba6c615e..8d7ab230919 100644
--- a/source/blender/blenkernel/BKE_world.h
+++ b/source/blender/blenkernel/BKE_world.h
@@ -38,6 +38,7 @@ struct World;
void BKE_world_free(struct World *sc);
void BKE_world_free_ex(struct World *sc, bool do_id_user);
+void BKE_world_init(struct World *wrld);
struct World *add_world(struct Main *bmian, const char *name);
struct World *BKE_world_copy(struct World *wrld);
struct World *localize_world(struct World *wrld);
diff --git a/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c b/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c
index 006cebf4573..9d5ef1079b8 100644
--- a/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c
+++ b/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c
@@ -314,9 +314,12 @@ int ccgSubSurf_getNumGLMeshBaseFaces(CCGSubSurf *ss)
if (ss->osd_topology_refiner != NULL) {
topology_refiner = ss->osd_topology_refiner;
}
- else {
+ else if (ss->osd_mesh != NULL) {
topology_refiner = openSubdiv_getGLMeshTopologyRefiner(ss->osd_mesh);
}
+ else {
+ return 0;
+ }
return openSubdiv_topologyRefinerGetNumFaces(topology_refiner);
}
@@ -327,9 +330,12 @@ int ccgSubSurf_getNumGLMeshBaseFaceVerts(CCGSubSurf *ss, int face)
if (ss->osd_topology_refiner != NULL) {
topology_refiner = ss->osd_topology_refiner;
}
- else {
+ else if (ss->osd_mesh != NULL) {
topology_refiner = openSubdiv_getGLMeshTopologyRefiner(ss->osd_mesh);
}
+ else {
+ return 0;
+ }
return openSubdiv_topologyRefinerGetNumFaceVerts(topology_refiner, face);
}
@@ -905,6 +911,10 @@ void ccgSubSurf_getMinMax(CCGSubSurf *ss, float r_min[3], float r_max[3])
{
int i;
BLI_assert(ss->skip_grids == true);
+ if (ss->osd_num_coarse_coords == 0) {
+ zero_v3(r_min);
+ zero_v3(r_max);
+ }
for (i = 0; i < ss->osd_num_coarse_coords; i++) {
/* Coarse coordinates has normals interleaved into the array. */
DO_MINMAX(ss->osd_coarse_coords[2 * i], r_min, r_max);
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index 6249e10d56f..4cf9885c716 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -328,21 +328,17 @@ void DM_init(
* Utility function to initialize a DerivedMesh for the desired number
* of vertices, edges and faces, with a layer setup copied from source
*/
-void DM_from_template(
+void DM_from_template_ex(
DerivedMesh *dm, DerivedMesh *source, DerivedMeshType type,
int numVerts, int numEdges, int numTessFaces,
- int numLoops, int numPolys)
+ int numLoops, int numPolys,
+ CustomDataMask mask)
{
- CustomData_copy(&source->vertData, &dm->vertData, CD_MASK_DERIVEDMESH,
- CD_CALLOC, numVerts);
- CustomData_copy(&source->edgeData, &dm->edgeData, CD_MASK_DERIVEDMESH,
- CD_CALLOC, numEdges);
- CustomData_copy(&source->faceData, &dm->faceData, CD_MASK_DERIVEDMESH,
- CD_CALLOC, numTessFaces);
- CustomData_copy(&source->loopData, &dm->loopData, CD_MASK_DERIVEDMESH,
- CD_CALLOC, numLoops);
- CustomData_copy(&source->polyData, &dm->polyData, CD_MASK_DERIVEDMESH,
- CD_CALLOC, numPolys);
+ CustomData_copy(&source->vertData, &dm->vertData, mask, CD_CALLOC, numVerts);
+ CustomData_copy(&source->edgeData, &dm->edgeData, mask, CD_CALLOC, numEdges);
+ CustomData_copy(&source->faceData, &dm->faceData, mask, CD_CALLOC, numTessFaces);
+ CustomData_copy(&source->loopData, &dm->loopData, mask, CD_CALLOC, numLoops);
+ CustomData_copy(&source->polyData, &dm->polyData, mask, CD_CALLOC, numPolys);
dm->cd_flag = source->cd_flag;
@@ -358,6 +354,17 @@ void DM_from_template(
dm->needsFree = 1;
dm->dirty = 0;
}
+void DM_from_template(
+ DerivedMesh *dm, DerivedMesh *source, DerivedMeshType type,
+ int numVerts, int numEdges, int numTessFaces,
+ int numLoops, int numPolys)
+{
+ DM_from_template_ex(
+ dm, source, type,
+ numVerts, numEdges, numTessFaces,
+ numLoops, numPolys,
+ CD_MASK_DERIVEDMESH);
+}
int DM_release(DerivedMesh *dm)
{
@@ -593,8 +600,6 @@ void DM_generate_tangent_tessface_data(DerivedMesh *dm, bool generate)
if (!polyindex)
return;
- CustomData_from_bmeshpoly(fdata, pdata, ldata, totface);
-
if (generate) {
for (i = 0; i < ldata->totlayer; i++) {
if (ldata->layers[i].type == CD_TANGENT)
@@ -603,6 +608,8 @@ void DM_generate_tangent_tessface_data(DerivedMesh *dm, bool generate)
CustomData_bmesh_update_active_layers(fdata, pdata, ldata);
}
+ BLI_assert(CustomData_from_bmeshpoly_test(fdata, pdata, ldata, true));
+
loopindex = MEM_mallocN(sizeof(*loopindex) * totface, __func__);
for (mf_idx = 0, mf = mface; mf_idx < totface; mf_idx++, mf++) {
@@ -1554,8 +1561,8 @@ void DM_update_weight_mcol(
ml = mloop + mp->loopstart;
for (j = 0; j < mp->totloop; j++, ml++, l_index++) {
- copy_v4_v4_char((char *)&wtcol_l[l_index],
- (char *)&wtcol_v[ml->v]);
+ copy_v4_v4_uchar(&wtcol_l[l_index][0],
+ &wtcol_v[ml->v][0]);
}
}
MEM_freeN(wtcol_v);
@@ -2266,12 +2273,9 @@ static void editbmesh_calc_modifiers(
#if 0 /* XXX Will re-enable this when we have global mod stack options. */
const bool do_final_wmcol = (scene->toolsettings->weights_preview == WP_WPREVIEW_FINAL) && do_wmcol;
#endif
-#ifndef WITH_OPENSUBDIV
const bool do_final_wmcol = false;
const bool do_init_wmcol = ((((Mesh *)ob->data)->drawflag & ME_DRAWEIGHT) && !do_final_wmcol);
-#else
- const bool do_init_wmcol = false;
-#endif
+
const bool do_init_statvis = ((((Mesh *)ob->data)->drawflag & ME_DRAW_STATVIS) && !do_init_wmcol);
const bool do_mod_wmcol = do_init_wmcol;
VirtualModifierData virtualModifierData;
@@ -2539,7 +2543,7 @@ static void editbmesh_calc_modifiers(
#ifdef WITH_OPENSUBDIV
/* The idea is to skip CPU-side ORCO calculation when
* we'll be using GPU backend of OpenSubdiv. This is so
- * playback performance is kept as high as posssible.
+ * playback performance is kept as high as possible.
*/
static bool calc_modifiers_skip_orco(const Object *ob)
{
@@ -2622,13 +2626,13 @@ static CustomDataMask object_get_datamask(const Scene *scene, Object *ob, bool *
{
Object *actob = scene->basact ? scene->basact->object : NULL;
CustomDataMask mask = ob->customdata_mask;
- bool editing = BKE_paint_select_face_test(ob);
if (r_need_mapping) {
*r_need_mapping = false;
}
if (ob == actob) {
+ bool editing = BKE_paint_select_face_test(ob);
/* weight paint and face select need original indices because of selection buffer drawing */
if (r_need_mapping) {
@@ -3055,7 +3059,7 @@ static void GetNormal(const SMikkTSpaceContext *pContext, float r_no[3], const i
}
}
else {
- const short *no = pMesh->mvert[pMesh->mloop[lt->tri[0]].v].no;
+ const short *no = pMesh->mvert[pMesh->mloop[lt->tri[vert_index]].v].no;
normal_short_to_float_v3(r_no, no);
}
}
@@ -3449,7 +3453,7 @@ void DM_draw_attrib_vertex(DMVertexAttribs *attribs, int a, int index, int vert,
if (attribs->mcol[b].array) {
const MLoopCol *cp = &attribs->mcol[b].array[loop];
- copy_v4_v4_char((char *)col, &cp->r);
+ copy_v4_v4_uchar(col, &cp->r);
}
else {
col[0] = 0; col[1] = 0; col[2] = 0; col[3] = 0;
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index 5b1a6ea7a51..b77ae45e94d 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -485,6 +485,9 @@ bPoseChannel *BKE_pose_channel_verify(bPose *pose, const char *name)
chan = MEM_callocN(sizeof(bPoseChannel), "verifyPoseChannel");
BLI_strncpy(chan->name, name, sizeof(chan->name));
+
+ chan->custom_scale = 1.0f;
+
/* init vars to prevent math errors */
unit_qt(chan->quat);
unit_axis_angle(chan->rotAxis, &chan->rotAngle);
diff --git a/source/blender/blenkernel/intern/appdir.c b/source/blender/blenkernel/intern/appdir.c
index ee6710e1130..639a502fb83 100644
--- a/source/blender/blenkernel/intern/appdir.c
+++ b/source/blender/blenkernel/intern/appdir.c
@@ -548,15 +548,7 @@ static void where_am_i(char *fullname, const size_t maxlen, const char *name)
BLI_strncpy(fullname, name, maxlen);
if (name[0] == '.') {
- char wdir[FILE_MAX] = "";
- BLI_current_working_dir(wdir, sizeof(wdir)); /* backup cwd to restore after */
-
- // not needed but avoids annoying /./ in name
- if (name[1] == SEP)
- BLI_join_dirfile(fullname, maxlen, wdir, name + 2);
- else
- BLI_join_dirfile(fullname, maxlen, wdir, name);
-
+ BLI_path_cwd(fullname, maxlen);
#ifdef _WIN32
BLI_path_program_extensions_add_win32(fullname, maxlen);
#endif
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index 3643aa23998..6afe7f1abe9 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -1141,8 +1141,7 @@ void BKE_armature_loc_world_to_pose(Object *ob, const float inloc[3], float outl
* Not exported, as it is only used in this file currently... */
static void get_offset_bone_mat(Bone *bone, float offs_bone[4][4])
{
- if (!bone->parent)
- return;
+ BLI_assert(bone->parent != NULL);
/* Bone transform itself. */
copy_m4_m3(offs_bone, bone->bone_mat);
@@ -1506,6 +1505,8 @@ void vec_roll_to_mat3_normalized(const float nor[3], const float roll, float mat
float theta;
float rMatrix[3][3], bMatrix[3][3];
+ BLI_ASSERT_UNIT_V3(nor);
+
theta = 1.0f + nor[1];
/* With old algo, 1.0e-13f caused T23954 and T31333, 1.0e-6f caused T27675 and T30438,
@@ -1566,16 +1567,15 @@ void vec_roll_to_mat3(const float vec[3], const float roll, float mat[3][3])
/* recursive part, calculates restposition of entire tree of children */
/* used by exiting editmode too */
-void BKE_armature_where_is_bone(Bone *bone, Bone *prevbone)
+void BKE_armature_where_is_bone(Bone *bone, Bone *prevbone, const bool use_recursion)
{
float vec[3];
/* Bone Space */
sub_v3_v3v3(vec, bone->tail, bone->head);
+ bone->length = len_v3(vec);
vec_roll_to_mat3(vec, bone->roll, bone->bone_mat);
- bone->length = len_v3v3(bone->head, bone->tail);
-
/* this is called on old file reading too... */
if (bone->xwidth == 0.0f) {
bone->xwidth = 0.1f;
@@ -1597,9 +1597,11 @@ void BKE_armature_where_is_bone(Bone *bone, Bone *prevbone)
}
/* and the kiddies */
- prevbone = bone;
- for (bone = bone->childbase.first; bone; bone = bone->next) {
- BKE_armature_where_is_bone(bone, prevbone);
+ if (use_recursion) {
+ prevbone = bone;
+ for (bone = bone->childbase.first; bone; bone = bone->next) {
+ BKE_armature_where_is_bone(bone, prevbone, use_recursion);
+ }
}
}
@@ -1611,7 +1613,7 @@ void BKE_armature_where_is(bArmature *arm)
/* hierarchical from root to children */
for (bone = arm->bonebase.first; bone; bone = bone->next) {
- BKE_armature_where_is_bone(bone, NULL);
+ BKE_armature_where_is_bone(bone, NULL, true);
}
}
@@ -2207,6 +2209,46 @@ BoundBox *BKE_armature_boundbox_get(Object *ob)
return ob->bb;
}
+bool BKE_pose_minmax(Object *ob, float r_min[3], float r_max[3], bool use_hidden, bool use_select)
+{
+ bool changed = false;
+
+ if (ob->pose) {
+ bArmature *arm = ob->data;
+ bPoseChannel *pchan;
+
+ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ /* XXX pchan->bone may be NULL for duplicated bones, see duplicateEditBoneObjects() comment
+ * (editarmature.c:2592)... Skip in this case too! */
+ if (pchan->bone &&
+ (!((use_hidden == false) && (PBONE_VISIBLE(arm, pchan->bone) == false)) &&
+ !((use_select == true) && ((pchan->bone->flag & BONE_SELECTED) == 0))))
+ {
+ bPoseChannel *pchan_tx = (pchan->custom && pchan->custom_tx) ? pchan->custom_tx : pchan;
+ BoundBox *bb_custom = ((pchan->custom) && !(arm->flag & ARM_NO_CUSTOM)) ?
+ BKE_object_boundbox_get(pchan->custom) : NULL;
+ if (bb_custom) {
+ float mat[4][4], smat[4][4];
+ scale_m4_fl(smat, PCHAN_CUSTOM_DRAW_SIZE(pchan));
+ mul_m4_series(mat, ob->obmat, pchan_tx->pose_mat, smat);
+ BKE_boundbox_minmax(bb_custom, mat, r_min, r_max);
+ }
+ else {
+ float vec[3];
+ mul_v3_m4v3(vec, ob->obmat, pchan_tx->pose_head);
+ minmax_v3v3_v3(r_min, r_max, vec);
+ mul_v3_m4v3(vec, ob->obmat, pchan_tx->pose_tail);
+ minmax_v3v3_v3(r_min, r_max, vec);
+ }
+
+ changed = true;
+ }
+ }
+ }
+
+ return changed;
+}
+
/************** Graph evaluation ********************/
bPoseChannel *BKE_armature_ik_solver_find_root(
diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c
index 0923ac7e743..f1300697b85 100644
--- a/source/blender/blenkernel/intern/blender.c
+++ b/source/blender/blenkernel/intern/blender.c
@@ -417,6 +417,7 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, const char *filepath
BKE_scene_set_background(G.main, curscene);
if (mode != LOAD_UNDO) {
+ RE_FreeAllPersistentData();
IMB_colormanagement_check_file_config(G.main);
}
@@ -1068,11 +1069,11 @@ int BKE_copybuffer_paste(bContext *C, const char *libname, ReportList *reports)
BKE_main_id_flag_all(bmain, LIB_PRE_EXISTING, true);
/* here appending/linking starts */
- mainl = BLO_library_append_begin(bmain, &bh, libname);
+ mainl = BLO_library_link_begin(bmain, &bh, libname);
- BLO_library_append_all(mainl, bh);
+ BLO_library_link_all(mainl, bh);
- BLO_library_append_end(C, mainl, &bh, 0, 0);
+ BLO_library_link_end(mainl, &bh, 0, scene, CTX_wm_view3d(C));
/* mark all library linked objects to be updated */
BKE_main_lib_objects_recalc_all(bmain);
diff --git a/source/blender/blenkernel/intern/boids.c b/source/blender/blenkernel/intern/boids.c
index 489e26c5cbe..64b9bf48c98 100644
--- a/source/blender/blenkernel/intern/boids.c
+++ b/source/blender/blenkernel/intern/boids.c
@@ -80,6 +80,9 @@ static int rule_goal_avoid(BoidRule *rule, BoidBrainData *bbd, BoidValues *val,
float priority = 0.0f, len = 0.0f;
int ret = 0;
+ int p = 0;
+ efd.index = cur_efd.index = &p;
+
pd_point_from_particle(bbd->sim, pa, &pa->state, &epoint);
/* first find out goal/predator with highest priority */
@@ -1006,9 +1009,11 @@ void boid_brain(BoidBrainData *bbd, int p, ParticleData *pa)
case eBoidRulesetType_Random:
{
/* use random rule for each particle (always same for same particle though) */
- rule = BLI_findlink(&state->rules, rand % BLI_listbase_count(&state->rules));
-
- apply_boid_rule(bbd, rule, &val, pa, -1.0);
+ const int n = BLI_listbase_count(&state->rules);
+ if (n) {
+ rule = BLI_findlink(&state->rules, rand % n);
+ apply_boid_rule(bbd, rule, &val, pa, -1.0);
+ }
break;
}
case eBoidRulesetType_Average:
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index c7bb6d4f5ce..c2a66adbf92 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -131,11 +131,9 @@ static void brush_defaults(Brush *brush)
/* Datablock add/copy/free/make_local */
-Brush *BKE_brush_add(Main *bmain, const char *name)
+void BKE_brush_init(Brush *brush)
{
- Brush *brush;
-
- brush = BKE_libblock_alloc(bmain, ID_BR, name);
+ BLI_assert(MEMCMP_STRUCT_OFS_IS_ZERO(brush, id));
/* enable fake user by default */
brush->id.flag |= LIB_FAKEUSER;
@@ -146,10 +144,32 @@ Brush *BKE_brush_add(Main *bmain, const char *name)
/* the default alpha falloff curve */
BKE_brush_curve_preset(brush, CURVE_PRESET_SMOOTH);
+}
+
+Brush *BKE_brush_add(Main *bmain, const char *name, short ob_mode)
+{
+ Brush *brush;
+
+ brush = BKE_libblock_alloc(bmain, ID_BR, name);
+
+ BKE_brush_init(brush);
+
+ brush->ob_mode = ob_mode;
return brush;
}
+struct Brush *BKE_brush_first_search(struct Main *bmain, short ob_mode)
+{
+ Brush *brush;
+
+ for (brush = bmain->brush.first; brush; brush = brush->id.next) {
+ if (brush->ob_mode & ob_mode)
+ return brush;
+ }
+ return NULL;
+}
+
Brush *BKE_brush_copy(Brush *brush)
{
Brush *brushn;
diff --git a/source/blender/blenkernel/intern/bvhutils.c b/source/blender/blenkernel/intern/bvhutils.c
index fa2fcd97ec3..9004985aebd 100644
--- a/source/blender/blenkernel/intern/bvhutils.c
+++ b/source/blender/blenkernel/intern/bvhutils.c
@@ -538,7 +538,7 @@ BVHTree *bvhtree_from_mesh_edges(BVHTreeFromMesh *data, DerivedMesh *dm, float e
tree = BLI_bvhtree_new(numEdges, epsilon, tree_type, axis);
if (tree != NULL) {
for (i = 0; i < numEdges; i++) {
- float co[4][3];
+ float co[2][3];
copy_v3_v3(co[0], vert[edge[i].v1].co);
copy_v3_v3(co[1], vert[edge[i].v2].co);
@@ -597,7 +597,8 @@ BVHTree *bvhtree_from_mesh_edges(BVHTreeFromMesh *data, DerivedMesh *dm, float e
static BVHTree *bvhtree_from_mesh_faces_create_tree(
float epsilon, int tree_type, int axis,
- BMEditMesh *em, MVert *vert, MFace *face, const int numFaces,
+ BMEditMesh *em, const bool em_all,
+ MVert *vert, MFace *face, const int numFaces,
BLI_bitmap *mask, int numFaces_active)
{
BVHTree *tree = NULL;
@@ -646,7 +647,10 @@ static BVHTree *bvhtree_from_mesh_faces_create_tree(
insert = insert_prev;
}
else if (insert) {
- if (BM_elem_flag_test(f, BM_ELEM_SELECT) || BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
+ if (em_all) {
+ /* pass */
+ }
+ else if (BM_elem_flag_test(f, BM_ELEM_SELECT) || BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
/* Don't insert triangles tessellated from faces that are hidden or selected */
insert = false;
}
@@ -746,7 +750,9 @@ static void bvhtree_from_mesh_faces_setup_data(
BVHTree *bvhtree_from_mesh_faces(BVHTreeFromMesh *data, DerivedMesh *dm, float epsilon, int tree_type, int axis)
{
BMEditMesh *em = data->em_evil;
- const int bvhcache_type = em ? BVHTREE_FROM_FACES_EDITMESH : BVHTREE_FROM_FACES;
+ const int bvhcache_type = em ?
+ (data->em_evil_all ? BVHTREE_FROM_FACES_EDITMESH_ALL : BVHTREE_FROM_FACES_EDITMESH_SNAP) :
+ BVHTREE_FROM_FACES;
BVHTree *tree;
MVert *vert = NULL;
MFace *face = NULL;
@@ -781,7 +787,10 @@ BVHTree *bvhtree_from_mesh_faces(BVHTreeFromMesh *data, DerivedMesh *dm, float e
BLI_assert(!(numFaces == 0 && dm->getNumPolys(dm) != 0));
}
- tree = bvhtree_from_mesh_faces_create_tree(epsilon, tree_type, axis, em, vert, face, numFaces, NULL, -1);
+ tree = bvhtree_from_mesh_faces_create_tree(
+ epsilon, tree_type, axis,
+ em, (bvhcache_type == BVHTREE_FROM_FACES_EDITMESH_ALL),
+ vert, face, numFaces, NULL, -1);
if (tree) {
/* Save on cache for later use */
/* printf("BVHTree built and saved on cache\n"); */
@@ -813,7 +822,9 @@ BVHTree *bvhtree_from_mesh_faces_ex(
BLI_bitmap *mask, int numFaces_active, float epsilon, int tree_type, int axis)
{
BVHTree *tree = bvhtree_from_mesh_faces_create_tree(
- epsilon, tree_type, axis, NULL, vert, face, numFaces,
+ epsilon, tree_type, axis,
+ NULL, false,
+ vert, face, numFaces,
mask, numFaces_active);
/* Setup BVHTreeFromMesh */
@@ -832,7 +843,8 @@ BVHTree *bvhtree_from_mesh_faces_ex(
static BVHTree *bvhtree_from_mesh_looptri_create_tree(
float epsilon, int tree_type, int axis,
- BMEditMesh *em, const MVert *vert, const MLoop *mloop, const MLoopTri *looptri, const int looptri_num,
+ BMEditMesh *em, const bool em_all,
+ const MVert *vert, const MLoop *mloop, const MLoopTri *looptri, const int looptri_num,
BLI_bitmap *mask, int looptri_num_active)
{
BVHTree *tree = NULL;
@@ -881,7 +893,10 @@ static BVHTree *bvhtree_from_mesh_looptri_create_tree(
insert = insert_prev;
}
else if (insert) {
- if (BM_elem_flag_test(f, BM_ELEM_SELECT) || BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
+ if (em_all) {
+ /* pass */
+ }
+ else if (BM_elem_flag_test(f, BM_ELEM_SELECT) || BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
/* Don't insert triangles tessellated from faces that are hidden or selected */
insert = false;
}
@@ -916,7 +931,7 @@ static BVHTree *bvhtree_from_mesh_looptri_create_tree(
else {
if (vert && looptri) {
for (i = 0; i < looptri_num; i++) {
- float co[4][3];
+ float co[3][3];
if (mask && !BLI_BITMAP_TEST_BOOL(mask, i)) {
continue;
}
@@ -972,6 +987,9 @@ static void bvhtree_from_mesh_looptri_setup_data(
if (vert_allocated) {
MEM_freeN((void *)vert);
}
+ if (loop_allocated) {
+ MEM_freeN((void *)mloop);
+ }
if (looptri_allocated) {
MEM_freeN((void *)looptri);
}
@@ -986,7 +1004,9 @@ static void bvhtree_from_mesh_looptri_setup_data(
BVHTree *bvhtree_from_mesh_looptri(BVHTreeFromMesh *data, DerivedMesh *dm, float epsilon, int tree_type, int axis)
{
BMEditMesh *em = data->em_evil;
- const int bvhcache_type = em ? BVHTREE_FROM_FACES_EDITMESH : BVHTREE_FROM_LOOPTRI;
+ const int bvhcache_type = em ?
+ (data->em_evil_all ? BVHTREE_FROM_FACES_EDITMESH_ALL : BVHTREE_FROM_FACES_EDITMESH_SNAP) :
+ BVHTREE_FROM_LOOPTRI;
BVHTree *tree;
MVert *mvert = NULL;
MLoop *mloop = NULL;
@@ -1041,7 +1061,8 @@ BVHTree *bvhtree_from_mesh_looptri(BVHTreeFromMesh *data, DerivedMesh *dm, float
}
tree = bvhtree_from_mesh_looptri_create_tree(
- epsilon, tree_type, axis, em,
+ epsilon, tree_type, axis,
+ em, (bvhcache_type == BVHTREE_FROM_FACES_EDITMESH_ALL),
mvert, mloop, looptri, looptri_num, NULL, -1);
if (tree) {
/* Save on cache for later use */
@@ -1074,7 +1095,9 @@ BVHTree *bvhtree_from_mesh_looptri_ex(
float epsilon, int tree_type, int axis)
{
BVHTree *tree = bvhtree_from_mesh_looptri_create_tree(
- epsilon, tree_type, axis, NULL, vert, mloop, looptri, looptri_num,
+ epsilon, tree_type, axis,
+ NULL, false,
+ vert, mloop, looptri, looptri_num,
mask, looptri_num_active);
/* Setup BVHTreeFromMesh */
diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c
index af3608901f8..46b74c58965 100644
--- a/source/blender/blenkernel/intern/camera.c
+++ b/source/blender/blenkernel/intern/camera.c
@@ -57,11 +57,9 @@
/****************************** Camera Datablock *****************************/
-void *BKE_camera_add(Main *bmain, const char *name)
+void BKE_camera_init(Camera *cam)
{
- Camera *cam;
-
- cam = BKE_libblock_alloc(bmain, ID_CA, name);
+ BLI_assert(MEMCMP_STRUCT_OFS_IS_ZERO(cam, id));
cam->lens = 35.0f;
cam->sensor_x = DEFAULT_SENSOR_WIDTH;
@@ -78,6 +76,15 @@ void *BKE_camera_add(Main *bmain, const char *name)
/* stereoscopy 3d */
cam->stereo.interocular_distance = 0.065f;
cam->stereo.convergence_distance = 30.f * 0.065f;
+}
+
+void *BKE_camera_add(Main *bmain, const char *name)
+{
+ Camera *cam;
+
+ cam = BKE_libblock_alloc(bmain, ID_CA, name);
+
+ BKE_camera_init(cam);
return cam;
}
@@ -169,15 +176,15 @@ float BKE_camera_object_dof_distance(Object *ob)
if (ob->type != OB_CAMERA)
return 0.0f;
if (cam->dof_ob) {
- /* too simple, better to return the distance on the view axis only
- * return len_v3v3(ob->obmat[3], cam->dof_ob->obmat[3]); */
- float mat[4][4], imat[4][4], obmat[4][4];
-
- copy_m4_m4(obmat, ob->obmat);
- normalize_m4(obmat);
- invert_m4_m4(imat, obmat);
- mul_m4_m4m4(mat, imat, cam->dof_ob->obmat);
- return fabsf(mat[3][2]);
+#if 0
+ /* too simple, better to return the distance on the view axis only */
+ return len_v3v3(ob->obmat[3], cam->dof_ob->obmat[3]);
+#else
+ float view_dir[3], dof_dir[3];
+ normalize_v3_v3(view_dir, ob->obmat[2]);
+ sub_v3_v3v3(dof_dir, ob->obmat[3], cam->dof_ob->obmat[3]);
+ return fabsf(dot_v3v3(view_dir, dof_dir));
+#endif
}
return cam->YF_dofdist;
}
@@ -442,8 +449,8 @@ void BKE_camera_view_frame_ex(
*r_drawsize = 1.0f;
depth = -(camera->clipsta + 0.1f) * scale[2];
fac = depth / (camera->lens / (-half_sensor));
- scale_x = 1.0f;
- scale_y = 1.0f;
+ scale_x = scale[0] / scale[2];
+ scale_y = scale[1] / scale[2];
}
else {
/* fixed size, variable depth (stays a reasonable size in the 3D view) */
@@ -565,7 +572,7 @@ static void camera_frame_fit_data_init(
static bool camera_frame_fit_calc_from_data(
CameraParams *params, CameraViewFrameData *data, float r_co[3], float *r_scale)
{
- float plane_tx[CAMERA_VIEWFRAME_NUM_PLANES][3];
+ float plane_tx[CAMERA_VIEWFRAME_NUM_PLANES][4];
unsigned int i;
if (data->tot <= 1) {
@@ -609,15 +616,13 @@ static bool camera_frame_fit_calc_from_data(
/* apply the dist-from-plane's to the transformed plane points */
for (i = 0; i < CAMERA_VIEWFRAME_NUM_PLANES; i++) {
- mul_v3_v3fl(plane_tx[i], data->normal_tx[i], sqrtf_signed(data->dist_vals_sq[i]));
+ float co[3];
+ mul_v3_v3fl(co, data->normal_tx[i], sqrtf_signed(data->dist_vals_sq[i]));
+ plane_from_point_normal_v3(plane_tx[i], co, data->normal_tx[i]);
}
- if ((!isect_plane_plane_v3(plane_isect_1, plane_isect_1_no,
- plane_tx[0], data->normal_tx[0],
- plane_tx[2], data->normal_tx[2])) ||
- (!isect_plane_plane_v3(plane_isect_2, plane_isect_2_no,
- plane_tx[1], data->normal_tx[1],
- plane_tx[3], data->normal_tx[3])))
+ if ((!isect_plane_plane_v3(plane_tx[0], plane_tx[2], plane_isect_1, plane_isect_1_no)) ||
+ (!isect_plane_plane_v3(plane_tx[1], plane_tx[3], plane_isect_2, plane_isect_2_no)))
{
return false;
}
@@ -960,11 +965,6 @@ void BKE_camera_to_gpu_dof(struct Object *camera, struct GPUFXSettings *r_fx_set
r_fx_settings->dof = &cam->gpu_dof;
r_fx_settings->dof->focal_length = cam->lens;
r_fx_settings->dof->sensor = BKE_camera_sensor_size(cam->sensor_fit, cam->sensor_x, cam->sensor_y);
- if (cam->dof_ob) {
- r_fx_settings->dof->focus_distance = len_v3v3(cam->dof_ob->obmat[3], camera->obmat[3]);
- }
- else {
- r_fx_settings->dof->focus_distance = cam->YF_dofdist;
- }
+ r_fx_settings->dof->focus_distance = BKE_camera_object_dof_distance(camera);
}
}
diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c
index c3168c0d6af..3b86c42d8c9 100644
--- a/source/blender/blenkernel/intern/cdderivedmesh.c
+++ b/source/blender/blenkernel/intern/cdderivedmesh.c
@@ -867,6 +867,7 @@ static void cdDM_drawMappedFacesGLSL(
const float (*nors)[3] = dm->getPolyDataArray(dm, CD_NORMAL);
const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL);
const int totpoly = dm->getNumPolys(dm);
+ const short dm_totmat = dm->totmat;
int a, b, matnr, new_matnr;
bool do_draw;
int orig;
@@ -966,7 +967,7 @@ static void cdDM_drawMappedFacesGLSL(
int *mat_orig_to_new;
int tot_active_mat;
GPUBuffer *buffer = NULL;
- char *varray;
+ unsigned char *varray;
size_t max_element_size = 0;
int tot_loops = 0;
@@ -1047,8 +1048,9 @@ static void cdDM_drawMappedFacesGLSL(
}
for (a = 0; a < totpoly; a++, mpoly++) {
+ const short mat_nr = ME_MAT_NR_TEST(mpoly->mat_nr, dm_totmat);
int j;
- int i = mat_orig_to_new[mpoly->mat_nr];
+ int i = mat_orig_to_new[mat_nr];
offset = tot_loops * max_element_size;
if (matconv[i].numdata != 0) {
@@ -1070,17 +1072,15 @@ static void cdDM_drawMappedFacesGLSL(
if (matconv[i].attribs.mcol[b].array) {
const MLoopCol *mloopcol = matconv[i].attribs.mcol[b].array;
for (j = 0; j < mpoly->totloop; j++)
- copy_v4_v4_char((char *)&varray[offset + j * max_element_size], &mloopcol[mpoly->loopstart + j].r);
+ copy_v4_v4_uchar(&varray[offset + j * max_element_size], &mloopcol[mpoly->loopstart + j].r);
offset += sizeof(unsigned char) * 4;
}
}
if (matconv[i].attribs.tottang && matconv[i].attribs.tang.array) {
- if (matconv[i].attribs.tface[b].array) {
- const float (*looptang)[4] = (const float (*)[4])matconv[i].attribs.tang.array;
- for (j = 0; j < mpoly->totloop; j++)
- copy_v4_v4((float *)&varray[offset + j * max_element_size], looptang[mpoly->loopstart + j]);
- offset += sizeof(float) * 4;
- }
+ const float (*looptang)[4] = (const float (*)[4])matconv[i].attribs.tang.array;
+ for (j = 0; j < mpoly->totloop; j++)
+ copy_v4_v4((float *)&varray[offset + j * max_element_size], looptang[mpoly->loopstart + j]);
+ offset += sizeof(float) * 4;
}
}
@@ -1258,14 +1258,15 @@ static void cdDM_buffer_copy_triangles(
GPUBufferMaterial *gpumat, *gpumaterials = dm->drawObject->materials;
int i, j, start;
- const int totmat = dm->drawObject->totmaterial;
+ const int gpu_totmat = dm->drawObject->totmaterial;
+ const short dm_totmat = dm->totmat;
const MPoly *mpoly = dm->getPolyArray(dm);
const MLoopTri *lt = dm->getLoopTriArray(dm);
const int totpoly = dm->getNumPolys(dm);
- FaceCount *fc = MEM_mallocN(sizeof(*fc) * totmat, "gpumaterial.facecount");
+ FaceCount *fc = MEM_mallocN(sizeof(*fc) * gpu_totmat, "gpumaterial.facecount");
- for (i = 0; i < totmat; i++) {
+ for (i = 0; i < gpu_totmat; i++) {
fc[i].i_visible = 0;
fc[i].i_tri_visible = 0;
fc[i].i_hidden = gpumaterials[i].totpolys - 1;
@@ -1273,8 +1274,9 @@ static void cdDM_buffer_copy_triangles(
}
for (i = 0; i < totpoly; i++) {
+ const short mat_nr = ME_MAT_NR_TEST(mpoly[i].mat_nr, dm_totmat);
int tottri = ME_POLY_TRI_TOT(&mpoly[i]);
- int mati = mat_orig_to_new[mpoly[i].mat_nr];
+ int mati = mat_orig_to_new[mat_nr];
gpumat = gpumaterials + mati;
if (mpoly[i].flag & ME_HIDE) {
@@ -1302,7 +1304,7 @@ static void cdDM_buffer_copy_triangles(
}
/* set the visible polygons */
- for (i = 0; i < totmat; i++) {
+ for (i = 0; i < gpu_totmat; i++) {
gpumaterials[i].totvisiblepolys = fc[i].i_visible;
}
@@ -1480,7 +1482,7 @@ static void cdDM_buffer_copy_mcol(
for (i = 0; i < totpoly; i++, mpoly++) {
for (j = 0; j < mpoly->totloop; j++) {
- copy_v3_v3_char((char *)&varray[start], &mloopcol[mpoly->loopstart + j].r);
+ copy_v3_v3_uchar(&varray[start], &mloopcol[mpoly->loopstart + j].r);
start += 3;
}
}
@@ -1695,12 +1697,12 @@ static GPUDrawObject *cdDM_GPUobject_new(DerivedMesh *dm)
GPUDrawObject *gdo;
const MPoly *mpoly;
const MLoop *mloop;
- int totmat = dm->totmat;
+ const short dm_totmat = dm->totmat;
GPUBufferMaterial *mat_info;
int i, totloops, totpolys;
/* object contains at least one material (default included) so zero means uninitialized dm */
- BLI_assert(totmat != 0);
+ BLI_assert(dm_totmat != 0);
mpoly = dm->getPolyArray(dm);
mloop = dm->getLoopArray(dm);
@@ -1710,10 +1712,10 @@ static GPUDrawObject *cdDM_GPUobject_new(DerivedMesh *dm)
/* get the number of points used by each material, treating
* each quad as two triangles */
- mat_info = MEM_callocN(sizeof(*mat_info) * totmat, "GPU_drawobject_new.mat_orig_to_new");
+ mat_info = MEM_callocN(sizeof(*mat_info) * dm_totmat, "GPU_drawobject_new.mat_orig_to_new");
for (i = 0; i < totpolys; i++) {
- const int mat_nr = mpoly[i].mat_nr;
+ const short mat_nr = ME_MAT_NR_TEST(mpoly[i].mat_nr, dm_totmat);
mat_info[mat_nr].totpolys++;
mat_info[mat_nr].totelements += 3 * ME_POLY_TRI_TOT(&mpoly[i]);
mat_info[mat_nr].totloops += mpoly[i].totloop;
@@ -1723,7 +1725,7 @@ static GPUDrawObject *cdDM_GPUobject_new(DerivedMesh *dm)
gdo->totvert = dm->getNumVerts(dm);
gdo->totedge = dm->getNumEdges(dm);
- GPU_buffer_material_finalize(gdo, mat_info, totmat);
+ GPU_buffer_material_finalize(gdo, mat_info, dm_totmat);
gdo->tot_loop_verts = totloops;
@@ -2419,10 +2421,11 @@ DerivedMesh *CDDM_copy_from_tessface(DerivedMesh *source)
/* note, the CD_ORIGINDEX layers are all 0, so if there is a direct
* relationship between mesh data this needs to be set by the caller. */
-DerivedMesh *CDDM_from_template(
+DerivedMesh *CDDM_from_template_ex(
DerivedMesh *source,
int numVerts, int numEdges, int numTessFaces,
- int numLoops, int numPolys)
+ int numLoops, int numPolys,
+ CustomDataMask mask)
{
CDDerivedMesh *cddm = cdDM_create("CDDM_from_template dest");
DerivedMesh *dm = &cddm->dm;
@@ -2434,7 +2437,11 @@ DerivedMesh *CDDM_from_template(
source->getPolyDataArray(source, CD_ORIGINDEX);
/* this does a copy of all non mvert/medge/mface layers */
- DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numTessFaces, numLoops, numPolys);
+ DM_from_template_ex(
+ dm, source, DM_TYPE_CDDM,
+ numVerts, numEdges, numTessFaces,
+ numLoops, numPolys,
+ mask);
/* now add mvert/medge/mface layers */
CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts);
@@ -2458,6 +2465,16 @@ DerivedMesh *CDDM_from_template(
return dm;
}
+DerivedMesh *CDDM_from_template(
+ DerivedMesh *source,
+ int numVerts, int numEdges, int numTessFaces,
+ int numLoops, int numPolys)
+{
+ return CDDM_from_template_ex(
+ source, numVerts, numEdges, numTessFaces,
+ numLoops, numPolys,
+ CD_MASK_DERIVEDMESH);
+}
void CDDM_apply_vert_coords(DerivedMesh *dm, float (*vertCoords)[3])
{
@@ -2530,7 +2547,7 @@ void CDDM_calc_normals_mapping_ex(DerivedMesh *dm, const bool only_face_normals)
/* calculate face normals */
BKE_mesh_calc_normals_poly(
- cddm->mvert, dm->numVertData, CDDM_get_loops(dm), CDDM_get_polys(dm),
+ cddm->mvert, NULL, dm->numVertData, CDDM_get_loops(dm), CDDM_get_polys(dm),
dm->numLoopData, dm->numPolyData, face_nors,
only_face_normals);
@@ -2580,7 +2597,7 @@ void CDDM_calc_normals(DerivedMesh *dm)
/* we don't want to overwrite any referenced layers */
cddm->mvert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT, dm->numVertData);
- BKE_mesh_calc_normals_poly(cddm->mvert, dm->numVertData, CDDM_get_loops(dm), CDDM_get_polys(dm),
+ BKE_mesh_calc_normals_poly(cddm->mvert, NULL, dm->numVertData, CDDM_get_loops(dm), CDDM_get_polys(dm),
dm->numLoopData, dm->numPolyData, NULL, false);
cddm->dm.dirty &= ~DM_DIRTY_NORMALS;
@@ -2629,7 +2646,7 @@ void CDDM_calc_loop_normals_spacearr(
if (!pnors) {
pnors = CustomData_add_layer(pdata, CD_NORMAL, CD_CALLOC, NULL, numPolys);
}
- BKE_mesh_calc_normals_poly(mverts, numVerts, mloops, mpolys, numLoops, numPolys, pnors,
+ BKE_mesh_calc_normals_poly(mverts, NULL, numVerts, mloops, mpolys, numLoops, numPolys, pnors,
(dm->dirty & DM_DIRTY_NORMALS) ? false : true);
dm->dirty &= ~DM_DIRTY_NORMALS;
diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c
index aad6681fa2a..7a3cc118eb5 100644
--- a/source/blender/blenkernel/intern/colortools.c
+++ b/source/blender/blenkernel/intern/colortools.c
@@ -725,6 +725,16 @@ void curvemapping_changed(CurveMapping *cumap, const bool rem_doubles)
cmp[a].y -= dy;
}
}
+
+ /* ensure zoom-level respects clipping */
+ if (BLI_rctf_size_x(&cumap->curr) > BLI_rctf_size_x(&cumap->clipr)) {
+ cumap->curr.xmin = cumap->clipr.xmin;
+ cumap->curr.xmax = cumap->clipr.xmax;
+ }
+ if (BLI_rctf_size_y(&cumap->curr) > BLI_rctf_size_y(&cumap->clipr)) {
+ cumap->curr.ymin = cumap->clipr.ymin;
+ cumap->curr.ymax = cumap->clipr.ymax;
+ }
}
@@ -975,7 +985,6 @@ void BKE_histogram_update_sample_line(Histogram *hist, ImBuf *ibuf, const ColorM
{
int i, x, y;
const float *fp;
- float rgb[3];
unsigned char *cp;
int x1 = 0.5f + hist->co[0][0] * ibuf->x;
@@ -1004,16 +1013,36 @@ void BKE_histogram_update_sample_line(Histogram *hist, ImBuf *ibuf, const ColorM
}
else {
if (ibuf->rect_float) {
+ float rgba[4];
fp = (ibuf->rect_float + (ibuf->channels) * (y * ibuf->x + x));
- copy_v3_v3(rgb, fp);
- IMB_colormanagement_processor_apply_v3(cm_processor, rgb);
+ switch (ibuf->channels) {
+ case 4:
+ copy_v4_v4(rgba, fp);
+ IMB_colormanagement_processor_apply_v4(cm_processor, rgba);
+ break;
+ case 3:
+ copy_v3_v3(rgba, fp);
+ IMB_colormanagement_processor_apply_v3(cm_processor, rgba);
+ rgba[3] = 1.0f;
+ break;
+ case 2:
+ copy_v3_fl(rgba, fp[0]);
+ rgba[3] = fp[1];
+ break;
+ case 1:
+ copy_v3_fl(rgba, fp[0]);
+ rgba[3] = 1.0f;
+ break;
+ default:
+ BLI_assert(0);
+ }
- hist->data_luma[i] = IMB_colormanagement_get_luminance(rgb);
- hist->data_r[i] = rgb[0];
- hist->data_g[i] = rgb[1];
- hist->data_b[i] = rgb[2];
- hist->data_a[i] = fp[3];
+ hist->data_luma[i] = IMB_colormanagement_get_luminance(rgba);
+ hist->data_r[i] = rgba[0];
+ hist->data_g[i] = rgba[1];
+ hist->data_b[i] = rgba[2];
+ hist->data_a[i] = rgba[3];
}
else if (ibuf->rect) {
cp = (unsigned char *)(ibuf->rect + y * ibuf->x + x);
@@ -1148,8 +1177,28 @@ void scopes_update(Scopes *scopes, ImBuf *ibuf, const ColorManagedViewSettings *
for (x = 0; x < ibuf->x; x++) {
float rgba[4], ycc[3], luma;
if (is_float) {
- copy_v4_v4(rgba, rf);
- IMB_colormanagement_processor_apply_v4(cm_processor, rgba);
+
+ switch (ibuf->channels) {
+ case 4:
+ copy_v4_v4(rgba, rf);
+ IMB_colormanagement_processor_apply_v4(cm_processor, rgba);
+ break;
+ case 3:
+ copy_v3_v3(rgba, rf);
+ IMB_colormanagement_processor_apply_v3(cm_processor, rgba);
+ rgba[3] = 1.0f;
+ break;
+ case 2:
+ copy_v3_fl(rgba, rf[0]);
+ rgba[3] = rf[1];
+ break;
+ case 1:
+ copy_v3_fl(rgba, rf[0]);
+ rgba[3] = 1.0f;
+ break;
+ default:
+ BLI_assert(0);
+ }
}
else {
for (c = 0; c < 4; c++)
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index 2aba4fcde27..03406c6c2a0 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -447,7 +447,7 @@ static void contarget_get_mesh_mat(Object *ob, const char *substring, float mat[
copy_v3_v3(plane, tmat[1]);
cross_v3_v3v3(mat[0], normal, plane);
- if (len_v3(mat[0]) < 1e-3f) {
+ if (len_squared_v3(mat[0]) < SQUARE(1e-3f)) {
copy_v3_v3(plane, tmat[0]);
cross_v3_v3v3(mat[0], normal, plane);
}
@@ -4882,11 +4882,12 @@ void BKE_constraints_solve(ListBase *conlist, bConstraintOb *cob, float ctime)
* since some constraints may not convert the solution back to the input space before blending
* but all are guaranteed to end up in good "worldspace" result
*/
- /* Note: all kind of stuff here before (caused trouble), much easier to just interpolate, or did I miss something? -jahka (r.32105) */
+ /* Note: all kind of stuff here before (caused trouble), much easier to just interpolate,
+ * or did I miss something? -jahka (r.32105) */
if (enf < 1.0f) {
float solution[4][4];
copy_m4_m4(solution, cob->matrix);
- blend_m4_m4m4(cob->matrix, oldmat, solution, enf);
+ interp_m4_m4m4(cob->matrix, oldmat, solution, enf);
}
}
}
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c
index aa9e9567ecf..3e0bdbe31af 100644
--- a/source/blender/blenkernel/intern/curve.c
+++ b/source/blender/blenkernel/intern/curve.c
@@ -161,15 +161,14 @@ void BKE_curve_free(Curve *cu)
MEM_freeN(cu->tb);
}
-Curve *BKE_curve_add(Main *bmain, const char *name, int type)
+void BKE_curve_init(Curve *cu)
{
- Curve *cu;
+ /* BLI_assert(MEMCMP_STRUCT_OFS_IS_ZERO(cu, id)); */ /* cu->type is already initialized... */
- cu = BKE_libblock_alloc(bmain, ID_CU, name);
copy_v3_fl(cu->size, 1.0f);
cu->flag = CU_FRONT | CU_BACK | CU_DEFORM_BOUNDS_OFF | CU_PATH_RADIUS;
cu->pathlen = 100;
- cu->resolu = cu->resolv = (type == OB_SURF) ? 4 : 12;
+ cu->resolu = cu->resolv = (cu->type == OB_SURF) ? 4 : 12;
cu->width = 1.0;
cu->wordspace = 1.0;
cu->spacing = cu->linedist = 1.0;
@@ -179,7 +178,6 @@ Curve *BKE_curve_add(Main *bmain, const char *name, int type)
cu->smallcaps_scale = 0.75f;
/* XXX: this one seems to be the best one in most cases, at least for curve deform... */
cu->twist_mode = CU_TWIST_MINIMUM;
- cu->type = type;
cu->bevfac1 = 0.0f;
cu->bevfac2 = 1.0f;
cu->bevfac1_mapping = CU_BEVFAC_MAP_RESOLU;
@@ -187,7 +185,7 @@ Curve *BKE_curve_add(Main *bmain, const char *name, int type)
cu->bb = BKE_boundbox_alloc_unit();
- if (type == OB_FONT) {
+ if (cu->type == OB_FONT) {
cu->vfont = cu->vfontb = cu->vfonti = cu->vfontbi = BKE_vfont_builtin_get();
cu->vfont->id.us += 4;
cu->str = MEM_mallocN(12, "str");
@@ -198,6 +196,16 @@ Curve *BKE_curve_add(Main *bmain, const char *name, int type)
cu->tb = MEM_callocN(MAXTEXTBOX * sizeof(TextBox), "textbox");
cu->tb[0].w = cu->tb[0].h = 0.0;
}
+}
+
+Curve *BKE_curve_add(Main *bmain, const char *name, int type)
+{
+ Curve *cu;
+
+ cu = BKE_libblock_alloc(bmain, ID_CU, name);
+ cu->type = type;
+
+ BKE_curve_init(cu);
return cu;
}
@@ -2626,7 +2634,7 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
BevPoint *bevp, *bevp2, *bevp1 = NULL, *bevp0;
const float treshold = 0.00001f;
float min, inp;
- float *seglen;
+ float *seglen = NULL;
struct BevelSort *sortdata, *sd, *sd1;
int a, b, nr, poly, resolu = 0, len = 0, segcount;
int *segbevcount;
diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c
index 416125e53ad..c9b059e259e 100644
--- a/source/blender/blenkernel/intern/customdata.c
+++ b/source/blender/blenkernel/intern/customdata.c
@@ -61,6 +61,8 @@
#include "BKE_mesh_remap.h"
#include "BKE_multires.h"
+#include "data_transfer_intern.h"
+
#include "bmesh.h"
#include <math.h>
@@ -305,13 +307,16 @@ static void layerInterp_normal(
const void **sources, const float *weights,
const float *UNUSED(sub_weights), int count, void *dest)
{
+ /* Note: This is linear interpolation, which is not optimal for vectors.
+ * Unfortunately, spherical interpolation of more than two values is hairy, so for now it will do... */
float no[3] = {0.0f};
while (count--) {
madd_v3_v3fl(no, (const float *)sources[count], weights[count]);
}
- copy_v3_v3((float *)dest, no);
+ /* Weighted sum of normalized vectors will **not** be normalized, even if weights are. */
+ normalize_v3_v3((float *)dest, no);
}
static void layerCopyValue_normal(const void *source, void *dest, const int mixmode, const float mixfactor)
@@ -926,6 +931,7 @@ static void layerInterp_mloopuv(
}
/* delay writing to the destination incase dest is in sources */
+ ((MLoopUV *)dest)->flag = ((MLoopUV *)sources)->flag;
copy_v2_v2(((MLoopUV *)dest)->uv, uv);
}
@@ -1373,9 +1379,16 @@ const CustomDataMask CD_MASK_BMESH =
CD_MASK_CREASE | CD_MASK_BWEIGHT | CD_MASK_RECAST | CD_MASK_PAINT_MASK |
CD_MASK_GRID_PAINT_MASK | CD_MASK_MVERT_SKIN | CD_MASK_FREESTYLE_EDGE | CD_MASK_FREESTYLE_FACE |
CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_FACEMAP;
-const CustomDataMask CD_MASK_FACECORNERS = /* XXX Not used anywhere! */
- CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_MTEXPOLY | CD_MASK_MLOOPUV |
- CD_MASK_MLOOPCOL | CD_MASK_NORMAL | CD_MASK_MLOOPTANGENT;
+/**
+ * cover values copied by #BKE_mesh_loops_to_tessdata
+ */
+const CustomDataMask CD_MASK_FACECORNERS =
+ CD_MASK_MTFACE | CD_MASK_MTEXPOLY | CD_MASK_MLOOPUV |
+ CD_MASK_MCOL | CD_MASK_MLOOPCOL |
+ CD_MASK_PREVIEW_MCOL | CD_MASK_PREVIEW_MLOOPCOL |
+ CD_MASK_ORIGSPACE | CD_MASK_ORIGSPACE_MLOOP |
+ CD_MASK_TESSLOOPNORMAL | CD_MASK_NORMAL |
+ CD_MASK_TANGENT | CD_MASK_MLOOPTANGENT;
const CustomDataMask CD_MASK_EVERYTHING =
CD_MASK_MVERT | CD_MASK_MDEFORMVERT | CD_MASK_MEDGE | CD_MASK_MFACE |
CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_ORIGINDEX | CD_MASK_NORMAL /* | CD_MASK_POLYINDEX */ | CD_MASK_PROP_FLT |
@@ -2501,6 +2514,10 @@ void CustomData_to_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData *l
void CustomData_from_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData *ldata, int total)
{
int i;
+
+ /* avoid accumulating extra layers */
+ BLI_assert(!CustomData_from_bmeshpoly_test(fdata, pdata, ldata, false));
+
for (i = 0; i < pdata->totlayer; i++) {
if (pdata->layers[i].type == CD_MTEXPOLY) {
CustomData_add_layer_named(fdata, CD_MTFACE, CD_CALLOC, NULL, total, pdata->layers[i].name);
@@ -2527,6 +2544,41 @@ void CustomData_from_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData
CustomData_bmesh_update_active_layers(fdata, pdata, ldata);
}
+#ifndef NDEBUG
+/**
+ * Debug check, used to assert when we expect layers to be in/out of sync.
+ *
+ * \param fallback: Use when there are no layers to handle,
+ * since callers may expect success or failure.
+ */
+bool CustomData_from_bmeshpoly_test(CustomData *fdata, CustomData *pdata, CustomData *ldata, bool fallback)
+{
+ int a_num = 0, b_num = 0;
+#define LAYER_CMP(l_a, t_a, l_b, t_b) \
+ ((a_num += CustomData_number_of_layers(l_a, t_a)) == (b_num += CustomData_number_of_layers(l_b, t_b)))
+
+ if (!LAYER_CMP(pdata, CD_MTEXPOLY, fdata, CD_MTFACE))
+ return false;
+ if (!LAYER_CMP(ldata, CD_MLOOPCOL, fdata, CD_MCOL))
+ return false;
+ if (!LAYER_CMP(ldata, CD_PREVIEW_MLOOPCOL, fdata, CD_PREVIEW_MCOL))
+ return false;
+ if (!LAYER_CMP(ldata, CD_ORIGSPACE_MLOOP, fdata, CD_ORIGSPACE))
+ return false;
+ if (!LAYER_CMP(ldata, CD_NORMAL, fdata, CD_TESSLOOPNORMAL))
+ return false;
+ if (!LAYER_CMP(ldata, CD_TANGENT, fdata, CD_TANGENT))
+ return false;
+
+#undef TEST_RET
+
+ /* if no layers are on either CustomData's,
+ * then there was nothing to do... */
+ return a_num ? true : fallback;
+}
+#endif
+
+
void CustomData_bmesh_update_active_layers(CustomData *fdata, CustomData *pdata, CustomData *ldata)
{
int act;
@@ -3878,6 +3930,38 @@ static void customdata_data_transfer_interp_generic(
MEM_freeN(tmp_dst);
}
+/* Normals are special, we need to take care of source & destination spaces... */
+void customdata_data_transfer_interp_normal_normals(
+ const CustomDataTransferLayerMap *laymap, void *data_dst,
+ const void **sources, const float *weights, const int count,
+ const float mix_factor)
+{
+ const int data_type = laymap->data_type;
+ const int mix_mode = laymap->mix_mode;
+
+ SpaceTransform *space_transform = laymap->interp_data;
+
+ const LayerTypeInfo *type_info = layerType_getInfo(data_type);
+ cd_interp interp_cd = type_info->interp;
+
+ float tmp_dst[3];
+
+ BLI_assert(data_type == CD_NORMAL);
+
+ if (!sources) {
+ /* Not supported here, abort. */
+ return;
+ }
+
+ interp_cd(sources, weights, NULL, count, tmp_dst);
+ if (space_transform) {
+ /* tmp_dst is in source space so far, bring it back in destination space. */
+ BLI_space_transform_invert_normal(space_transform, tmp_dst);
+ }
+
+ CustomData_data_mix_value(data_type, tmp_dst, data_dst, mix_mode, mix_factor);
+}
+
void CustomData_data_transfer(const MeshPairRemap *me_remap, const CustomDataTransferLayerMap *laymap)
{
MeshPairRemapItem *mapit = me_remap->items;
diff --git a/source/blender/blenkernel/intern/data_transfer.c b/source/blender/blenkernel/intern/data_transfer.c
index 53b6f4a1019..43d23e92901 100644
--- a/source/blender/blenkernel/intern/data_transfer.c
+++ b/source/blender/blenkernel/intern/data_transfer.c
@@ -291,7 +291,7 @@ static void data_transfer_dtdata_type_preprocess(
poly_nors_dst = CustomData_add_layer(pdata_dst, CD_NORMAL, CD_CALLOC, NULL, num_polys_dst);
CustomData_set_layer_flag(pdata_dst, CD_NORMAL, CD_FLAG_TEMPORARY);
}
- BKE_mesh_calc_normals_poly(verts_dst, num_verts_dst, loops_dst, polys_dst,
+ BKE_mesh_calc_normals_poly(verts_dst, NULL, num_verts_dst, loops_dst, polys_dst,
num_loops_dst, num_polys_dst, poly_nors_dst, true);
}
/* Cache loop nors into a temp CDLayer. */
@@ -428,7 +428,7 @@ void data_transfer_layersmapping_add_item(
ListBase *r_map, const int cddata_type, const int mix_mode, const float mix_factor, const float *mix_weights,
const void *data_src, void *data_dst, const int data_src_n, const int data_dst_n,
const size_t elem_size, const size_t data_size, const size_t data_offset, const uint64_t data_flag,
- cd_datatransfer_interp interp)
+ cd_datatransfer_interp interp, void *interp_data)
{
CustomDataTransferLayerMap *item = MEM_mallocN(sizeof(*item), __func__);
@@ -450,17 +450,18 @@ void data_transfer_layersmapping_add_item(
item->data_flag = data_flag;
item->interp = interp;
+ item->interp_data = interp_data;
BLI_addtail(r_map, item);
}
static void data_transfer_layersmapping_add_item_cd(
ListBase *r_map, const int cddata_type, const int mix_mode, const float mix_factor, const float *mix_weights,
- void *data_src, void *data_dst)
+ void *data_src, void *data_dst, cd_datatransfer_interp interp, void *interp_data)
{
data_transfer_layersmapping_add_item(
r_map, cddata_type, mix_mode, mix_factor, mix_weights, data_src, data_dst,
- 0, 0, 0, 0, 0, 0, NULL);
+ 0, 0, 0, 0, 0, 0, interp, interp_data);
}
/* Note: All those layer mapping handlers return false *only* if they were given invalid parameters.
@@ -473,7 +474,8 @@ static bool data_transfer_layersmapping_cdlayers_multisrc_to_dst(
ListBase *r_map, const int cddata_type, const int mix_mode, const float mix_factor, const float *mix_weights,
const int num_elem_dst, const bool use_create, const bool use_delete,
CustomData *cd_src, CustomData *cd_dst, const bool use_dupref_dst,
- const int tolayers, bool *use_layers_src, const int num_layers_src)
+ const int tolayers, bool *use_layers_src, const int num_layers_src,
+ cd_datatransfer_interp interp, void *interp_data)
{
void *data_src, *data_dst = NULL;
int idx_src = num_layers_src;
@@ -527,7 +529,7 @@ static bool data_transfer_layersmapping_cdlayers_multisrc_to_dst(
data_dst = CustomData_get_layer_n(cd_dst, cddata_type, idx_src);
}
data_transfer_layersmapping_add_item_cd(r_map, cddata_type, mix_mode, mix_factor, mix_weights,
- data_src, data_dst);
+ data_src, data_dst, interp, interp_data);
}
}
break;
@@ -571,7 +573,7 @@ static bool data_transfer_layersmapping_cdlayers_multisrc_to_dst(
data_dst = CustomData_get_layer_n(cd_dst, cddata_type, idx_dst);
}
data_transfer_layersmapping_add_item_cd(r_map, cddata_type, mix_mode, mix_factor, mix_weights,
- data_src, data_dst);
+ data_src, data_dst, interp, interp_data);
}
}
@@ -599,7 +601,8 @@ static bool data_transfer_layersmapping_cdlayers(
ListBase *r_map, const int cddata_type, const int mix_mode, const float mix_factor, const float *mix_weights,
const int num_elem_dst, const bool use_create, const bool use_delete,
CustomData *cd_src, CustomData *cd_dst, const bool use_dupref_dst,
- const int fromlayers, const int tolayers)
+ const int fromlayers, const int tolayers,
+ cd_datatransfer_interp interp, void *interp_data)
{
int idx_src, idx_dst;
void *data_src, *data_dst = NULL;
@@ -626,7 +629,7 @@ static bool data_transfer_layersmapping_cdlayers(
if (r_map) {
data_transfer_layersmapping_add_item_cd(r_map, cddata_type, mix_mode, mix_factor, mix_weights,
- data_src, data_dst);
+ data_src, data_dst, interp, interp_data);
}
}
else if (fromlayers == DT_LAYERS_ACTIVE_SRC || fromlayers >= 0) {
@@ -719,7 +722,7 @@ static bool data_transfer_layersmapping_cdlayers(
if (r_map) {
data_transfer_layersmapping_add_item_cd(
- r_map, cddata_type, mix_mode, mix_factor, mix_weights, data_src, data_dst);
+ r_map, cddata_type, mix_mode, mix_factor, mix_weights, data_src, data_dst, interp, interp_data);
}
}
else if (fromlayers == DT_LAYERS_ALL_SRC) {
@@ -734,7 +737,8 @@ static bool data_transfer_layersmapping_cdlayers(
ret = data_transfer_layersmapping_cdlayers_multisrc_to_dst(
r_map, cddata_type, mix_mode, mix_factor, mix_weights,
num_elem_dst, use_create, use_delete, cd_src, cd_dst, use_dupref_dst,
- tolayers, use_layers_src, num_src);
+ tolayers, use_layers_src, num_src,
+ interp, interp_data);
if (use_layers_src) {
MEM_freeN(use_layers_src);
@@ -751,10 +755,14 @@ static bool data_transfer_layersmapping_cdlayers(
static bool data_transfer_layersmapping_generate(
ListBase *r_map, Object *ob_src, Object *ob_dst, DerivedMesh *dm_src, DerivedMesh *dm_dst, Mesh *me_dst,
const int elem_type, int cddata_type, int mix_mode, float mix_factor, const float *mix_weights,
- const int num_elem_dst, const bool use_create, const bool use_delete, const int fromlayers, const int tolayers)
+ const int num_elem_dst, const bool use_create, const bool use_delete, const int fromlayers, const int tolayers,
+ SpaceTransform *space_transform)
{
CustomData *cd_src, *cd_dst;
+ cd_datatransfer_interp interp = NULL;
+ void *interp_data = NULL;
+
if (elem_type == ME_VERT) {
if (!(cddata_type & CD_FAKE)) {
cd_src = dm_src->getVertDataLayout(dm_src);
@@ -763,7 +771,8 @@ static bool data_transfer_layersmapping_generate(
if (!data_transfer_layersmapping_cdlayers(r_map, cddata_type, mix_mode, mix_factor, mix_weights,
num_elem_dst, use_create, use_delete,
cd_src, cd_dst, dm_dst != NULL,
- fromlayers, tolayers))
+ fromlayers, tolayers,
+ interp, interp_data))
{
/* We handle specific source selection cases here. */
return false;
@@ -795,7 +804,7 @@ static bool data_transfer_layersmapping_generate(
dm_src->getNumVerts(dm_src),
dm_dst ? dm_dst->getNumVerts(dm_dst) : me_dst->totvert,
elem_size, data_size, data_offset, data_flag,
- data_transfer_interp_char);
+ data_transfer_interp_char, interp_data);
}
return true;
}
@@ -827,7 +836,8 @@ static bool data_transfer_layersmapping_generate(
if (!data_transfer_layersmapping_cdlayers(r_map, cddata_type, mix_mode, mix_factor, mix_weights,
num_elem_dst, use_create, use_delete,
cd_src, cd_dst, dm_dst != NULL,
- fromlayers, tolayers))
+ fromlayers, tolayers,
+ interp, interp_data))
{
/* We handle specific source selection cases here. */
return false;
@@ -859,7 +869,7 @@ static bool data_transfer_layersmapping_generate(
dm_src->getNumEdges(dm_src),
dm_dst ? dm_dst->getNumEdges(dm_dst) : me_dst->totedge,
elem_size, data_size, data_offset, data_flag,
- data_transfer_interp_char);
+ data_transfer_interp_char, interp_data);
}
return true;
}
@@ -888,7 +898,7 @@ static bool data_transfer_layersmapping_generate(
dm_src->getNumEdges(dm_src),
dm_dst ? dm_dst->getNumEdges(dm_dst) : me_dst->totedge,
elem_size, data_size, data_offset, data_flag,
- data_transfer_interp_char);
+ data_transfer_interp_char, interp_data);
}
return true;
}
@@ -904,7 +914,7 @@ static bool data_transfer_layersmapping_generate(
dm_dst ? dm_dst->getEdgeArray(dm_dst) : me_dst->medge,
dm_src->getNumEdges(dm_src),
dm_dst ? dm_dst->getNumEdges(dm_dst) : me_dst->totedge,
- elem_size, data_size, data_offset, data_flag, NULL);
+ elem_size, data_size, data_offset, data_flag, NULL, interp_data);
return true;
}
else {
@@ -918,6 +928,8 @@ static bool data_transfer_layersmapping_generate(
else if (cddata_type == CD_FAKE_LNOR) {
/* Preprocess should have generated it, Postprocess will convert it back to CD_CUSTOMLOOPNORMAL. */
cddata_type = CD_NORMAL;
+ interp_data = space_transform;
+ interp = customdata_data_transfer_interp_normal_normals;
}
if (!(cddata_type & CD_FAKE)) {
@@ -927,7 +939,8 @@ static bool data_transfer_layersmapping_generate(
if (!data_transfer_layersmapping_cdlayers(
r_map, cddata_type, mix_mode, mix_factor, mix_weights,
num_elem_dst, use_create, use_delete, cd_src, cd_dst, dm_dst != NULL,
- fromlayers, tolayers))
+ fromlayers, tolayers,
+ interp, interp_data))
{
/* We handle specific source selection cases here. */
return false;
@@ -950,7 +963,8 @@ static bool data_transfer_layersmapping_generate(
if (!data_transfer_layersmapping_cdlayers(
r_map, cddata_type, mix_mode, mix_factor, mix_weights,
num_elem_dst, use_create, use_delete, cd_src, cd_dst, dm_dst != NULL,
- fromlayers, tolayers))
+ fromlayers, tolayers,
+ interp, interp_data))
{
/* We handle specific source selection cases here. */
return false;
@@ -969,7 +983,7 @@ static bool data_transfer_layersmapping_generate(
dm_dst ? dm_dst->getPolyArray(dm_dst) : me_dst->mpoly,
dm_src->getNumPolys(dm_src),
dm_dst ? dm_dst->getNumPolys(dm_dst) : me_dst->totpoly,
- elem_size, data_size, data_offset, data_flag, NULL);
+ elem_size, data_size, data_offset, data_flag, NULL, interp_data);
return true;
}
else {
@@ -1035,28 +1049,28 @@ void BKE_object_data_transfer_layout(
data_transfer_layersmapping_generate(
NULL, ob_src, ob_dst, dm_src, NULL, me_dst, ME_VERT, cddata_type, 0, 0.0f, NULL,
- num_elem_dst, use_create, use_delete, fromlayers, tolayers);
+ num_elem_dst, use_create, use_delete, fromlayers, tolayers, NULL);
}
if (DT_DATATYPE_IS_EDGE(dtdata_type)) {
const int num_elem_dst = me_dst->totedge;
data_transfer_layersmapping_generate(
NULL, ob_src, ob_dst, dm_src, NULL, me_dst, ME_EDGE, cddata_type, 0, 0.0f, NULL,
- num_elem_dst, use_create, use_delete, fromlayers, tolayers);
+ num_elem_dst, use_create, use_delete, fromlayers, tolayers, NULL);
}
if (DT_DATATYPE_IS_LOOP(dtdata_type)) {
const int num_elem_dst = me_dst->totloop;
data_transfer_layersmapping_generate(
NULL, ob_src, ob_dst, dm_src, NULL, me_dst, ME_LOOP, cddata_type, 0, 0.0f, NULL,
- num_elem_dst, use_create, use_delete, fromlayers, tolayers);
+ num_elem_dst, use_create, use_delete, fromlayers, tolayers, NULL);
}
if (DT_DATATYPE_IS_POLY(dtdata_type)) {
const int num_elem_dst = me_dst->totpoly;
data_transfer_layersmapping_generate(
NULL, ob_src, ob_dst, dm_src, NULL, me_dst, ME_POLY, cddata_type, 0, 0.0f, NULL,
- num_elem_dst, use_create, use_delete, fromlayers, tolayers);
+ num_elem_dst, use_create, use_delete, fromlayers, tolayers, NULL);
}
}
}
@@ -1198,7 +1212,7 @@ bool BKE_object_data_transfer_dm(
if (data_transfer_layersmapping_generate(
&lay_map, ob_src, ob_dst, dm_src, dm_dst, me_dst, ME_VERT,
cddata_type, mix_mode, mix_factor, weights[VDATA],
- num_verts_dst, use_create, use_delete, fromlayers, tolayers))
+ num_verts_dst, use_create, use_delete, fromlayers, tolayers, space_transform))
{
CustomDataTransferLayerMap *lay_mapit;
@@ -1249,7 +1263,7 @@ bool BKE_object_data_transfer_dm(
if (data_transfer_layersmapping_generate(
&lay_map, ob_src, ob_dst, dm_src, dm_dst, me_dst, ME_EDGE,
cddata_type, mix_mode, mix_factor, weights[EDATA],
- num_edges_dst, use_create, use_delete, fromlayers, tolayers))
+ num_edges_dst, use_create, use_delete, fromlayers, tolayers, space_transform))
{
CustomDataTransferLayerMap *lay_mapit;
@@ -1312,7 +1326,7 @@ bool BKE_object_data_transfer_dm(
if (data_transfer_layersmapping_generate(
&lay_map, ob_src, ob_dst, dm_src, dm_dst, me_dst, ME_LOOP,
cddata_type, mix_mode, mix_factor, weights[LDATA],
- num_loops_dst, use_create, use_delete, fromlayers, tolayers))
+ num_loops_dst, use_create, use_delete, fromlayers, tolayers, space_transform))
{
CustomDataTransferLayerMap *lay_mapit;
@@ -1367,7 +1381,7 @@ bool BKE_object_data_transfer_dm(
if (data_transfer_layersmapping_generate(
&lay_map, ob_src, ob_dst, dm_src, dm_dst, me_dst, ME_POLY,
cddata_type, mix_mode, mix_factor, weights[PDATA],
- num_polys_dst, use_create, use_delete, fromlayers, tolayers))
+ num_polys_dst, use_create, use_delete, fromlayers, tolayers, space_transform))
{
CustomDataTransferLayerMap *lay_mapit;
diff --git a/source/blender/blenkernel/intern/data_transfer_intern.h b/source/blender/blenkernel/intern/data_transfer_intern.h
index 501b749b464..352eedc6ec2 100644
--- a/source/blender/blenkernel/intern/data_transfer_intern.h
+++ b/source/blender/blenkernel/intern/data_transfer_intern.h
@@ -45,7 +45,7 @@ void data_transfer_layersmapping_add_item(
const float mix_factor, const float *mix_weights,
const void *data_src, void *data_dst, const int data_src_n, const int data_dst_n,
const size_t elem_size, const size_t data_size, const size_t data_offset, const uint64_t data_flag,
- cd_datatransfer_interp interp);
+ cd_datatransfer_interp interp, void *interp_data);
/* Type-specific. */
@@ -55,4 +55,10 @@ bool data_transfer_layersmapping_vgroups(
struct Object *ob_src, struct Object *ob_dst, struct CustomData *cd_src, struct CustomData *cd_dst,
const bool use_dupref_dst, const int fromlayers, const int tolayers);
+/* Defined in customdata.c */
+void customdata_data_transfer_interp_normal_normals(
+ const CustomDataTransferLayerMap *laymap, void *data_dst,
+ const void **sources, const float *weights, const int count,
+ const float mix_factor);
+
#endif /* __DATA_TRANSFER_INTERN_H__ */
diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c
index 6670c3359d7..f904369ae97 100644
--- a/source/blender/blenkernel/intern/deform.c
+++ b/source/blender/blenkernel/intern/deform.c
@@ -1163,7 +1163,7 @@ static bool data_transfer_layersmapping_vgroups_multisrc_to_dst(
}
data_transfer_layersmapping_add_item(r_map, CD_FAKE_MDEFORMVERT, mix_mode, mix_factor, mix_weights,
data_src, data_dst, idx_src, idx_src,
- elem_size, 0, 0, 0, vgroups_datatransfer_interp);
+ elem_size, 0, 0, 0, vgroups_datatransfer_interp, NULL);
}
}
break;
@@ -1211,7 +1211,7 @@ static bool data_transfer_layersmapping_vgroups_multisrc_to_dst(
data_transfer_layersmapping_add_item(
r_map, CD_FAKE_MDEFORMVERT, mix_mode, mix_factor, mix_weights,
data_src, data_dst, idx_src, idx_dst,
- elem_size, 0, 0, 0, vgroups_datatransfer_interp);
+ elem_size, 0, 0, 0, vgroups_datatransfer_interp, NULL);
}
}
break;
@@ -1317,7 +1317,7 @@ bool data_transfer_layersmapping_vgroups(
data_transfer_layersmapping_add_item(r_map, CD_FAKE_MDEFORMVERT, mix_mode, mix_factor, mix_weights,
data_src, data_dst, idx_src, idx_dst,
- elem_size, 0, 0, 0, vgroups_datatransfer_interp);
+ elem_size, 0, 0, 0, vgroups_datatransfer_interp, NULL);
}
}
else {
diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c
index 62491f1ff6e..42b6b311dff 100644
--- a/source/blender/blenkernel/intern/depsgraph.c
+++ b/source/blender/blenkernel/intern/depsgraph.c
@@ -513,7 +513,6 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Main *bmain, Sc
}
/* also build a custom data mask for dependencies that need certain layers */
- node->customdata_mask = 0;
if (ob->type == OB_ARMATURE) {
if (ob->pose) {
@@ -1143,9 +1142,12 @@ void dag_add_relation(DagForest *forest, DagNode *fob1, DagNode *fob2, short rel
if ((rel & DAG_RL_DATA_DATA) != 0) {
if (fob1->type == ID_OB) {
if ((fob1->eval_flags & DAG_EVAL_NEED_CPU) == 0) {
- Object *object = fob1->ob;
- /* Make sure object has all the data on CPU. */
- object->recalc |= OB_RECALC_DATA;
+ Object *ob2 = fob2->ob;
+ if (ob2->recalc & OB_RECALC_ALL) {
+ /* Make sure object has all the data on CPU. */
+ Object *ob1 = fob1->ob;
+ ob1->recalc |= OB_RECALC_DATA;
+ }
fob1->eval_flags |= DAG_EVAL_NEED_CPU;
}
}
@@ -1349,16 +1351,32 @@ void graph_print_adj_list(DagForest *dag)
* to do their own updates based on changes... */
static void (*EditorsUpdateIDCb)(Main *bmain, ID *id) = NULL;
static void (*EditorsUpdateSceneCb)(Main *bmain, Scene *scene, int updated) = NULL;
+static void (*EditorsUpdateScenePreCb)(Main *bmain, Scene *scene, bool time) = NULL;
-void DAG_editors_update_cb(void (*id_func)(Main *bmain, ID *id), void (*scene_func)(Main *bmain, Scene *scene, int updated))
+void DAG_editors_update_cb(void (*id_func)(Main *bmain, ID *id),
+ void (*scene_func)(Main *bmain, Scene *scene, int updated),
+ void (*scene_pre_func)(Main *bmain, Scene *scene, bool time))
{
if (DEG_depsgraph_use_legacy()) {
EditorsUpdateIDCb = id_func;
EditorsUpdateSceneCb = scene_func;
+ EditorsUpdateScenePreCb = scene_pre_func;
}
else {
/* New dependency graph. */
- DEG_editors_set_update_cb(id_func, scene_func);
+ DEG_editors_set_update_cb(id_func, scene_func, scene_pre_func);
+ }
+}
+
+void DAG_editors_update_pre(Main *bmain, Scene *scene, bool time)
+{
+ if (DEG_depsgraph_use_legacy()) {
+ if (EditorsUpdateScenePreCb != NULL) {
+ EditorsUpdateScenePreCb(bmain, scene, time);
+ }
+ }
+ else {
+ DEG_editors_update_pre(bmain, scene, time);
}
}
@@ -1428,7 +1446,7 @@ static void dag_scene_free(Scene *sce)
}
}
-/* Chech whether object data needs to be evaluated before it
+/* Check whether object data needs to be evaluated before it
* might be used by others.
*
* Means that mesh object needs to have proper derivedFinal,
@@ -1640,7 +1658,7 @@ static void dag_scene_build(Main *bmain, Scene *sce)
/* temporal...? */
sce->recalc |= SCE_PRV_CHANGED; /* test for 3d preview */
- /* Make sure that new dependencies which came from invisble layers
+ /* Make sure that new dependencies which came from invisible layers
* are tagged for update (if they're needed for objects which were
* tagged for update).
*/
@@ -2000,25 +2018,50 @@ void DAG_scene_flush_update(Main *bmain, Scene *sce, unsigned int lay, const sho
dag_tag_renderlayers(sce, lay);
}
-static int object_modifiers_use_time(Object *ob)
+static bool modifier_nlastrips_use_time(ListBase *strips)
+{
+ NlaStrip *strip;
+
+ if (strips) {
+ for (strip = strips->first; strip; strip = strip->next) {
+ if (modifier_nlastrips_use_time(&strip->strips)) {
+ return true;
+ }
+ else if (strip->act) {
+ FCurve *fcu;
+
+ for (fcu = strip->act->curves.first; fcu; fcu = fcu->next) {
+ if (fcu->rna_path && strstr(fcu->rna_path, "modifiers["))
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+static bool object_modifiers_use_time(Object *ob)
{
ModifierData *md;
/* check if a modifier in modifier stack needs time input */
- for (md = ob->modifiers.first; md; md = md->next)
+ for (md = ob->modifiers.first; md; md = md->next) {
if (modifier_dependsOnTime(md))
- return 1;
+ return true;
+ }
/* check whether any modifiers are animated */
if (ob->adt) {
AnimData *adt = ob->adt;
+ NlaTrack *nlt;
FCurve *fcu;
/* action - check for F-Curves with paths containing 'modifiers[' */
if (adt->action) {
for (fcu = adt->action->curves.first; fcu; fcu = fcu->next) {
if (fcu->rna_path && strstr(fcu->rna_path, "modifiers["))
- return 1;
+ return true;
}
}
@@ -2030,14 +2073,17 @@ static int object_modifiers_use_time(Object *ob)
*/
for (fcu = adt->drivers.first; fcu; fcu = fcu->next) {
if (fcu->rna_path && strstr(fcu->rna_path, "modifiers["))
- return 1;
+ return true;
}
- /* XXX: also, should check NLA strips, though for now assume that nobody uses
- * that and we can omit that for performance reasons... */
+ /* Also check NLA Strips... [#T45938] */
+ for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) {
+ if (modifier_nlastrips_use_time(&nlt->strips))
+ return true;
+ }
}
- return 0;
+ return false;
}
static short animdata_use_time(AnimData *adt)
@@ -2474,7 +2520,8 @@ void DAG_on_visible_update(Main *bmain, const bool do_time)
}
}
-static void dag_id_flush_update__isDependentTexture(void *userData, Object *UNUSED(ob), ID **idpoin)
+static void dag_id_flush_update__isDependentTexture(
+ void *userData, Object *UNUSED(ob), ID **idpoin, int UNUSED(cd_flag))
{
struct { ID *id; bool is_dependent; } *data = userData;
@@ -3485,9 +3532,15 @@ void DAG_exit(void)
/* ************************ API *********************** */
void DAG_editors_update_cb(DEG_EditorUpdateIDCb id_func,
- DEG_EditorUpdateSceneCb scene_func)
+ DEG_EditorUpdateSceneCb scene_func,
+ DEG_EditorUpdateScenePreCb scene_func_pre)
+{
+ DEG_editors_set_update_cb(id_func, scene_func, scene_func_pre);
+}
+
+void DAG_editors_update_pre(Main *bmain, Scene *scene, bool time)
{
- DEG_editors_set_update_cb(id_func, scene_func);
+ DEG_editors_update_pre(bmain, scene, time);
}
/* Tag all relations for update. */
diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c
index 3213b59b92d..a2d555d0918 100644
--- a/source/blender/blenkernel/intern/displist.c
+++ b/source/blender/blenkernel/intern/displist.c
@@ -1521,7 +1521,7 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba
BKE_curve_bevelList_free(&ob->curve_cache->bev);
- /* We only re-evlauate path if evaluation is not happening for orco.
+ /* We only re-evaluate path if evaluation is not happening for orco.
* If the calculation happens for orco, we should never free data which
* was needed before and only not needed for orco calculation.
*/
@@ -1600,7 +1600,7 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba
float bottom_no[3] = {0.0f};
float top_no[3] = {0.0f};
float firstblend = 0.0f, lastblend = 0.0f;
- int i, start, steps;
+ int i, start, steps = 0;
if (nu->flagu & CU_NURB_CYCLIC) {
calc_bevfac_mapping_default(bl,
diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c
index 7f1d2e877ed..f3ce988ee17 100644
--- a/source/blender/blenkernel/intern/dynamicpaint.c
+++ b/source/blender/blenkernel/intern/dynamicpaint.c
@@ -1773,8 +1773,8 @@ static DerivedMesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd,
}
else {
col[l_index].r =
- col[l_index].g =
- col[l_index].b = FTOCHAR(pPoint[v_index].wetness);
+ col[l_index].g =
+ col[l_index].b = FTOCHAR(pPoint[v_index].wetness);
col[l_index].a = 255;
}
}
@@ -2085,7 +2085,7 @@ static int dynamicPaint_findNeighbourPixel(PaintUVPoint *tempPoints, DerivedMesh
int i, edge1_index, edge2_index,
e1_index, e2_index, target_tri;
float closest_point[2], lambda, dir_vec[2];
- int target_uv1, target_uv2, final_pixel[2], final_index;
+ int target_uv1 = 0, target_uv2 = 0, final_pixel[2], final_index;
const float *s_uv1, *s_uv2, *t_uv1, *t_uv2;
@@ -3416,7 +3416,7 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface,
{
float proxDist = -1.0f;
float hitCo[3] = {0.0f, 0.0f, 0.0f};
- int tri;
+ int tri = 0;
/* if inverse prox and no hit found, skip this sample */
if (inner_proximity && !hit_found) continue;
diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c
index f463cab1a10..88ae279050c 100644
--- a/source/blender/blenkernel/intern/editderivedmesh.c
+++ b/source/blender/blenkernel/intern/editderivedmesh.c
@@ -397,7 +397,7 @@ static void emDM_calcLoopTangents(DerivedMesh *dm)
mesh2tangent.precomputedLoopNormals = tlnors;
mesh2tangent.looptris = em->looptris;
mesh2tangent.cd_loop_uv_offset = cd_loop_uv_offset;
- mesh2tangent.orco = orco;
+ mesh2tangent.orco = (const float (*)[3])orco;
mesh2tangent.tangent = tangent;
mesh2tangent.numTessFaces = totface;
@@ -1248,7 +1248,7 @@ static void emdm_pass_attrib_vertex_glsl(const DMVertexAttribs *attribs, const B
GLubyte col[4];
if (attribs->mcol[i].em_offset != -1) {
const MLoopCol *cp = BM_ELEM_CD_GET_VOID_P(loop, attribs->mcol[i].em_offset);
- copy_v4_v4_char((char *)col, &cp->r);
+ copy_v4_v4_uchar(col, &cp->r);
}
else {
col[0] = 0; col[1] = 0; col[2] = 0; col[3] = 0;
@@ -2170,8 +2170,8 @@ static void statvis_calc_overhang(
rgb_float_to_uchar(r_face_colors[index], fcol);
}
else {
- unsigned char *fallback = is_max ? col_fallback_max : col_fallback;
- copy_v4_v4_char((char *)r_face_colors[index], (const char *)fallback);
+ const unsigned char *fallback = is_max ? col_fallback_max : col_fallback;
+ copy_v4_v4_uchar(r_face_colors[index], fallback);
}
}
}
@@ -2210,7 +2210,7 @@ static void statvis_calc_thickness(
struct BMLoop *(*looptris)[3] = em->looptris;
/* fallback */
- const char col_fallback[4] = {64, 64, 64, 255};
+ const unsigned char col_fallback[4] = {64, 64, 64, 255};
struct BMBVHTree *bmtree;
@@ -2305,7 +2305,7 @@ static void statvis_calc_thickness(
rgb_float_to_uchar(r_face_colors[i], fcol);
}
else {
- copy_v4_v4_char((char *)r_face_colors[i], (const char *)col_fallback);
+ copy_v4_v4_uchar(r_face_colors[i], col_fallback);
}
}
}
@@ -2357,7 +2357,7 @@ static void statvis_calc_intersect(
index = BM_elem_index_get(f_hit);
- copy_v3_v3_char((char *)r_face_colors[index], (const char *)col);
+ copy_v3_v3_uchar(r_face_colors[index], col);
}
}
MEM_freeN(overlap);
@@ -2382,7 +2382,7 @@ static void statvis_calc_distort(
const float minmax_irange = 1.0f / (max - min);
/* fallback */
- const char col_fallback[4] = {64, 64, 64, 255};
+ const unsigned char col_fallback[4] = {64, 64, 64, 255};
/* now convert into global space */
BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, index) {
@@ -2431,7 +2431,7 @@ static void statvis_calc_distort(
rgb_float_to_uchar(r_face_colors[index], fcol);
}
else {
- copy_v4_v4_char((char *)r_face_colors[index], (const char *)col_fallback);
+ copy_v4_v4_uchar(r_face_colors[index], col_fallback);
}
}
}
@@ -2453,7 +2453,7 @@ static void statvis_calc_sharp(
int i;
/* fallback */
- const char col_fallback[4] = {64, 64, 64, 255};
+ const unsigned char col_fallback[4] = {64, 64, 64, 255};
(void)vertexCos; /* TODO */
@@ -2481,7 +2481,7 @@ static void statvis_calc_sharp(
rgb_float_to_uchar(r_vert_colors[i], fcol);
}
else {
- copy_v4_v4_char((char *)r_vert_colors[i], (const char *)col_fallback);
+ copy_v4_v4_uchar(r_vert_colors[i], col_fallback);
}
}
}
diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c
index bf53acc1d95..e66fa86c4b1 100644
--- a/source/blender/blenkernel/intern/effect.c
+++ b/source/blender/blenkernel/intern/effect.c
@@ -687,10 +687,10 @@ int get_effector_data(EffectorCache *eff, EffectorData *efd, EffectedPoint *poin
}
static void get_effector_tot(EffectorCache *eff, EffectorData *efd, EffectedPoint *point, int *tot, int *p, int *step)
{
- if (eff->pd->shape == PFIELD_SHAPE_POINTS) {
- efd->index = p;
+ *p = 0;
+ efd->index = p;
- *p = 0;
+ if (eff->pd->shape == PFIELD_SHAPE_POINTS) {
*tot = eff->ob->derivedFinal ? eff->ob->derivedFinal->numVertData : 1;
if (*tot && eff->pd->forcefield == PFIELD_HARMONIC && point->index >= 0) {
@@ -699,9 +699,6 @@ static void get_effector_tot(EffectorCache *eff, EffectorData *efd, EffectedPoin
}
}
else if (eff->psys) {
- efd->index = p;
-
- *p = 0;
*tot = eff->psys->totpart;
if (eff->pd->forcefield == PFIELD_CHARGE) {
@@ -727,7 +724,6 @@ static void get_effector_tot(EffectorCache *eff, EffectorData *efd, EffectedPoin
}
}
else {
- *p = 0;
*tot = 1;
}
}
diff --git a/source/blender/blenkernel/intern/fmodifier.c b/source/blender/blenkernel/intern/fmodifier.c
index 2305ae89abd..2c301c04100 100644
--- a/source/blender/blenkernel/intern/fmodifier.c
+++ b/source/blender/blenkernel/intern/fmodifier.c
@@ -103,8 +103,8 @@ static FModifierTypeInfo FMI_MODNAME = {
/* Generators available:
* 1) simple polynomial generator:
- * - Exanded form - (y = C[0]*(x^(n)) + C[1]*(x^(n-1)) + ... + C[n])
- * - Factorized form - (y = (C[0][0]*x + C[0][1]) * (C[1][0]*x + C[1][1]) * ... * (C[n][0]*x + C[n][1]))
+ * - Expanded form - (y = C[0]*(x^(n)) + C[1]*(x^(n-1)) + ... + C[n])
+ * - Factorized form - (y = (C[0][0]*x + C[0][1]) * (C[1][0]*x + C[1][1]) * ... * (C[n][0]*x + C[n][1]))
*/
static void fcm_generator_free(FModifier *fcm)
@@ -849,7 +849,7 @@ static FModifierTypeInfo FMI_FILTER = {
NULL, /* copy data */
NULL, /* new data */
NULL /*fcm_filter_verify*/, /* verify */
- NULL, /* evlauate time */
+ NULL, /* evaluate time */
fcm_filter_evaluate, /* evaluate */
NULL, /* evaluate time with storage */
NULL /* evaluate with storage */
diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c
index 2adf8ebc615..b12e16d9502 100644
--- a/source/blender/blenkernel/intern/font.c
+++ b/source/blender/blenkernel/intern/font.c
@@ -203,7 +203,27 @@ static VFontData *vfont_get_data(Main *bmain, VFont *vfont)
return vfont->data;
}
-VFont *BKE_vfont_load(Main *bmain, const char *name)
+/* Bad naming actually in this case... */
+void BKE_vfont_init(VFont *vfont)
+{
+ PackedFile *pf = get_builtin_packedfile();
+
+ if (pf) {
+ VFontData *vfd;
+
+ vfd = BLI_vfontdata_from_freetypefont(pf);
+ if (vfd) {
+ vfont->data = vfd;
+
+ BLI_strncpy(vfont->name, FO_BUILTIN_NAME, sizeof(vfont->name));
+ }
+
+ /* Free the packed file */
+ freePackedFile(pf);
+ }
+}
+
+VFont *BKE_vfont_load(Main *bmain, const char *filepath)
{
char filename[FILE_MAXFILE];
VFont *vfont = NULL;
@@ -211,16 +231,16 @@ VFont *BKE_vfont_load(Main *bmain, const char *name)
PackedFile *temp_pf = NULL;
bool is_builtin;
- if (STREQ(name, FO_BUILTIN_NAME)) {
- BLI_strncpy(filename, name, sizeof(filename));
+ if (STREQ(filepath, FO_BUILTIN_NAME)) {
+ BLI_strncpy(filename, filepath, sizeof(filename));
pf = get_builtin_packedfile();
is_builtin = true;
}
else {
- BLI_split_file_part(name, filename, sizeof(filename));
- pf = newPackedFile(NULL, name, bmain->name);
- temp_pf = newPackedFile(NULL, name, bmain->name);
+ BLI_split_file_part(filepath, filename, sizeof(filename));
+ pf = newPackedFile(NULL, filepath, bmain->name);
+ temp_pf = newPackedFile(NULL, filepath, bmain->name);
is_builtin = false;
}
@@ -237,7 +257,7 @@ VFont *BKE_vfont_load(Main *bmain, const char *name)
if (vfd->name[0] != '\0') {
BLI_strncpy(vfont->id.name + 2, vfd->name, sizeof(vfont->id.name) - 2);
}
- BLI_strncpy(vfont->name, name, sizeof(vfont->name));
+ BLI_strncpy(vfont->name, filepath, sizeof(vfont->name));
/* if autopack is on store the packedfile in de font structure */
if (!is_builtin && (G.fileflags & G_AUTOPACK)) {
@@ -259,6 +279,37 @@ VFont *BKE_vfont_load(Main *bmain, const char *name)
return vfont;
}
+VFont *BKE_vfont_load_exists_ex(struct Main *bmain, const char *filepath, bool *r_exists)
+{
+ VFont *vfont;
+ char str[FILE_MAX], strtest[FILE_MAX];
+
+ BLI_strncpy(str, filepath, sizeof(str));
+ BLI_path_abs(str, bmain->name);
+
+ /* first search an identical filepath */
+ for (vfont = bmain->vfont.first; vfont; vfont = vfont->id.next) {
+ BLI_strncpy(strtest, vfont->name, sizeof(vfont->name));
+ BLI_path_abs(strtest, ID_BLEND_PATH(bmain, &vfont->id));
+
+ if (BLI_path_cmp(strtest, str) == 0) {
+ vfont->id.us++; /* officially should not, it doesn't link here! */
+ if (r_exists)
+ *r_exists = true;
+ return vfont;
+ }
+ }
+
+ if (r_exists)
+ *r_exists = false;
+ return BKE_vfont_load(bmain, filepath);
+}
+
+VFont *BKE_vfont_load_exists(struct Main *bmain, const char *filepath)
+{
+ return BKE_vfont_load_exists_ex(bmain, filepath, NULL);
+}
+
static VFont *which_vfont(Curve *cu, CharInfo *info)
{
switch (info->flag & (CU_CHINFO_BOLD | CU_CHINFO_ITALIC)) {
@@ -777,7 +828,7 @@ makebreak:
if ((tb_scale.h != 0.0f) &&
(cu->totbox > (curbox + 1)) &&
- ((-(yof - tb_scale.y)) > (tb_scale.h - (linedist * cu->fsize)) - yof_scale))
+ ((-(yof - tb_scale.y)) > (tb_scale.h - linedist) - yof_scale))
{
maxlen = 0;
curbox++;
diff --git a/source/blender/blenkernel/intern/idcode.c b/source/blender/blenkernel/intern/idcode.c
index cf1eb8838e9..68a741bc3fc 100644
--- a/source/blender/blenkernel/intern/idcode.c
+++ b/source/blender/blenkernel/intern/idcode.c
@@ -103,12 +103,12 @@ static IDType *idtype_from_name(const char *str)
return NULL;
}
-static IDType *idtype_from_code(int code)
+static IDType *idtype_from_code(short idcode)
{
int i = ARRAY_SIZE(idtypes);
while (i--)
- if (code == idtypes[i].code)
+ if (idcode == idtypes[i].code)
return &idtypes[i];
return NULL;
@@ -120,9 +120,9 @@ static IDType *idtype_from_code(int code)
* \param code The code to check.
* \return Boolean, 0 when invalid.
*/
-bool BKE_idcode_is_valid(int code)
+bool BKE_idcode_is_valid(short idcode)
{
- return idtype_from_code(code) ? true : false;
+ return idtype_from_code(idcode) ? true : false;
}
/**
@@ -131,9 +131,9 @@ bool BKE_idcode_is_valid(int code)
* \param code The code to check.
* \return Boolean, 0 when non linkable.
*/
-bool BKE_idcode_is_linkable(int code)
+bool BKE_idcode_is_linkable(short idcode)
{
- IDType *idt = idtype_from_code(code);
+ IDType *idt = idtype_from_code(idcode);
BLI_assert(idt);
return idt ? ((idt->flags & IDTYPE_FLAGS_ISLINKABLE) != 0) : false;
}
@@ -145,9 +145,9 @@ bool BKE_idcode_is_linkable(int code)
* \return A static string representing the name of
* the code.
*/
-const char *BKE_idcode_to_name(int code)
+const char *BKE_idcode_to_name(short idcode)
{
- IDType *idt = idtype_from_code(code);
+ IDType *idt = idtype_from_code(idcode);
BLI_assert(idt);
return idt ? idt->name : NULL;
}
@@ -158,7 +158,7 @@ const char *BKE_idcode_to_name(int code)
* \param name The name to convert.
* \return The code for the name, or 0 if invalid.
*/
-int BKE_idcode_from_name(const char *name)
+short BKE_idcode_from_name(const char *name)
{
IDType *idt = idtype_from_name(name);
BLI_assert(idt);
@@ -168,7 +168,7 @@ int BKE_idcode_from_name(const char *name)
/**
* Convert an idcode into an idfilter (e.g. ID_OB -> FILTER_ID_OB).
*/
-int BKE_idcode_to_idfilter(const int idcode)
+int BKE_idcode_to_idfilter(const short idcode)
{
#define CASE_IDFILTER(_id) case ID_##_id: return FILTER_ID_##_id
@@ -211,7 +211,7 @@ int BKE_idcode_to_idfilter(const int idcode)
/**
* Convert an idfilter into an idcode (e.g. FILTER_ID_OB -> ID_OB).
*/
-int BKE_idcode_from_idfilter(const int idfilter)
+short BKE_idcode_from_idfilter(const int idfilter)
{
#define CASE_IDFILTER(_id) case FILTER_ID_##_id: return ID_##_id
@@ -258,9 +258,9 @@ int BKE_idcode_from_idfilter(const int idfilter)
* \return A static string representing the name of
* the code.
*/
-const char *BKE_idcode_to_name_plural(int code)
+const char *BKE_idcode_to_name_plural(short idcode)
{
- IDType *idt = idtype_from_code(code);
+ IDType *idt = idtype_from_code(idcode);
BLI_assert(idt);
return idt ? idt->plural : NULL;
}
@@ -271,9 +271,9 @@ const char *BKE_idcode_to_name_plural(int code)
* \param code The code to convert.
* \return A static string representing the i18n context of the code.
*/
-const char *BKE_idcode_to_translation_context(int code)
+const char *BKE_idcode_to_translation_context(short idcode)
{
- IDType *idt = idtype_from_code(code);
+ IDType *idt = idtype_from_code(idcode);
BLI_assert(idt);
return idt ? idt->i18n_context : BLT_I18NCONTEXT_DEFAULT;
}
@@ -284,7 +284,7 @@ const char *BKE_idcode_to_translation_context(int code)
* \param index start as 0.
* \return the code, 0 when all codes have been returned.
*/
-int BKE_idcode_iter_step(int *index)
+short BKE_idcode_iter_step(int *index)
{
return (*index < ARRAY_SIZE(idtypes)) ? idtypes[(*index)++].code : 0;
}
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index ef760f2da26..3ffd03dc3be 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -280,14 +280,9 @@ void BKE_image_free_packedfiles(Image *ima)
image_free_packedfiles(ima);
}
-static void image_free_views(Image *ima)
-{
- BLI_freelistN(&ima->views);
-}
-
void BKE_image_free_views(Image *image)
{
- image_free_views(image);
+ BLI_freelistN(&image->views);
}
static void image_free_anims(Image *ima)
@@ -350,7 +345,7 @@ void BKE_image_free(Image *ima)
}
}
- image_free_views(ima);
+ BKE_image_free_views(ima);
MEM_freeN(ima->stereo3d_format);
}
@@ -704,8 +699,7 @@ void BKE_image_alpha_mode_from_extension(Image *image)
Image *BKE_image_load(Main *bmain, const char *filepath)
{
Image *ima;
- int file, len;
- const char *libname;
+ int file;
char str[FILE_MAX];
BLI_strncpy(str, filepath, sizeof(str));
@@ -717,13 +711,7 @@ Image *BKE_image_load(Main *bmain, const char *filepath)
return NULL;
close(file);
- /* create a short library name */
- len = strlen(filepath);
-
- while (len > 0 && filepath[len - 1] != '/' && filepath[len - 1] != '\\') len--;
- libname = filepath + len;
-
- ima = image_alloc(bmain, libname, IMA_SRC_FILE, IMA_TYPE_IMAGE);
+ ima = image_alloc(bmain, BLI_path_basename(filepath), IMA_SRC_FILE, IMA_TYPE_IMAGE);
BLI_strncpy(ima->name, filepath, sizeof(ima->name));
if (BLI_testextensie_array(filepath, imb_ext_movie))
@@ -746,7 +734,7 @@ Image *BKE_image_load_exists_ex(const char *filepath, bool *r_exists)
BLI_strncpy(str, filepath, sizeof(str));
BLI_path_abs(str, G.main->name);
- /* first search an identical image */
+ /* first search an identical filepath */
for (ima = G.main->image.first; ima; ima = ima->id.next) {
if (ima->source != IMA_SRC_VIEWER && ima->source != IMA_SRC_GENERATED) {
BLI_strncpy(strtest, ima->name, sizeof(ima->name));
@@ -873,8 +861,6 @@ Image *BKE_image_add_generated(Main *bmain, unsigned int width, unsigned int hei
}
ima->ok = IMA_OK_LOADED;
- if (stereo3d)
- ima->flag |= IMA_IS_STEREO | IMA_IS_MULTIVIEW;
}
return ima;
@@ -964,7 +950,7 @@ void BKE_image_memorypack(Image *ima)
{
ImBuf *ibuf;
- if ((ima->flag & IMA_IS_MULTIVIEW)) {
+ if (BKE_image_is_multiview(ima)) {
image_memorypack_multiview(ima);
return;
}
@@ -1872,12 +1858,23 @@ void BKE_image_stamp_buf(
struct ColorManagedDisplay *display;
const char *display_device;
+ /* vars for calculating wordwrap */
+ struct {
+ struct ResultBLF info;
+ rctf rect;
+ } wrap;
+
/* this could be an argument if we want to operate on non linear float imbuf's
* for now though this is only used for renders which use scene settings */
#define TEXT_SIZE_CHECK(str, w, h) \
((str[0]) && ((void)(h = h_fixed), (w = BLF_width(mono, str, sizeof(str)))))
+ /* must enable BLF_WORD_WRAP before using */
+#define TEXT_SIZE_CHECK_WORD_WRAP(str, w, h) \
+ ((str[0]) && (BLF_boundbox_ex(mono, str, sizeof(str), &wrap.rect, &wrap.info), \
+ (void)(h = h_fixed * wrap.info.lines), (w = BLI_rctf_size_x(&wrap.rect))))
+
#define BUFF_MARGIN_X 2
#define BUFF_MARGIN_Y 1
@@ -1895,6 +1892,7 @@ void BKE_image_stamp_buf(
/* set before return */
BLF_size(mono, scene->r.stamp_font_id, 72);
+ BLF_wordwrap(mono, width - (BUFF_MARGIN_X * 2));
BLF_buffer(mono, rectf, rect, width, height, channels, display);
BLF_buffer_col(mono, scene->r.fg_stamp[0], scene->r.fg_stamp[1], scene->r.fg_stamp[2], 1.0);
@@ -1917,14 +1915,14 @@ void BKE_image_stamp_buf(
/* and draw the text. */
BLF_position(mono, x, y + y_ofs, 0.0);
- BLF_draw_buffer(mono, stamp_data.file);
+ BLF_draw_buffer(mono, stamp_data.file, BLF_DRAW_STR_DUMMY_MAX);
/* the extra pixel for background. */
y -= BUFF_MARGIN_Y * 2;
}
/* Top left corner, below File */
- if (TEXT_SIZE_CHECK(stamp_data.note, w, h)) {
+ if (TEXT_SIZE_CHECK(stamp_data.date, w, h)) {
y -= h;
/* and space for background. */
@@ -1932,14 +1930,14 @@ void BKE_image_stamp_buf(
0, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y);
BLF_position(mono, x, y + y_ofs, 0.0);
- BLF_draw_buffer(mono, stamp_data.note);
+ BLF_draw_buffer(mono, stamp_data.date, BLF_DRAW_STR_DUMMY_MAX);
/* the extra pixel for background. */
y -= BUFF_MARGIN_Y * 2;
}
- /* Top left corner, below File (or Note) */
- if (TEXT_SIZE_CHECK(stamp_data.date, w, h)) {
+ /* Top left corner, below File, Date */
+ if (TEXT_SIZE_CHECK(stamp_data.rendertime, w, h)) {
y -= h;
/* and space for background. */
@@ -1947,23 +1945,25 @@ void BKE_image_stamp_buf(
0, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y);
BLF_position(mono, x, y + y_ofs, 0.0);
- BLF_draw_buffer(mono, stamp_data.date);
+ BLF_draw_buffer(mono, stamp_data.rendertime, BLF_DRAW_STR_DUMMY_MAX);
/* the extra pixel for background. */
y -= BUFF_MARGIN_Y * 2;
}
- /* Top left corner, below File, Date or Note */
- if (TEXT_SIZE_CHECK(stamp_data.rendertime, w, h)) {
+ /* Top left corner, below File, Date, Rendertime */
+ BLF_enable(mono, BLF_WORD_WRAP);
+ if (TEXT_SIZE_CHECK_WORD_WRAP(stamp_data.note, w, h)) {
y -= h;
/* and space for background. */
buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display,
0, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y);
- BLF_position(mono, x, y + y_ofs, 0.0);
- BLF_draw_buffer(mono, stamp_data.rendertime);
+ BLF_position(mono, x, y + y_ofs + (h - h_fixed), 0.0);
+ BLF_draw_buffer(mono, stamp_data.note, BLF_DRAW_STR_DUMMY_MAX);
}
+ BLF_disable(mono, BLF_WORD_WRAP);
x = 0;
y = 0;
@@ -1977,7 +1977,7 @@ void BKE_image_stamp_buf(
/* and pad the text. */
BLF_position(mono, x, y + y_ofs, 0.0);
- BLF_draw_buffer(mono, stamp_data.marker);
+ BLF_draw_buffer(mono, stamp_data.marker, BLF_DRAW_STR_DUMMY_MAX);
/* space width. */
x += w + pad;
@@ -1992,7 +1992,7 @@ void BKE_image_stamp_buf(
/* and pad the text. */
BLF_position(mono, x, y + y_ofs, 0.0);
- BLF_draw_buffer(mono, stamp_data.time);
+ BLF_draw_buffer(mono, stamp_data.time, BLF_DRAW_STR_DUMMY_MAX);
/* space width. */
x += w + pad;
@@ -2006,7 +2006,7 @@ void BKE_image_stamp_buf(
/* and pad the text. */
BLF_position(mono, x, y + y_ofs, 0.0);
- BLF_draw_buffer(mono, stamp_data.frame);
+ BLF_draw_buffer(mono, stamp_data.frame, BLF_DRAW_STR_DUMMY_MAX);
/* space width. */
x += w + pad;
@@ -2018,7 +2018,7 @@ void BKE_image_stamp_buf(
buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display,
x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y);
BLF_position(mono, x, y + y_ofs, 0.0);
- BLF_draw_buffer(mono, stamp_data.camera);
+ BLF_draw_buffer(mono, stamp_data.camera, BLF_DRAW_STR_DUMMY_MAX);
/* space width. */
x += w + pad;
@@ -2030,7 +2030,7 @@ void BKE_image_stamp_buf(
buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display,
x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y);
BLF_position(mono, x, y + y_ofs, 0.0);
- BLF_draw_buffer(mono, stamp_data.cameralens);
+ BLF_draw_buffer(mono, stamp_data.cameralens, BLF_DRAW_STR_DUMMY_MAX);
}
if (TEXT_SIZE_CHECK(stamp_data.scene, w, h)) {
@@ -2044,7 +2044,7 @@ void BKE_image_stamp_buf(
/* and pad the text. */
BLF_position(mono, x, y + y_ofs, 0.0);
- BLF_draw_buffer(mono, stamp_data.scene);
+ BLF_draw_buffer(mono, stamp_data.scene, BLF_DRAW_STR_DUMMY_MAX);
}
if (TEXT_SIZE_CHECK(stamp_data.strip, w, h)) {
@@ -2058,13 +2058,15 @@ void BKE_image_stamp_buf(
x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y);
BLF_position(mono, x, y + y_ofs, 0.0);
- BLF_draw_buffer(mono, stamp_data.strip);
+ BLF_draw_buffer(mono, stamp_data.strip, BLF_DRAW_STR_DUMMY_MAX);
}
/* cleanup the buffer. */
BLF_buffer(mono, NULL, NULL, 0, 0, 0, NULL);
+ BLF_wordwrap(mono, 0);
#undef TEXT_SIZE_CHECK
+#undef TEXT_SIZE_CHECK_WORD_WRAP
#undef BUFF_MARGIN_X
#undef BUFF_MARGIN_Y
}
@@ -2474,15 +2476,8 @@ void BKE_image_verify_viewer_views(const RenderData *rd, Image *ima, ImageUser *
BLI_lock_thread(LOCK_DRAW_IMAGE);
- if (BKE_scene_multiview_is_stereo3d(rd)) {
- ima->flag |= IMA_IS_STEREO;
- ima->flag |= IMA_IS_MULTIVIEW;
- }
- else {
- ima->flag &= ~IMA_IS_STEREO;
- ima->flag &= ~IMA_IS_MULTIVIEW;
+ if (!BKE_scene_multiview_is_stereo3d(rd))
iuser->flag &= ~IMA_SHOW_STEREO;
- }
/* see if all scene render views are in the image view list */
do_reset = (BKE_scene_multiview_num_views_get(rd) != BLI_listbase_count(&ima->views));
@@ -2528,6 +2523,17 @@ void BKE_image_walk_all_users(const Main *mainp, void *customdata,
if (tex->type == TEX_IMAGE && tex->ima) {
callback(tex->ima, &tex->iuser, customdata);
}
+
+ if (tex->nodetree) {
+ bNode *node;
+ for (node = tex->nodetree->nodes.first; node; node = node->next) {
+ if (node->id && node->type == TEX_NODE_IMAGE) {
+ Image *ima = (Image *)node->id;
+ ImageUser *iuser = node->storage;
+ callback(ima, iuser, customdata);
+ }
+ }
+ }
}
/* image window, compo node users */
@@ -2578,21 +2584,10 @@ static void image_init_imageuser(Image *ima, ImageUser *iuser)
RenderResult *rr = ima->rr;
iuser->multi_index = 0;
- iuser->layer = iuser->view = 0;
- iuser->passtype = SCE_PASS_COMBINED;
-
- if (rr) {
- RenderLayer *rl = rr->layers.first;
-
- if (rl) {
- RenderPass *rp = rl->passes.first;
-
- if (rp)
- iuser->passtype = rp->passtype;
- }
+ iuser->layer = iuser->pass = iuser->view = 0;
+ if (rr)
BKE_image_multilayer_index(rr, iuser);
- }
}
void BKE_image_init_imageuser(Image *ima, ImageUser *iuser)
@@ -2740,6 +2735,52 @@ void BKE_image_signal(Image *ima, ImageUser *iuser, int signal)
}
}
+#define PASSTYPE_UNSET -1
+/* return renderpass for a given pass index and active view */
+/* fallback to available if there are missing passes for active view */
+static RenderPass *image_render_pass_get(RenderLayer *rl, const int pass, const int view, int *r_passindex)
+{
+ RenderPass *rpass_ret = NULL;
+ RenderPass *rpass;
+
+ int rp_index = 0;
+ int rp_passtype = PASSTYPE_UNSET;
+
+ for (rpass = rl->passes.first; rpass; rpass = rpass->next, rp_index++) {
+ if (rp_index == pass) {
+ rpass_ret = rpass;
+ if (view == 0) {
+ /* no multiview or left eye */
+ break;
+ }
+ else {
+ rp_passtype = rpass->passtype;
+ }
+ }
+ /* multiview */
+ else if ((rp_passtype != PASSTYPE_UNSET) &&
+ (rpass->passtype == rp_passtype) &&
+ (rpass->view_id == view))
+ {
+ rpass_ret = rpass;
+ break;
+ }
+ }
+
+ /* fallback to the first pass in the layer */
+ if (rpass_ret == NULL) {
+ rp_index = 0;
+ rpass_ret = rl->passes.first;
+ }
+
+ if (r_passindex) {
+ *r_passindex = (rpass == rpass_ret ? rp_index : pass);
+ }
+
+ return rpass_ret;
+}
+#undef PASSTYPE_UNSET
+
/* if layer or pass changes, we need an index for the imbufs list */
/* note it is called for rendered results, but it doesnt use the index! */
/* and because rendered results use fake layer/passes, don't correct for wrong indices here */
@@ -2759,27 +2800,16 @@ RenderPass *BKE_image_multilayer_index(RenderResult *rr, ImageUser *iuser)
if (RE_HasFakeLayer(rr)) rl_index += 1;
for (rl = rr->layers.first; rl; rl = rl->next, rl_index++) {
- for (rpass = rl->passes.first; rpass; rpass = rpass->next, index++) {
- if (iuser->layer == rl_index &&
- iuser->passtype == rpass->passtype &&
- rv_index == rpass->view_id)
- {
- break;
- }
- }
- if (rpass)
+ if (iuser->layer == rl_index) {
+ int rp_index;
+ rpass = image_render_pass_get(rl, iuser->pass, rv_index, &rp_index);
+ iuser->multi_index = index + rp_index;
break;
+ }
+ else {
+ index += BLI_listbase_count(&rl->passes);
+ }
}
- iuser->multi_index = (rpass ? index : 0);
- }
-
- if (rpass == NULL) {
- rl = rr->layers.first;
- if (rl)
- rpass = rl->passes.first;
-
- if (rpass && iuser)
- iuser->passtype = rpass->passtype;
}
return rpass;
@@ -2788,7 +2818,7 @@ RenderPass *BKE_image_multilayer_index(RenderResult *rr, ImageUser *iuser)
void BKE_image_multiview_index(Image *ima, ImageUser *iuser)
{
if (iuser) {
- bool is_stereo = (ima->flag & IMA_IS_STEREO) && (iuser->flag & IMA_SHOW_STEREO);
+ bool is_stereo = BKE_image_is_stereo(ima) && (iuser->flag & IMA_SHOW_STEREO);
if (is_stereo) {
iuser->multi_index = iuser->multiview_eye;
}
@@ -2821,27 +2851,27 @@ bool BKE_image_is_multilayer(Image *ima)
return false;
}
-static void image_init_multilayer_multiview_flag(Image *ima, RenderResult *rr)
+bool BKE_image_is_multiview(Image *ima)
+{
+ return (BLI_listbase_count_ex(&ima->views, 2) > 1);
+}
+
+bool BKE_image_is_stereo(Image *ima)
+{
+ return BKE_image_is_multiview(ima) &&
+ (BLI_findstring(&ima->views, STEREO_LEFT_NAME, offsetof(ImageView, name)) &&
+ BLI_findstring(&ima->views, STEREO_RIGHT_NAME, offsetof(ImageView, name)));
+}
+
+static void image_init_multilayer_multiview(Image *ima, RenderResult *rr)
{
+ BKE_image_free_views(ima);
if (rr) {
- if (RE_RenderResult_is_stereo(rr)) {
- ima->flag |= IMA_IS_STEREO;
- ima->flag |= IMA_IS_MULTIVIEW;
- }
- else {
- ima->flag &= ~IMA_IS_STEREO;
- if (BLI_listbase_count_ex(&rr->views, 2) > 1)
- ima->flag |= IMA_IS_MULTIVIEW;
- else
- ima->flag &= ~IMA_IS_MULTIVIEW;
- }
- }
- else {
- ima->flag &= ~IMA_IS_STEREO;
- ima->flag &= ~IMA_IS_MULTIVIEW;
+ BLI_duplicatelist(&ima->views, &rr->views);
}
}
+
RenderResult *BKE_image_acquire_renderresult(Scene *scene, Image *ima)
{
RenderResult *rr = NULL;
@@ -2854,8 +2884,8 @@ RenderResult *BKE_image_acquire_renderresult(Scene *scene, Image *ima)
else
rr = ima->renders[ima->render_slot];
- /* set proper multiview flag */
- image_init_multilayer_multiview_flag(ima, rr);
+ /* set proper views */
+ image_init_multilayer_multiview(ima, rr);
}
return rr;
@@ -3013,39 +3043,15 @@ static void image_add_buffer_cb(void *base, const char *str, ImBuf *ibuf, const
}
#endif /* WITH_OPENEXR */
-#ifdef WITH_OPENEXR
-static void image_update_multiview_flags(Image *ima)
-{
- if (BLI_listbase_count_ex(&ima->views, 2) > 1) {
- ima->flag |= IMA_IS_MULTIVIEW;
-
- if (BLI_findstring(&ima->views, STEREO_LEFT_NAME, offsetof(ImageView, name)) &&
- BLI_findstring(&ima->views, STEREO_RIGHT_NAME, offsetof(ImageView, name)))
- {
- ima->flag |= IMA_IS_STEREO;
- }
- else {
- ima->flag &= ~IMA_IS_STEREO;
- }
- }
- else {
- ima->flag &= ~IMA_IS_STEREO;
- ima->flag &= ~IMA_IS_MULTIVIEW;
- }
-}
-#endif /* WITH_OPENEXR */
-
/* after imbuf load, openexr type can return with a exrhandle open */
/* in that case we have to build a render-result */
#ifdef WITH_OPENEXR
static void image_create_multiview(Image *ima, ImBuf *ibuf, const int frame)
{
- image_free_views(ima);
+ BKE_image_free_views(ima);
IMB_exr_multiview_convert(ibuf->userdata, ima, image_add_view_cb, image_add_buffer_cb, frame);
- image_update_multiview_flags(ima);
-
IMB_exr_close(ibuf->userdata);
}
#endif /* WITH_OPENEXR */
@@ -3058,7 +3064,9 @@ static void image_create_multilayer(Image *ima, ImBuf *ibuf, int framenr)
const char *colorspace = ima->colorspace_settings.name;
bool predivide = (ima->alpha_mode == IMA_ALPHA_PREMUL);
- ima->rr = RE_MultilayerConvert(ibuf->userdata, colorspace, predivide, ibuf->x, ibuf->y);
+ /* only load rr once for multiview */
+ if (!ima->rr)
+ ima->rr = RE_MultilayerConvert(ibuf->userdata, colorspace, predivide, ibuf->x, ibuf->y);
IMB_exr_close(ibuf->userdata);
@@ -3066,8 +3074,8 @@ static void image_create_multilayer(Image *ima, ImBuf *ibuf, int framenr)
if (ima->rr)
ima->rr->framenr = framenr;
- /* set proper multiview flag */
- image_init_multilayer_multiview_flag(ima, ima->rr);
+ /* set proper views */
+ image_init_multilayer_multiview(ima, ima->rr);
}
#endif /* WITH_OPENEXR */
@@ -3105,7 +3113,7 @@ static int imbuf_alpha_flags_for_image(Image *ima)
/* the number of files will vary according to the stereo format */
static size_t image_num_files(Image *ima)
{
- const bool is_multiview = (ima->flag & IMA_IS_MULTIVIEW) != 0;
+ const bool is_multiview = BKE_image_is_multiview(ima);
if (!is_multiview) {
return 1;
@@ -3187,7 +3195,7 @@ static ImBuf *load_sequence_single(Image *ima, ImageUser *iuser, int frame, cons
static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int frame)
{
struct ImBuf *ibuf = NULL;
- const bool is_multiview = (ima->flag & IMA_IS_MULTIVIEW) != 0;
+ const bool is_multiview = BKE_image_is_multiview(ima);
const size_t totfiles = image_num_files(ima);
bool assign = false;
@@ -3207,7 +3215,7 @@ static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int frame)
for (i = 0; i < totfiles; i++)
ibuf_arr[i] = load_sequence_single(ima, iuser, frame, i, &assign);
- if ((ima->flag & IMA_IS_STEREO) && ima->views_format == R_IMF_VIEWS_STEREO_3D)
+ if (BKE_image_is_stereo(ima) && ima->views_format == R_IMF_VIEWS_STEREO_3D)
IMB_ImBufFromStereo3d(ima->stereo3d_format, ibuf_arr[0], &ibuf_arr[0], &ibuf_arr[1]);
/* return the original requested ImBuf */
@@ -3344,7 +3352,7 @@ static ImBuf *load_movie_single(Image *ima, ImageUser *iuser, int frame, const s
static ImBuf *image_load_movie_file(Image *ima, ImageUser *iuser, int frame)
{
struct ImBuf *ibuf = NULL;
- const bool is_multiview = (ima->flag & IMA_IS_MULTIVIEW) != 0;
+ const bool is_multiview = BKE_image_is_multiview(ima);
const size_t totfiles = image_num_files(ima);
size_t i;
@@ -3372,7 +3380,7 @@ static ImBuf *image_load_movie_file(Image *ima, ImageUser *iuser, int frame)
ibuf_arr[i] = load_movie_single(ima, iuser, frame, i);
}
- if ((ima->flag & IMA_IS_STEREO) && ima->views_format == R_IMF_VIEWS_STEREO_3D)
+ if (BKE_image_is_stereo(ima) && ima->views_format == R_IMF_VIEWS_STEREO_3D)
IMB_ImBufFromStereo3d(ima->stereo3d_format, ibuf_arr[0], &ibuf_arr[0], &ibuf_arr[1]);
for (i = 0; i < totviews; i++) {
@@ -3500,7 +3508,7 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra)
{
struct ImBuf *ibuf = NULL;
bool assign = false;
- const bool is_multiview = (ima->flag & IMA_IS_MULTIVIEW) != 0;
+ const bool is_multiview = BKE_image_is_multiview(ima);
const size_t totfiles = image_num_files(ima);
bool has_packed = BKE_image_has_packedfile(ima);
@@ -3533,7 +3541,7 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra)
ibuf_arr[i] = load_image_single(ima, iuser, cfra, i, has_packed, &assign);
/* multi-views/multi-layers OpenEXR files directly populate ima, and return NULL ibuf... */
- if ((ima->flag & IMA_IS_STEREO) && ima->views_format == R_IMF_VIEWS_STEREO_3D &&
+ if (BKE_image_is_stereo(ima) && ima->views_format == R_IMF_VIEWS_STEREO_3D &&
ibuf_arr[0] && totfiles == 1 && totviews >= 2)
{
IMB_ImBufFromStereo3d(ima->stereo3d_format, ibuf_arr[0], &ibuf_arr[0], &ibuf_arr[1]);
@@ -3613,7 +3621,7 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc
float *rectf, *rectz;
unsigned int *rect;
float dither;
- int channels, layer, passtype;
+ int channels, layer, pass;
ImBuf *ibuf;
int from_render = (ima->render_slot == ima->last_render_slot);
int actview;
@@ -3630,10 +3638,10 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc
channels = 4;
layer = iuser->layer;
- passtype = iuser->passtype;
+ pass = iuser->pass;
actview = iuser->view;
- if ((ima->flag & IMA_IS_STEREO) && (iuser->flag & IMA_SHOW_STEREO))
+ if (BKE_image_is_stereo(ima) && (iuser->flag & IMA_SHOW_STEREO))
actview = iuser->multiview_eye;
if (from_render) {
@@ -3693,19 +3701,10 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc
else if (rres.layers.first) {
RenderLayer *rl = BLI_findlink(&rres.layers, layer - (rres.have_combined ? 1 : 0));
if (rl) {
- RenderPass *rpass;
-
- for (rpass = rl->passes.first; rpass; rpass = rpass->next) {
- if (passtype == rpass->passtype &&
- actview == rpass->view_id)
- {
- break;
- }
- }
-
+ RenderPass *rpass = image_render_pass_get(rl, pass, actview, NULL);
if (rpass) {
rectf = rpass->rect;
- if (passtype == SCE_PASS_COMBINED) {
+ if (pass == 0) {
if (rectf == NULL) {
/* Happens when Save Buffers is enabled.
* Use display buffer stored in the render layer.
@@ -3816,12 +3815,12 @@ static size_t image_get_multiview_index(Image *ima, ImageUser *iuser)
return iuser ? iuser->multi_index : index;
}
else if (is_backdrop) {
- if ((ima->flag & IMA_IS_STEREO)) {
+ if (BKE_image_is_stereo(ima)) {
/* backdrop hackaround (since there is no iuser */
return ima->eye;
}
}
- else if ((ima->flag & IMA_IS_MULTIVIEW)) {
+ else if (BKE_image_is_multiview(ima)) {
return iuser ? iuser->multi_index : index;
}
@@ -4310,9 +4309,12 @@ void BKE_image_update_frame(const Main *bmain, int cfra)
void BKE_image_user_file_path(ImageUser *iuser, Image *ima, char *filepath)
{
- if ((ima->flag & IMA_IS_MULTIVIEW) && (ima->rr == NULL)) {
+ if (BKE_image_is_multiview(ima) && (ima->rr == NULL)) {
ImageView *iv = BLI_findlink(&ima->views, iuser->view);
- BLI_strncpy(filepath, iv->filepath, FILE_MAX);
+ if (iv->filepath[0])
+ BLI_strncpy(filepath, iv->filepath, FILE_MAX);
+ else
+ BLI_strncpy(filepath, ima->name, FILE_MAX);
}
else {
BLI_strncpy(filepath, ima->name, FILE_MAX);
@@ -4442,14 +4444,7 @@ float *BKE_image_get_float_pixels_for_frame(struct Image *image, int frame)
int BKE_image_sequence_guess_offset(Image *image)
{
- unsigned short numlen;
- char head[FILE_MAX], tail[FILE_MAX];
- char num[FILE_MAX] = {0};
-
- BLI_stringdec(image->name, head, tail, &numlen);
- BLI_strncpy(num, image->name + strlen(head), numlen + 1);
-
- return atoi(num);
+ return BLI_stringdec(image->name, NULL, NULL, NULL);
}
bool BKE_image_has_anim(Image *ima)
@@ -4607,15 +4602,12 @@ static void image_update_views_format(Image *ima, ImageUser *iuser)
BKE_image_free_views(ima);
if (!is_multiview) {
- goto monoview;
+ /* nothing to do */
}
else if (ima->views_format == R_IMF_VIEWS_STEREO_3D) {
size_t i;
const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME};
- ima->flag |= IMA_IS_MULTIVIEW;
- ima->flag |= IMA_IS_STEREO;
-
for (i = 0; i < 2; i++) {
image_add_view(ima, names[i], ima->name);
}
@@ -4630,7 +4622,8 @@ static void image_update_views_format(Image *ima, ImageUser *iuser)
BKE_scene_multiview_view_prefix_get(scene, name, prefix, &ext);
if (prefix[0] == '\0') {
- goto monoview;
+ BKE_image_free_views(ima);
+ return;
}
/* create all the image views */
@@ -4666,15 +4659,7 @@ static void image_update_views_format(Image *ima, ImageUser *iuser)
}
/* all good */
- if (BLI_listbase_count_ex(&ima->views, 2) > 1) {
- ima->flag |= IMA_IS_MULTIVIEW;
- if (BKE_scene_multiview_is_stereo3d(&scene->r))
- ima->flag |= IMA_IS_STEREO;
- }
- else {
-monoview:
- ima->flag &= ~IMA_IS_STEREO;
- ima->flag &= ~IMA_IS_MULTIVIEW;
+ if (!BKE_image_is_multiview(ima)) {
BKE_image_free_views(ima);
}
}
diff --git a/source/blender/blenkernel/intern/image_gen.c b/source/blender/blenkernel/intern/image_gen.c
index 4f9ed5f258d..303d0c6adfc 100644
--- a/source/blender/blenkernel/intern/image_gen.c
+++ b/source/blender/blenkernel/intern/image_gen.c
@@ -309,26 +309,26 @@ static void checker_board_text(unsigned char *rect, float *rect_float, int width
BLF_buffer_col(mono, 1.0, 1.0, 1.0, 1.0);
BLF_position(mono, pen_x - outline, pen_y, 0.0);
- BLF_draw_buffer(mono, text);
+ BLF_draw_buffer(mono, text, 2);
BLF_position(mono, pen_x + outline, pen_y, 0.0);
- BLF_draw_buffer(mono, text);
+ BLF_draw_buffer(mono, text, 2);
BLF_position(mono, pen_x, pen_y - outline, 0.0);
- BLF_draw_buffer(mono, text);
+ BLF_draw_buffer(mono, text, 2);
BLF_position(mono, pen_x, pen_y + outline, 0.0);
- BLF_draw_buffer(mono, text);
+ BLF_draw_buffer(mono, text, 2);
BLF_position(mono, pen_x - outline, pen_y - outline, 0.0);
- BLF_draw_buffer(mono, text);
+ BLF_draw_buffer(mono, text, 2);
BLF_position(mono, pen_x + outline, pen_y + outline, 0.0);
- BLF_draw_buffer(mono, text);
+ BLF_draw_buffer(mono, text, 2);
BLF_position(mono, pen_x - outline, pen_y + outline, 0.0);
- BLF_draw_buffer(mono, text);
+ BLF_draw_buffer(mono, text, 2);
BLF_position(mono, pen_x + outline, pen_y - outline, 0.0);
- BLF_draw_buffer(mono, text);
+ BLF_draw_buffer(mono, text, 2);
BLF_buffer_col(mono, 0.0, 0.0, 0.0, 1.0);
BLF_position(mono, pen_x, pen_y, 0.0);
- BLF_draw_buffer(mono, text);
+ BLF_draw_buffer(mono, text, 2);
text[1]++;
}
diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c
index b591dc19685..362f41335d2 100644
--- a/source/blender/blenkernel/intern/key.c
+++ b/source/blender/blenkernel/intern/key.c
@@ -58,6 +58,7 @@
#include "BKE_key.h"
#include "BKE_lattice.h"
#include "BKE_library.h"
+#include "BKE_mesh.h"
#include "BKE_editmesh.h"
#include "BKE_scene.h"
@@ -1392,26 +1393,51 @@ float *BKE_key_evaluate_object(Object *ob, int *r_totelem)
return BKE_key_evaluate_object_ex(ob, r_totelem, NULL, 0);
}
-Key **BKE_key_from_object_p(Object *ob)
+Key **BKE_key_from_id_p(ID *id)
{
- if (ob == NULL)
- return NULL;
-
- if (ob->type == OB_MESH) {
- Mesh *me = ob->data;
- return &me->key;
- }
- else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
- Curve *cu = ob->data;
- return &cu->key;
+ switch (GS(id->name)) {
+ case ID_ME:
+ {
+ Mesh *me = (Mesh *)id;
+ return &me->key;
+ }
+ case ID_CU:
+ {
+ Curve *cu = (Curve *)id;
+ if (cu->vfont == NULL) {
+ return &cu->key;
+ }
+ break;
+ }
+ case ID_LT:
+ {
+ Lattice *lt = (Lattice *)id;
+ return &lt->key;
+ }
}
- else if (ob->type == OB_LATTICE) {
- Lattice *lt = ob->data;
- return &lt->key;
+
+ return NULL;
+}
+
+Key *BKE_key_from_id(ID *id)
+{
+ Key **key_p;
+ key_p = BKE_key_from_id_p(id);
+ if (key_p) {
+ return *key_p;
}
+
return NULL;
}
+Key **BKE_key_from_object_p(Object *ob)
+{
+ if (ob == NULL || ob->data == NULL)
+ return NULL;
+
+ return BKE_key_from_id_p(ob->data);
+}
+
Key *BKE_key_from_object(Object *ob)
{
Key **key_p;
@@ -1774,6 +1800,66 @@ void BKE_keyblock_convert_to_mesh(KeyBlock *kb, Mesh *me)
}
}
+/**
+ * Computes normals (vertices, polygons and/or loops ones) of given mesh for given shape key.
+ *
+ * \param kb the KeyBlock to use to compute normals.
+ * \param mesh the Mesh to apply keyblock to.
+ * \param r_vertnors if non-NULL, an array of vectors, same length as number of vertices.
+ * \param r_polynors if non-NULL, an array of vectors, same length as number of polygons.
+ * \param r_loopnors if non-NULL, an array of vectors, same length as number of loops.
+ */
+void BKE_keyblock_mesh_calc_normals(
+ struct KeyBlock *kb, struct Mesh *mesh,
+ float (*r_vertnors)[3], float (*r_polynors)[3], float (*r_loopnors)[3])
+{
+ /* We use a temp, shallow copy of mesh to work. */
+ Mesh me;
+ bool free_polynors = false;
+
+ if (r_vertnors == NULL && r_polynors == NULL && r_loopnors == NULL) {
+ return;
+ }
+
+ me = *mesh;
+ me.mvert = MEM_dupallocN(mesh->mvert);
+ CustomData_reset(&me.vdata);
+ CustomData_reset(&me.edata);
+ CustomData_reset(&me.pdata);
+ CustomData_reset(&me.ldata);
+ CustomData_reset(&me.fdata);
+
+ BKE_keyblock_convert_to_mesh(kb, &me);
+
+ if (r_polynors == NULL && r_loopnors != NULL) {
+ r_polynors = MEM_mallocN(sizeof(float[3]) * me.totpoly, __func__);
+ free_polynors = true;
+ }
+ BKE_mesh_calc_normals_poly(
+ me.mvert, r_vertnors, me.totvert, me.mloop, me.mpoly, me.totloop, me.totpoly, r_polynors, false);
+
+ if (r_loopnors) {
+ short (*clnors)[2] = CustomData_get_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL); /* May be NULL. */
+
+ BKE_mesh_normals_loop_split(
+ me.mvert, me.totvert, me.medge, me.totedge,
+ me.mloop, r_loopnors, me.totloop, me.mpoly, r_polynors, me.totpoly,
+ (me.flag & ME_AUTOSMOOTH) != 0, me.smoothresh, NULL, clnors, NULL);
+ }
+
+ CustomData_free(&me.vdata, me.totvert);
+ CustomData_free(&me.edata, me.totedge);
+ CustomData_free(&me.pdata, me.totpoly);
+ CustomData_free(&me.ldata, me.totloop);
+ CustomData_free(&me.fdata, me.totface);
+ MEM_freeN(me.mvert);
+
+ if (free_polynors) {
+ MEM_freeN(r_polynors);
+ }
+}
+
+
/************************* raw coords ************************/
void BKE_keyblock_update_from_vertcos(Object *ob, KeyBlock *kb, float (*vertCos)[3])
{
diff --git a/source/blender/blenkernel/intern/lamp.c b/source/blender/blenkernel/intern/lamp.c
index 44e35c645de..8e350896eb8 100644
--- a/source/blender/blenkernel/intern/lamp.c
+++ b/source/blender/blenkernel/intern/lamp.c
@@ -53,12 +53,10 @@
#include "BKE_main.h"
#include "BKE_node.h"
-Lamp *BKE_lamp_add(Main *bmain, const char *name)
+void BKE_lamp_init(Lamp *la)
{
- Lamp *la;
-
- la = BKE_libblock_alloc(bmain, ID_LA, name);
-
+ BLI_assert(MEMCMP_STRUCT_OFS_IS_ZERO(la, id));
+
la->r = la->g = la->b = la->k = 1.0f;
la->haint = la->energy = 1.0f;
la->dist = 25.0f;
@@ -100,6 +98,16 @@ Lamp *BKE_lamp_add(Main *bmain, const char *name)
la->shadow_frustum_size = 10.0f;
curvemapping_initialize(la->curfalloff);
+}
+
+Lamp *BKE_lamp_add(Main *bmain, const char *name)
+{
+ Lamp *la;
+
+ la = BKE_libblock_alloc(bmain, ID_LA, name);
+
+ BKE_lamp_init(la);
+
return la;
}
diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c
index 009e1d20328..0e5228a6db4 100644
--- a/source/blender/blenkernel/intern/lattice.c
+++ b/source/blender/blenkernel/intern/lattice.c
@@ -251,12 +251,10 @@ void BKE_lattice_resize(Lattice *lt, int uNew, int vNew, int wNew, Object *ltOb)
MEM_freeN(vertexCos);
}
-Lattice *BKE_lattice_add(Main *bmain, const char *name)
+void BKE_lattice_init(Lattice *lt)
{
- Lattice *lt;
-
- lt = BKE_libblock_alloc(bmain, ID_LT, name);
-
+ BLI_assert(MEMCMP_STRUCT_OFS_IS_ZERO(lt, id));
+
lt->flag = LT_GRID;
lt->typeu = lt->typev = lt->typew = KEY_BSPLINE;
@@ -264,7 +262,16 @@ Lattice *BKE_lattice_add(Main *bmain, const char *name)
lt->def = MEM_callocN(sizeof(BPoint), "lattvert"); /* temporary */
BKE_lattice_resize(lt, 2, 2, 2, NULL); /* creates a uniform lattice */
lt->actbp = LT_ACTBP_NONE;
-
+}
+
+Lattice *BKE_lattice_add(Main *bmain, const char *name)
+{
+ Lattice *lt;
+
+ lt = BKE_libblock_alloc(bmain, ID_LT, name);
+
+ BKE_lattice_init(lt);
+
return lt;
}
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index 8bb2864a604..f8f92825479 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -59,6 +59,7 @@
#include "DNA_movieclip_types.h"
#include "DNA_mask_types.h"
#include "DNA_node_types.h"
+#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_speaker_types.h"
@@ -95,6 +96,7 @@
#include "BKE_lamp.h"
#include "BKE_lattice.h"
#include "BKE_library.h"
+#include "BKE_library_query.h"
#include "BKE_linestyle.h"
#include "BKE_mesh.h"
#include "BKE_material.h"
@@ -119,6 +121,9 @@
#include "RNA_access.h"
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+
#ifdef WITH_PYTHON
#include "BPY_extern.h"
#endif
@@ -644,7 +649,7 @@ int set_listbasepointers(Main *main, ListBase **lb)
* Allocates and returns memory of the right size for the specified block type,
* initialized to zero.
*/
-static ID *alloc_libblock_notest(short type)
+void *BKE_libblock_alloc_notest(short type)
{
ID *id = NULL;
@@ -766,7 +771,7 @@ void *BKE_libblock_alloc(Main *bmain, short type, const char *name)
ID *id = NULL;
ListBase *lb = which_libbase(bmain, type);
- id = alloc_libblock_notest(type);
+ id = BKE_libblock_alloc_notest(type);
if (id) {
BKE_main_lock(bmain);
BLI_addtail(lb, id);
@@ -781,6 +786,121 @@ void *BKE_libblock_alloc(Main *bmain, short type, const char *name)
return id;
}
+/**
+ * Initialize an ID of given type, such that it has valid 'empty' data.
+ * ID is assumed to be just calloc'ed.
+ */
+void BKE_libblock_init_empty(ID *id)
+{
+ /* Note that only ID types that are not valid when filled of zero should have a callback here. */
+ switch (GS(id->name)) {
+ case ID_SCE:
+ BKE_scene_init((Scene *)id);
+ break;
+ case ID_LI:
+ /* Nothing to do. */
+ break;
+ case ID_OB:
+ {
+ Object *ob = (Object *)id;
+ ob->type = OB_EMPTY;
+ BKE_object_init(ob);
+ break;
+ }
+ case ID_ME:
+ BKE_mesh_init((Mesh *)id);
+ break;
+ case ID_CU:
+ BKE_curve_init((Curve *)id);
+ break;
+ case ID_MB:
+ BKE_mball_init((MetaBall *)id);
+ break;
+ case ID_MA:
+ BKE_material_init((Material *)id);
+ break;
+ case ID_TE:
+ BKE_texture_default((Tex *)id);
+ break;
+ case ID_IM:
+ /* Image is a bit complicated, for now assume NULLified im is OK. */
+ break;
+ case ID_LT:
+ BKE_lattice_init((Lattice *)id);
+ break;
+ case ID_LA:
+ BKE_lamp_init((Lamp *)id);
+ break;
+ case ID_SPK:
+ BKE_speaker_init((Speaker *)id);
+ break;
+ case ID_CA:
+ BKE_camera_init((Camera *)id);
+ break;
+ case ID_IP:
+ /* Should not be needed - animation from lib pre-2.5 is broken anyway. */
+ BLI_assert(0);
+ break;
+ case ID_KE:
+ /* Shapekeys are a complex topic too - they depend on their 'user' data type...
+ * They are not linkable, though, so it should never reach here anyway. */
+ BLI_assert(0);
+ break;
+ case ID_WO:
+ BKE_world_init((World *)id);
+ break;
+ case ID_SCR:
+ /* Nothing to do. */
+ break;
+ case ID_VF:
+ BKE_vfont_init((VFont *)id);
+ break;
+ case ID_TXT:
+ BKE_text_init((Text *)id);
+ break;
+ case ID_SCRIPT:
+ BLI_assert(0);
+ break;
+ case ID_SO:
+ /* Another fuzzy case, think NULLified content is OK here... */
+ break;
+ case ID_GR:
+ /* Nothing to do. */
+ break;
+ case ID_AR:
+ /* Nothing to do. */
+ break;
+ case ID_AC:
+ /* Nothing to do. */
+ break;
+ case ID_NT:
+ ntreeInitDefault((bNodeTree *)id);
+ break;
+ case ID_BR:
+ BKE_brush_init((Brush *)id);
+ break;
+ case ID_PA:
+ /* Nothing to do. */
+ break;
+ case ID_PC:
+ /* Nothing to do. */
+ break;
+ case ID_WM:
+ /* We should never reach this. */
+ BLI_assert(0);
+ break;
+ case ID_GD:
+ /* Nothing to do. */
+ break;
+ case ID_MSK:
+ /* Nothing to do. */
+ break;
+ case ID_LS:
+ BKE_linestyle_init((FreestyleLineStyle *)id);
+ break;
+ }
+}
+
/* by spec, animdata is first item after ID */
/* and, trust that BKE_animdata_from_id() will only find AnimData for valid ID-types */
static void id_copy_animdata(ID *id, const bool do_action)
@@ -834,7 +954,7 @@ void *BKE_libblock_copy_nolib(ID *id, const bool do_action)
ID *idn;
size_t idn_len;
- idn = alloc_libblock_notest(GS(id->name));
+ idn = BKE_libblock_alloc_notest(GS(id->name));
assert(idn != NULL);
BLI_strncpy(idn->name, id->name, sizeof(idn->name));
@@ -861,6 +981,31 @@ void *BKE_libblock_copy(ID *id)
return BKE_libblock_copy_ex(G.main, id);
}
+static bool id_relink_looper(void *UNUSED(user_data), ID **id_pointer, const int cd_flag)
+{
+ ID *id = *id_pointer;
+ if (id) {
+ /* See: NEW_ID macro */
+ if (id->newid) {
+ BKE_library_update_ID_link_user(id->newid, id, cd_flag);
+ *id_pointer = id->newid;
+ }
+ else if (id->flag & LIB_NEW) {
+ id->flag &= ~LIB_NEW;
+ BKE_libblock_relink(id);
+ }
+ }
+ return true;
+}
+
+void BKE_libblock_relink(ID *id)
+{
+ if (id->lib)
+ return;
+
+ BKE_library_foreach_ID_link(id, id_relink_looper, NULL, 0);
+}
+
static void BKE_library_free(Library *lib)
{
if (lib->packedfile)
@@ -1097,6 +1242,8 @@ void BKE_main_free(Main *mainvar)
ListBase *lbarray[MAX_LIBARRAY];
int a;
+ MEM_SAFE_FREE(mainvar->blen_thumb);
+
a = set_listbasepointers(mainvar, lbarray);
while (a--) {
ListBase *lb = lbarray[a];
@@ -1142,6 +1289,7 @@ void BKE_main_free(Main *mainvar)
case 30: BKE_libblock_free_ex(mainvar, id, false); break;
case 31: BKE_libblock_free_ex(mainvar, id, false); break;
case 32: BKE_libblock_free_ex(mainvar, id, false); break;
+ case 33: BKE_libblock_free_ex(mainvar, id, false); break;
default:
BLI_assert(0);
break;
@@ -1166,6 +1314,74 @@ void BKE_main_unlock(struct Main *bmain)
BLI_spin_unlock((SpinLock *) bmain->lock);
}
+/**
+ * Generates a raw .blend file thumbnail data from given image.
+ *
+ * \param bmain If not NULL, also store generated data in this Main.
+ * \param img ImBuf image to generate thumbnail data from.
+ * \return The generated .blend file raw thumbnail data.
+ */
+BlendThumbnail *BKE_main_thumbnail_from_imbuf(Main *bmain, ImBuf *img)
+{
+ BlendThumbnail *data = NULL;
+
+ if (bmain) {
+ MEM_SAFE_FREE(bmain->blen_thumb);
+ }
+
+ if (img) {
+ const size_t sz = BLEN_THUMB_MEMSIZE(img->x, img->y);
+ data = MEM_mallocN(sz, __func__);
+
+ IMB_rect_from_float(img); /* Just in case... */
+ data->width = img->x;
+ data->height = img->y;
+ memcpy(data->rect, img->rect, sz - sizeof(*data));
+ }
+
+ if (bmain) {
+ bmain->blen_thumb = data;
+ }
+ return data;
+}
+
+/**
+ * Generates an image from raw .blend file thumbnail \a data.
+ *
+ * \param bmain Use this bmain->blen_thumb data if given \a data is NULL.
+ * \param data Raw .blend file thumbnail data.
+ * \return An ImBuf from given data, or NULL if invalid.
+ */
+ImBuf *BKE_main_thumbnail_to_imbuf(Main *bmain, BlendThumbnail *data)
+{
+ ImBuf *img = NULL;
+
+ if (!data && bmain) {
+ data = bmain->blen_thumb;
+ }
+
+ if (data) {
+ /* Note: we cannot use IMB_allocFromBuffer(), since it tries to dupalloc passed buffer, which will fail
+ * here (we do not want to pass the first two ints!). */
+ img = IMB_allocImBuf((unsigned int)data->width, (unsigned int)data->height, 32, IB_rect | IB_metadata);
+ memcpy(img->rect, data->rect, BLEN_THUMB_MEMSIZE(data->width, data->height) - sizeof(*data));
+ }
+
+ return img;
+}
+
+/**
+ * Generates an empty (black) thumbnail for given Main.
+ */
+void BKE_main_thumbnail_create(struct Main *bmain)
+{
+ MEM_SAFE_FREE(bmain->blen_thumb);
+
+ bmain->blen_thumb = MEM_callocN(BLEN_THUMB_MEMSIZE(BLEN_THUMB_SIZE, BLEN_THUMB_SIZE), __func__);
+ bmain->blen_thumb->width = BLEN_THUMB_SIZE;
+ bmain->blen_thumb->height = BLEN_THUMB_SIZE;
+}
+
/* ***************** ID ************************ */
ID *BKE_libblock_find_name_ex(struct Main *bmain, const short type, const char *name)
{
@@ -1620,7 +1836,7 @@ void rename_id(ID *id, const char *name)
*/
void name_uiprefix_id(char *name, const ID *id)
{
- name[0] = id->lib ? 'L' : ' ';
+ name[0] = id->lib ? (ID_MISSING(id) ? 'M' : 'L') : ' ';
name[1] = (id->flag & LIB_FAKEUSER) ? 'F' : ((id->us == 0) ? '0' : ' ');
name[2] = ' ';
diff --git a/source/blender/blenkernel/intern/library_query.c b/source/blender/blenkernel/intern/library_query.c
index 6d2e2f1ecd4..a800b3d8834 100644
--- a/source/blender/blenkernel/intern/library_query.c
+++ b/source/blender/blenkernel/intern/library_query.c
@@ -30,10 +30,12 @@
#include <stdlib.h>
+#include "DNA_actuator_types.h"
#include "DNA_anim_types.h"
#include "DNA_brush_types.h"
#include "DNA_camera_types.h"
#include "DNA_constraint_types.h"
+#include "DNA_controller_types.h"
#include "DNA_group_types.h"
#include "DNA_gpencil_types.h"
#include "DNA_key_types.h"
@@ -47,7 +49,9 @@
#include "DNA_mask_types.h"
#include "DNA_node_types.h"
#include "DNA_object_force.h"
+#include "DNA_rigidbody_types.h"
#include "DNA_scene_types.h"
+#include "DNA_sensor_types.h"
#include "DNA_sequence_types.h"
#include "DNA_screen_types.h"
#include "DNA_speaker_types.h"
@@ -61,9 +65,12 @@
#include "BKE_animsys.h"
#include "BKE_constraint.h"
#include "BKE_fcurve.h"
+#include "BKE_library.h"
#include "BKE_library_query.h"
#include "BKE_modifier.h"
#include "BKE_particle.h"
+#include "BKE_rigidbody.h"
+#include "BKE_sca.h"
#include "BKE_sequencer.h"
#include "BKE_tracking.h"
@@ -80,16 +87,19 @@
/* TODO(sergey): Make it less creepy without too much duplicated code.. */ \
return; \
} \
- } (void) 0
+ } ((void)0)
#define FOREACH_CALLBACK_INVOKE_ID(self_id, id, flag, callback, user_data, cb_flag) \
- FOREACH_CALLBACK_INVOKE_ID_PP(self_id, &(id), flag, callback, user_data, cb_flag) \
+ { \
+ CHECK_TYPE_ANY(id, ID *, void *); \
+ FOREACH_CALLBACK_INVOKE_ID_PP(self_id, (ID **)&(id), flag, callback, user_data, cb_flag); \
+ } ((void)0)
#define FOREACH_CALLBACK_INVOKE(self_id, id_super, flag, callback, user_data, cb_flag) \
{ \
CHECK_TYPE(&((id_super)->id), ID *); \
FOREACH_CALLBACK_INVOKE_ID_PP(self_id, (ID **)&id_super, flag, callback, user_data, cb_flag); \
- } (void) 0
+ } ((void)0)
typedef struct LibraryForeachIDData {
ID *self_id;
@@ -98,11 +108,18 @@ typedef struct LibraryForeachIDData {
void *user_data;
} LibraryForeachIDData;
-static void library_foreach_modifiersForeachIDLink(void *user_data, Object *UNUSED(object),
- ID **id_pointer)
+static void library_foreach_rigidbodyworldSceneLooper(
+ struct RigidBodyWorld *UNUSED(rbw), ID **id_pointer, void *user_data, int cd_flag)
{
LibraryForeachIDData *data = (LibraryForeachIDData *) user_data;
- FOREACH_CALLBACK_INVOKE_ID_PP(data->self_id, id_pointer, data->flag, data->callback, data->user_data, IDWALK_NOP);
+ FOREACH_CALLBACK_INVOKE_ID_PP(data->self_id, id_pointer, data->flag, data->callback, data->user_data, cd_flag);
+}
+
+static void library_foreach_modifiersForeachIDLink(
+ void *user_data, Object *UNUSED(object), ID **id_pointer, int cd_flag)
+{
+ LibraryForeachIDData *data = (LibraryForeachIDData *) user_data;
+ FOREACH_CALLBACK_INVOKE_ID_PP(data->self_id, id_pointer, data->flag, data->callback, data->user_data, cd_flag);
}
static void library_foreach_constraintObjectLooper(bConstraint *UNUSED(con), ID **id_pointer,
@@ -112,6 +129,34 @@ static void library_foreach_constraintObjectLooper(bConstraint *UNUSED(con), ID
FOREACH_CALLBACK_INVOKE_ID_PP(data->self_id, id_pointer, data->flag, data->callback, data->user_data, IDWALK_NOP);
}
+static void library_foreach_particlesystemsObjectLooper(
+ ParticleSystem *UNUSED(psys), ID **id_pointer, void *user_data, int cd_flag)
+{
+ LibraryForeachIDData *data = (LibraryForeachIDData *) user_data;
+ FOREACH_CALLBACK_INVOKE_ID_PP(data->self_id, id_pointer, data->flag, data->callback, data->user_data, cd_flag);
+}
+
+static void library_foreach_sensorsObjectLooper(
+ bSensor *UNUSED(sensor), ID **id_pointer, void *user_data, int cd_flag)
+{
+ LibraryForeachIDData *data = (LibraryForeachIDData *) user_data;
+ FOREACH_CALLBACK_INVOKE_ID_PP(data->self_id, id_pointer, data->flag, data->callback, data->user_data, cd_flag);
+}
+
+static void library_foreach_controllersObjectLooper(
+ bController *UNUSED(controller), ID **id_pointer, void *user_data, int cd_flag)
+{
+ LibraryForeachIDData *data = (LibraryForeachIDData *) user_data;
+ FOREACH_CALLBACK_INVOKE_ID_PP(data->self_id, id_pointer, data->flag, data->callback, data->user_data, cd_flag);
+}
+
+static void library_foreach_actuatorsObjectLooper(
+ bActuator *UNUSED(actuator), ID **id_pointer, void *user_data, int cd_flag)
+{
+ LibraryForeachIDData *data = (LibraryForeachIDData *) user_data;
+ FOREACH_CALLBACK_INVOKE_ID_PP(data->self_id, id_pointer, data->flag, data->callback, data->user_data, cd_flag);
+}
+
static void library_foreach_animationData(LibraryForeachIDData *data, AnimData *adt)
{
FCurve *fcu;
@@ -131,11 +176,10 @@ static void library_foreach_animationData(LibraryForeachIDData *data, AnimData *
}
}
-
static void library_foreach_mtex(LibraryForeachIDData *data, MTex *mtex)
{
FOREACH_CALLBACK_INVOKE(data->self_id, mtex->object, data->flag, data->callback, data->user_data, IDWALK_NOP);
- FOREACH_CALLBACK_INVOKE(data->self_id, mtex->tex, data->flag, data->callback, data->user_data, IDWALK_NOP);
+ FOREACH_CALLBACK_INVOKE(data->self_id, mtex->tex, data->flag, data->callback, data->user_data, IDWALK_USER);
}
@@ -170,12 +214,15 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
case ID_SCE:
{
Scene *scene = (Scene *) id;
+ ToolSettings *toolsett = scene->toolsettings;
SceneRenderLayer *srl;
Base *base;
CALLBACK_INVOKE(scene->camera, IDWALK_NOP);
- CALLBACK_INVOKE(scene->world, IDWALK_NOP);
+ CALLBACK_INVOKE(scene->world, IDWALK_USER);
CALLBACK_INVOKE(scene->set, IDWALK_NOP);
+ CALLBACK_INVOKE(scene->clip, IDWALK_NOP);
+ CALLBACK_INVOKE(scene->nodetree, IDWALK_NOP);
if (scene->basact) {
CALLBACK_INVOKE(scene->basact->object, IDWALK_NOP);
}
@@ -186,10 +233,10 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
FreestyleLineSet *fls;
if (srl->mat_override) {
- CALLBACK_INVOKE(srl->mat_override, IDWALK_NOP);
+ CALLBACK_INVOKE(srl->mat_override, IDWALK_USER);
}
if (srl->light_override) {
- CALLBACK_INVOKE(srl->light_override, IDWALK_NOP);
+ CALLBACK_INVOKE(srl->light_override, IDWALK_USER);
}
for (fmc = srl->freestyleConfig.modules.first; fmc; fmc = fmc->next) {
if (fmc->script) {
@@ -198,10 +245,10 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
}
for (fls = srl->freestyleConfig.linesets.first; fls; fls = fls->next) {
if (fls->group) {
- CALLBACK_INVOKE(fls->group, IDWALK_NOP);
+ CALLBACK_INVOKE(fls->group, IDWALK_USER);
}
if (fls->linestyle) {
- CALLBACK_INVOKE(fls->linestyle, IDWALK_NOP);
+ CALLBACK_INVOKE(fls->linestyle, IDWALK_USER);
}
}
}
@@ -212,74 +259,136 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
{
CALLBACK_INVOKE(seq->scene, IDWALK_NOP);
CALLBACK_INVOKE(seq->scene_camera, IDWALK_NOP);
- CALLBACK_INVOKE(seq->clip, IDWALK_NOP);
- CALLBACK_INVOKE(seq->mask, IDWALK_NOP);
+ CALLBACK_INVOKE(seq->clip, IDWALK_USER);
+ CALLBACK_INVOKE(seq->mask, IDWALK_USER);
+ CALLBACK_INVOKE(seq->sound, IDWALK_USER);
}
SEQ_END
}
- CALLBACK_INVOKE(scene->gpd, IDWALK_NOP);
+ CALLBACK_INVOKE(scene->gpd, IDWALK_USER);
for (base = scene->base.first; base; base = base->next) {
- CALLBACK_INVOKE(base->object, IDWALK_NOP);
+ CALLBACK_INVOKE(base->object, IDWALK_USER);
+ }
+
+ if (toolsett) {
+ CALLBACK_INVOKE(toolsett->skgen_template, IDWALK_NOP);
+ CALLBACK_INVOKE(toolsett->particle.scene, IDWALK_NOP);
+ CALLBACK_INVOKE(toolsett->particle.object, IDWALK_NOP);
+ CALLBACK_INVOKE(toolsett->particle.shape_object, IDWALK_NOP);
+ CALLBACK_INVOKE(toolsett->imapaint.stencil, IDWALK_NOP);
+ CALLBACK_INVOKE(toolsett->imapaint.clone, IDWALK_NOP);
+ CALLBACK_INVOKE(toolsett->imapaint.canvas, IDWALK_NOP);
+ if (toolsett->vpaint) {
+ CALLBACK_INVOKE(toolsett->vpaint->paint.brush, IDWALK_NOP);
+ CALLBACK_INVOKE(toolsett->vpaint->paint.palette, IDWALK_NOP);
+ }
+ if (toolsett->wpaint) {
+ CALLBACK_INVOKE(toolsett->wpaint->paint.brush, IDWALK_NOP);
+ CALLBACK_INVOKE(toolsett->wpaint->paint.palette, IDWALK_NOP);
+ }
+ if (toolsett->sculpt) {
+ CALLBACK_INVOKE(toolsett->sculpt->paint.brush, IDWALK_NOP);
+ CALLBACK_INVOKE(toolsett->sculpt->paint.palette, IDWALK_NOP);
+ CALLBACK_INVOKE(toolsett->sculpt->gravity_object, IDWALK_NOP);
+ }
+ if (toolsett->uvsculpt) {
+ CALLBACK_INVOKE(toolsett->uvsculpt->paint.brush, IDWALK_NOP);
+ CALLBACK_INVOKE(toolsett->uvsculpt->paint.palette, IDWALK_NOP);
+ }
}
+
+ if (scene->rigidbody_world) {
+ BKE_rigidbody_world_id_loop(scene->rigidbody_world, library_foreach_rigidbodyworldSceneLooper, &data);
+ }
+
break;
}
case ID_OB:
{
Object *object = (Object *) id;
+ ParticleSystem *psys;
+
+ /* object data special case */
+ if (object->type == OB_EMPTY) {
+ /* empty can have NULL or Image */
+ CALLBACK_INVOKE_ID(object->data, IDWALK_USER);
+ }
+ else {
+ /* when set, this can't be NULL */
+ if (object->data) {
+ CALLBACK_INVOKE_ID(object->data, IDWALK_USER | IDWALK_NEVER_NULL);
+ }
+ }
+
CALLBACK_INVOKE(object->parent, IDWALK_NOP);
CALLBACK_INVOKE(object->track, IDWALK_NOP);
- CALLBACK_INVOKE(object->proxy, IDWALK_NOP);
+ /* object->proxy is refcounted, but not object->proxy_group... *sigh* */
+ CALLBACK_INVOKE(object->proxy, IDWALK_USER);
CALLBACK_INVOKE(object->proxy_group, IDWALK_NOP);
CALLBACK_INVOKE(object->proxy_from, IDWALK_NOP);
- CALLBACK_INVOKE(object->poselib, IDWALK_NOP);
+ CALLBACK_INVOKE(object->poselib, IDWALK_USER);
for (i = 0; i < object->totcol; i++) {
- CALLBACK_INVOKE(object->mat[i], IDWALK_NOP);
+ CALLBACK_INVOKE(object->mat[i], IDWALK_USER);
}
- CALLBACK_INVOKE(object->gpd, IDWALK_NOP);
- CALLBACK_INVOKE(object->dup_group, IDWALK_NOP);
+ CALLBACK_INVOKE(object->gpd, IDWALK_USER);
+ CALLBACK_INVOKE(object->dup_group, IDWALK_USER);
+
if (object->particlesystem.first) {
- ParticleSystem *particle_system;
- for (particle_system = object->particlesystem.first;
- particle_system;
- particle_system = particle_system->next)
- {
- CALLBACK_INVOKE(particle_system->target_ob, IDWALK_NOP);
- CALLBACK_INVOKE(particle_system->parent, IDWALK_NOP);
+ ParticleSystem *psys;
+ for (psys = object->particlesystem.first; psys; psys = psys->next) {
+ CALLBACK_INVOKE(psys->target_ob, IDWALK_NOP);
+ CALLBACK_INVOKE(psys->parent, IDWALK_NOP);
}
}
+ if (object->pd) {
+ CALLBACK_INVOKE(object->pd->tex, IDWALK_USER);
+ CALLBACK_INVOKE(object->pd->f_source, IDWALK_NOP);
+ }
+
if (object->pose) {
- bPoseChannel *pose_channel;
- for (pose_channel = object->pose->chanbase.first;
- pose_channel;
- pose_channel = pose_channel->next)
- {
- CALLBACK_INVOKE(pose_channel->custom, IDWALK_NOP);
- BKE_constraints_id_loop(&pose_channel->constraints,
- library_foreach_constraintObjectLooper,
- &data);
+ bPoseChannel *pchan;
+ for (pchan = object->pose->chanbase.first; pchan; pchan = pchan->next) {
+ CALLBACK_INVOKE(pchan->custom, IDWALK_USER);
+ BKE_constraints_id_loop(&pchan->constraints, library_foreach_constraintObjectLooper, &data);
+ }
+ }
+
+ if (object->rigidbody_constraint) {
+ CALLBACK_INVOKE(object->rigidbody_constraint->ob1, IDWALK_NOP);
+ CALLBACK_INVOKE(object->rigidbody_constraint->ob2, IDWALK_NOP);
+ }
+
+ if (object->lodlevels.first) {
+ LodLevel *level;
+ for (level = object->lodlevels.first; level; level = level->next) {
+ CALLBACK_INVOKE(level->source, IDWALK_NOP);
}
}
- modifiers_foreachIDLink(object,
- library_foreach_modifiersForeachIDLink,
- &data);
- BKE_constraints_id_loop(&object->constraints,
- library_foreach_constraintObjectLooper,
- &data);
+ modifiers_foreachIDLink(object, library_foreach_modifiersForeachIDLink, &data);
+ BKE_constraints_id_loop(&object->constraints, library_foreach_constraintObjectLooper, &data);
+
+ for (psys = object->particlesystem.first; psys; psys = psys->next) {
+ BKE_particlesystem_id_loop(psys, library_foreach_particlesystemsObjectLooper, &data);
+ }
+
+ BKE_sca_sensors_id_loop(&object->sensors, library_foreach_sensorsObjectLooper, &data);
+ BKE_sca_controllers_id_loop(&object->controllers, library_foreach_controllersObjectLooper, &data);
+ BKE_sca_actuators_id_loop(&object->actuators, library_foreach_actuatorsObjectLooper, &data);
break;
}
case ID_ME:
{
Mesh *mesh = (Mesh *) id;
- CALLBACK_INVOKE(mesh->texcomesh, IDWALK_NOP);
- CALLBACK_INVOKE(mesh->key, IDWALK_NOP);
+ CALLBACK_INVOKE(mesh->texcomesh, IDWALK_USER);
+ CALLBACK_INVOKE(mesh->key, IDWALK_USER);
for (i = 0; i < mesh->totcol; i++) {
- CALLBACK_INVOKE(mesh->mat[i], IDWALK_NOP);
+ CALLBACK_INVOKE(mesh->mat[i], IDWALK_USER);
}
break;
}
@@ -290,14 +399,14 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
CALLBACK_INVOKE(curve->bevobj, IDWALK_NOP);
CALLBACK_INVOKE(curve->taperobj, IDWALK_NOP);
CALLBACK_INVOKE(curve->textoncurve, IDWALK_NOP);
- CALLBACK_INVOKE(curve->key, IDWALK_NOP);
+ CALLBACK_INVOKE(curve->key, IDWALK_USER);
for (i = 0; i < curve->totcol; i++) {
- CALLBACK_INVOKE(curve->mat[i], IDWALK_NOP);
+ CALLBACK_INVOKE(curve->mat[i], IDWALK_USER);
}
- CALLBACK_INVOKE(curve->vfont, IDWALK_NOP);
- CALLBACK_INVOKE(curve->vfontb, IDWALK_NOP);
- CALLBACK_INVOKE(curve->vfonti, IDWALK_NOP);
- CALLBACK_INVOKE(curve->vfontbi, IDWALK_NOP);
+ CALLBACK_INVOKE(curve->vfont, IDWALK_USER);
+ CALLBACK_INVOKE(curve->vfontb, IDWALK_USER);
+ CALLBACK_INVOKE(curve->vfonti, IDWALK_USER);
+ CALLBACK_INVOKE(curve->vfontbi, IDWALK_USER);
break;
}
@@ -305,7 +414,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
{
MetaBall *metaball = (MetaBall *) id;
for (i = 0; i < metaball->totcol; i++) {
- CALLBACK_INVOKE(metaball->mat[i], IDWALK_NOP);
+ CALLBACK_INVOKE(metaball->mat[i], IDWALK_USER);
}
break;
}
@@ -319,7 +428,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
}
}
CALLBACK_INVOKE(material->nodetree, IDWALK_NOP);
- CALLBACK_INVOKE(material->group, IDWALK_NOP);
+ CALLBACK_INVOKE(material->group, IDWALK_USER);
break;
}
@@ -327,14 +436,24 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
{
Tex *texture = (Tex *) id;
CALLBACK_INVOKE(texture->nodetree, IDWALK_NOP);
- CALLBACK_INVOKE(texture->ima, IDWALK_NOP);
+ CALLBACK_INVOKE(texture->ima, IDWALK_USER);
+ if (texture->env) {
+ CALLBACK_INVOKE(texture->env->object, IDWALK_NOP);
+ CALLBACK_INVOKE(texture->env->ima, IDWALK_USER);
+ }
+ if (texture->pd)
+ CALLBACK_INVOKE(texture->pd->object, IDWALK_NOP);
+ if (texture->vd)
+ CALLBACK_INVOKE(texture->vd->object, IDWALK_NOP);
+ if (texture->ot)
+ CALLBACK_INVOKE(texture->ot->object, IDWALK_NOP);
break;
}
case ID_LT:
{
Lattice *lattice = (Lattice *) id;
- CALLBACK_INVOKE(lattice->key, IDWALK_NOP);
+ CALLBACK_INVOKE(lattice->key, IDWALK_USER);
break;
}
@@ -367,7 +486,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
case ID_SCR:
{
bScreen *screen = (bScreen *) id;
- CALLBACK_INVOKE(screen->scene, IDWALK_NOP);
+ CALLBACK_INVOKE(screen->scene, IDWALK_USER_ONE);
break;
}
@@ -386,19 +505,16 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
case ID_SPK:
{
Speaker *speaker = (Speaker *) id;
- CALLBACK_INVOKE(speaker->sound, IDWALK_NOP);
+ CALLBACK_INVOKE(speaker->sound, IDWALK_USER);
break;
}
case ID_GR:
{
Group *group = (Group *) id;
- GroupObject *group_object;
- for (group_object = group->gobject.first;
- group_object;
- group_object = group_object->next)
- {
- CALLBACK_INVOKE(group_object->ob, IDWALK_NOP);
+ GroupObject *gob;
+ for (gob = group->gobject.first; gob; gob = gob->next) {
+ CALLBACK_INVOKE(gob->ob, IDWALK_NOP);
}
break;
}
@@ -407,8 +523,9 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
{
bNodeTree *ntree = (bNodeTree *) id;
bNode *node;
+ CALLBACK_INVOKE(ntree->gpd, IDWALK_USER);
for (node = ntree->nodes.first; node; node = node->next) {
- CALLBACK_INVOKE_ID(node->id, IDWALK_NOP);
+ CALLBACK_INVOKE_ID(node->id, IDWALK_USER);
}
break;
}
@@ -417,6 +534,8 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
{
Brush *brush = (Brush *) id;
CALLBACK_INVOKE(brush->toggle_brush, IDWALK_NOP);
+ CALLBACK_INVOKE(brush->clone.image, IDWALK_NOP);
+ CALLBACK_INVOKE(brush->paint_curve, IDWALK_USER);
library_foreach_mtex(&data, &brush->mtex);
library_foreach_mtex(&data, &brush->mask_mtex);
break;
@@ -424,13 +543,39 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
case ID_PA:
{
- ParticleSettings *particle_settings = (ParticleSettings *) id;
- CALLBACK_INVOKE(particle_settings->dup_group, IDWALK_NOP);
- CALLBACK_INVOKE(particle_settings->dup_ob, IDWALK_NOP);
- CALLBACK_INVOKE(particle_settings->bb_ob, IDWALK_NOP);
- if (particle_settings->effector_weights) {
- CALLBACK_INVOKE(particle_settings->effector_weights->group, IDWALK_NOP);
+ ParticleSettings *psett = (ParticleSettings *) id;
+ CALLBACK_INVOKE(psett->dup_group, IDWALK_NOP);
+ CALLBACK_INVOKE(psett->dup_ob, IDWALK_NOP);
+ CALLBACK_INVOKE(psett->bb_ob, IDWALK_NOP);
+
+ for (i = 0; i < MAX_MTEX; i++) {
+ if (psett->mtex[i]) {
+ library_foreach_mtex(&data, psett->mtex[i]);
+ }
+ }
+
+ if (psett->effector_weights) {
+ CALLBACK_INVOKE(psett->effector_weights->group, IDWALK_NOP);
+ }
+
+ if (psett->boids) {
+ BoidState *state;
+ BoidRule *rule;
+
+ for (state = psett->boids->states.first; state; state = state->next) {
+ for (rule = state->rules.first; rule; rule = rule->next) {
+ if (rule->type == eBoidRuleType_Avoid) {
+ BoidRuleGoalAvoid *gabr = (BoidRuleGoalAvoid *)rule;
+ CALLBACK_INVOKE(gabr->ob, IDWALK_NOP);
+ }
+ else if (rule->type == eBoidRuleType_FollowLeader) {
+ BoidRuleFollowLeader *flbr = (BoidRuleFollowLeader *)rule;
+ CALLBACK_INVOKE(flbr->ob, IDWALK_NOP);
+ }
+ }
+ }
}
+
break;
}
@@ -439,18 +584,14 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
MovieClip *clip = (MovieClip *) id;
MovieTracking *tracking = &clip->tracking;
MovieTrackingObject *object;
- CALLBACK_INVOKE(clip->gpd, IDWALK_NOP);
- for (object = tracking->objects.first;
- object;
- object = object->next)
- {
+
+ CALLBACK_INVOKE(clip->gpd, IDWALK_USER);
+ for (object = tracking->objects.first; object; object = object->next) {
ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object);
MovieTrackingTrack *track;
- for (track = tracksbase->first;
- track;
- track = track->next)
- {
- CALLBACK_INVOKE(track->gpd, IDWALK_NOP);
+
+ for (track = tracksbase->first; track; track = track->next) {
+ CALLBACK_INVOKE(track->gpd, IDWALK_USER);
}
}
break;
@@ -460,20 +601,13 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
{
Mask *mask = (Mask *) id;
MaskLayer *mask_layer;
- for (mask_layer = mask->masklayers.first;
- mask_layer;
- mask_layer = mask_layer->next)
- {
+ for (mask_layer = mask->masklayers.first; mask_layer; mask_layer = mask_layer->next) {
MaskSpline *mask_spline;
- for (mask_spline = mask_layer->splines.first;
- mask_spline;
- mask_spline = mask_spline->next)
- {
- int i;
+ for (mask_spline = mask_layer->splines.first; mask_spline; mask_spline = mask_spline->next) {
for (i = 0; i < mask_spline->tot_point; i++) {
MaskSplinePoint *point = &mask_spline->points[i];
- CALLBACK_INVOKE_ID(point->parent.id, IDWALK_NOP);
+ CALLBACK_INVOKE_ID(point->parent.id, IDWALK_USER);
}
}
}
@@ -483,7 +617,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
case ID_LS:
{
FreestyleLineStyle *linestyle = (FreestyleLineStyle *) id;
- LineStyleModifier *m;
+ LineStyleModifier *lsm;
for (i = 0; i < MAX_MTEX; i++) {
if (linestyle->mtex[i]) {
library_foreach_mtex(&data, linestyle->mtex[i]);
@@ -491,25 +625,25 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
}
CALLBACK_INVOKE(linestyle->nodetree, IDWALK_NOP);
- for (m = (LineStyleModifier *)linestyle->color_modifiers.first; m; m = m->next) {
- if (m->type == LS_MODIFIER_DISTANCE_FROM_OBJECT) {
- LineStyleColorModifier_DistanceFromObject *p = (LineStyleColorModifier_DistanceFromObject *)m;
+ for (lsm = linestyle->color_modifiers.first; lsm; lsm = lsm->next) {
+ if (lsm->type == LS_MODIFIER_DISTANCE_FROM_OBJECT) {
+ LineStyleColorModifier_DistanceFromObject *p = (LineStyleColorModifier_DistanceFromObject *)lsm;
if (p->target) {
CALLBACK_INVOKE(p->target, IDWALK_NOP);
}
}
}
- for (m = (LineStyleModifier *)linestyle->alpha_modifiers.first; m; m = m->next) {
- if (m->type == LS_MODIFIER_DISTANCE_FROM_OBJECT) {
- LineStyleAlphaModifier_DistanceFromObject *p = (LineStyleAlphaModifier_DistanceFromObject *)m;
+ for (lsm = linestyle->alpha_modifiers.first; lsm; lsm = lsm->next) {
+ if (lsm->type == LS_MODIFIER_DISTANCE_FROM_OBJECT) {
+ LineStyleAlphaModifier_DistanceFromObject *p = (LineStyleAlphaModifier_DistanceFromObject *)lsm;
if (p->target) {
CALLBACK_INVOKE(p->target, IDWALK_NOP);
}
}
}
- for (m = (LineStyleModifier *)linestyle->thickness_modifiers.first; m; m = m->next) {
- if (m->type == LS_MODIFIER_DISTANCE_FROM_OBJECT) {
- LineStyleThicknessModifier_DistanceFromObject *p = (LineStyleThicknessModifier_DistanceFromObject *)m;
+ for (lsm = linestyle->thickness_modifiers.first; lsm; lsm = lsm->next) {
+ if (lsm->type == LS_MODIFIER_DISTANCE_FROM_OBJECT) {
+ LineStyleThicknessModifier_DistanceFromObject *p = (LineStyleThicknessModifier_DistanceFromObject *)lsm;
if (p->target) {
CALLBACK_INVOKE(p->target, IDWALK_NOP);
}
@@ -517,7 +651,6 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
}
break;
}
-
}
#undef CALLBACK_INVOKE_ID
@@ -526,3 +659,19 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
#undef FOREACH_CALLBACK_INVOKE_ID
#undef FOREACH_CALLBACK_INVOKE
+
+/**
+ * re-usable function, use when replacing ID's
+ */
+void BKE_library_update_ID_link_user(ID *id_dst, ID *id_src, const int cd_flag)
+{
+ if (cd_flag & IDWALK_USER) {
+ id_us_min(id_src);
+ id_us_plus(id_dst);
+ }
+ else if (cd_flag & IDWALK_USER_ONE) {
+ if (id_dst->us == 0) {
+ id_us_plus(id_dst);
+ }
+ }
+}
diff --git a/source/blender/blenkernel/intern/linestyle.c b/source/blender/blenkernel/intern/linestyle.c
index ac2c4e35dce..93d2b549fee 100644
--- a/source/blender/blenkernel/intern/linestyle.c
+++ b/source/blender/blenkernel/intern/linestyle.c
@@ -80,8 +80,10 @@ static const char *modifier_name[LS_MODIFIER_NUM] = {
"3D Curvature",
};
-static void default_linestyle_settings(FreestyleLineStyle *linestyle)
+void BKE_linestyle_init(FreestyleLineStyle *linestyle)
{
+ BLI_assert(MEMCMP_STRUCT_OFS_IS_ZERO(linestyle, id));
+
linestyle->panel = LS_PANEL_STROKES;
linestyle->r = linestyle->g = linestyle->b = 0.0f;
linestyle->alpha = 1.0f;
@@ -118,7 +120,7 @@ FreestyleLineStyle *BKE_linestyle_new(struct Main *bmain, const char *name)
linestyle = (FreestyleLineStyle *)BKE_libblock_alloc(bmain, ID_LS, name);
- default_linestyle_settings(linestyle);
+ BKE_linestyle_init(linestyle);
return linestyle;
}
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index fa0d34b8db6..a69b5fd87b5 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -78,7 +78,7 @@ Material defmaterial;
/* called on startup, creator.c */
void init_def_material(void)
{
- init_material(&defmaterial);
+ BKE_material_init(&defmaterial);
}
/* not material itself */
@@ -122,8 +122,10 @@ void BKE_material_free_ex(Material *ma, bool do_id_user)
GPU_material_free(&ma->gpumaterial);
}
-void init_material(Material *ma)
+void BKE_material_init(Material *ma)
{
+ BLI_assert(MEMCMP_STRUCT_OFS_IS_ZERO(ma, id));
+
ma->r = ma->g = ma->b = ma->ref = 0.8;
ma->specr = ma->specg = ma->specb = 1.0;
ma->mirr = ma->mirg = ma->mirb = 1.0;
@@ -221,7 +223,7 @@ Material *BKE_material_add(Main *bmain, const char *name)
ma = BKE_libblock_alloc(bmain, ID_MA, name);
- init_material(ma);
+ BKE_material_init(ma);
return ma;
}
@@ -1078,7 +1080,10 @@ static void do_init_render_material(Material *ma, int r_mode, float *amb)
static void init_render_nodetree(bNodeTree *ntree, Material *basemat, int r_mode, float *amb)
{
bNode *node;
-
+
+ /* parses the geom+tex nodes */
+ ntreeShaderGetTexcoMode(ntree, r_mode, &basemat->texco, &basemat->mode_l);
+
for (node = ntree->nodes.first; node; node = node->next) {
if (node->id) {
if (GS(node->id->name) == ID_MA) {
@@ -1115,9 +1120,6 @@ void init_render_material(Material *mat, int r_mode, float *amb)
mat->mode_l = (mat->mode & MA_MODE_PIPELINE) | MA_SHLESS;
mat->mode2_l = mat->mode2 & MA_MODE2_PIPELINE;
- /* parses the geom+tex nodes */
- ntreeShaderGetTexcoMode(mat->nodetree, r_mode, &mat->texco, &mat->mode_l);
-
init_render_nodetree(mat->nodetree, mat, r_mode, amb);
if (!mat->nodetree->execdata)
diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c
index c09cd1aabdc..bd9fd331584 100644
--- a/source/blender/blenkernel/intern/mball.c
+++ b/source/blender/blenkernel/intern/mball.c
@@ -91,19 +91,26 @@ void BKE_mball_free(MetaBall *mb)
if (mb->disp.first) BKE_displist_free(&mb->disp);
}
-MetaBall *BKE_mball_add(Main *bmain, const char *name)
+void BKE_mball_init(MetaBall *mb)
{
- MetaBall *mb;
-
- mb = BKE_libblock_alloc(bmain, ID_MB, name);
-
+ BLI_assert(MEMCMP_STRUCT_OFS_IS_ZERO(mb, id));
+
mb->size[0] = mb->size[1] = mb->size[2] = 1.0;
mb->texflag = MB_AUTOSPACE;
mb->wiresize = 0.4f;
mb->rendersize = 0.2f;
mb->thresh = 0.6f;
-
+}
+
+MetaBall *BKE_mball_add(Main *bmain, const char *name)
+{
+ MetaBall *mb;
+
+ mb = BKE_libblock_alloc(bmain, ID_MB, name);
+
+ BKE_mball_init(mb);
+
return mb;
}
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index f85e54a8362..318040db2be 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -490,12 +490,10 @@ static void mesh_tessface_clear_intern(Mesh *mesh, int free_customdata)
mesh->totface = 0;
}
-Mesh *BKE_mesh_add(Main *bmain, const char *name)
+void BKE_mesh_init(Mesh *me)
{
- Mesh *me;
-
- me = BKE_libblock_alloc(bmain, ID_ME, name);
-
+ BLI_assert(MEMCMP_STRUCT_OFS_IS_ZERO(me, id));
+
me->size[0] = me->size[1] = me->size[2] = 1.0;
me->smoothresh = 30;
me->texflag = ME_AUTOSPACE;
@@ -511,6 +509,15 @@ Mesh *BKE_mesh_add(Main *bmain, const char *name)
CustomData_reset(&me->fdata);
CustomData_reset(&me->pdata);
CustomData_reset(&me->ldata);
+}
+
+Mesh *BKE_mesh_add(Main *bmain, const char *name)
+{
+ Mesh *me;
+
+ me = BKE_libblock_alloc(bmain, ID_ME, name);
+
+ BKE_mesh_init(me);
return me;
}
@@ -2199,8 +2206,9 @@ void BKE_mesh_calc_normals_split(Mesh *mesh)
}
else {
polynors = MEM_mallocN(sizeof(float[3]) * mesh->totpoly, __func__);
- BKE_mesh_calc_normals_poly(mesh->mvert, mesh->totvert, mesh->mloop, mesh->mpoly, mesh->totloop, mesh->totpoly,
- polynors, false);
+ BKE_mesh_calc_normals_poly(
+ mesh->mvert, NULL, mesh->totvert,
+ mesh->mloop, mesh->mpoly, mesh->totloop, mesh->totpoly, polynors, false);
free_polynors = true;
}
@@ -2340,6 +2348,19 @@ Mesh *BKE_mesh_new_from_object(
tmpcu = (Curve *)tmpobj->data;
tmpcu->id.us--;
+ /* Copy cached display list, it might be needed by the stack evaluation.
+ * Ideally stack should be able to use render-time display list, but doing
+ * so is quite tricky and not safe so close to the release.
+ *
+ * TODO(sergey): Look into more proper solution.
+ */
+ if (ob->curve_cache != NULL) {
+ if (tmpobj->curve_cache == NULL) {
+ tmpobj->curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for curve types");
+ }
+ BKE_displist_copy(&tmpobj->curve_cache->disp, &ob->curve_cache->disp);
+ }
+
/* if getting the original caged mesh, delete object modifiers */
if (cage)
BKE_object_free_modifiers(tmpobj);
diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c
index d4787bd250c..a65ac5151a8 100644
--- a/source/blender/blenkernel/intern/mesh_evaluate.c
+++ b/source/blender/blenkernel/intern/mesh_evaluate.c
@@ -51,6 +51,7 @@
#include "BLI_task.h"
#include "BKE_customdata.h"
+#include "BKE_global.h"
#include "BKE_mesh.h"
#include "BKE_multires.h"
#include "BKE_report.h"
@@ -132,7 +133,7 @@ void BKE_mesh_calc_normals_mapping_ex(
if (only_face_normals == false) {
/* vertex normals are optional, they require some extra calculations,
* so make them optional */
- BKE_mesh_calc_normals_poly(mverts, numVerts, mloop, mpolys, numLoops, numPolys, pnors, false);
+ BKE_mesh_calc_normals_poly(mverts, NULL, numVerts, mloop, mpolys, numLoops, numPolys, pnors, false);
}
else {
/* only calc poly normals */
@@ -221,18 +222,20 @@ static void mesh_calc_normals_poly_accum(
}
void BKE_mesh_calc_normals_poly(
- MVert *mverts, int numVerts,
+ MVert *mverts, float (*r_vertnors)[3], int numVerts,
const MLoop *mloop, const MPoly *mpolys,
int UNUSED(numLoops), int numPolys, float (*r_polynors)[3],
const bool only_face_normals)
{
float (*pnors)[3] = r_polynors;
- float (*tnorms)[3];
+ float (*vnors)[3] = r_vertnors;
+ bool free_vnors = false;
int i;
const MPoly *mp;
if (only_face_normals) {
BLI_assert((pnors != NULL) || (numPolys == 0));
+ BLI_assert(r_vertnors == NULL);
#pragma omp parallel for if (numPolys > BKE_MESH_OMP_LIMIT)
for (i = 0; i < numPolys; i++) {
@@ -242,25 +245,30 @@ void BKE_mesh_calc_normals_poly(
}
/* first go through and calculate normals for all the polys */
- tnorms = MEM_callocN(sizeof(*tnorms) * (size_t)numVerts, __func__);
+ if (vnors == NULL) {
+ vnors = MEM_callocN(sizeof(*vnors) * (size_t)numVerts, __func__);
+ free_vnors = true;
+ }
+ else {
+ memset(vnors, 0, sizeof(*vnors) * (size_t)numVerts);
+ }
+ mp = mpolys;
if (pnors) {
- mp = mpolys;
for (i = 0; i < numPolys; i++, mp++) {
- mesh_calc_normals_poly_accum(mp, mloop + mp->loopstart, mverts, pnors[i], tnorms);
+ mesh_calc_normals_poly_accum(mp, mloop + mp->loopstart, mverts, pnors[i], vnors);
}
}
else {
float tpnor[3]; /* temp poly normal */
- mp = mpolys;
for (i = 0; i < numPolys; i++, mp++) {
- mesh_calc_normals_poly_accum(mp, mloop + mp->loopstart, mverts, tpnor, tnorms);
+ mesh_calc_normals_poly_accum(mp, mloop + mp->loopstart, mverts, tpnor, vnors);
}
}
for (i = 0; i < numVerts; i++) {
MVert *mv = &mverts[i];
- float *no = tnorms[i];
+ float *no = vnors[i];
if (UNLIKELY(normalize_v3(no) == 0.0f)) {
/* following Mesh convention; we use vertex coordinate itself for normal in this case */
@@ -270,7 +278,9 @@ void BKE_mesh_calc_normals_poly(
normal_float_to_short_v3(mv->no, no);
}
- MEM_freeN(tnorms);
+ if (free_vnors) {
+ MEM_freeN(vnors);
+ }
}
void BKE_mesh_calc_normals(Mesh *mesh)
@@ -278,7 +288,7 @@ void BKE_mesh_calc_normals(Mesh *mesh)
#ifdef DEBUG_TIME
TIMEIT_START(BKE_mesh_calc_normals);
#endif
- BKE_mesh_calc_normals_poly(mesh->mvert, mesh->totvert,
+ BKE_mesh_calc_normals_poly(mesh->mvert, NULL, mesh->totvert,
mesh->mloop, mesh->mpoly, mesh->totloop, mesh->totpoly,
NULL, false);
#ifdef DEBUG_TIME
@@ -883,7 +893,9 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, LoopSpli
clnors_avg[0] /= clnors_nbr;
clnors_avg[1] /= clnors_nbr;
/* Fix/update all clnors of this fan with computed average value. */
- printf("Invalid clnors in this fan!\n");
+ if (G.debug & G_DEBUG) {
+ printf("Invalid clnors in this fan!\n");
+ }
while ((clnor = BLI_SMALLSTACK_POP(clnors))) {
//print_v2("org clnor", clnor);
clnor[0] = (short)clnors_avg[0];
@@ -1338,12 +1350,14 @@ void BKE_mesh_normals_loop_split(
* Compute internal representation of given custom normals (as an array of float[2]).
* It also makes sure the mesh matches those custom normals, by setting sharp edges flag as needed to get a
* same custom lnor for all loops sharing a same smooth fan.
- * If use_vertices if true, custom_loopnors is assumed to be per-vertex, not per-loop
+ * If use_vertices if true, r_custom_loopnors is assumed to be per-vertex, not per-loop
* (this allows to set whole vert's normals at once, useful in some cases).
+ * r_custom_loopnors is expected to have normalized normals, or zero ones, in which case they will be replaced
+ * by default loop/vertex normal.
*/
static void mesh_normals_loop_custom_set(
const MVert *mverts, const int numVerts, MEdge *medges, const int numEdges,
- MLoop *mloops, float (*custom_loopnors)[3], const int numLoops,
+ MLoop *mloops, float (*r_custom_loopnors)[3], const int numLoops,
MPoly *mpolys, const float (*polynors)[3], const int numPolys,
short (*r_clnors_data)[2], const bool use_vertices)
{
@@ -1369,6 +1383,22 @@ static void mesh_normals_loop_custom_set(
mpolys, polynors, numPolys, use_split_normals, split_angle,
&lnors_spacearr, NULL, loop_to_poly);
+ /* Set all given zero vectors to their default value. */
+ if (use_vertices) {
+ for (i = 0; i < numVerts; i++) {
+ if (is_zero_v3(r_custom_loopnors[i])) {
+ normal_short_to_float_v3(r_custom_loopnors[i], mverts[i].no);
+ }
+ }
+ }
+ else {
+ for (i = 0; i < numLoops; i++) {
+ if (is_zero_v3(r_custom_loopnors[i])) {
+ copy_v3_v3(r_custom_loopnors[i], lnors[i]);
+ }
+ }
+ }
+
/* Now, check each current smooth fan (one lnor space per smooth fan!), and if all its matching custom lnors
* are not (enough) equal, add sharp edges as needed.
* This way, next time we run BKE_mesh_normals_loop_split(), we'll get lnor spacearr/smooth fans matching
@@ -1384,7 +1414,9 @@ static void mesh_normals_loop_custom_set(
* Maybe we should set those loops' edges as sharp?
*/
BLI_BITMAP_ENABLE(done_loops, i);
- printf("WARNING! Getting invalid NULL loop space for loop %d!\n", i);
+ if (G.debug & G_DEBUG) {
+ printf("WARNING! Getting invalid NULL loop space for loop %d!\n", i);
+ }
continue;
}
@@ -1406,11 +1438,7 @@ static void mesh_normals_loop_custom_set(
const int lidx = GET_INT_FROM_POINTER(loops->link);
MLoop *ml = &mloops[lidx];
const int nidx = lidx;
- float *nor = custom_loopnors[nidx];
-
- if (is_zero_v3(nor)) {
- nor = lnors[nidx];
- }
+ float *nor = r_custom_loopnors[nidx];
if (!org_nor) {
org_nor = nor;
@@ -1432,7 +1460,26 @@ static void mesh_normals_loop_custom_set(
loops = loops->next;
BLI_BITMAP_ENABLE(done_loops, lidx);
}
- BLI_BITMAP_ENABLE(done_loops, i); /* For single loops, where lnors_spacearr.lspacearr[i]->loops is NULL. */
+
+ /* We also have to check between last and first loops, otherwise we may miss some sharp edges here!
+ * This is just a simplified version of above while loop.
+ * See T45984. */
+ loops = lnors_spacearr.lspacearr[i]->loops;
+ if (loops && org_nor) {
+ const int lidx = GET_INT_FROM_POINTER(loops->link);
+ MLoop *ml = &mloops[lidx];
+ const int nidx = lidx;
+ float *nor = r_custom_loopnors[nidx];
+
+ if (dot_v3v3(org_nor, nor) < LNOR_SPACE_TRIGO_THRESHOLD) {
+ const MPoly *mp = &mpolys[loop_to_poly[lidx]];
+ const MLoop *mlp = &mloops[(lidx == mp->loopstart) ? mp->loopstart + mp->totloop - 1 : lidx - 1];
+ medges[(prev_ml->e == mlp->e) ? prev_ml->e : ml->e].flag |= ME_SHARP;
+ }
+ }
+
+ /* For single loops, where lnors_spacearr.lspacearr[i]->loops is NULL. */
+ BLI_BITMAP_ENABLE(done_loops, i);
}
}
@@ -1450,7 +1497,9 @@ static void mesh_normals_loop_custom_set(
for (i = 0; i < numLoops; i++) {
if (!lnors_spacearr.lspacearr[i]) {
BLI_BITMAP_DISABLE(done_loops, i);
- printf("WARNING! Still getting invalid NULL loop space in second loop for loop %d!\n", i);
+ if (G.debug & G_DEBUG) {
+ printf("WARNING! Still getting invalid NULL loop space in second loop for loop %d!\n", i);
+ }
continue;
}
@@ -1469,11 +1518,7 @@ static void mesh_normals_loop_custom_set(
while (loops) {
const int lidx = GET_INT_FROM_POINTER(loops->link);
const int nidx = use_vertices ? (int)mloops[lidx].v : lidx;
- float *nor = custom_loopnors[nidx];
-
- if (is_zero_v3(nor)) {
- nor = lnors[nidx];
- }
+ float *nor = r_custom_loopnors[nidx];
nbr_nors++;
add_v3_v3(avg_nor, nor);
@@ -1493,7 +1538,7 @@ static void mesh_normals_loop_custom_set(
}
else {
const int nidx = use_vertices ? (int)mloops[i].v : i;
- float *nor = custom_loopnors[nidx];
+ float *nor = r_custom_loopnors[nidx];
BKE_lnor_space_custom_normal_to_data(lnors_spacearr.lspacearr[i], nor, r_clnors_data[i]);
BLI_BITMAP_DISABLE(done_loops, i);
@@ -1509,21 +1554,21 @@ static void mesh_normals_loop_custom_set(
void BKE_mesh_normals_loop_custom_set(
const MVert *mverts, const int numVerts, MEdge *medges, const int numEdges,
- MLoop *mloops, float (*custom_loopnors)[3], const int numLoops,
+ MLoop *mloops, float (*r_custom_loopnors)[3], const int numLoops,
MPoly *mpolys, const float (*polynors)[3], const int numPolys,
short (*r_clnors_data)[2])
{
- mesh_normals_loop_custom_set(mverts, numVerts, medges, numEdges, mloops, custom_loopnors, numLoops,
+ mesh_normals_loop_custom_set(mverts, numVerts, medges, numEdges, mloops, r_custom_loopnors, numLoops,
mpolys, polynors, numPolys, r_clnors_data, false);
}
void BKE_mesh_normals_loop_custom_from_vertices_set(
- const MVert *mverts, float (*custom_vertnors)[3], const int numVerts,
+ const MVert *mverts, float (*r_custom_vertnors)[3], const int numVerts,
MEdge *medges, const int numEdges, MLoop *mloops, const int numLoops,
MPoly *mpolys, const float (*polynors)[3], const int numPolys,
short (*r_clnors_data)[2])
{
- mesh_normals_loop_custom_set(mverts, numVerts, medges, numEdges, mloops, custom_vertnors, numLoops,
+ mesh_normals_loop_custom_set(mverts, numVerts, medges, numEdges, mloops, r_custom_vertnors, numLoops,
mpolys, polynors, numPolys, r_clnors_data, true);
}
@@ -1531,7 +1576,7 @@ void BKE_mesh_normals_loop_custom_from_vertices_set(
* Computes average per-vertex normals from given custom loop normals.
*
* @param clnors The computed custom loop normals.
- * @param r_vert_clnors The (already allocated) array wher to store averaged per-vertex normals.
+ * @param r_vert_clnors The (already allocated) array where to store averaged per-vertex normals.
*/
void BKE_mesh_normals_loop_to_vertex(
const int numVerts, const MLoop *mloops, const int numLoops,
@@ -3211,7 +3256,7 @@ void BKE_mesh_flush_hidden_from_polys_ex(MVert *mvert,
j = mp->totloop;
for (ml = &mloop[mp->loopstart]; j--; ml++) {
mvert[ml->v].flag &= (char)~ME_HIDE;
- medge[ml->e].flag &= (char)~ME_HIDE;
+ medge[ml->e].flag &= (short)~ME_HIDE;
}
}
}
diff --git a/source/blender/blenkernel/intern/mesh_mapping.c b/source/blender/blenkernel/intern/mesh_mapping.c
index ef9136397fa..8dce3c372f6 100644
--- a/source/blender/blenkernel/intern/mesh_mapping.c
+++ b/source/blender/blenkernel/intern/mesh_mapping.c
@@ -65,7 +65,7 @@ UvVertMap *BKE_mesh_uv_vert_map_create(
unsigned int a;
int i, totuv, nverts;
- bool *winding;
+ bool *winding = NULL;
BLI_buffer_declare_static(vec2f, tf_uv_buf, BLI_BUFFER_NOP, 32);
totuv = 0;
@@ -94,10 +94,10 @@ UvVertMap *BKE_mesh_uv_vert_map_create(
mp = mpoly;
for (a = 0; a < totpoly; a++, mp++) {
if (!selected || (!(mp->flag & ME_HIDE) && (mp->flag & ME_FACE_SEL))) {
- float (*tf_uv)[2];
+ float (*tf_uv)[2] = NULL;
if (use_winding) {
- tf_uv = (float (*)[2])BLI_buffer_resize_data(&tf_uv_buf, vec2f, mp->totloop);
+ tf_uv = (float (*)[2])BLI_buffer_reinit_data(&tf_uv_buf, vec2f, (size_t)mp->totloop);
}
nverts = mp->totloop;
diff --git a/source/blender/blenkernel/intern/mesh_remap.c b/source/blender/blenkernel/intern/mesh_remap.c
index 993921c22e0..258131f46ed 100644
--- a/source/blender/blenkernel/intern/mesh_remap.c
+++ b/source/blender/blenkernel/intern/mesh_remap.c
@@ -237,7 +237,7 @@ static void mesh_calc_eigen_matrix(
/* Protect against 1D/2D degenerated cases! */
/* Note: not sure why we need square root of eigen values here (which are equivalent to singular values,
- * as far as I have understood), but it seems to heavily reduce (if not completly nullify)
+ * as far as I have understood), but it seems to heavily reduce (if not completely nullify)
* the error due to non-uniform scalings... */
evi = (evi < 1e-6f && evi > -1e-6f) ? ((evi < 0.0f) ? -1e-3f : 1e-3f) : sqrtf_signed(evi);
mul_v3_fl(eigen_vec[i], evi);
@@ -455,14 +455,13 @@ void BKE_mesh_remap_calc_verts_from_dm(
BVHTreeNearest nearest = {0};
BVHTreeRayHit rayhit = {0};
float hit_dist;
+ float tmp_co[3], tmp_no[3];
if (mode == MREMAP_MODE_VERT_NEAREST) {
bvhtree_from_mesh_verts(&treedata, dm_src, 0.0f, 2, 6);
nearest.index = -1;
for (i = 0; i < numverts_dst; i++) {
- float tmp_co[3];
-
copy_v3_v3(tmp_co, verts_dst[i].co);
/* Convert the vertex to tree coordinates, if needed. */
@@ -488,8 +487,6 @@ void BKE_mesh_remap_calc_verts_from_dm(
nearest.index = -1;
for (i = 0; i < numverts_dst; i++) {
- float tmp_co[3];
-
copy_v3_v3(tmp_co, verts_dst[i].co);
/* Convert the vertex to tree coordinates, if needed. */
@@ -548,8 +545,6 @@ void BKE_mesh_remap_calc_verts_from_dm(
if (mode == MREMAP_MODE_VERT_POLYINTERP_VNORPROJ) {
for (i = 0; i < numverts_dst; i++) {
- float tmp_co[3], tmp_no[3];
-
copy_v3_v3(tmp_co, verts_dst[i].co);
normal_short_to_float_v3(tmp_no, verts_dst[i].no);
@@ -580,8 +575,6 @@ void BKE_mesh_remap_calc_verts_from_dm(
nearest.index = -1;
for (i = 0; i < numverts_dst; i++) {
- float tmp_co[3];
-
copy_v3_v3(tmp_co, verts_dst[i].co);
/* Convert the vertex to tree coordinates, if needed. */
@@ -656,6 +649,7 @@ void BKE_mesh_remap_calc_edges_from_dm(
BVHTreeNearest nearest = {0};
BVHTreeRayHit rayhit = {0};
float hit_dist;
+ float tmp_co[3], tmp_no[3];
if (mode == MREMAP_MODE_EDGE_VERT_NEAREST) {
const int num_verts_src = dm_src->getNumVerts(dm_src);
@@ -694,8 +688,6 @@ void BKE_mesh_remap_calc_edges_from_dm(
/* Compute closest verts only once! */
if (v_dst_to_src_map[vidx_dst].hit_dist == -1.0f) {
- float tmp_co[3];
-
copy_v3_v3(tmp_co, verts_dst[vidx_dst].co);
/* Convert the vertex to tree coordinates, if needed. */
@@ -786,8 +778,6 @@ void BKE_mesh_remap_calc_edges_from_dm(
nearest.index = -1;
for (i = 0; i < numedges_dst; i++) {
- float tmp_co[3];
-
interp_v3_v3v3(tmp_co, verts_dst[edges_dst[i].v1].co, verts_dst[edges_dst[i].v2].co, 0.5f);
/* Convert the vertex to tree coordinates, if needed. */
@@ -814,8 +804,6 @@ void BKE_mesh_remap_calc_edges_from_dm(
bvhtree_from_mesh_looptri(&treedata, dm_src, 0.0f, 2, 6);
for (i = 0; i < numedges_dst; i++) {
- float tmp_co[3];
-
interp_v3_v3v3(tmp_co, verts_dst[edges_dst[i].v1].co, verts_dst[edges_dst[i].v2].co, 0.5f);
/* Convert the vertex to tree coordinates, if needed. */
@@ -872,8 +860,8 @@ void BKE_mesh_remap_calc_edges_from_dm(
/* For each dst edge, we sample some rays from it (interpolated from its vertices)
* and use their hits to interpolate from source edges. */
const MEdge *me = &edges_dst[i];
- float tmp_co[3], v1_co[3], v2_co[3];
- float tmp_no[3], v1_no[3], v2_no[3];
+ float v1_co[3], v2_co[3];
+ float v1_no[3], v2_no[3];
int grid_size;
float edge_dst_len;
@@ -1150,6 +1138,7 @@ void BKE_mesh_remap_calc_loops_from_dm(
BVHTreeRayHit rayhit = {0};
int num_trees = 0;
float hit_dist;
+ float tmp_co[3], tmp_no[3];
const bool use_from_vert = (mode & MREMAP_USE_VERT);
@@ -1234,7 +1223,7 @@ void BKE_mesh_remap_calc_loops_from_dm(
CustomData_set_layer_flag(pdata_dst, CD_NORMAL, CD_FLAG_TEMPORARY);
}
if (dirty_nors_dst) {
- BKE_mesh_calc_normals_poly(verts_dst, numverts_dst, loops_dst, polys_dst,
+ BKE_mesh_calc_normals_poly(verts_dst, NULL, numverts_dst, loops_dst, polys_dst,
numloops_dst, numpolys_dst, poly_nors_dst, true);
}
}
@@ -1440,13 +1429,18 @@ void BKE_mesh_remap_calc_loops_from_dm(
}
for (pidx_dst = 0, mp_dst = polys_dst; pidx_dst < numpolys_dst; pidx_dst++, mp_dst++) {
- float (*pnor_dst)[3] = &poly_nors_dst[pidx_dst];
+ float pnor_dst[3];
/* Only in use_from_vert case, we may need polys' centers as fallback in case we cannot decide which
* corner to use from normals only. */
float pcent_dst[3];
bool pcent_dst_valid = false;
+ if (mode == MREMAP_MODE_LOOP_NEAREST_POLYNOR) {
+ copy_v3_v3(pnor_dst, poly_nors_dst[pidx_dst]);
+ BLI_space_transform_apply_normal(space_transform, pnor_dst);
+ }
+
if ((size_t)mp_dst->totloop > islands_res_buff_size) {
islands_res_buff_size = (size_t)mp_dst->totloop + MREMAP_DEFAULT_BUFSIZE;
for (tindex = 0; tindex < num_trees; tindex++) {
@@ -1460,7 +1454,6 @@ void BKE_mesh_remap_calc_loops_from_dm(
ml_dst = &loops_dst[mp_dst->loopstart];
for (plidx_dst = 0; plidx_dst < mp_dst->totloop; plidx_dst++, ml_dst++) {
if (use_from_vert) {
- float tmp_co[3];
MeshElemMap *vert_to_refelem_map_src = NULL;
copy_v3_v3(tmp_co, verts_dst[ml_dst->v].co);
@@ -1479,12 +1472,14 @@ void BKE_mesh_remap_calc_loops_from_dm(
int best_index_src = -1;
if (mode == MREMAP_MODE_LOOP_NEAREST_LOOPNOR) {
- nor_dst = &loop_nors_dst[plidx_dst + mp_dst->loopstart];
+ copy_v3_v3(tmp_no, loop_nors_dst[plidx_dst + mp_dst->loopstart]);
+ BLI_space_transform_apply_normal(space_transform, tmp_no);
+ nor_dst = &tmp_no;
nors_src = loop_nors_src;
vert_to_refelem_map_src = vert_to_loop_map_src;
}
else { /* if (mode == MREMAP_MODE_LOOP_NEAREST_POLYNOR) { */
- nor_dst = pnor_dst;
+ nor_dst = &pnor_dst;
nors_src = poly_nors_src;
vert_to_refelem_map_src = vert_to_poly_map_src;
}
@@ -1556,8 +1551,6 @@ void BKE_mesh_remap_calc_loops_from_dm(
}
}
else if (mode & MREMAP_USE_NORPROJ) {
- float tmp_co[3], tmp_no[3];
-
int n = (ray_radius > 0.0f) ? MREMAP_RAYCAST_APPROXIMATE_NR : 1;
float w = 1.0f;
@@ -1615,8 +1608,6 @@ void BKE_mesh_remap_calc_loops_from_dm(
}
}
else { /* Nearest poly either to use all its loops/verts or just closest one. */
- float tmp_co[3];
-
copy_v3_v3(tmp_co, verts_dst[ml_dst->v].co);
nearest.index = -1;
@@ -1739,7 +1730,6 @@ void BKE_mesh_remap_calc_loops_from_dm(
* Note we could be much more subtle here, again that's for later... */
int j;
float best_dist_sq = FLT_MAX;
- float tmp_co[3];
ml_dst = &loops_dst[lidx_dst];
copy_v3_v3(tmp_co, verts_dst[ml_dst->v].co);
@@ -1824,7 +1814,6 @@ void BKE_mesh_remap_calc_loops_from_dm(
/* Find a new valid loop in that new poly (nearest point on poly for now).
* Note we could be much more subtle here, again that's for later... */
float best_dist_sq = FLT_MAX;
- float tmp_co[3];
int j;
ml_dst = &loops_dst[lidx_dst];
@@ -1987,6 +1976,7 @@ void BKE_mesh_remap_calc_polys_from_dm(
const float full_weight = 1.0f;
const float max_dist_sq = max_dist * max_dist;
float (*poly_nors_dst)[3] = NULL;
+ float tmp_co[3], tmp_no[3];
int i;
BLI_assert(mode & MREMAP_MODE_POLY);
@@ -1999,7 +1989,7 @@ void BKE_mesh_remap_calc_polys_from_dm(
CustomData_set_layer_flag(pdata_dst, CD_NORMAL, CD_FLAG_TEMPORARY);
}
if (dirty_nors_dst) {
- BKE_mesh_calc_normals_poly(verts_dst, numverts_dst, loops_dst, polys_dst, numloops_dst, numpolys_dst,
+ BKE_mesh_calc_normals_poly(verts_dst, NULL, numverts_dst, loops_dst, polys_dst, numloops_dst, numpolys_dst,
poly_nors_dst, true);
}
}
@@ -2028,7 +2018,6 @@ void BKE_mesh_remap_calc_polys_from_dm(
for (i = 0; i < numpolys_dst; i++) {
MPoly *mp = &polys_dst[i];
- float tmp_co[3];
BKE_mesh_calc_poly_center(mp, &loops_dst[mp->loopstart], verts_dst, tmp_co);
@@ -2055,7 +2044,6 @@ void BKE_mesh_remap_calc_polys_from_dm(
for (i = 0; i < numpolys_dst; i++) {
MPoly *mp = &polys_dst[i];
- float tmp_co[3], tmp_no[3];
BKE_mesh_calc_poly_center(mp, &loops_dst[mp->loopstart], verts_dst, tmp_co);
copy_v3_v3(tmp_no, poly_nors_dst[i]);
@@ -2104,7 +2092,6 @@ void BKE_mesh_remap_calc_polys_from_dm(
* and use their hits to interpolate from source polys. */
/* Note: dst poly is early-converted into src space! */
MPoly *mp = &polys_dst[i];
- float tmp_co[3], tmp_no[3];
int tot_rays, done_rays = 0;
float poly_area_2d_inv, done_area = 0.0f;
diff --git a/source/blender/blenkernel/intern/mesh_validate.c b/source/blender/blenkernel/intern/mesh_validate.c
index e21dde9c726..ab469ac3996 100644
--- a/source/blender/blenkernel/intern/mesh_validate.c
+++ b/source/blender/blenkernel/intern/mesh_validate.c
@@ -241,6 +241,7 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
struct {
int verts : 1;
int verts_weight : 1;
+ int loops_edge : 1;
};
int as_flag;
} fix_flag;
@@ -564,6 +565,7 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
if (do_fixes) {
int prev_e = ml->e;
ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(edge_hash, v1, v2));
+ fix_flag.loops_edge = true;
PRINT_ERR("\tLoop %u has invalid edge reference (%d), fixed using edge %u\n",
sp->loopstart + j, prev_e, ml->e);
}
@@ -580,6 +582,7 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
if (do_fixes) {
int prev_e = ml->e;
ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(edge_hash, v1, v2));
+ fix_flag.loops_edge = true;
PRINT_ERR("\tPoly %u has invalid edge reference (%d), fixed using edge %u\n",
sp->index, prev_e, ml->e);
}
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
index b2c0c6d6d0a..716da14cae6 100644
--- a/source/blender/blenkernel/intern/modifier.c
+++ b/source/blender/blenkernel/intern/modifier.c
@@ -215,8 +215,7 @@ void modifiers_clearErrors(Object *ob)
}
}
-void modifiers_foreachObjectLink(Object *ob, ObjectWalkFunc walk,
- void *userData)
+void modifiers_foreachObjectLink(Object *ob, ObjectWalkFunc walk, void *userData)
{
ModifierData *md = ob->modifiers.first;
diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c
index 7a8c4ad4564..432ae32f02b 100644
--- a/source/blender/blenkernel/intern/movieclip.c
+++ b/source/blender/blenkernel/intern/movieclip.c
@@ -603,9 +603,8 @@ static void detect_clip_source(MovieClip *clip)
MovieClip *BKE_movieclip_file_add(Main *bmain, const char *name)
{
MovieClip *clip;
- int file, len;
- const char *libname;
- char str[FILE_MAX], strtest[FILE_MAX];
+ int file;
+ char str[FILE_MAX];
BLI_strncpy(str, name, sizeof(str));
BLI_path_abs(str, bmain->name);
@@ -616,29 +615,10 @@ MovieClip *BKE_movieclip_file_add(Main *bmain, const char *name)
return NULL;
close(file);
- /* ** first search an identical clip ** */
- for (clip = bmain->movieclip.first; clip; clip = clip->id.next) {
- BLI_strncpy(strtest, clip->name, sizeof(clip->name));
- BLI_path_abs(strtest, G.main->name);
-
- if (STREQ(strtest, str)) {
- BLI_strncpy(clip->name, name, sizeof(clip->name)); /* for stringcode */
- clip->id.us++; /* officially should not, it doesn't link here! */
-
- return clip;
- }
- }
-
/* ** add new movieclip ** */
/* create a short library name */
- len = strlen(name);
-
- while (len > 0 && name[len - 1] != '/' && name[len - 1] != '\\')
- len--;
- libname = name + len;
-
- clip = movieclip_alloc(bmain, libname);
+ clip = movieclip_alloc(bmain, BLI_path_basename(name));
BLI_strncpy(clip->name, name, sizeof(clip->name));
detect_clip_source(clip);
@@ -655,6 +635,37 @@ MovieClip *BKE_movieclip_file_add(Main *bmain, const char *name)
return clip;
}
+MovieClip *BKE_movieclip_file_add_exists_ex(Main *bmain, const char *filepath, bool *r_exists)
+{
+ MovieClip *clip;
+ char str[FILE_MAX], strtest[FILE_MAX];
+
+ BLI_strncpy(str, filepath, sizeof(str));
+ BLI_path_abs(str, bmain->name);
+
+ /* first search an identical filepath */
+ for (clip = bmain->movieclip.first; clip; clip = clip->id.next) {
+ BLI_strncpy(strtest, clip->name, sizeof(clip->name));
+ BLI_path_abs(strtest, ID_BLEND_PATH(bmain, &clip->id));
+
+ if (BLI_path_cmp(strtest, str) == 0) {
+ clip->id.us++; /* officially should not, it doesn't link here! */
+ if (r_exists)
+ *r_exists = true;
+ return clip;
+ }
+ }
+
+ if (r_exists)
+ *r_exists = false;
+ return BKE_movieclip_file_add(bmain, filepath);
+}
+
+MovieClip *BKE_movieclip_file_add_exists(Main *bmain, const char *filepath)
+{
+ return BKE_movieclip_file_add_exists_ex(bmain, filepath, NULL);
+}
+
static void real_ibuf_size(MovieClip *clip, MovieClipUser *user, ImBuf *ibuf, int *width, int *height)
{
*width = ibuf->x;
@@ -847,7 +858,7 @@ static ImBuf *movieclip_get_postprocessed_ibuf(MovieClip *clip, MovieClipUser *u
bool need_postprocess = false;
/* cache isn't threadsafe itself and also loading of movies
- * can't happen from concurent threads that's why we use lock here */
+ * can't happen from concurrent threads that's why we use lock here */
BLI_lock_thread(LOCK_MOVIECLIP);
/* try to obtain cached postprocessed frame first */
diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c
index 9ef5b697079..fbba6249b73 100644
--- a/source/blender/blenkernel/intern/multires.c
+++ b/source/blender/blenkernel/intern/multires.c
@@ -1464,10 +1464,10 @@ DerivedMesh *multires_make_derived_from_derived(DerivedMesh *dm,
gridData = result->getGridData(result);
result->getGridKey(result, &key);
- subGridData = MEM_callocN(sizeof(CCGElem *) * numGrids, "subGridData*");
+ subGridData = MEM_mallocN(sizeof(CCGElem *) * numGrids, "subGridData*");
for (i = 0; i < numGrids; i++) {
- subGridData[i] = MEM_callocN(key.elem_size * gridSize * gridSize, "subGridData");
+ subGridData[i] = MEM_mallocN(key.elem_size * gridSize * gridSize, "subGridData");
memcpy(subGridData[i], gridData[i], key.elem_size * gridSize * gridSize);
}
diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c
index a04eb9bd611..65245477c7f 100644
--- a/source/blender/blenkernel/intern/nla.c
+++ b/source/blender/blenkernel/intern/nla.c
@@ -1178,7 +1178,34 @@ static void nlastrip_fix_resize_overlaps(NlaStrip *strip)
NlaStrip *nls = strip->next;
float offset = 0.0f;
- if (strip->end > nls->start) {
+ if (nls->type == NLASTRIP_TYPE_TRANSITION) {
+ /* transition strips should grow/shrink to accomodate the resized strip,
+ * but if the strip's bounds now exceed the transition, we're forced to
+ * offset everything to maintain the balance
+ */
+ if (strip->end <= nls->start) {
+ /* grow the transition to fill the void */
+ nls->start = strip->end;
+ }
+ else if (strip->end < nls->end) {
+ /* shrink the transition to give the strip room */
+ nls->start = strip->end;
+ }
+ else {
+ /* shrink transition down to 1 frame long (so that it can still be found),
+ * then offset everything else by the remaining defict to give the strip room
+ */
+ nls->start = nls->end - 1.0f;
+ offset = ceilf(strip->end - nls->start); /* XXX: review whether preventing fractionals is good here... */
+
+ /* apply necessary offset to ensure that the strip has enough space */
+ for (; nls; nls = nls->next) {
+ nls->start += offset;
+ nls->end += offset;
+ }
+ }
+ }
+ else if (strip->end > nls->start) {
/* NOTE: need to ensure we don't have a fractional frame offset, even if that leaves a gap,
* otherwise it will be very hard to get rid of later
*/
@@ -1198,7 +1225,34 @@ static void nlastrip_fix_resize_overlaps(NlaStrip *strip)
NlaStrip *nls = strip->prev;
float offset = 0.0f;
- if (strip->start < nls->end) {
+ if (nls->type == NLASTRIP_TYPE_TRANSITION) {
+ /* transition strips should grow/shrink to accomodate the resized strip,
+ * but if the strip's bounds now exceed the transition, we're forced to
+ * offset everything to maintain the balance
+ */
+ if (strip->start >= nls->end) {
+ /* grow the transition to fill the void */
+ nls->end = strip->start;
+ }
+ else if (strip->start > nls->start) {
+ /* shrink the transition to give the strip room */
+ nls->end = strip->start;
+ }
+ else {
+ /* shrink transition down to 1 frame long (so that it can still be found),
+ * then offset everything else by the remaining defict to give the strip room
+ */
+ nls->end = nls->start + 1.0f;
+ offset = ceilf(nls->end - strip->start); /* XXX: review whether preventing fractionals is good here... */
+
+ /* apply necessary offset to ensure that the strip has enough space */
+ for (; nls; nls = nls->next) {
+ nls->start -= offset;
+ nls->end -= offset;
+ }
+ }
+ }
+ else if (strip->start < nls->end) {
/* NOTE: need to ensure we don't have a fractional frame offset, even if that leaves a gap,
* otherwise it will be very hard to get rid of later
*/
@@ -1778,7 +1832,7 @@ bool BKE_nla_tweakmode_enter(AnimData *adt)
}
return false;
}
-
+
/* go over all the tracks up to the active one, tagging each strip that uses the same
* action as the active strip, but leaving everything else alone
*/
@@ -1791,6 +1845,13 @@ bool BKE_nla_tweakmode_enter(AnimData *adt)
}
}
+ /* tag all other strips in active track that uses the same action as the active strip */
+ for (strip = activeTrack->strips.first; strip; strip = strip->next) {
+ if ((strip->act == activeStrip->act) && (strip != activeStrip))
+ strip->flag |= NLASTRIP_FLAG_TWEAKUSER;
+ else
+ strip->flag &= ~NLASTRIP_FLAG_TWEAKUSER;
+ }
/* go over all the tracks after AND INCLUDING the active one, tagging them as being disabled
* - the active track needs to also be tagged, otherwise, it'll overlap with the tweaks going on
@@ -1852,8 +1913,19 @@ void BKE_nla_tweakmode_exit(AnimData *adt)
for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) {
nlt->flag &= ~NLATRACK_DISABLED;
- for (strip = nlt->strips.first; strip; strip = strip->next)
+ for (strip = nlt->strips.first; strip; strip = strip->next) {
+ /* sync strip extents if this strip uses the same action */
+ if ((adt->actstrip) && (adt->actstrip->act == strip->act) && (strip->flag & NLASTRIP_FLAG_SYNC_LENGTH)) {
+ /* recalculate the length of the action */
+ calc_action_range(strip->act, &strip->actstart, &strip->actend, 0);
+
+ /* adjust the strip extents in response to this */
+ BKE_nlastrip_recalculate_bounds(strip);
+ }
+
+ /* clear tweakuser flag */
strip->flag &= ~NLASTRIP_FLAG_TWEAKUSER;
+ }
}
/* handle AnimData level changes:
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index 3bcdb93729f..d3460dcb481 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -818,6 +818,10 @@ void nodeChainIter(
bNodeLink *link;
for (link = ntree->links.first; link; link = link->next) {
+ if ((link->flag & NODE_LINK_VALID) == 0) {
+ /* Skip links marked as cyclic. */
+ continue;
+ }
if (link->tonode && link->fromnode) {
/* is the link part of the chain meaning node_start == fromnode (or tonode for reversed case)? */
if ((reversed && (link->tonode == node_start)) ||
@@ -1147,6 +1151,11 @@ void nodeDetachNode(struct bNode *node)
}
}
+void ntreeInitDefault(bNodeTree *ntree)
+{
+ ntree_set_typeinfo(ntree, NULL);
+}
+
bNodeTree *ntreeAddTree(Main *bmain, const char *name, const char *idname)
{
bNodeTree *ntree;
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 4ddda70e2e7..e56887b0a1c 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -471,7 +471,7 @@ void BKE_object_free(Object *ob)
BKE_object_free_ex(ob, true);
}
-static void unlink_object__unlinkModifierLinks(void *userData, Object *ob, Object **obpoin)
+static void unlink_object__unlinkModifierLinks(void *userData, Object *ob, Object **obpoin, int UNUSED(cd_flag))
{
Object *unlinkOb = userData;
@@ -976,19 +976,10 @@ void *BKE_object_obdata_add_from_type(Main *bmain, int type, const char *name)
}
}
-/* more general add: creates minimum required data, but without vertices etc. */
-Object *BKE_object_add_only_object(Main *bmain, int type, const char *name)
+void BKE_object_init(Object *ob)
{
- Object *ob;
+ /* BLI_assert(MEMCMP_STRUCT_OFS_IS_ZERO(ob, id)); */ /* ob->type is already initialized... */
- if (!name)
- name = get_obdata_defname(type);
-
- ob = BKE_libblock_alloc(bmain, ID_OB, name);
-
- /* default object vars */
- ob->type = type;
-
ob->col[0] = ob->col[1] = ob->col[2] = 1.0;
ob->col[3] = 1.0;
@@ -1016,7 +1007,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 (ELEM(type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
+ if (ELEM(ob->type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
ob->trackflag = OB_NEGZ;
ob->upflag = OB_POSY;
}
@@ -1045,6 +1036,7 @@ Object *BKE_object_add_only_object(Main *bmain, int type, const char *name)
ob->step_height = 0.15f;
ob->jump_speed = 10.0f;
ob->fall_speed = 55.0f;
+ ob->max_jumps = 1;
ob->col_group = 0x01;
ob->col_mask = 0xffff;
ob->preview = NULL;
@@ -1056,6 +1048,22 @@ Object *BKE_object_add_only_object(Main *bmain, int type, const char *name)
/* Animation Visualization defaults */
animviz_settings_init(&ob->avs);
+}
+
+/* more general add: creates minimum required data, but without vertices etc. */
+Object *BKE_object_add_only_object(Main *bmain, int type, const char *name)
+{
+ Object *ob;
+
+ if (!name)
+ name = get_obdata_defname(type);
+
+ ob = BKE_libblock_alloc(bmain, ID_OB, name);
+
+ /* default object vars */
+ ob->type = type;
+
+ BKE_object_init(ob);
return ob;
}
@@ -1579,8 +1587,7 @@ Object *BKE_object_copy(Object *ob)
}
static void extern_local_object__modifiersForeachIDLink(
- void *UNUSED(userData), Object *UNUSED(ob),
- ID **idpoin)
+ void *UNUSED(userData), Object *UNUSED(ob), ID **idpoin, int UNUSED(cd_flag))
{
if (*idpoin) {
/* intentionally omit ID_OB */
@@ -1955,9 +1962,15 @@ void BKE_object_mat3_to_rot(Object *ob, float mat[3][3], bool use_compat)
}
case ROT_MODE_AXISANGLE:
{
- mat3_to_axis_angle(ob->rotAxis, &ob->rotAngle, mat);
- sub_v3_v3(ob->rotAxis, ob->drotAxis);
- ob->rotAngle -= ob->drotAngle;
+ float quat[4];
+ float dquat[4];
+
+ /* without drot we could apply 'mat' directly */
+ mat3_to_quat(quat, mat);
+ axis_angle_to_quat(dquat, ob->drotAxis, ob->drotAngle);
+ invert_qt(dquat);
+ mul_qt_qtqt(quat, dquat, quat);
+ quat_to_axis_angle(ob->rotAxis, &ob->rotAngle, quat);
break;
}
default: /* euler */
@@ -2660,6 +2673,76 @@ void BKE_boundbox_calc_size_aabb(const BoundBox *bb, float r_size[3])
r_size[2] = 0.5f * fabsf(bb->vec[0][2] - bb->vec[1][2]);
}
+void BKE_boundbox_minmax(const BoundBox *bb, float obmat[4][4], float r_min[3], float r_max[3])
+{
+ int i;
+ for (i = 0; i < 8; i++) {
+ float vec[3];
+ mul_v3_m4v3(vec, obmat, bb->vec[i]);
+ minmax_v3v3_v3(r_min, r_max, vec);
+ }
+}
+
+/**
+ * Returns a BBox which each dimensions are at least epsilon.
+ * \note In case a given dimension needs to be enlarged, its final value will be in [epsilon, 3 * epsilon] range.
+ *
+ * \param bb the input bbox to check.
+ * \param bb_temp the temp bbox to modify (\a bb content is never changed).
+ * \param epsilon the minimum dimension to ensure.
+ * \return either bb (if nothing needed to be changed) or bb_temp.
+ */
+BoundBox *BKE_boundbox_ensure_minimum_dimensions(BoundBox *bb, BoundBox *bb_temp, const float epsilon)
+{
+ if (fabsf(bb->vec[0][0] - bb->vec[4][0]) < epsilon) {
+ /* Flat along X axis... */
+ *bb_temp = *bb;
+ bb = bb_temp;
+ bb->vec[0][0] -= epsilon;
+ bb->vec[1][0] -= epsilon;
+ bb->vec[2][0] -= epsilon;
+ bb->vec[3][0] -= epsilon;
+ bb->vec[4][0] += epsilon;
+ bb->vec[5][0] += epsilon;
+ bb->vec[6][0] += epsilon;
+ bb->vec[7][0] += epsilon;
+ }
+
+ if (fabsf(bb->vec[0][1] - bb->vec[3][1]) < epsilon) {
+ /* Flat along Y axis... */
+ if (bb != bb_temp) {
+ *bb_temp = *bb;
+ bb = bb_temp;
+ }
+ bb->vec[0][1] -= epsilon;
+ bb->vec[1][1] -= epsilon;
+ bb->vec[4][1] -= epsilon;
+ bb->vec[5][1] -= epsilon;
+ bb->vec[2][1] += epsilon;
+ bb->vec[3][1] += epsilon;
+ bb->vec[6][1] += epsilon;
+ bb->vec[7][1] += epsilon;
+ }
+
+ if (fabsf(bb->vec[0][2] - bb->vec[1][2]) < epsilon) {
+ /* Flat along Z axis... */
+ if (bb != bb_temp) {
+ *bb_temp = *bb;
+ bb = bb_temp;
+ }
+ bb->vec[0][2] -= epsilon;
+ bb->vec[3][2] -= epsilon;
+ bb->vec[4][2] -= epsilon;
+ bb->vec[7][2] -= epsilon;
+ bb->vec[1][2] += epsilon;
+ bb->vec[2][2] += epsilon;
+ bb->vec[5][2] += epsilon;
+ bb->vec[6][2] += epsilon;
+ }
+
+ return bb;
+}
+
BoundBox *BKE_object_boundbox_get(Object *ob)
{
BoundBox *bb = NULL;
@@ -2735,7 +2818,6 @@ void BKE_object_minmax(Object *ob, float min_r[3], float max_r[3], const bool us
{
BoundBox bb;
float vec[3];
- int a;
bool changed = false;
switch (ob->type) {
@@ -2744,11 +2826,7 @@ void BKE_object_minmax(Object *ob, float min_r[3], float max_r[3], const bool us
case OB_SURF:
{
bb = *BKE_curve_boundbox_get(ob);
-
- for (a = 0; a < 8; a++) {
- mul_m4_v3(ob->obmat, bb.vec[a]);
- minmax_v3v3_v3(min_r, max_r, bb.vec[a]);
- }
+ BKE_boundbox_minmax(&bb, ob->obmat, min_r, max_r);
changed = true;
break;
}
@@ -2771,23 +2849,7 @@ void BKE_object_minmax(Object *ob, float min_r[3], float max_r[3], const bool us
}
case OB_ARMATURE:
{
- if (ob->pose) {
- bArmature *arm = ob->data;
- bPoseChannel *pchan;
-
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- /* XXX pchan->bone may be NULL for duplicated bones, see duplicateEditBoneObjects() comment
- * (editarmature.c:2592)... Skip in this case too! */
- if (pchan->bone && !((use_hidden == false) && (PBONE_VISIBLE(arm, pchan->bone) == false))) {
- mul_v3_m4v3(vec, ob->obmat, pchan->pose_head);
- minmax_v3v3_v3(min_r, max_r, vec);
- mul_v3_m4v3(vec, ob->obmat, pchan->pose_tail);
- minmax_v3v3_v3(min_r, max_r, vec);
-
- changed = true;
- }
- }
- }
+ changed = BKE_pose_minmax(ob, min_r, max_r, use_hidden, false);
break;
}
case OB_MESH:
@@ -2796,11 +2858,7 @@ void BKE_object_minmax(Object *ob, float min_r[3], float max_r[3], const bool us
if (me) {
bb = *BKE_mesh_boundbox_get(ob);
-
- for (a = 0; a < 8; a++) {
- mul_m4_v3(ob->obmat, bb.vec[a]);
- minmax_v3v3_v3(min_r, max_r, bb.vec[a]);
- }
+ BKE_boundbox_minmax(&bb, ob->obmat, min_r, max_r);
changed = true;
}
break;
@@ -3676,38 +3734,6 @@ bool BKE_object_is_animated(Scene *scene, Object *ob)
return false;
}
-static void copy_object__forwardModifierLinks(void *UNUSED(userData), Object *UNUSED(ob), ID **idpoin)
-{
- /* this is copied from ID_NEW; it might be better to have a macro */
- if (*idpoin && (*idpoin)->newid) *idpoin = (*idpoin)->newid;
-}
-
-void BKE_object_relink(Object *ob)
-{
- if (ob->id.lib)
- return;
-
- BKE_constraints_relink(&ob->constraints);
- if (ob->pose) {
- bPoseChannel *chan;
- for (chan = ob->pose->chanbase.first; chan; chan = chan->next) {
- BKE_constraints_relink(&chan->constraints);
- }
- }
- modifiers_foreachIDLink(ob, copy_object__forwardModifierLinks, NULL);
-
- if (ob->adt)
- BKE_animdata_relink(ob->adt);
-
- if (ob->rigidbody_constraint)
- BKE_rigidbody_relink_constraint(ob->rigidbody_constraint);
-
- ID_NEW(ob->parent);
-
- ID_NEW(ob->proxy);
- ID_NEW(ob->proxy_group);
-}
-
MovieClip *BKE_object_movieclip_get(Scene *scene, Object *ob, bool use_default)
{
MovieClip *clip = use_default ? scene->clip : NULL;
diff --git a/source/blender/blenkernel/intern/packedFile.c b/source/blender/blenkernel/intern/packedFile.c
index 151889b10a1..a1669c745e6 100644
--- a/source/blender/blenkernel/intern/packedFile.c
+++ b/source/blender/blenkernel/intern/packedFile.c
@@ -582,7 +582,7 @@ int unpackImage(ReportList *reports, Image *ima, int how)
{
int ret_value = RET_ERROR;
- if (ima != NULL && ima->name[0]) {
+ if (ima != NULL) {
while (ima->packedfiles.last) {
char localname[FILE_MAX], absname[FILE_MAX];
char *newname;
@@ -605,7 +605,9 @@ int unpackImage(ReportList *reports, Image *ima, int how)
}
/* keep the new name in the image for non-pack specific reasons */
- BLI_strncpy(ima->name, newname, sizeof(imapf->filepath));
+ if (how != PF_REMOVE) {
+ BLI_strncpy(ima->name, newname, sizeof(imapf->filepath));
+ }
MEM_freeN(newname);
}
else {
diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c
index 328731a11a9..06844b09a9b 100644
--- a/source/blender/blenkernel/intern/paint.c
+++ b/source/blender/blenkernel/intern/paint.c
@@ -128,6 +128,32 @@ void BKE_paint_reset_overlay_invalid(OverlayControlFlags flag)
overlay_flags &= ~(flag);
}
+Paint *BKE_paint_get_active_from_paintmode(Scene *sce, PaintMode mode)
+{
+ if (sce) {
+ ToolSettings *ts = sce->toolsettings;
+
+ switch (mode) {
+ case ePaintSculpt:
+ return &ts->sculpt->paint;
+ case ePaintVertex:
+ return &ts->vpaint->paint;
+ case ePaintWeight:
+ return &ts->wpaint->paint;
+ case ePaintTexture2D:
+ case ePaintTextureProjective:
+ return &ts->imapaint.paint;
+ case ePaintSculptUV:
+ return &ts->uvsculpt->paint;
+ case ePaintInvalid:
+ return NULL;
+ default:
+ return &ts->imapaint.paint;
+ }
+ }
+
+ return NULL;
+}
Paint *BKE_paint_get_active(Scene *sce)
{
@@ -223,39 +249,39 @@ PaintMode BKE_paintmode_get_active_from_context(const bContext *C)
if ((sima = CTX_wm_space_image(C)) != NULL) {
if (obact && obact->mode == OB_MODE_EDIT) {
if (sima->mode == SI_MODE_PAINT)
- return PAINT_TEXTURE_2D;
+ return ePaintTexture2D;
else if (ts->use_uv_sculpt)
- return PAINT_SCULPT_UV;
+ return ePaintSculptUV;
}
else {
- return PAINT_TEXTURE_2D;
+ return ePaintTexture2D;
}
}
else if (obact) {
switch (obact->mode) {
case OB_MODE_SCULPT:
- return PAINT_SCULPT;
+ return ePaintSculpt;
case OB_MODE_VERTEX_PAINT:
- return PAINT_VERTEX;
+ return ePaintVertex;
case OB_MODE_WEIGHT_PAINT:
- return PAINT_WEIGHT;
+ return ePaintWeight;
case OB_MODE_TEXTURE_PAINT:
- return PAINT_TEXTURE_PROJECTIVE;
+ return ePaintTextureProjective;
case OB_MODE_EDIT:
if (ts->use_uv_sculpt)
- return PAINT_SCULPT_UV;
- return PAINT_TEXTURE_2D;
+ return ePaintSculptUV;
+ return ePaintTexture2D;
default:
- return PAINT_TEXTURE_2D;
+ return ePaintTexture2D;
}
}
else {
/* default to image paint */
- return PAINT_TEXTURE_2D;
+ return ePaintTexture2D;
}
}
- return PAINT_INVALID;
+ return ePaintInvalid;
}
Brush *BKE_paint_brush(Paint *p)
@@ -418,23 +444,51 @@ void BKE_paint_cavity_curve_preset(Paint *p, int preset)
curvemapping_changed(p->cavity_curve, false);
}
-void BKE_paint_init(UnifiedPaintSettings *ups, Paint *p, const char col[3])
+short BKE_paint_object_mode_from_paint_mode(PaintMode mode)
{
+ switch (mode) {
+ case ePaintSculpt:
+ return OB_MODE_SCULPT;
+ case ePaintVertex:
+ return OB_MODE_VERTEX_PAINT;
+ case ePaintWeight:
+ return OB_MODE_WEIGHT_PAINT;
+ case ePaintTextureProjective:
+ return OB_MODE_TEXTURE_PAINT;
+ case ePaintTexture2D:
+ return OB_MODE_TEXTURE_PAINT;
+ case ePaintSculptUV:
+ return OB_MODE_EDIT;
+ case ePaintInvalid:
+ default:
+ return 0;
+ }
+}
+
+void BKE_paint_init(Scene *sce, PaintMode mode, const char col[3])
+{
+ UnifiedPaintSettings *ups = &sce->toolsettings->unified_paint_settings;
Brush *brush;
+ Paint *paint = BKE_paint_get_active_from_paintmode(sce, mode);
/* If there's no brush, create one */
- brush = BKE_paint_brush(p);
- if (brush == NULL)
- brush = BKE_brush_add(G.main, "Brush");
- BKE_paint_brush_set(p, brush);
+ brush = BKE_paint_brush(paint);
+ if (brush == NULL) {
+ short ob_mode = BKE_paint_object_mode_from_paint_mode(mode);
+ brush = BKE_brush_first_search(G.main, ob_mode);
+
+ if (!brush)
+ brush = BKE_brush_add(G.main, "Brush", ob_mode);
+ BKE_paint_brush_set(paint, brush);
+ }
- memcpy(p->paint_cursor_col, col, 3);
- p->paint_cursor_col[3] = 128;
+ memcpy(paint->paint_cursor_col, col, 3);
+ paint->paint_cursor_col[3] = 128;
ups->last_stroke_valid = false;
zero_v3(ups->average_stroke_accum);
ups->average_stroke_counter = 0;
- if (!p->cavity_curve)
- BKE_paint_cavity_curve_preset(p, CURVE_PRESET_LINE);
+ if (!paint->cavity_curve)
+ BKE_paint_cavity_curve_preset(paint, CURVE_PRESET_LINE);
}
void BKE_paint_free(Paint *paint)
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index dd43e63b9c3..a59a0b73b69 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -77,6 +77,7 @@
#include "BKE_cdderivedmesh.h"
#include "BKE_collision.h"
#include "BKE_effect.h"
+#include "BKE_library_query.h"
#include "BKE_particle.h"
#include "BKE_global.h"
@@ -4209,13 +4210,39 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys)
invert_m4_m4(psys->imat, ob->obmat);
}
+/* ID looper */
+
+void BKE_particlesystem_id_loop(ParticleSystem *psys, ParticleSystemIDFunc func, void *userdata)
+{
+ ParticleTarget *pt;
+
+ func(psys, (ID **)&psys->part, userdata, IDWALK_NOP);
+ func(psys, (ID **)&psys->target_ob, userdata, IDWALK_NOP);
+ func(psys, (ID **)&psys->parent, userdata, IDWALK_NOP);
+
+ for (pt = psys->targets.first; pt; pt = pt->next) {
+ func(psys, (ID **)&pt->ob, userdata, IDWALK_NOP);
+ }
+
+ if (psys->part->phystype == PART_PHYS_BOIDS) {
+ ParticleData *pa;
+ int p;
+
+ for (p = 0, pa = psys->particles; p < psys->totpart; p++, pa++) {
+ func(psys, (ID **)&pa->boid->ground, userdata, IDWALK_NOP);
+ }
+ }
+}
+
/* **** Depsgraph evaluation **** */
void BKE_particle_system_eval(EvaluationContext *UNUSED(eval_ctx),
+ Scene *scene,
Object *ob,
ParticleSystem *psys)
{
if (G.debug & G_DEBUG_DEPSGRAPH) {
printf("%s on %s:%s\n", __func__, ob->id.name, psys->name);
}
+ BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_DEPSGRAPH);
}
diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c
index 3e236079a66..ff4cae09437 100644
--- a/source/blender/blenkernel/intern/pbvh_bmesh.c
+++ b/source/blender/blenkernel/intern/pbvh_bmesh.c
@@ -575,7 +575,7 @@ static void pbvh_bmesh_edge_loops(BLI_Buffer *buf, BMEdge *e)
buf->count = 2;
}
else {
- BLI_buffer_resize(buf, BM_edge_face_count(e));
+ BLI_buffer_reinit(buf, BM_edge_face_count(e));
BM_iter_as_array(NULL, BM_LOOPS_OF_EDGE, e, buf->data, buf->count);
}
}
diff --git a/source/blender/blenkernel/intern/property.c b/source/blender/blenkernel/intern/property.c
index 100df5fd121..dc4063b42ed 100644
--- a/source/blender/blenkernel/intern/property.c
+++ b/source/blender/blenkernel/intern/property.c
@@ -142,8 +142,8 @@ void BKE_bproperty_object_set(Object *ob, bProperty *propc)
bProperty *prop;
prop = BKE_bproperty_object_get(ob, propc->name);
if (prop) {
- BKE_bproperty_free(prop);
BLI_remlink(&ob->prop, prop);
+ BKE_bproperty_free(prop);
}
BLI_addtail(&ob->prop, BKE_bproperty_copy(propc));
}
diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c
index 476b9a22238..0f1f9b4bdf7 100644
--- a/source/blender/blenkernel/intern/rigidbody.c
+++ b/source/blender/blenkernel/intern/rigidbody.c
@@ -58,6 +58,7 @@
#include "BKE_effect.h"
#include "BKE_global.h"
#include "BKE_library.h"
+#include "BKE_library_query.h"
#include "BKE_mesh.h"
#include "BKE_object.h"
#include "BKE_pointcache.h"
@@ -957,6 +958,20 @@ void BKE_rigidbody_world_groups_relink(RigidBodyWorld *rbw)
rbw->effector_weights->group = (Group *)rbw->effector_weights->group->id.newid;
}
+void BKE_rigidbody_world_id_loop(RigidBodyWorld *rbw, RigidbodyWorldIDFunc func, void *userdata)
+{
+ func(rbw, (ID **)&rbw->group, userdata, IDWALK_NOP);
+ func(rbw, (ID **)&rbw->constraints, userdata, IDWALK_NOP);
+ func(rbw, (ID **)&rbw->effector_weights->group, userdata, IDWALK_NOP);
+
+ if (rbw->objects) {
+ int i;
+ for (i = 0; i < rbw->numbodies; i++) {
+ func(rbw, (ID **)&rbw->objects[i], userdata, IDWALK_NOP);
+ }
+ }
+}
+
/* Add rigid body settings to the specified object */
RigidBodyOb *BKE_rigidbody_create_object(Scene *scene, Object *ob, short type)
{
@@ -1597,6 +1612,7 @@ void BKE_rigidbody_calc_center_of_mass(Object *ob, float r_center[3]) { zero_v3(
struct RigidBodyWorld *BKE_rigidbody_create_world(Scene *scene) { return NULL; }
struct RigidBodyWorld *BKE_rigidbody_world_copy(RigidBodyWorld *rbw) { return NULL; }
void BKE_rigidbody_world_groups_relink(struct RigidBodyWorld *rbw) {}
+void BKE_rigidbody_world_id_loop(struct RigidBodyWorld *rbw, RigidbodyWorldIDFunc func, void *userdata) {}
struct RigidBodyOb *BKE_rigidbody_create_object(Scene *scene, Object *ob, short type) { return NULL; }
struct RigidBodyCon *BKE_rigidbody_create_constraint(Scene *scene, Object *ob, short type) { return NULL; }
struct RigidBodyWorld *BKE_rigidbody_get_world(Scene *scene) { return NULL; }
diff --git a/source/blender/blenkernel/intern/sca.c b/source/blender/blenkernel/intern/sca.c
index c902659c039..88a28228639 100644
--- a/source/blender/blenkernel/intern/sca.c
+++ b/source/blender/blenkernel/intern/sca.c
@@ -48,6 +48,7 @@
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_library.h"
+#include "BKE_library_query.h"
#include "BKE_sca.h"
/* ******************* SENSORS ************************ */
@@ -903,6 +904,179 @@ void unlink_logicbricks(void **poin, void ***ppoin, short *tot)
}
}
+void BKE_sca_sensors_id_loop(ListBase *senslist, SCASensorIDFunc func, void *userdata)
+{
+ bSensor *sensor;
+
+ for (sensor = senslist->first; sensor; sensor = sensor->next) {
+ func(sensor, (ID **)&sensor->ob, userdata, IDWALK_NOP);
+
+ switch (sensor->type) {
+ case SENS_TOUCH: /* DEPRECATED */
+ {
+ bTouchSensor *ts = sensor->data;
+ func(sensor, (ID **)&ts->ma, userdata, IDWALK_NOP);
+ break;
+ }
+ case SENS_MESSAGE:
+ {
+ bMessageSensor *ms = sensor->data;
+ func(sensor, (ID **)&ms->fromObject, userdata, IDWALK_NOP);
+ break;
+ }
+ case SENS_ALWAYS:
+ case SENS_NEAR:
+ case SENS_KEYBOARD:
+ case SENS_PROPERTY:
+ case SENS_MOUSE:
+ case SENS_COLLISION:
+ case SENS_RADAR:
+ case SENS_RANDOM:
+ case SENS_RAY:
+ case SENS_JOYSTICK:
+ case SENS_ACTUATOR:
+ case SENS_DELAY:
+ case SENS_ARMATURE:
+ default:
+ break;
+ }
+ }
+}
+
+void BKE_sca_controllers_id_loop(ListBase *contlist, SCAControllerIDFunc func, void *userdata)
+{
+ bController *controller;
+
+ for (controller = contlist->first; controller; controller = controller->next) {
+ switch (controller->type) {
+ case CONT_PYTHON:
+ {
+ bPythonCont *pc = controller->data;
+ func(controller, (ID **)&pc->text, userdata, IDWALK_NOP);
+ break;
+ }
+ case CONT_LOGIC_AND:
+ case CONT_LOGIC_OR:
+ case CONT_EXPRESSION:
+ case CONT_LOGIC_NAND:
+ case CONT_LOGIC_NOR:
+ case CONT_LOGIC_XOR:
+ case CONT_LOGIC_XNOR:
+ default:
+ break;
+ }
+ }
+}
+
+void BKE_sca_actuators_id_loop(ListBase *actlist, SCAActuatorIDFunc func, void *userdata)
+{
+ bActuator *actuator;
+
+ for (actuator = actlist->first; actuator; actuator = actuator->next) {
+ func(actuator, (ID **)&actuator->ob, userdata, IDWALK_NOP);
+
+ switch (actuator->type) {
+ case ACT_ADD_OBJECT: /* DEPRECATED */
+ {
+ bAddObjectActuator *aoa = actuator->data;
+ func(actuator, (ID **)&aoa->ob, userdata, IDWALK_NOP);
+ break;
+ }
+ case ACT_ACTION:
+ {
+ bActionActuator *aa = actuator->data;
+ func(actuator, (ID **)&aa->act, userdata, IDWALK_NOP);
+ break;
+ }
+ case ACT_SOUND:
+ {
+ bSoundActuator *sa = actuator->data;
+ func(actuator, (ID **)&sa->sound, userdata, IDWALK_NOP);
+ break;
+ }
+ case ACT_EDIT_OBJECT:
+ {
+ bEditObjectActuator *eoa = actuator->data;
+ func(actuator, (ID **)&eoa->ob, userdata, IDWALK_NOP);
+ func(actuator, (ID **)&eoa->me, userdata, IDWALK_NOP);
+ break;
+ }
+ case ACT_SCENE:
+ {
+ bSceneActuator *sa = actuator->data;
+ func(actuator, (ID **)&sa->scene, userdata, IDWALK_NOP);
+ func(actuator, (ID **)&sa->camera, userdata, IDWALK_NOP);
+ break;
+ }
+ case ACT_PROPERTY:
+ {
+ bPropertyActuator *pa = actuator->data;
+ func(actuator, (ID **)&pa->ob, userdata, IDWALK_NOP);
+ break;
+ }
+ case ACT_OBJECT:
+ {
+ bObjectActuator *oa = actuator->data;
+ func(actuator, (ID **)&oa->reference, userdata, IDWALK_NOP);
+ break;
+ }
+ case ACT_CAMERA:
+ {
+ bCameraActuator *ca = actuator->data;
+ func(actuator, (ID **)&ca->ob, userdata, IDWALK_NOP);
+ break;
+ }
+ case ACT_MESSAGE:
+ {
+ bMessageActuator *ma = actuator->data;
+ func(actuator, (ID **)&ma->toObject, userdata, IDWALK_NOP);
+ break;
+ }
+ case ACT_2DFILTER:
+ {
+ bTwoDFilterActuator *tdfa = actuator->data;
+ func(actuator, (ID **)&tdfa->text, userdata, IDWALK_NOP);
+ break;
+ }
+ case ACT_PARENT:
+ {
+ bParentActuator *pa = actuator->data;
+ func(actuator, (ID **)&pa->ob, userdata, IDWALK_NOP);
+ break;
+ }
+ case ACT_ARMATURE:
+ {
+ bArmatureActuator *aa = actuator->data;
+ func(actuator, (ID **)&aa->target, userdata, IDWALK_NOP);
+ func(actuator, (ID **)&aa->subtarget, userdata, IDWALK_NOP);
+ break;
+ }
+ case ACT_STEERING:
+ {
+ bSteeringActuator *sa = actuator->data;
+ func(actuator, (ID **)&sa->target, userdata, IDWALK_NOP);
+ func(actuator, (ID **)&sa->navmesh, userdata, IDWALK_NOP);
+ break;
+ }
+ /* Note: some types seems to be non-implemented? ACT_LAMP, ACT_MATERIAL... */
+ case ACT_IPO: /* DEPRECATED */
+ case ACT_LAMP:
+ case ACT_MATERIAL:
+ case ACT_END_OBJECT: /* DEPRECATED */
+ case ACT_CONSTRAINT:
+ case ACT_GROUP:
+ case ACT_RANDOM:
+ case ACT_GAME:
+ case ACT_VISIBILITY:
+ case ACT_SHAPEACTION:
+ case ACT_STATE:
+ case ACT_MOUSE:
+ default:
+ break;
+ }
+ }
+}
+
const char *sca_state_name_get(Object *ob, short bit)
{
bController *cont;
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index 701483af43f..cc656775c14 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -464,15 +464,15 @@ void BKE_scene_free(Scene *sce)
BKE_previewimg_free(&sce->preview);
}
-Scene *BKE_scene_add(Main *bmain, const char *name)
+void BKE_scene_init(Scene *sce)
{
- Scene *sce;
ParticleEditSettings *pset;
int a;
const char *colorspace_name;
SceneRenderView *srv;
- sce = BKE_libblock_alloc(bmain, ID_SCE, name);
+ BLI_assert(MEMCMP_STRUCT_OFS_IS_ZERO(sce, id));
+
sce->lay = sce->layact = 1;
sce->r.mode = R_GAMMA | R_OSA | R_SHADOW | R_SSS | R_ENVMAP | R_RAYTRACE;
@@ -743,6 +743,15 @@ Scene *BKE_scene_add(Main *bmain, const char *name)
copy_v2_fl2(sce->safe_areas.action_center, 15.0f / 100.0f, 5.0f / 100.0f);
sce->preview = NULL;
+}
+
+Scene *BKE_scene_add(Main *bmain, const char *name)
+{
+ Scene *sce;
+
+ sce = BKE_libblock_alloc(bmain, ID_SCE, name);
+
+ BKE_scene_init(sce);
return sce;
}
@@ -1360,7 +1369,7 @@ static void scene_do_rb_simulation_recursive(Scene *scene, float ctime)
*
* Ideally Mballs shouldn't do such an iteration and use DAG
* queries instead. For the time being we've got new DAG
- * let's keep it simple and update mballs in a ingle thread.
+ * let's keep it simple and update mballs in a single thread.
*/
#define MBALL_SINGLETHREAD_HACK
@@ -1587,7 +1596,9 @@ static void scene_free_unused_opensubdiv_cache(Scene *scene)
if (md != NULL && md->type == eModifierType_Subsurf) {
SubsurfModifierData *smd = (SubsurfModifierData *) md;
bool object_in_editmode = object->mode == OB_MODE_EDIT;
- if (!smd->use_opensubdiv) {
+ if (!smd->use_opensubdiv ||
+ DAG_get_eval_flags_for_object(scene, object) & DAG_EVAL_NEED_CPU)
+ {
if (smd->mCache != NULL) {
ccgSubSurf_free_osd_mesh(smd->mCache);
}
@@ -1804,6 +1815,11 @@ void BKE_scene_update_tagged(EvaluationContext *eval_ctx, Main *bmain, Scene *sc
else
#endif
{
+#ifdef OPENSUBDIV_GL_WORKAROUND
+ if (DEG_needs_eval(scene->depsgraph)) {
+ scene_free_unused_opensubdiv_cache(scene);
+ }
+#endif
DEG_evaluate_on_refresh(eval_ctx, scene->depsgraph, scene);
/* TODO(sergey): This is to beocme a node in new depsgraph. */
BKE_mask_update_scene(bmain, scene);
@@ -1885,6 +1901,8 @@ void BKE_scene_update_for_newframe_ex(EvaluationContext *eval_ctx, Main *bmain,
(void) do_invisible_flush;
#endif
+ DAG_editors_update_pre(bmain, sce, true);
+
/* keep this first */
BLI_callback_exec(bmain, &sce->id, BLI_CB_EVT_FRAME_CHANGE_PRE);
BLI_callback_exec(bmain, &sce->id, BLI_CB_EVT_SCENE_UPDATE_PRE);
@@ -2165,8 +2183,8 @@ bool BKE_scene_use_new_shading_nodes(const Scene *scene)
bool BKE_scene_use_shading_nodes_custom(Scene *scene)
{
- RenderEngineType *type = RE_engines_find(scene->r.engine);
- return (type && type->flag & RE_USE_SHADING_NODES_CUSTOM);
+ RenderEngineType *type = RE_engines_find(scene->r.engine);
+ return (type && type->flag & RE_USE_SHADING_NODES_CUSTOM);
}
bool BKE_scene_uses_blender_internal(const Scene *scene)
diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c
index 83aac79ae0b..6742a1fe80d 100644
--- a/source/blender/blenkernel/intern/screen.c
+++ b/source/blender/blenkernel/intern/screen.c
@@ -313,7 +313,16 @@ void BKE_area_region_free(SpaceType *st, ARegion *ar)
ar->v2d.tab_offset = NULL;
}
- BLI_freelistN(&ar->panels);
+ if (!BLI_listbase_is_empty(&ar->panels)) {
+ Panel *pa, *pa_next;
+ for (pa = ar->panels.first; pa; pa = pa_next) {
+ pa_next = pa->next;
+ if (pa->activedata) {
+ MEM_freeN(pa->activedata);
+ }
+ MEM_freeN(pa);
+ }
+ }
for (uilst = ar->ui_lists.first; uilst; uilst = uilst->next) {
if (uilst->dyn_data) {
diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c
index 3e6edbe01e8..f375c2b1e4f 100644
--- a/source/blender/blenkernel/intern/seqeffects.c
+++ b/source/blender/blenkernel/intern/seqeffects.c
@@ -38,11 +38,13 @@
#include "BLI_math.h" /* windows needs for M_PI */
#include "BLI_utildefines.h"
+#include "BLI_rect.h"
#include "BLI_string.h"
#include "DNA_scene_types.h"
#include "DNA_sequence_types.h"
#include "DNA_anim_types.h"
+#include "DNA_space_types.h"
#include "BKE_fcurve.h"
#include "BKE_sequencer.h"
@@ -2480,7 +2482,7 @@ void BKE_sequence_effect_speed_rebuild_map(Scene *scene, Sequence *seq, bool for
if ((seq->seq1->enddisp != seq->seq1->start) &&
(seq->seq1->len != 0))
{
- fallback_fac = 1.0f;
+ fallback_fac = (float) seq->seq1->len / (float) (seq->seq1->enddisp - seq->seq1->start);
flags = SEQ_SPEED_INTEGRATE;
fcu = NULL;
}
@@ -2892,7 +2894,8 @@ static void init_text_effect(Sequence *seq)
BLI_strncpy(data->text, "Text", sizeof(data->text));
data->loc[0] = 0.5f;
- data->align = SEQ_TEXT_ALIGN_CENTER;
+ data->align = SEQ_TEXT_ALIGN_X_CENTER;
+ data->align_y = SEQ_TEXT_ALIGN_Y_BOTTOM;
}
static int num_inputs_text(void)
@@ -2919,32 +2922,70 @@ static ImBuf *do_text_effect(const SeqRenderData *context, Sequence *seq, float
struct ColorManagedDisplay *display;
const char *display_device;
const int mono = blf_mono_font_render; // XXX
+ int line_height;
int y_ofs, x, y;
+ float proxy_size_comp;
display_device = context->scene->display_settings.display_device;
display = IMB_colormanagement_display_get_named(display_device);
+ /* Compensate text size for preview render size. */
+ if (ELEM(context->preview_render_size, SEQ_PROXY_RENDER_SIZE_SCENE, SEQ_PROXY_RENDER_SIZE_FULL)) {
+ proxy_size_comp = context->scene->r.size / 100.0f;
+ }
+ else if (context->preview_render_size == SEQ_PROXY_RENDER_SIZE_100) {
+ proxy_size_comp = 1.0f;
+ }
+ else {
+ proxy_size_comp = context->preview_render_size / 100.0f;
+ }
+
/* set before return */
- BLF_size(mono, (context->scene->r.size / 100.0f) * data->text_size, 72);
+ BLF_size(mono, proxy_size_comp * data->text_size, 72);
+
+ BLF_enable(mono, BLF_WORD_WRAP);
+
+ /* use max width to enable newlines only */
+ BLF_wordwrap(mono, (data->wrap_width != 0.0f) ? data->wrap_width * width : -1);
BLF_buffer(mono, out->rect_float, (unsigned char *)out->rect, width, height, out->channels, display);
+ line_height = BLF_height_max(mono);
+
y_ofs = -BLF_descender(mono);
x = (data->loc[0] * width);
y = (data->loc[1] * height) + y_ofs;
- if (data->align == SEQ_TEXT_ALIGN_LEFT) {
- /* pass */
+ if ((data->align == SEQ_TEXT_ALIGN_X_LEFT) &&
+ (data->align_y == SEQ_TEXT_ALIGN_Y_TOP))
+ {
+ y -= line_height;
}
else {
- const int w = BLF_width(mono, data->text, sizeof(data->text));
+ /* vars for calculating wordwrap */
+ struct {
+ struct ResultBLF info;
+ rctf rect;
+ } wrap;
+
+ BLF_boundbox_ex(mono, data->text, sizeof(data->text), &wrap.rect, &wrap.info);
- if (data->align == SEQ_TEXT_ALIGN_RIGHT) {
- x -= w;
+ if (data->align == SEQ_TEXT_ALIGN_X_RIGHT) {
+ x -= BLI_rctf_size_x(&wrap.rect);
}
- else { /* SEQ_TEXT_ALIGN_CENTER */
- x -= w / 2;
+ else if (data->align == SEQ_TEXT_ALIGN_X_CENTER) {
+ x -= BLI_rctf_size_x(&wrap.rect) / 2;
+ }
+
+ if (data->align_y == SEQ_TEXT_ALIGN_Y_TOP) {
+ y -= line_height;
+ }
+ else if (data->align_y == SEQ_TEXT_ALIGN_Y_BOTTOM) {
+ y += (wrap.info.lines - 1) * line_height;
+ }
+ else if (data->align_y == SEQ_TEXT_ALIGN_Y_CENTER) {
+ y += (((wrap.info.lines - 1) / 2) * line_height) - (line_height / 2);
}
}
@@ -2952,17 +2993,19 @@ static ImBuf *do_text_effect(const SeqRenderData *context, Sequence *seq, float
if (data->flag & SEQ_TEXT_SHADOW) {
int fontx, fonty;
fontx = BLF_width_max(mono);
- fonty = BLF_height_max(mono);
- BLF_position(mono, x + max_ii(fontx / 25, 1), y + max_ii(fonty / 25, 1), 0.0);
- BLF_buffer_col(mono, 0.0f, 0.0f, 0.0f, 1.0);
- BLF_draw_buffer(mono, data->text);
+ fonty = line_height;
+ BLF_position(mono, x + max_ii(fontx / 25, 1), y + max_ii(fonty / 25, 1), 0.0f);
+ BLF_buffer_col(mono, 0.0f, 0.0f, 0.0f, 1.0f);
+ BLF_draw_buffer(mono, data->text, BLF_DRAW_STR_DUMMY_MAX);
}
- BLF_position(mono, x, y, 0.0);
- BLF_buffer_col(mono, 1.0f, 1.0f, 1.0f, 1.0);
- BLF_draw_buffer(mono, data->text);
+ BLF_position(mono, x, y, 0.0f);
+ BLF_buffer_col(mono, 1.0f, 1.0f, 1.0f, 1.0f);
+ BLF_draw_buffer(mono, data->text, BLF_DRAW_STR_DUMMY_MAX);
BLF_buffer(mono, NULL, NULL, 0, 0, 0, NULL);
+ BLF_disable(mono, BLF_WORD_WRAP);
+
return out;
}
diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c
index aa0e13124b8..c070ad73156 100644
--- a/source/blender/blenkernel/intern/sequencer.c
+++ b/source/blender/blenkernel/intern/sequencer.c
@@ -563,6 +563,8 @@ void BKE_sequencer_new_render_data(
r_context->skip_cache = false;
r_context->is_proxy_render = false;
r_context->view_id = 0;
+ r_context->gpu_offscreen = NULL;
+ r_context->gpu_samples = (scene->r.mode & R_OSA) ? scene->r.osa : 0;
}
/* ************************* iterator ************************** */
@@ -1013,6 +1015,15 @@ void BKE_sequencer_sort(Scene *scene)
*(ed->seqbasep) = seqbase;
}
+/** Comparision function suitable to be used with BLI_listbase_sort()... */
+int BKE_sequencer_cmp_time_startdisp(const void *a, const void *b)
+{
+ const Sequence *seq_a = a;
+ const Sequence *seq_b = b;
+
+ return (seq_a->startdisp > seq_b->startdisp);
+}
+
static int clear_scene_in_allseqs_cb(Sequence *seq, void *arg_pt)
{
if (seq->scene == (Scene *)arg_pt)
@@ -3009,6 +3020,7 @@ static ImBuf *seq_render_mask(const SeqRenderData *context, Mask *mask, float nr
return NULL;
}
else {
+ AnimData *adt;
Mask *mask_temp;
MaskRasterHandle *mr_handle;
@@ -3016,6 +3028,10 @@ static ImBuf *seq_render_mask(const SeqRenderData *context, Mask *mask, float nr
BKE_mask_evaluate(mask_temp, mask->sfra + nr, true);
+ /* anim-data */
+ adt = BKE_animdata_from_id(&mask->id);
+ BKE_animsys_evaluate_animdata(context->scene, &mask_temp->id, adt, nr, ADT_RECALC_ANIM);
+
maskbuf = MEM_mallocN(sizeof(float) * context->rectx * context->recty, __func__);
mr_handle = BKE_maskrasterize_handle_new();
@@ -3083,10 +3099,17 @@ static ImBuf *seq_render_mask_strip(const SeqRenderData *context, Sequence *seq,
static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq, float nr, float cfra)
{
ImBuf *ibuf = NULL;
- float frame;
- float oldcfra;
+ double frame;
Object *camera;
- ListBase oldmarkers;
+
+ struct {
+ int scemode;
+ int cfra;
+ float subframe;
+#ifdef DURIAN_CAMERA_SWITCH
+ ListBase markers;
+#endif
+ } orig_data;
/* Old info:
* Hack! This function can be called from do_render_seq(), in that case
@@ -3124,10 +3147,11 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq
const bool do_seq_gl = is_rendering ?
0 /* (context->scene->r.seq_flag & R_SEQ_GL_REND) */ :
(context->scene->r.seq_flag & R_SEQ_GL_PREV) != 0;
- int do_seq;
// bool have_seq = false; /* UNUSED */
bool have_comp = false;
bool use_gpencil = true;
+ /* do we need to re-evaluate the frame after rendering? */
+ bool is_frame_update = false;
Scene *scene;
int is_thread_main = BLI_thread_is_main();
@@ -3137,13 +3161,19 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq
}
scene = seq->scene;
- frame = scene->r.sfra + nr + seq->anim_startofs;
+ frame = (double)scene->r.sfra + (double)nr + (double)seq->anim_startofs;
// have_seq = (scene->r.scemode & R_DOSEQ) && scene->ed && scene->ed->seqbase.first); /* UNUSED */
have_comp = (scene->r.scemode & R_DOCOMP) && scene->use_nodes && scene->nodetree;
- oldcfra = scene->r.cfra;
- scene->r.cfra = frame;
+ orig_data.scemode = scene->r.scemode;
+ orig_data.cfra = scene->r.cfra;
+ orig_data.subframe = scene->r.subframe;
+#ifdef DURIAN_CAMERA_SWITCH
+ orig_data.markers = scene->markers;
+#endif
+
+ BKE_scene_frame_set(scene, frame);
if (seq->scene_camera) {
camera = seq->scene_camera;
@@ -3153,27 +3183,24 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq
camera = scene->camera;
}
- if (seq->flag & SEQ_SCENE_NO_GPENCIL) {
- use_gpencil = false;
+ if (have_comp == false && camera == NULL) {
+ goto finally;
}
- if (have_comp == false && camera == NULL) {
- scene->r.cfra = oldcfra;
- return NULL;
+ if (seq->flag & SEQ_SCENE_NO_GPENCIL) {
+ use_gpencil = false;
}
/* prevent eternal loop */
- do_seq = scene->r.scemode & R_DOSEQ;
scene->r.scemode &= ~R_DOSEQ;
#ifdef DURIAN_CAMERA_SWITCH
/* stooping to new low's in hackyness :( */
- oldmarkers = scene->markers;
BLI_listbase_clear(&scene->markers);
-#else
- (void)oldmarkers;
#endif
+ is_frame_update = (orig_data.cfra != scene->r.cfra) || (orig_data.subframe != scene->r.subframe);
+
if ((sequencer_view3d_cb && do_seq_gl && camera) && is_thread_main) {
char err_out[256] = "unknown";
int width = (scene->r.xsch * scene->r.size) / 100;
@@ -3187,10 +3214,14 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq
/* opengl offscreen render */
BKE_scene_update_for_newframe(context->eval_ctx, context->bmain, scene, scene->lay);
- ibuf = sequencer_view3d_cb(scene, camera, width, height, IB_rect,
- context->scene->r.seq_prev_type,
- (context->scene->r.seq_flag & R_SEQ_SOLID_TEX) != 0,
- use_gpencil, true, scene->r.alphamode, viewname, err_out);
+ ibuf = sequencer_view3d_cb(
+ /* set for OpenGL render (NULL when scrubbing) */
+ scene, camera, width, height, IB_rect,
+ context->scene->r.seq_prev_type,
+ (context->scene->r.seq_flag & R_SEQ_SOLID_TEX) != 0,
+ use_gpencil, true, scene->r.alphamode,
+ context->gpu_samples, viewname,
+ context->gpu_offscreen, err_out);
if (ibuf == NULL) {
fprintf(stderr, "seq_render_scene_strip failed to get opengl buffer: %s\n", err_out);
}
@@ -3268,19 +3299,21 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq
// BIF_end_render_callbacks();
}
-
+
+
+finally:
/* restore */
- scene->r.scemode |= do_seq;
-
- scene->r.cfra = oldcfra;
+ scene->r.scemode = orig_data.scemode;
+ scene->r.cfra = orig_data.cfra;
+ scene->r.subframe = orig_data.subframe;
- if (frame != oldcfra) {
+ if (is_frame_update) {
BKE_scene_update_for_newframe(context->eval_ctx, context->bmain, scene, scene->lay);
}
-
+
#ifdef DURIAN_CAMERA_SWITCH
/* stooping to new low's in hackyness :( */
- scene->markers = oldmarkers;
+ scene->markers = orig_data.markers;
#endif
return ibuf;
@@ -3395,7 +3428,7 @@ static ImBuf *do_render_strip_uncached(const SeqRenderData *context, Sequence *s
case SEQ_TYPE_MASK:
{
- /* ibuf is alwats new */
+ /* ibuf is always new */
ibuf = seq_render_mask_strip(context, seq, nr);
copy_to_ibuf_still(context, seq, nr, ibuf);
@@ -3417,7 +3450,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 = !ELEM(type, SEQ_TYPE_IMAGE, SEQ_TYPE_MOVIE, SEQ_TYPE_SCENE);
+ bool is_preprocessed = !ELEM(type, SEQ_TYPE_IMAGE, SEQ_TYPE_MOVIE, SEQ_TYPE_SCENE, SEQ_TYPE_MOVIECLIP);
ibuf = BKE_sequencer_cache_get(context, seq, cfra, SEQ_STRIPELEM_IBUF);
diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c
index 5ecd2fc74e8..40c58cea3d9 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_editmesh.h"
#include "BKE_mesh.h" /* for OMP limits. */
#include "BKE_subsurf.h"
@@ -278,6 +279,16 @@ static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc, bool for
BLI_SPACE_TRANSFORM_SETUP(&local2aux, calc->ob, calc->smd->auxTarget);
}
+ /* use editmesh to avoid array allocation */
+ if (calc->smd->target && calc->target->type == DM_TYPE_EDITBMESH) {
+ treeData.em_evil = BKE_editmesh_from_object(calc->smd->target);
+ treeData.em_evil_all = true;
+ }
+ if (calc->smd->auxTarget && auxMesh->type == DM_TYPE_EDITBMESH) {
+ auxData.em_evil = BKE_editmesh_from_object(calc->smd->auxTarget);
+ auxData.em_evil_all = true;
+ }
+
/* After sucessufuly build the trees, start projection vertexs */
if (bvhtree_from_mesh_looptri(&treeData, calc->target, 0.0, 4, 6) &&
(auxMesh == NULL || bvhtree_from_mesh_looptri(&auxData, auxMesh, 0.0, 4, 6)))
diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c
index b03c99c7a45..dac395645c9 100644
--- a/source/blender/blenkernel/intern/softbody.c
+++ b/source/blender/blenkernel/intern/softbody.c
@@ -1993,7 +1993,7 @@ static int _softbody_calc_forces_slice_in_a_thread(Scene *scene, Object *ob, flo
compare = (obp->colball + bp->colball);
sub_v3_v3v3(def, bp->pos, obp->pos);
/* rather check the AABBoxes before ever calulating the real distance */
- /* mathematically it is completly nuts, but performance is pretty much (3) times faster */
+ /* mathematically it is completely nuts, but performance is pretty much (3) times faster */
if ((ABS(def[0]) > compare) || (ABS(def[1]) > compare) || (ABS(def[2]) > compare)) continue;
distance = normalize_v3(def);
if (distance < compare ) {
@@ -2361,7 +2361,7 @@ static void softbody_calc_forces(Scene *scene, Object *ob, float forcetime, floa
sub_v3_v3v3(def, bp->pos, obp->pos);
/* rather check the AABBoxes before ever calulating the real distance */
- /* mathematically it is completly nuts, but performance is pretty much (3) times faster */
+ /* mathematically it is completely nuts, but performance is pretty much (3) times faster */
if ((ABS(def[0]) > compare) || (ABS(def[1]) > compare) || (ABS(def[2]) > compare)) continue;
distance = normalize_v3(def);
diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c
index 0b89931aa75..7e7cc8745fd 100644
--- a/source/blender/blenkernel/intern/sound.c
+++ b/source/blender/blenkernel/intern/sound.c
@@ -71,27 +71,20 @@ static int sound_cfra;
static char **audio_device_names = NULL;
#endif
-bSound *BKE_sound_new_file(struct Main *bmain, const char *filename)
+bSound *BKE_sound_new_file(struct Main *bmain, const char *filepath)
{
bSound *sound;
-
- char str[FILE_MAX];
const char *path;
+ char str[FILE_MAX];
- size_t len;
-
- BLI_strncpy(str, filename, sizeof(str));
+ BLI_strncpy(str, filepath, sizeof(str));
path = /*bmain ? bmain->name :*/ G.main->name;
BLI_path_abs(str, path);
- len = strlen(filename);
- while (len > 0 && filename[len - 1] != '/' && filename[len - 1] != '\\')
- len--;
-
- sound = BKE_libblock_alloc(bmain, ID_SO, filename + len);
- BLI_strncpy(sound->name, filename, FILE_MAX);
+ sound = BKE_libblock_alloc(bmain, ID_SO, BLI_path_basename(filepath));
+ BLI_strncpy(sound->name, filepath, FILE_MAX);
/* sound->type = SOUND_TYPE_FILE; */ /* XXX unused currently */
BKE_sound_load(bmain, sound);
@@ -99,6 +92,37 @@ bSound *BKE_sound_new_file(struct Main *bmain, const char *filename)
return sound;
}
+bSound *BKE_sound_new_file_exists_ex(struct Main *bmain, const char *filepath, bool *r_exists)
+{
+ bSound *sound;
+ char str[FILE_MAX], strtest[FILE_MAX];
+
+ BLI_strncpy(str, filepath, sizeof(str));
+ BLI_path_abs(str, bmain->name);
+
+ /* first search an identical filepath */
+ for (sound = bmain->sound.first; sound; sound = sound->id.next) {
+ BLI_strncpy(strtest, sound->name, sizeof(sound->name));
+ BLI_path_abs(strtest, ID_BLEND_PATH(bmain, &sound->id));
+
+ if (BLI_path_cmp(strtest, str) == 0) {
+ sound->id.us++; /* officially should not, it doesn't link here! */
+ if (r_exists)
+ *r_exists = true;
+ return sound;
+ }
+ }
+
+ if (r_exists)
+ *r_exists = false;
+ return BKE_sound_new_file(bmain, filepath);
+}
+
+bSound *BKE_sound_new_file_exists(struct Main *bmain, const char *filepath)
+{
+ return BKE_sound_new_file_exists_ex(bmain, filepath, NULL);
+}
+
void BKE_sound_free(bSound *sound)
{
if (sound->packedfile) {
diff --git a/source/blender/blenkernel/intern/speaker.c b/source/blender/blenkernel/intern/speaker.c
index 7a800555144..30296c7813c 100644
--- a/source/blender/blenkernel/intern/speaker.c
+++ b/source/blender/blenkernel/intern/speaker.c
@@ -37,11 +37,9 @@
#include "BKE_main.h"
#include "BKE_speaker.h"
-void *BKE_speaker_add(Main *bmain, const char *name)
+void BKE_speaker_init(Speaker *spk)
{
- Speaker *spk;
-
- spk = BKE_libblock_alloc(bmain, ID_SPK, name);
+ BLI_assert(MEMCMP_STRUCT_OFS_IS_ZERO(spk, id));
spk->attenuation = 1.0f;
spk->cone_angle_inner = 360.0f;
@@ -55,6 +53,15 @@ void *BKE_speaker_add(Main *bmain, const char *name)
spk->volume = 1.0f;
spk->volume_max = 1.0f;
spk->volume_min = 0.0f;
+}
+
+void *BKE_speaker_add(Main *bmain, const char *name)
+{
+ Speaker *spk;
+
+ spk = BKE_libblock_alloc(bmain, ID_SPK, name);
+
+ BKE_speaker_init(spk);
return spk;
}
diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c
index 998bb9835a8..a2c625a7ec3 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -796,7 +796,7 @@ static void ss_sync_from_derivedmesh(CCGSubSurf *ss,
{
#ifdef WITH_OPENSUBDIV
/* Reset all related descriptors if actual mesh topology changed or if
- * other evlauation-related settings changed.
+ * other evaluation-related settings changed.
*/
if (!ccgSubSurf_needGrids(ss)) {
/* TODO(sergey): Use vertex coordinates and flat subdiv flag. */
@@ -1913,7 +1913,6 @@ static void ccgDM_buffer_copy_normal(
int start = 0;
CCG_key_top_level(&key, ss);
- ccgdm_pbvh_update(ccgdm);
for (i = 0; i < totface; i++) {
CCGFace *f = ccgdm->faceMap[i].face;
@@ -2008,7 +2007,8 @@ static void ccgDM_buffer_copy_triangles(
const int *mat_orig_to_new)
{
GPUBufferMaterial *gpumat, *gpumaterials = dm->drawObject->materials;
- const int totmat = dm->drawObject->totmaterial;
+ const int gpu_totmat = dm->drawObject->totmaterial;
+ const short dm_totmat = dm->totmat;
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
CCGSubSurf *ss = ccgdm->ss;
CCGKey key;
@@ -2016,13 +2016,14 @@ static void ccgDM_buffer_copy_triangles(
int gridFaces = gridSize - 1;
DMFlagMat *faceFlags = ccgdm->faceFlags;
int i, totface = ccgSubSurf_getNumFaces(ss);
- int matnr = -1, start;
+ short mat_nr = -1;
+ int start;
int totloops = 0;
- FaceCount *fc = MEM_mallocN(sizeof(*fc) * totmat, "gpumaterial.facecount");
+ FaceCount *fc = MEM_mallocN(sizeof(*fc) * gpu_totmat, "gpumaterial.facecount");
CCG_key_top_level(&key, ss);
- for (i = 0; i < totmat; i++) {
+ for (i = 0; i < gpu_totmat; i++) {
fc[i].i_visible = 0;
fc[i].i_tri_visible = 0;
fc[i].i_hidden = gpumaterials[i].totpolys - 1;
@@ -2037,14 +2038,14 @@ static void ccgDM_buffer_copy_triangles(
int mati;
if (faceFlags) {
- matnr = faceFlags[index].mat_nr;
+ mat_nr = ME_MAT_NR_TEST(faceFlags[index].mat_nr, dm_totmat);
is_hidden = (faceFlags[index].flag & ME_HIDE) != 0;
}
else {
- matnr = 0;
+ mat_nr = 0;
is_hidden = false;
}
- mati = mat_orig_to_new[matnr];
+ mati = mat_orig_to_new[mat_nr];
gpumat = dm->drawObject->materials + mati;
if (is_hidden) {
@@ -2094,7 +2095,7 @@ static void ccgDM_buffer_copy_triangles(
}
/* set the visible polygons */
- for (i = 0; i < totmat; i++) {
+ for (i = 0; i < gpu_totmat; i++) {
gpumaterials[i].totvisiblepolys = fc[i].i_visible;
}
@@ -2116,10 +2117,9 @@ static void ccgDM_buffer_copy_vertex(
int totedge = ccgSubSurf_getNumEdges(ss);
int start = 0;
int edgeSize = ccgSubSurf_getEdgeSize(ss);
-
+
CCG_key_top_level(&key, ss);
- ccgdm_pbvh_update(ccgdm);
-
+
for (i = 0; i < totface; i++) {
CCGFace *f = ccgdm->faceMap[i].face;
int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
@@ -2167,7 +2167,7 @@ static void ccgDM_buffer_copy_color(
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
CCGSubSurf *ss = ccgdm->ss;
CCGKey key;
- const char *mloopcol = user_data;
+ const unsigned char *mloopcol = user_data;
int gridSize = ccgSubSurf_getGridSize(ss);
int gridFaces = gridSize - 1;
int i, totface = ccgSubSurf_getNumFaces(ss);
@@ -2184,10 +2184,10 @@ static void ccgDM_buffer_copy_color(
for (S = 0; S < numVerts; S++) {
for (y = 0; y < gridFaces; y++) {
for (x = 0; x < gridFaces; x++) {
- copy_v3_v3_char((char *)&varray[start + 0], &mloopcol[iface * 16 + 0]);
- copy_v3_v3_char((char *)&varray[start + 3], &mloopcol[iface * 16 + 12]);
- copy_v3_v3_char((char *)&varray[start + 6], &mloopcol[iface * 16 + 8]);
- copy_v3_v3_char((char *)&varray[start + 9], &mloopcol[iface * 16 + 4]);
+ copy_v3_v3_uchar(&varray[start + 0], &mloopcol[iface * 16 + 0]);
+ copy_v3_v3_uchar(&varray[start + 3], &mloopcol[iface * 16 + 12]);
+ copy_v3_v3_uchar(&varray[start + 6], &mloopcol[iface * 16 + 8]);
+ copy_v3_v3_uchar(&varray[start + 9], &mloopcol[iface * 16 + 4]);
start += 12;
iface++;
@@ -2243,7 +2243,7 @@ static void ccgDM_buffer_copy_uv_texpaint(
int i, totface = ccgSubSurf_getNumFaces(ss);
int start = 0;
DMFlagMat *faceFlags = ccgdm->faceFlags;
- int totmaterial = dm->totmat;
+ int dm_totmat = dm->totmat;
MLoopUV **mloopuv_base;
MLoopUV *stencil_base;
int stencil;
@@ -2252,9 +2252,9 @@ static void ccgDM_buffer_copy_uv_texpaint(
/* should have been checked for before, reassert */
BLI_assert(DM_get_loop_data_layer(dm, CD_MLOOPUV));
- mloopuv_base = MEM_mallocN(totmaterial * sizeof(*mloopuv_base), "texslots");
+ mloopuv_base = MEM_mallocN(dm_totmat * sizeof(*mloopuv_base), "texslots");
- for (i = 0; i < totmaterial; i++) {
+ for (i = 0; i < dm_totmat; i++) {
mloopuv_base[i] = DM_paint_uvlayer_active_get(dm, i);
}
@@ -2385,9 +2385,9 @@ static void ccgDM_buffer_copy_edge(
/* part one, handle all normal edges */
for (j = 0; j < totedge; j++) {
CCGFace *f;
- int fhandle;
- int totvert;
- unsigned int S;
+ int fhandle = 0;
+ int totvert = 0;
+ unsigned int S = 0;
CCGEdge *e = ccgdm->edgeMap[j].edge;
bool isloose = !ccgSubSurf_getEdgeNumFaces(e);
@@ -2541,7 +2541,7 @@ static GPUDrawObject *ccgDM_GPUObjectNew(DerivedMesh *dm)
GPUDrawObject *gdo;
DMFlagMat *faceFlags = ccgdm->faceFlags;
int gridFaces = ccgSubSurf_getGridSize(ss) - 1;
- int totmat = (faceFlags) ? dm->totmat : 1;
+ const short dm_totmat = (faceFlags) ? dm->totmat : 1;
GPUBufferMaterial *matinfo;
int i;
unsigned int tot_internal_edges = 0;
@@ -2552,16 +2552,16 @@ static GPUDrawObject *ccgDM_GPUObjectNew(DerivedMesh *dm)
int totface = ccgSubSurf_getNumFaces(ss);
/* object contains at least one material (default included) so zero means uninitialized dm */
- BLI_assert(totmat != 0);
+ BLI_assert(dm_totmat != 0);
- matinfo = MEM_callocN(sizeof(*matinfo) * totmat, "GPU_drawobject_new.mat_orig_to_new");
+ matinfo = MEM_callocN(sizeof(*matinfo) * dm_totmat, "GPU_drawobject_new.mat_orig_to_new");
if (faceFlags) {
for (i = 0; i < totface; i++) {
CCGFace *f = ccgdm->faceMap[i].face;
int numVerts = ccgSubSurf_getFaceNumVerts(f);
int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f));
- int new_matnr = faceFlags[index].mat_nr;
+ const short new_matnr = ME_MAT_NR_TEST(faceFlags[index].mat_nr, dm_totmat);
matinfo[new_matnr].totelements += numVerts * gridFaces * gridFaces * 6;
matinfo[new_matnr].totloops += numVerts * gridFaces * gridFaces * 4;
matinfo[new_matnr].totpolys++;
@@ -2584,7 +2584,7 @@ static GPUDrawObject *ccgDM_GPUObjectNew(DerivedMesh *dm)
gdo->totvert = 0; /* used to count indices, doesn't really matter for ccgsubsurf */
gdo->totedge = (totedge * edgeSize + tot_internal_edges);
- GPU_buffer_material_finalize(gdo, matinfo, totmat);
+ GPU_buffer_material_finalize(gdo, matinfo, dm_totmat);
/* store total number of points used for triangles */
gdo->tot_triangle_point = ccgSubSurf_getNumFinalFaces(ss) * 6;
@@ -2705,6 +2705,13 @@ static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes)
GPU_buffers_unbind();
}
+typedef struct {
+ DMVertexAttribs attribs;
+ int numdata;
+
+ GPUAttrib datatypes[GPU_MAX_ATTRIB]; /* TODO, messing up when switching materials many times - [#21056]*/
+} GPUMaterialConv;
+
/* Only used by non-editmesh types */
static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm,
DMSetMaterial setMaterial,
@@ -2715,14 +2722,15 @@ static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm,
CCGSubSurf *ss = ccgdm->ss;
CCGKey key;
GPUVertexAttribs gattribs;
- DMVertexAttribs attribs = {{{NULL}}};
- /* MTFace *tf = dm->getTessFaceDataArray(dm, CD_MTFACE); */ /* UNUSED */
+ int a, b, do_draw, new_matnr;
+ DMFlagMat *faceFlags = ccgdm->faceFlags;
+ unsigned char *varray;
+ size_t max_element_size = 0;
+ int tot_loops = 0;
+ int totpoly = ccgSubSurf_getNumFaces(ss);
int gridSize = ccgSubSurf_getGridSize(ss);
int gridFaces = gridSize - 1;
int edgeSize = ccgSubSurf_getEdgeSize(ss);
- DMFlagMat *faceFlags = ccgdm->faceFlags;
- const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL);
- int a, i, do_draw, numVerts, matnr, new_matnr, totface;
#ifdef WITH_OPENSUBDIV
if (ccgdm->useGpuBackend) {
@@ -2791,154 +2799,358 @@ static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm,
}
#endif
+ glShadeModel(GL_SMOOTH);
+
CCG_key_top_level(&key, ss);
ccgdm_pbvh_update(ccgdm);
- do_draw = 0;
- matnr = -1;
+ /* workaround for NVIDIA GPUs on Mac not supporting vertex arrays + interleaved formats, see T43342 */
+ if ((GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_MAC, GPU_DRIVER_ANY) && (U.gameflags & USER_DISABLE_VBO)) ||
+ setDrawOptions != NULL)
+ {
+ const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL);
+ DMVertexAttribs attribs = {{{NULL}}};
+ int i;
+ int matnr = -1;
+ do_draw = 0;
#define PASSATTRIB(dx, dy, vert) { \
if (attribs.totorco) \
index = getFaceIndex(ss, f, S, x + dx, y + dy, edgeSize, gridSize); \
else \
index = 0; \
- DM_draw_attrib_vertex(&attribs, a, index, vert, ((a) * 4) + vert); \
+ DM_draw_attrib_vertex(&attribs, a, index, vert, ((a) * 4) + vert); \
} (void)0
- totface = ccgSubSurf_getNumFaces(ss);
- for (a = 0, i = 0; i < totface; i++) {
- CCGFace *f = ccgdm->faceMap[i].face;
- const float (*ln)[3] = NULL;
- int S, x, y, drawSmooth;
- int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f));
- int origIndex = ccgDM_getFaceMapIndex(ss, f);
-
- numVerts = ccgSubSurf_getFaceNumVerts(f);
-
- if (faceFlags) {
- drawSmooth = (lnors || (faceFlags[index].flag & ME_SMOOTH));
- new_matnr = faceFlags[index].mat_nr + 1;
- }
- else {
- drawSmooth = 1;
- new_matnr = 1;
- }
-
- if (lnors) {
- ln = lnors;
- lnors += (gridFaces * gridFaces * numVerts) * 4;
- }
+ totpoly = ccgSubSurf_getNumFaces(ss);
+ for (a = 0, i = 0; i < totpoly; i++) {
+ CCGFace *f = ccgdm->faceMap[i].face;
+ const float (*ln)[3] = NULL;
+ int S, x, y, drawSmooth;
+ int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f));
+ int origIndex = ccgDM_getFaceMapIndex(ss, f);
- if (new_matnr != matnr) {
- do_draw = setMaterial(matnr = new_matnr, &gattribs);
- if (do_draw)
- DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
- }
+ int numVerts = ccgSubSurf_getFaceNumVerts(f);
- if (!do_draw || (setDrawOptions && (origIndex != ORIGINDEX_NONE) &&
- (setDrawOptions(userData, origIndex) == DM_DRAW_OPTION_SKIP)))
- {
- a += gridFaces * gridFaces * numVerts;
- continue;
- }
+ if (faceFlags) {
+ drawSmooth = (lnors || (faceFlags[index].flag & ME_SMOOTH));
+ new_matnr = faceFlags[index].mat_nr + 1;
+ }
+ else {
+ drawSmooth = 1;
+ new_matnr = 1;
+ }
- glShadeModel(drawSmooth ? GL_SMOOTH : GL_FLAT);
- for (S = 0; S < numVerts; S++) {
- CCGElem *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
- CCGElem *vda, *vdb;
+ if (lnors) {
+ ln = lnors;
+ lnors += (gridFaces * gridFaces * numVerts) * 4;
+ }
- if (ln) {
- glBegin(GL_QUADS);
- for (y = 0; y < gridFaces; y++) {
- for (x = 0; x < gridFaces; x++) {
- float *aco = CCG_grid_elem_co(&key, faceGridData, x, y);
- float *bco = CCG_grid_elem_co(&key, faceGridData, x + 1, y);
- float *cco = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 1);
- float *dco = CCG_grid_elem_co(&key, faceGridData, x, y + 1);
+ if (new_matnr != matnr) {
+ do_draw = setMaterial(matnr = new_matnr, &gattribs);
+ if (do_draw)
+ DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
+ }
- PASSATTRIB(0, 1, 1);
- glNormal3fv(ln[1]);
- glVertex3fv(dco);
- PASSATTRIB(1, 1, 2);
- glNormal3fv(ln[2]);
- glVertex3fv(cco);
- PASSATTRIB(1, 0, 3);
- glNormal3fv(ln[3]);
- glVertex3fv(bco);
- PASSATTRIB(0, 0, 0);
- glNormal3fv(ln[0]);
- glVertex3fv(aco);
+ if (!do_draw || (setDrawOptions && (origIndex != ORIGINDEX_NONE) &&
+ (setDrawOptions(userData, origIndex) == DM_DRAW_OPTION_SKIP)))
+ {
+ a += gridFaces * gridFaces * numVerts;
+ continue;
+ }
- ln += 4;
- a++;
+ glShadeModel(drawSmooth ? GL_SMOOTH : GL_FLAT);
+ for (S = 0; S < numVerts; S++) {
+ CCGElem *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
+ CCGElem *vda, *vdb;
+
+ if (ln) {
+ glBegin(GL_QUADS);
+ for (y = 0; y < gridFaces; y++) {
+ for (x = 0; x < gridFaces; x++) {
+ float *aco = CCG_grid_elem_co(&key, faceGridData, x, y);
+ float *bco = CCG_grid_elem_co(&key, faceGridData, x + 1, y);
+ float *cco = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 1);
+ float *dco = CCG_grid_elem_co(&key, faceGridData, x, y + 1);
+
+ PASSATTRIB(0, 1, 1);
+ glNormal3fv(ln[1]);
+ glVertex3fv(dco);
+ PASSATTRIB(1, 1, 2);
+ glNormal3fv(ln[2]);
+ glVertex3fv(cco);
+ PASSATTRIB(1, 0, 3);
+ glNormal3fv(ln[3]);
+ glVertex3fv(bco);
+ PASSATTRIB(0, 0, 0);
+ glNormal3fv(ln[0]);
+ glVertex3fv(aco);
+
+ ln += 4;
+ a++;
+ }
}
+ glEnd();
}
- glEnd();
- }
- else if (drawSmooth) {
- for (y = 0; y < gridFaces; y++) {
- glBegin(GL_QUAD_STRIP);
- for (x = 0; x < gridFaces; x++) {
+ else if (drawSmooth) {
+ for (y = 0; y < gridFaces; y++) {
+ glBegin(GL_QUAD_STRIP);
+ for (x = 0; x < gridFaces; x++) {
+ vda = CCG_grid_elem(&key, faceGridData, x, y + 0);
+ vdb = CCG_grid_elem(&key, faceGridData, x, y + 1);
+
+ PASSATTRIB(0, 0, 0);
+ glNormal3fv(CCG_elem_no(&key, vda));
+ glVertex3fv(CCG_elem_co(&key, vda));
+
+ PASSATTRIB(0, 1, 1);
+ glNormal3fv(CCG_elem_no(&key, vdb));
+ glVertex3fv(CCG_elem_co(&key, vdb));
+
+ if (x != gridFaces - 1)
+ a++;
+ }
+
vda = CCG_grid_elem(&key, faceGridData, x, y + 0);
vdb = CCG_grid_elem(&key, faceGridData, x, y + 1);
-
- PASSATTRIB(0, 0, 0);
+
+ PASSATTRIB(0, 0, 3);
glNormal3fv(CCG_elem_no(&key, vda));
glVertex3fv(CCG_elem_co(&key, vda));
- PASSATTRIB(0, 1, 1);
+ PASSATTRIB(0, 1, 2);
glNormal3fv(CCG_elem_no(&key, vdb));
glVertex3fv(CCG_elem_co(&key, vdb));
- if (x != gridFaces - 1)
+ glEnd();
+
+ a++;
+ }
+ }
+ else {
+ glBegin(GL_QUADS);
+ for (y = 0; y < gridFaces; y++) {
+ for (x = 0; x < gridFaces; x++) {
+ float *aco = CCG_grid_elem_co(&key, faceGridData, x, y);
+ float *bco = CCG_grid_elem_co(&key, faceGridData, x + 1, y);
+ float *cco = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 1);
+ float *dco = CCG_grid_elem_co(&key, faceGridData, x, y + 1);
+
+ ccgDM_glNormalFast(aco, bco, cco, dco);
+
+ PASSATTRIB(0, 1, 1);
+ glVertex3fv(dco);
+ PASSATTRIB(1, 1, 2);
+ glVertex3fv(cco);
+ PASSATTRIB(1, 0, 3);
+ glVertex3fv(bco);
+ PASSATTRIB(0, 0, 0);
+ glVertex3fv(aco);
+
a++;
+ }
}
+ glEnd();
+ }
+ }
+ }
- vda = CCG_grid_elem(&key, faceGridData, x, y + 0);
- vdb = CCG_grid_elem(&key, faceGridData, x, y + 1);
+#undef PASSATTRIB
+ }
+ else {
+ GPUMaterialConv *matconv;
+ size_t offset;
+ int *mat_orig_to_new;
+ int tot_active_mat;
+ GPUBuffer *buffer = NULL;
- PASSATTRIB(0, 0, 3);
- glNormal3fv(CCG_elem_no(&key, vda));
- glVertex3fv(CCG_elem_co(&key, vda));
+ GPU_vertex_setup(dm);
+ GPU_normal_setup(dm);
+ GPU_triangle_setup(dm);
- PASSATTRIB(0, 1, 2);
- glNormal3fv(CCG_elem_no(&key, vdb));
- glVertex3fv(CCG_elem_co(&key, vdb));
+ tot_active_mat = dm->drawObject->totmaterial;
- glEnd();
+ matconv = MEM_callocN(sizeof(*matconv) * tot_active_mat,
+ "cdDM_drawMappedFacesGLSL.matconv");
+ mat_orig_to_new = MEM_mallocN(sizeof(*mat_orig_to_new) * dm->totmat,
+ "cdDM_drawMappedFacesGLSL.mat_orig_to_new");
- a++;
+ /* part one, check what attributes are needed per material */
+ for (a = 0; a < tot_active_mat; a++) {
+ new_matnr = dm->drawObject->materials[a].mat_nr;
+
+ /* map from original material index to new
+ * GPUBufferMaterial index */
+ mat_orig_to_new[new_matnr] = a;
+ do_draw = setMaterial(new_matnr + 1, &gattribs);
+
+ if (do_draw) {
+ int numdata = 0;
+ DM_vertex_attributes_from_gpu(dm, &gattribs, &matconv[a].attribs);
+
+ if (matconv[a].attribs.totorco && matconv[a].attribs.orco.array) {
+ matconv[a].datatypes[numdata].index = matconv[a].attribs.orco.gl_index;
+ matconv[a].datatypes[numdata].size = 3;
+ matconv[a].datatypes[numdata].type = GL_FLOAT;
+ numdata++;
+ }
+ for (b = 0; b < matconv[a].attribs.tottface; b++) {
+ if (matconv[a].attribs.tface[b].array) {
+ matconv[a].datatypes[numdata].index = matconv[a].attribs.tface[b].gl_index;
+ matconv[a].datatypes[numdata].size = 2;
+ matconv[a].datatypes[numdata].type = GL_FLOAT;
+ numdata++;
+ }
+ }
+ for (b = 0; b < matconv[a].attribs.totmcol; b++) {
+ if (matconv[a].attribs.mcol[b].array) {
+ matconv[a].datatypes[numdata].index = matconv[a].attribs.mcol[b].gl_index;
+ matconv[a].datatypes[numdata].size = 4;
+ matconv[a].datatypes[numdata].type = GL_UNSIGNED_BYTE;
+ numdata++;
+ }
+ }
+ if (matconv[a].attribs.tottang && matconv[a].attribs.tang.array) {
+ matconv[a].datatypes[numdata].index = matconv[a].attribs.tang.gl_index;
+ matconv[a].datatypes[numdata].size = 4;
+ matconv[a].datatypes[numdata].type = GL_FLOAT;
+ numdata++;
+ }
+ if (numdata != 0) {
+ matconv[a].numdata = numdata;
+ max_element_size = max_ii(GPU_attrib_element_size(matconv[a].datatypes, numdata), max_element_size);
}
}
- else {
- glBegin(GL_QUADS);
- for (y = 0; y < gridFaces; y++) {
- for (x = 0; x < gridFaces; x++) {
- float *aco = CCG_grid_elem_co(&key, faceGridData, x, y);
- float *bco = CCG_grid_elem_co(&key, faceGridData, x + 1, y);
- float *cco = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 1);
- float *dco = CCG_grid_elem_co(&key, faceGridData, x, y + 1);
+ }
- ccgDM_glNormalFast(aco, bco, cco, dco);
+ /* part two, generate and fill the arrays with the data */
+ if (max_element_size > 0) {
+ buffer = GPU_buffer_alloc(max_element_size * dm->drawObject->tot_loop_verts, false);
- PASSATTRIB(0, 1, 1);
- glVertex3fv(dco);
- PASSATTRIB(1, 1, 2);
- glVertex3fv(cco);
- PASSATTRIB(1, 0, 3);
- glVertex3fv(bco);
- PASSATTRIB(0, 0, 0);
- glVertex3fv(aco);
-
- a++;
+ if (buffer == NULL) {
+ buffer = GPU_buffer_alloc(max_element_size * dm->drawObject->tot_loop_verts, true);
+ }
+ varray = GPU_buffer_lock_stream(buffer, GPU_BINDING_ARRAY);
+ if (varray == NULL) {
+ GPU_buffers_unbind();
+ GPU_buffer_free(buffer);
+ MEM_freeN(mat_orig_to_new);
+ MEM_freeN(matconv);
+ fprintf(stderr, "Out of memory, can't draw object\n");
+ return;
+ }
+
+ for (a = 0; a < totpoly; a++) {
+ CCGFace *f = ccgdm->faceMap[a].face;
+ int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f));
+ int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
+ int i;
+
+ if (faceFlags) {
+ i = mat_orig_to_new[faceFlags[index].mat_nr];
+ }
+ else {
+ i = mat_orig_to_new[0];
+ }
+
+ if (matconv[i].numdata != 0) {
+ for (S = 0; S < numVerts; S++) {
+ for (y = 0; y < gridFaces; y++) {
+ for (x = 0; x < gridFaces; x++) {
+
+ offset = tot_loops * max_element_size;
+
+ if (matconv[i].attribs.totorco && matconv[i].attribs.orco.array) {
+ int index;
+
+ index = getFaceIndex(ss, f, S, x, y, edgeSize, gridSize);
+ copy_v3_v3((float *)&varray[offset],
+ (float *)matconv[i].attribs.orco.array[index]);
+ index = getFaceIndex(ss, f, S, x + 1, y, edgeSize, gridSize);
+ copy_v3_v3((float *)&varray[offset + max_element_size],
+ (float *)matconv[i].attribs.orco.array[index]);
+ index = getFaceIndex(ss, f, S, x + 1, y + 1, edgeSize, gridSize);
+ copy_v3_v3((float *)&varray[offset + 2 * max_element_size],
+ (float *)matconv[i].attribs.orco.array[index]);
+ index = getFaceIndex(ss, f, S, x, y + 1, edgeSize, gridSize);
+ copy_v3_v3((float *)&varray[offset + 3 * max_element_size],
+ (float *)matconv[i].attribs.orco.array[index]);
+
+ offset += sizeof(float) * 3;
+ }
+ for (b = 0; b < matconv[i].attribs.tottface; b++) {
+ if (matconv[i].attribs.tface[b].array) {
+ const MLoopUV *mloopuv = matconv[i].attribs.tface[b].array + tot_loops;
+
+ copy_v2_v2((float *)&varray[offset], mloopuv[0].uv);
+ copy_v2_v2((float *)&varray[offset + max_element_size], mloopuv[3].uv);
+ copy_v2_v2((float *)&varray[offset + 2 * max_element_size], mloopuv[2].uv);
+ copy_v2_v2((float *)&varray[offset + 3 * max_element_size], mloopuv[1].uv);
+
+ offset += sizeof(float) * 2;
+ }
+ }
+ for (b = 0; b < matconv[i].attribs.totmcol; b++) {
+ if (matconv[i].attribs.mcol[b].array) {
+ const MLoopCol *mloopcol = matconv[i].attribs.mcol[b].array + tot_loops;
+
+ copy_v4_v4_uchar(&varray[offset], &mloopcol[0].r);
+ copy_v4_v4_uchar(&varray[offset + max_element_size], &mloopcol[3].r);
+ copy_v4_v4_uchar(&varray[offset + 2 * max_element_size], &mloopcol[2].r);
+ copy_v4_v4_uchar(&varray[offset + 3 * max_element_size], &mloopcol[1].r);
+
+ offset += sizeof(unsigned char) * 4;
+ }
+ }
+ if (matconv[i].attribs.tottang && matconv[i].attribs.tang.array) {
+ const float (*looptang)[4] = (const float (*)[4])matconv[i].attribs.tang.array + tot_loops;
+
+ copy_v4_v4((float *)&varray[offset], looptang[0]);
+ copy_v4_v4((float *)&varray[offset + max_element_size], looptang[3]);
+ copy_v4_v4((float *)&varray[offset + 2 * max_element_size], looptang[2]);
+ copy_v4_v4((float *)&varray[offset + 3 * max_element_size], looptang[1]);
+
+ offset += sizeof(float) * 4;
+ }
+
+ tot_loops += 4;
+ }
+ }
}
}
- glEnd();
+ else {
+ tot_loops += 4 * numVerts * gridFaces * gridFaces;
+ }
}
+ GPU_buffer_unlock(buffer, GPU_BINDING_ARRAY);
}
+
+ for (a = 0; a < tot_active_mat; a++) {
+ new_matnr = dm->drawObject->materials[a].mat_nr;
+
+ do_draw = setMaterial(new_matnr + 1, &gattribs);
+
+ if (do_draw) {
+ if (matconv[a].numdata) {
+ GPU_interleaved_attrib_setup(buffer, matconv[a].datatypes, matconv[a].numdata, max_element_size);
+ }
+ GPU_buffer_draw_elements(dm->drawObject->triangles, GL_TRIANGLES,
+ dm->drawObject->materials[a].start, dm->drawObject->materials[a].totelements);
+ if (matconv[a].numdata) {
+ GPU_interleaved_attrib_unbind();
+ }
+ }
+ }
+
+ GPU_buffers_unbind();
+ if (buffer)
+ GPU_buffer_free(buffer);
+
+ MEM_freeN(mat_orig_to_new);
+ MEM_freeN(matconv);
}
-#undef PASSATTRIB
+ glShadeModel(GL_FLAT);
}
static void ccgDM_drawFacesGLSL(DerivedMesh *dm, DMSetMaterial setMaterial)
@@ -4805,7 +5017,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived(
*
* TODO(sergey): There was a good eason why final calculation
* used to free entirely cached subsurf structure. reason of
- * this is to be investiated still to be sure we don't have
+ * this is to be investigated still to be sure we don't have
* regressions here.
*/
if (use_gpu_backend) {
diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c
index 89456763b95..6e41ed3f9a6 100644
--- a/source/blender/blenkernel/intern/text.c
+++ b/source/blender/blenkernel/intern/text.c
@@ -171,14 +171,12 @@ void BKE_text_free(Text *text)
#endif
}
-Text *BKE_text_add(Main *bmain, const char *name)
+void BKE_text_init(Text *ta)
{
- Text *ta;
TextLine *tmp;
-
- ta = BKE_libblock_alloc(bmain, ID_TXT, name);
- ta->id.us = 1;
-
+
+ BLI_assert(MEMCMP_STRUCT_OFS_IS_ZERO(ta, id));
+
ta->name = NULL;
init_undo_text(ta);
@@ -206,6 +204,15 @@ Text *BKE_text_add(Main *bmain, const char *name)
ta->curc = 0;
ta->sell = ta->lines.first;
ta->selc = 0;
+}
+
+Text *BKE_text_add(Main *bmain, const char *name)
+{
+ Text *ta;
+
+ ta = BKE_libblock_alloc(bmain, ID_TXT, name);
+
+ BKE_text_init(ta);
return ta;
}
@@ -1914,9 +1921,13 @@ struct LinkInt {
int value;
};
-/* unindentLines points to a ListBase composed of LinkInt elements, listing the numbers
- * of the lines that should not be indented back. */
-static void txt_undo_add_unindent_op(Text *text, const ListBase *line_index_mask, const int line_index_mask_len)
+/**
+ * UnindentLines points to a #ListBase composed of #LinkInt elements, listing the numbers
+ * of the lines that should not be indented back.
+ */
+static void txt_undo_add_unprefix_op(
+ Text *text, char undo_op,
+ const ListBase *line_index_mask, const int line_index_mask_len)
{
struct LinkInt *idata;
@@ -1929,7 +1940,7 @@ static void txt_undo_add_unindent_op(Text *text, const ListBase *line_index_mask
/* Opening buffer sequence with OP */
text->undo_pos++;
- text->undo_buf[text->undo_pos] = UNDO_UNINDENT;
+ text->undo_buf[text->undo_pos] = undo_op;
text->undo_pos++;
/* Adding number of line numbers to read */
txt_undo_store_uint32(text->undo_buf, &text->undo_pos, line_index_mask_len);
@@ -1944,7 +1955,7 @@ static void txt_undo_add_unindent_op(Text *text, const ListBase *line_index_mask
/* Adding current selection */
txt_undo_store_cursors(text);
/* Closing with OP (same as above) */
- text->undo_buf[text->undo_pos] = UNDO_UNINDENT;
+ text->undo_buf[text->undo_pos] = undo_op;
/* Marking as last undo operation */
text->undo_buf[text->undo_pos + 1] = 0;
}
@@ -2244,7 +2255,6 @@ void txt_do_undo(Text *text)
break;
case UNDO_INDENT:
case UNDO_COMMENT:
- case UNDO_UNCOMMENT:
case UNDO_DUPLICATE:
case UNDO_MOVE_LINES_UP:
case UNDO_MOVE_LINES_DOWN:
@@ -2259,9 +2269,6 @@ void txt_do_undo(Text *text)
else if (op == UNDO_COMMENT) {
txt_uncomment(text);
}
- else if (op == UNDO_UNCOMMENT) {
- txt_comment(text);
- }
else if (op == UNDO_DUPLICATE) {
txt_delete_line(text, text->curl->next);
}
@@ -2275,7 +2282,10 @@ void txt_do_undo(Text *text)
text->undo_pos--;
break;
case UNDO_UNINDENT:
+ case UNDO_UNCOMMENT:
{
+ void (*txt_prefix_fn)(Text *);
+ void (*txt_unprefix_fn)(Text *);
int count;
int i;
/* Get and restore the cursors */
@@ -2284,7 +2294,16 @@ void txt_do_undo(Text *text)
txt_move_to(text, selln, selc, 1);
/* Un-unindent */
- txt_indent(text);
+ if (op == UNDO_UNINDENT) {
+ txt_prefix_fn = txt_indent;
+ txt_unprefix_fn = txt_unindent;
+ }
+ else {
+ txt_prefix_fn = txt_comment;
+ txt_unprefix_fn = txt_uncomment;
+ }
+
+ txt_prefix_fn(text);
/* Get the count */
count = txt_undo_read_uint32(text->undo_buf, &text->undo_pos);
@@ -2293,8 +2312,8 @@ void txt_do_undo(Text *text)
for (i = 0; i < count; i++) {
txt_move_to(text, txt_undo_read_uint32(text->undo_buf, &text->undo_pos), 0, 0);
- /* Un-un-unindent */
- txt_unindent(text);
+ /* Un-un-unindent/comment */
+ txt_unprefix_fn(text);
}
/* Restore selection */
txt_move_to(text, curln, curc, 0);
@@ -2823,26 +2842,19 @@ bool txt_replace_char(Text *text, unsigned int add)
return true;
}
-void txt_indent(Text *text)
+/**
+ * Generic prefix operation, use for comment & indent.
+ *
+ * \note caller must handle undo.
+ */
+static void txt_select_prefix(Text *text, const char *add)
{
int len, num, curc_old;
char *tmp;
- const char *add = "\t";
- int indentlen = 1;
-
- /* hardcoded: TXT_TABSIZE = 4 spaces: */
- int spaceslen = TXT_TABSIZE;
+ const int indentlen = strlen(add);
- if (ELEM(NULL, text->curl, text->sell)) {
- return;
- }
-
- /* insert spaces rather than tabs */
- if (text->flags & TXT_TABSTOSPACES) {
- add = tab_to_spaces;
- indentlen = spaceslen;
- }
+ BLI_assert(!ELEM(NULL, text->curl, text->sell));
curc_old = text->curc;
@@ -2886,36 +2898,31 @@ void txt_indent(Text *text)
num--;
}
- if (!undoing) {
- txt_undo_add_op(text, UNDO_INDENT);
- }
+ /* caller must handle undo */
}
-void txt_unindent(Text *text)
+/**
+ * Generic un-prefix operation, use for comment & indent.
+ *
+ * \param r_line_index_mask: List of lines that are already at indent level 0,
+ * to store them later into the undo buffer.
+ *
+ * \note caller must handle undo.
+ */
+static void txt_select_unprefix(
+ Text *text, const char *remove,
+ ListBase *r_line_index_mask, int *r_line_index_mask_len)
{
int num = 0;
- const char *remove = "\t";
- int indentlen = 1;
+ const int indentlen = strlen(remove);
bool unindented_first = false;
-
- /* List of lines that are already at indent level 0, to store them later into the undo buffer */
- ListBase line_index_mask = {NULL, NULL};
- int line_index_mask_len = 0;
- int curl_span_init = 0;
+ int curl_span_init = 0;
- /* hardcoded: TXT_TABSIZE = 4 spaces: */
- int spaceslen = TXT_TABSIZE;
-
- if (ELEM(NULL, text->curl, text->sell)) {
- return;
- }
+ BLI_assert(!ELEM(NULL, text->curl, text->sell));
- /* insert spaces rather than tabs */
- if (text->flags & TXT_TABSTOSPACES) {
- remove = tab_to_spaces;
- indentlen = spaceslen;
- }
+ BLI_listbase_clear(r_line_index_mask);
+ *r_line_index_mask_len = 0;
if (!undoing) {
curl_span_init = txt_get_span(text->lines.first, text->curl);
@@ -2936,8 +2943,8 @@ void txt_unindent(Text *text)
struct LinkInt *idata = MEM_mallocN(sizeof(struct LinkInt), __func__);
idata->value = curl_span_init + num;
BLI_assert(idata->value == txt_get_span(text->lines.first, text->curl));
- BLI_addtail(&line_index_mask, idata);
- line_index_mask_len += 1;
+ BLI_addtail(r_line_index_mask, idata);
+ (*r_line_index_mask_len) += 1;
}
}
@@ -2964,57 +2971,20 @@ void txt_unindent(Text *text)
text->curl = text->curl->prev;
num--;
}
-
- if (!undoing) {
- txt_undo_add_unindent_op(text, &line_index_mask, line_index_mask_len);
- }
- BLI_freelistN(&line_index_mask);
+ /* caller must handle undo */
}
void txt_comment(Text *text)
{
- int len, num;
- char *tmp;
- char add = '#';
+ const char *prefix = "#";
- if (!text->curl) return;
- if (!text->sell) return; // Need to change this need to check if only one line is selected to more than one
+ if (ELEM(NULL, text->curl, text->sell)) {
+ return;
+ }
- num = 0;
- while (true) {
- tmp = MEM_mallocN(text->curl->len + 2, "textline_string");
-
- text->curc = 0;
- if (text->curc) memcpy(tmp, text->curl->line, text->curc);
- tmp[text->curc] = add;
-
- len = text->curl->len - text->curc;
- if (len > 0) memcpy(tmp + text->curc + 1, text->curl->line + text->curc, len);
- tmp[text->curl->len + 1] = 0;
+ txt_select_prefix(text, prefix);
- make_new_line(text->curl, tmp);
-
- text->curc++;
-
- txt_make_dirty(text);
- txt_clean_text(text);
-
- if (text->curl == text->sell) {
- text->selc = text->sell->len;
- break;
- }
- else {
- text->curl = text->curl->next;
- num++;
- }
- }
- text->curc = 0;
- while (num > 0) {
- text->curl = text->curl->prev;
- num--;
- }
-
if (!undoing) {
txt_undo_add_op(text, UNDO_COMMENT);
}
@@ -3022,46 +2992,55 @@ void txt_comment(Text *text)
void txt_uncomment(Text *text)
{
- int num = 0;
- char remove = '#';
+ const char *prefix = "#";
+ ListBase line_index_mask;
+ int line_index_mask_len;
- if (!text->curl) return;
- if (!text->sell) return;
+ if (ELEM(NULL, text->curl, text->sell)) {
+ return;
+ }
- while (true) {
- int i = 0;
-
- if (text->curl->line[i] == remove) {
- while (i < text->curl->len) {
- text->curl->line[i] = text->curl->line[i + 1];
- i++;
- }
- text->curl->len--;
- }
-
-
- txt_make_dirty(text);
- txt_clean_text(text);
-
- if (text->curl == text->sell) {
- text->selc = text->sell->len;
- break;
- }
- else {
- text->curl = text->curl->next;
- num++;
- }
-
+ txt_select_unprefix(text, prefix, &line_index_mask, &line_index_mask_len);
+
+ if (!undoing) {
+ txt_undo_add_unprefix_op(text, UNDO_UNCOMMENT, &line_index_mask, line_index_mask_len);
}
- text->curc = 0;
- while (num > 0) {
- text->curl = text->curl->prev;
- num--;
+
+ BLI_freelistN(&line_index_mask);
+}
+
+void txt_indent(Text *text)
+{
+ const char *prefix = (text->flags & TXT_TABSTOSPACES) ? tab_to_spaces : "\t";
+
+ if (ELEM(NULL, text->curl, text->sell)) {
+ return;
}
+
+ txt_select_prefix(text, prefix);
+
+ if (!undoing) {
+ txt_undo_add_op(text, UNDO_INDENT);
+ }
+}
+
+void txt_unindent(Text *text)
+{
+ const char *prefix = (text->flags & TXT_TABSTOSPACES) ? tab_to_spaces : "\t";
+ ListBase line_index_mask;
+ int line_index_mask_len;
+ if (ELEM(NULL, text->curl, text->sell)) {
+ return;
+ }
+
+ txt_select_unprefix(text, prefix, &line_index_mask, &line_index_mask_len);
+
if (!undoing) {
- txt_undo_add_op(text, UNDO_UNCOMMENT);
+ txt_undo_add_unprefix_op(text, UNDO_UNINDENT, &line_index_mask, line_index_mask_len);
}
+
+ BLI_freelistN(&line_index_mask);
}
void txt_move_lines(struct Text *text, const int direction)
diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c
index 88a412d5e95..463ca250ad5 100644
--- a/source/blender/blenkernel/intern/texture.c
+++ b/source/blender/blenkernel/intern/texture.c
@@ -580,6 +580,8 @@ void BKE_texture_free(Tex *tex)
void BKE_texture_default(Tex *tex)
{
+ /* BLI_assert(MEMCMP_STRUCT_OFS_IS_ZERO(tex, id)); */ /* Not here, can be called with some pointers set. :/ */
+
tex->type = TEX_IMAGE;
tex->ima = NULL;
tex->stype = 0;
diff --git a/source/blender/blenkernel/intern/unit.c b/source/blender/blenkernel/intern/unit.c
index 64d561491e2..ab8fbabd329 100644
--- a/source/blender/blenkernel/intern/unit.c
+++ b/source/blender/blenkernel/intern/unit.c
@@ -730,11 +730,10 @@ void bUnit_ToUnitAltName(char *str, int len_max, const char *orig_str, int syste
bUnitCollection *usys = unit_get_system(system, type);
bUnitDef *unit;
- bUnitDef *unit_def = unit_default(usys);
/* find and substitute all units */
for (unit = usys->units; unit->name; unit++) {
- if (len_max > 0 && (unit->name_alt || unit == unit_def)) {
+ if (len_max > 0 && unit->name_alt) {
const char *found = unit_find_str(orig_str, unit->name_short);
if (found) {
int offset = (int)(found - orig_str);
diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c
index e4736b1f54c..88c98b6d9d8 100644
--- a/source/blender/blenkernel/intern/world.c
+++ b/source/blender/blenkernel/intern/world.c
@@ -31,6 +31,7 @@
#include <string.h>
+#include <stdlib.h>
#include <math.h>
#include "MEM_guardedalloc.h"
@@ -83,12 +84,10 @@ void BKE_world_free(World *wrld)
BKE_world_free_ex(wrld, true);
}
-World *add_world(Main *bmain, const char *name)
+void BKE_world_init(World *wrld)
{
- World *wrld;
+ BLI_assert(MEMCMP_STRUCT_OFS_IS_ZERO(wrld, id));
- wrld = BKE_libblock_alloc(bmain, ID_WO, name);
-
wrld->horr = 0.05f;
wrld->horg = 0.05f;
wrld->horb = 0.05f;
@@ -113,6 +112,15 @@ World *add_world(Main *bmain, const char *name)
wrld->preview = NULL;
wrld->miststa = 5.0f;
wrld->mistdist = 25.0f;
+}
+
+World *add_world(Main *bmain, const char *name)
+{
+ World *wrld;
+
+ wrld = BKE_libblock_alloc(bmain, ID_WO, name);
+
+ BKE_world_init(wrld);
return wrld;
}
diff --git a/source/blender/blenkernel/intern/writeavi.c b/source/blender/blenkernel/intern/writeavi.c
index cec455e01b9..82e4405225a 100644
--- a/source/blender/blenkernel/intern/writeavi.c
+++ b/source/blender/blenkernel/intern/writeavi.c
@@ -147,7 +147,9 @@ bMovieHandle *BKE_movie_handle_get(const char imtype)
#endif
/* in case all above are disabled */
- (void)imtype;return &mh;
+ (void)imtype;
+
+ return (mh.append_movie != append_stub) ? &mh : NULL;
}
/* ****************************************************************** */
@@ -298,8 +300,10 @@ static void context_free_avi(void *context_v)
void BKE_movie_filepath_get(char *string, RenderData *rd, bool preview, const char *suffix)
{
bMovieHandle *mh = BKE_movie_handle_get(rd->im_format.imtype);
- if (mh->get_movie_path)
+ if (mh && mh->get_movie_path) {
mh->get_movie_path(string, rd, preview, suffix);
- else
+ }
+ else {
string[0] = '\0';
+ }
}
diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c
index 0668e7f95e2..1a63bacf17a 100644
--- a/source/blender/blenkernel/intern/writeffmpeg.c
+++ b/source/blender/blenkernel/intern/writeffmpeg.c
@@ -746,7 +746,7 @@ static AVStream *alloc_audio_stream(FFMpegContext *context, RenderData *rd, int
av_dict_free(&opts);
/* need to prevent floating point exception when using vorbis audio codec,
- * initialize this value in the same way as it's done in FFmpeg iteslf (sergey) */
+ * initialize this value in the same way as it's done in FFmpeg itself (sergey) */
st->codec->time_base.num = 1;
st->codec->time_base.den = st->codec->sample_rate;
@@ -1198,8 +1198,6 @@ int BKE_ffmpeg_append(void *context_v, RenderData *rd, int start_frame, int fram
static void end_ffmpeg_impl(FFMpegContext *context, int is_autosplit)
{
- unsigned int i;
-
PRINT("Closing ffmpeg...\n");
#if 0
@@ -1234,15 +1232,6 @@ static void end_ffmpeg_impl(FFMpegContext *context, int is_autosplit)
context->video_stream = 0;
}
-
- /* Close the output file */
- if (context->outfile) {
- for (i = 0; i < context->outfile->nb_streams; i++) {
- if (&context->outfile->streams[i]) {
- av_freep(&context->outfile->streams[i]);
- }
- }
- }
/* free the temp buffer */
if (context->current_frame) {
delete_picture(context->current_frame);
@@ -1254,7 +1243,7 @@ static void end_ffmpeg_impl(FFMpegContext *context, int is_autosplit)
}
}
if (context->outfile) {
- av_free(context->outfile);
+ avformat_free_context(context->outfile);
context->outfile = 0;
}
if (context->audio_input_buffer) {
diff --git a/source/blender/blenlib/BLI_alloca.h b/source/blender/blenlib/BLI_alloca.h
index fd814940624..b44e6c66d2a 100644
--- a/source/blender/blenlib/BLI_alloca.h
+++ b/source/blender/blenlib/BLI_alloca.h
@@ -34,8 +34,13 @@
#endif
#if defined(__GNUC__) || defined(__clang__)
+#if defined(__cplusplus) && (__cplusplus > 199711L)
+#define BLI_array_alloca(arr, realsize) \
+ (decltype(arr))alloca(sizeof(*arr) * (realsize))
+#else
#define BLI_array_alloca(arr, realsize) \
(typeof(arr))alloca(sizeof(*arr) * (realsize))
+#endif
#else
#define BLI_array_alloca(arr, realsize) \
alloca(sizeof(*arr) * (realsize))
diff --git a/source/blender/blenlib/BLI_buffer.h b/source/blender/blenlib/BLI_buffer.h
index 4e5b61da532..6ea9e765c1d 100644
--- a/source/blender/blenlib/BLI_buffer.h
+++ b/source/blender/blenlib/BLI_buffer.h
@@ -23,27 +23,12 @@
/** \file BLI_buffer.h
* \ingroup bli
- *
- * \note this more or less fills same purpose as BLI_array, but makes
- * it much easier to resize the array outside of the function it was
- * declared in since.
- *
- * Usage examples:
- * \code{.c}
- * BLI_buffer_declare_static(int, my_int_array, BLI_BUFFER_NOP, 32);
- *
- * BLI_buffer_append(my_int_array, int, 42);
- * assert(my_int_array.count == 1);
- * assert(BLI_buffer_at(my_int_array, int, 0) == 42);
- *
- * BLI_buffer_free(&my_int_array);
- * \endcode
*/
typedef struct {
void *data;
- const int elem_size;
- int count, alloc_count;
+ const size_t elem_size;
+ size_t count, alloc_count;
int flag;
} BLI_Buffer;
@@ -79,7 +64,7 @@ enum {
#define BLI_buffer_at(buffer_, type_, index_) ( \
(((type_ *)(buffer_)->data)[ \
(BLI_assert(sizeof(type_) == (buffer_)->elem_size)), \
- (BLI_assert(index_ >= 0 && index_ < (buffer_)->count)), \
+ (BLI_assert((int)(index_) >= 0 && (size_t)(index_) < (buffer_)->count)), \
index_]))
#define BLI_buffer_array(buffer_, type_) ( \
@@ -88,6 +73,9 @@ enum {
#define BLI_buffer_resize_data(buffer_, type_, new_count_) ( \
(BLI_buffer_resize(buffer_, new_count_), new_count_ ? BLI_buffer_array(buffer_, type_) : NULL))
+#define BLI_buffer_reinit_data(buffer_, type_, new_count_) ( \
+ (BLI_buffer_reinit(buffer_, new_count_), new_count_ ? BLI_buffer_array(buffer_, type_) : NULL))
+
#define BLI_buffer_append(buffer_, type_, val_) ( \
BLI_buffer_resize(buffer_, (buffer_)->count + 1), \
(BLI_buffer_at(buffer_, type_, (buffer_)->count - 1) = val_) \
@@ -98,7 +86,10 @@ enum {
} (void)0
/* Never decreases the amount of memory allocated */
-void BLI_buffer_resize(BLI_Buffer *buffer, int new_count);
+void BLI_buffer_resize(BLI_Buffer *buffer, const size_t new_count);
+
+/* Ensure size, throwing away old data, respecting BLI_BUFFER_USE_CALLOC */
+void BLI_buffer_reinit(BLI_Buffer *buffer, const size_t new_count);
/* Does not free the buffer structure itself */
void _bli_buffer_free(BLI_Buffer *buffer);
diff --git a/source/blender/blenlib/BLI_fileops.h b/source/blender/blenlib/BLI_fileops.h
index 33dae45ac26..53ebc81fe22 100644
--- a/source/blender/blenlib/BLI_fileops.h
+++ b/source/blender/blenlib/BLI_fileops.h
@@ -89,7 +89,7 @@ bool BLI_is_dir(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
bool BLI_is_file(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
bool BLI_dir_create_recursive(const char *dir) ATTR_NONNULL();
double BLI_dir_free_space(const char *dir) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-char *BLI_current_working_dir(char *dir, const size_t maxlen) ATTR_NONNULL();
+char *BLI_current_working_dir(char *dir, const size_t maxlen) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
/* Filelist */
diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h
index 1a25f9f897f..dfc51895c77 100644
--- a/source/blender/blenlib/BLI_math_geom.h
+++ b/source/blender/blenlib/BLI_math_geom.h
@@ -119,14 +119,25 @@ float dist_signed_squared_to_corner_v3v3v3(
float closest_to_line_v3(float r[3], const float p[3], const float l1[3], const float l2[3]);
float closest_to_line_v2(float r[2], const float p[2], const float l1[2], const float l2[2]);
void closest_to_line_segment_v3(float r_close[3], const float p[3], const float l1[3], const float l2[3]);
+void closest_to_plane_normalized_v3(float r_close[3], const float plane[4], const float pt[3]);
void closest_to_plane_v3(float r_close[3], const float plane[4], const float pt[3]);
+void closest_to_plane3_normalized_v3(float r_close[3], const float plane[3], const float pt[3]);
+void closest_to_plane3_v3(float r_close[3], const float plane[3], const float pt[3]);
/* Set 'r' to the point in triangle (t1, t2, t3) closest to point 'p' */
void closest_on_tri_to_point_v3(float r[3], const float p[3], const float t1[3], const float t2[3], const float t3[3]);
+float line_point_factor_v3_ex(
+ const float p[3], const float l1[3], const float l2[3],
+ const float epsilon, const float fallback);
+float line_point_factor_v3(
+ const float p[3], const float l1[3], const float l2[3]);
-float line_point_factor_v3(const float p[3], const float l1[3], const float l2[3]);
-float line_point_factor_v2(const float p[2], const float l1[2], const float l2[2]);
+float line_point_factor_v2_ex(
+ const float p[2], const float l1[2], const float l2[2],
+ const float epsilon, const float fallback);
+float line_point_factor_v2(
+ const float p[2], const float l1[2], const float l2[2]);
float line_plane_factor_v3(const float plane_co[3], const float plane_no[3],
const float l1[3], const float l2[3]);
@@ -165,16 +176,19 @@ bool isect_line_line_strict_v3(const float v1[3], const float v2[3],
bool isect_ray_plane_v3(
const float p1[3], const float d[3],
- const float v0[3], const float v1[3], const float v2[3],
+ const float plane[4],
float *r_lambda, const bool clip);
bool isect_point_planes_v3(float (*planes)[4], int totplane, const float p[3]);
bool isect_line_plane_v3(float out[3], const float l1[3], const float l2[3],
const float plane_co[3], const float plane_no[3]) ATTR_WARN_UNUSED_RESULT;
-bool isect_plane_plane_v3(float r_isect_co[3], float r_isect_no[3],
- const float plane_a_co[3], const float plane_a_no[3],
- const float plane_b_co[3], const float plane_b_no[3]) ATTR_WARN_UNUSED_RESULT;
+bool isect_plane_plane_plane_v3(
+ const float plane_a[4], const float plane_b[4], const float plane_c[4],
+ float r_isect_co[3]) ATTR_WARN_UNUSED_RESULT;
+bool isect_plane_plane_v3(
+ const float plane_a[4], const float plane_b[4],
+ float r_isect_co[3], float r_isect_no[3]) ATTR_WARN_UNUSED_RESULT;
/* line/ray triangle */
bool isect_line_tri_v3(
diff --git a/source/blender/blenlib/BLI_math_inline.h b/source/blender/blenlib/BLI_math_inline.h
index 2bf3b9532dd..840cf24f8cf 100644
--- a/source/blender/blenlib/BLI_math_inline.h
+++ b/source/blender/blenlib/BLI_math_inline.h
@@ -46,9 +46,9 @@ extern "C" {
# define MINLINE static inline
# if (defined(__APPLE__) && defined(__ppc__))
/* static inline __attribute__ here breaks osx ppc gcc42 build */
-# define MALWAYS_INLINE static __attribute__((always_inline))
+# define MALWAYS_INLINE static __attribute__((always_inline)) __attribute__((unused))
# else
-# define MALWAYS_INLINE static inline __attribute__((always_inline))
+# define MALWAYS_INLINE static inline __attribute__((always_inline)) __attribute__((unused))
# endif
# endif
#else
diff --git a/source/blender/blenlib/BLI_math_matrix.h b/source/blender/blenlib/BLI_math_matrix.h
index d7a309e0835..5900e391d3e 100644
--- a/source/blender/blenlib/BLI_math_matrix.h
+++ b/source/blender/blenlib/BLI_math_matrix.h
@@ -153,10 +153,14 @@ void transpose_m4_m4(float R[4][4], float A[4][4]);
int compare_m4m4(float mat1[4][4], float mat2[4][4], float limit);
-void normalize_m3(float R[3][3]);
-void normalize_m3_m3(float R[3][3], float A[3][3]);
-void normalize_m4(float R[4][4]);
-void normalize_m4_m4(float R[4][4], float A[4][4]);
+void normalize_m3_ex(float R[3][3], float r_scale[3]) ATTR_NONNULL();
+void normalize_m3(float R[3][3]) ATTR_NONNULL();
+void normalize_m3_m3_ex(float R[3][3], float A[3][3], float r_scale[3]) ATTR_NONNULL();
+void normalize_m3_m3(float R[3][3], float A[3][3]) ATTR_NONNULL();
+void normalize_m4_ex(float R[4][4], float r_scale[3]) ATTR_NONNULL();
+void normalize_m4(float R[4][4]) ATTR_NONNULL();
+void normalize_m4_m4_ex(float R[4][4], float A[4][4], float r_scale[3]) ATTR_NONNULL();
+void normalize_m4_m4(float R[4][4], float A[4][4]) ATTR_NONNULL();
void orthogonalize_m3(float R[3][3], int axis);
void orthogonalize_m4(float R[4][4], int axis);
@@ -215,6 +219,8 @@ void mat4_to_loc_rot_size(float loc[3], float rot[3][3], float size[3], float wm
void mat4_to_loc_quat(float loc[3], float quat[4], float wmat[4][4]);
void mat4_decompose(float loc[3], float quat[4], float size[3], float wmat[4][4]);
+void mat3_polar_decompose(float mat3[3][3], float r_U[3][3], float r_P[3][3]);
+
void loc_eul_size_to_mat4(float R[4][4],
const float loc[3], const float eul[3], const float size[3]);
void loc_eulO_size_to_mat4(float R[4][4],
@@ -227,6 +233,9 @@ void loc_axisangle_size_to_mat4(float R[4][4],
void blend_m3_m3m3(float R[3][3], float A[3][3], float B[3][3], const float t);
void blend_m4_m4m4(float R[4][4], float A[4][4], float B[4][4], const float t);
+void interp_m3_m3m3(float R[3][3], float A[3][3], float B[3][3], const float t);
+void interp_m4_m4m4(float R[4][4], float A[4][4], float B[4][4], const float t);
+
bool is_negative_m3(float mat[3][3]);
bool is_negative_m4(float mat[4][4]);
diff --git a/source/blender/blenlib/BLI_math_solvers.h b/source/blender/blenlib/BLI_math_solvers.h
index ec9ba5538e2..810c84cc830 100644
--- a/source/blender/blenlib/BLI_math_solvers.h
+++ b/source/blender/blenlib/BLI_math_solvers.h
@@ -46,6 +46,7 @@ extern "C" {
bool BLI_eigen_solve_selfadjoint_m3(const float m3[3][3], float r_eigen_values[3], float r_eigen_vectors[3][3]);
+void BLI_svd_m3(const float m3[3][3], float r_U[3][3], float r_S[], float r_V[3][3]);
/**************************** Inline Definitions ******************************/
#if 0 /* None so far. */
diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h
index 493c285d251..01c00ddb48e 100644
--- a/source/blender/blenlib/BLI_math_vector.h
+++ b/source/blender/blenlib/BLI_math_vector.h
@@ -61,11 +61,14 @@ MINLINE void swap_v2_v2(float a[2], float b[2]);
MINLINE void swap_v3_v3(float a[3], float b[3]);
MINLINE void swap_v4_v4(float a[4], float b[4]);
+/* unsigned char */
+MINLINE void copy_v2_v2_uchar(unsigned char r[2], const unsigned char a[2]);
+MINLINE void copy_v3_v3_uchar(unsigned char r[3], const unsigned char a[3]);
+MINLINE void copy_v4_v4_uchar(unsigned char r[4], const unsigned char a[4]);
/* char */
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]);
@@ -307,7 +310,7 @@ MINLINE void normal_float_to_short_v3(short r[3], const float n[3]);
void minmax_v3v3_v3(float min[3], float max[3], const float vec[3]);
void minmax_v2v2_v2(float min[2], float max[2], const float vec[2]);
-void minmax_v3v3_v3_array(float r_min[3], float r_max[3], float (*vec_arr)[3], int nbr);
+void minmax_v3v3_v3_array(float r_min[3], float r_max[3], const float (*vec_arr)[3], int nbr);
void dist_ensure_v3_v3fl(float v1[3], const float v2[3], const float dist);
void dist_ensure_v2_v2fl(float v1[2], const float v2[2], const float dist);
diff --git a/source/blender/blenlib/BLI_memory_utils.h b/source/blender/blenlib/BLI_memory_utils.h
new file mode 100644
index 00000000000..32bbdf8a7b5
--- /dev/null
+++ b/source/blender/blenlib/BLI_memory_utils.h
@@ -0,0 +1,34 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __BLI_MEMORY_UTILS_H__
+#define __BLI_MEMORY_UTILS_H__
+
+/** \file BLI_memory_utils.h
+ * \ingroup bli
+ * \brief Generic memory manipulation API.
+ */
+
+/* it may be defined already */
+#ifndef __BLI_UTILDEFINES_H__
+bool BLI_memory_is_zero(const void *arr, const size_t size);
+#endif
+
+#endif /* __BLI_MEMORY_UTILS_H__ */
diff --git a/source/blender/blenlib/BLI_path_util.h b/source/blender/blenlib/BLI_path_util.h
index a344c9d2bc1..1a626ff44bd 100644
--- a/source/blender/blenlib/BLI_path_util.h
+++ b/source/blender/blenlib/BLI_path_util.h
@@ -99,12 +99,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);
-/**
- * dir can be any input, like from buttons, and this function
- * converts it to a regular full path.
- * Also removes garbage from directory paths, like /../ or double slashes etc
- */
-
/* removes trailing slash */
void BLI_cleanup_file(const char *relabase, char *path) ATTR_NONNULL(2);
/* same as above but adds a trailing slash */
@@ -118,25 +112,13 @@ bool BLI_path_make_safe(char *path) ATTR_NONNULL(1);
/* go back one directory */
bool BLI_parent_dir(char *path) ATTR_NONNULL();
-/**
- * Blender's path code replacement function.
- * Bases \a path strings leading with "//" by the
- * directory \a basepath, and replaces instances of
- * '#' with the \a framenum. Results are written
- * back into \a path.
- *
- * \a path The path to convert
- * \a basepath The directory to base relative paths with.
- * \a framenum The framenumber to replace the frame code with.
- * \retval Returns true if the path was relative (started with "//").
- */
bool BLI_path_abs(char *path, const char *basepath) ATTR_NONNULL();
bool BLI_path_frame(char *path, int frame, int digits) ATTR_NONNULL();
bool BLI_path_frame_range(char *path, int sta, int end, int digits) ATTR_NONNULL();
bool BLI_path_frame_get(char *path, int *r_frame, int *numdigits) ATTR_NONNULL();
-void BLI_path_frame_strip(char *path, bool setsharp, char *ext) ATTR_NONNULL();
+void BLI_path_frame_strip(char *path, bool set_frame_char, char *ext) ATTR_NONNULL();
bool BLI_path_frame_check_chars(const char *path) ATTR_NONNULL();
-bool BLI_path_cwd(char *path) ATTR_NONNULL();
+bool BLI_path_cwd(char *path, const size_t maxlen) ATTR_NONNULL();
void BLI_path_rel(char *file, const char *relfile) ATTR_NONNULL();
bool BLI_path_is_rel(const char *path) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
@@ -158,10 +140,6 @@ bool BLI_path_suffix(char *string, size_t maxlen, const char *suffix, const char
# define BLI_path_ncmp strncmp
#endif
-#ifdef WITH_ICONV
-void BLI_string_to_utf8(char *original, char *utf_8, const char *code);
-#endif
-
/* these values need to be hardcoded in structs, dna does not recognize defines */
/* also defined in DNA_space_types.h */
#ifndef FILE_MAXDIR
@@ -183,5 +161,4 @@ void BLI_string_to_utf8(char *original, char *utf_8, const char *code);
}
#endif
-#endif
-
+#endif /* __BLI_PATH_UTIL_H__ */
diff --git a/source/blender/blenlib/BLI_rect.h b/source/blender/blenlib/BLI_rect.h
index a98931d2ae8..59bf3644912 100644
--- a/source/blender/blenlib/BLI_rect.h
+++ b/source/blender/blenlib/BLI_rect.h
@@ -66,6 +66,8 @@ void BLI_rctf_interp(struct rctf *rect, const struct rctf *rect_a, const struct
//void BLI_rcti_interp(struct rctf *rect, struct rctf *rect_a, struct rctf *rect_b, float fac);
bool BLI_rctf_clamp_pt_v(const struct rctf *rect, float xy[2]);
bool BLI_rcti_clamp_pt_v(const struct rcti *rect, int xy[2]);
+bool BLI_rctf_clamp(struct rctf *rect, const struct rctf *rect_bounds, float r_xy[2]);
+bool BLI_rcti_clamp(struct rcti *rect, const struct rcti *rect_bounds, int r_xy[2]);
bool BLI_rctf_compare(const struct rctf *rect_a, const struct rctf *rect_b, const float limit);
bool BLI_rcti_compare(const struct rcti *rect_a, const struct rcti *rect_b);
bool BLI_rctf_isect(const struct rctf *src1, const struct rctf *src2, struct rctf *dest);
diff --git a/source/blender/blenlib/BLI_utildefines.h b/source/blender/blenlib/BLI_utildefines.h
index 65e8dcdba4a..31852fa0f43 100644
--- a/source/blender/blenlib/BLI_utildefines.h
+++ b/source/blender/blenlib/BLI_utildefines.h
@@ -513,6 +513,17 @@ extern "C" {
sizeof(*(struct_var)) - OFFSETOF_STRUCT(struct_var, member)); \
} (void)0
+/* defined
+ * in memory_utils.c for now. I do not know where we should put it actually... */
+#ifndef __BLI_MEMORY_UTILS_H__
+extern bool BLI_memory_is_zero(const void *arr, const size_t arr_size);
+#endif
+
+#define MEMCMP_STRUCT_OFS_IS_ZERO(struct_var, member) \
+ (BLI_memory_is_zero( \
+ (char *)(struct_var) + OFFSETOF_STRUCT(struct_var, member), \
+ sizeof(*(struct_var)) - OFFSETOF_STRUCT(struct_var, member)))
+
/* Warning-free macros for storing ints in pointers. Use these _only_
* for storing an int in a pointer, not a pointer in an int (64bit)! */
#define SET_INT_IN_POINTER(i) ((void *)(intptr_t)(i))
@@ -623,9 +634,9 @@ extern "C" {
#else
# if (defined(__APPLE__) && defined(__ppc__))
/* static inline __attribute__ here breaks osx ppc gcc42 build */
-# define BLI_INLINE static __attribute__((always_inline))
+# define BLI_INLINE static __attribute__((always_inline)) __attribute__((__unused__))
# else
-# define BLI_INLINE static inline __attribute__((always_inline))
+# define BLI_INLINE static inline __attribute__((always_inline)) __attribute__((__unused__))
# endif
#endif
diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt
index dcf7c3b5d39..0de614a5ca7 100644
--- a/source/blender/blenlib/CMakeLists.txt
+++ b/source/blender/blenlib/CMakeLists.txt
@@ -88,6 +88,7 @@ set(SRC
intern/math_statistics.c
intern/math_vector.c
intern/math_vector_inline.c
+ intern/memory_utils.c
intern/noise.c
intern/path_util.c
intern/polyfill2d.c
@@ -169,6 +170,7 @@ set(SRC
BLI_math_statistics.h
BLI_math_vector.h
BLI_memarena.h
+ BLI_memory_utils.h
BLI_mempool.h
BLI_noise.h
BLI_path_util.h
diff --git a/source/blender/blenlib/intern/BLI_filelist.c b/source/blender/blenlib/intern/BLI_filelist.c
index 62690ff4f3c..527d9934797 100644
--- a/source/blender/blenlib/intern/BLI_filelist.c
+++ b/source/blender/blenlib/intern/BLI_filelist.c
@@ -333,7 +333,8 @@ void BLI_filelist_entry_datetime_to_string(
const struct stat *st, const int64_t ts, const bool compact,
char r_time[FILELIST_DIRENTRY_TIME_LEN], char r_date[FILELIST_DIRENTRY_DATE_LEN])
{
- const struct tm *tm = localtime(st ? &st->st_mtime : &ts);
+ time_t ts_mtime = ts;
+ const struct tm *tm = localtime(st ? &st->st_mtime : &ts_mtime);
const time_t zero = 0;
/* Prevent impossible dates in windows. */
diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c
index 91ac0ce1c43..7e6dabdffef 100644
--- a/source/blender/blenlib/intern/BLI_ghash.c
+++ b/source/blender/blenlib/intern/BLI_ghash.c
@@ -653,7 +653,7 @@ GHash *BLI_ghash_copy(GHash *gh, GHashKeyCopyFP keycopyfp, GHashValCopyFP valcop
}
/**
- * Reverve given ammount of entries (resize \a gh accordingly if needed).
+ * Reserve given amount of entries (resize \a gh accordingly if needed).
*/
void BLI_ghash_reserve(GHash *gh, const unsigned int nentries_reserve)
{
diff --git a/source/blender/blenlib/intern/array_utils.c b/source/blender/blenlib/intern/array_utils.c
index 65c653c9b4f..cef912e42a3 100644
--- a/source/blender/blenlib/intern/array_utils.c
+++ b/source/blender/blenlib/intern/array_utils.c
@@ -90,7 +90,7 @@ void _bli_array_wrap(void *arr_v, unsigned int arr_len, size_t arr_stride, int d
/**
*In-place array permute.
- * (re-arrange elemrnts based on an array of indices).
+ * (re-arrange elements based on an array of indices).
*
* Access via #BLI_array_wrap
*/
diff --git a/source/blender/blenlib/intern/buffer.c b/source/blender/blenlib/intern/buffer.c
index 9e96205a5e8..24b2228c884 100644
--- a/source/blender/blenlib/intern/buffer.c
+++ b/source/blender/blenlib/intern/buffer.c
@@ -20,30 +20,55 @@
/** \file blender/blenlib/intern/buffer.c
* \ingroup bli
+ *
+ * Primitive generic buffer library.
+ *
+ * - Automatically grow as needed.
+ * (currently never shrinks).
+ * - Can be passed between functions.
+ * - Supports using stack memory by default,
+ * falling back to heap as needed.
+ *
+ * Usage examples:
+ * \code{.c}
+ * BLI_buffer_declare_static(int, my_int_array, BLI_BUFFER_NOP, 32);
+ *
+ * BLI_buffer_append(my_int_array, int, 42);
+ * assert(my_int_array.count == 1);
+ * assert(BLI_buffer_at(my_int_array, int, 0) == 42);
+ *
+ * BLI_buffer_free(&my_int_array);
+ * \endcode
+ *
+ * \note this more or less fills same purpose as #BLI_array,
+ * but supports resizing the array outside of the function
+ * it was declared in.
*/
+#include <string.h>
+
#include "MEM_guardedalloc.h"
#include "BLI_buffer.h"
#include "BLI_utildefines.h"
-#include <string.h>
+#include "BLI_strict_flags.h"
-static void *buffer_alloc(BLI_Buffer *buffer, int len)
+static void *buffer_alloc(BLI_Buffer *buffer, const size_t len)
{
return ((buffer->flag & BLI_BUFFER_USE_CALLOC) ?
MEM_callocN : MEM_mallocN)
(buffer->elem_size * len, "BLI_Buffer.data");
}
-static void *buffer_realloc(BLI_Buffer *buffer, int len)
+static void *buffer_realloc(BLI_Buffer *buffer, const size_t len)
{
return ((buffer->flag & BLI_BUFFER_USE_CALLOC) ?
MEM_recallocN_id : MEM_reallocN_id)
(buffer->data, buffer->elem_size * len, "BLI_Buffer.data");
}
-void BLI_buffer_resize(BLI_Buffer *buffer, int new_count)
+void BLI_buffer_resize(BLI_Buffer *buffer, const size_t new_count)
{
if (UNLIKELY(new_count > buffer->alloc_count)) {
if (buffer->flag & BLI_BUFFER_USE_STATIC) {
@@ -65,6 +90,47 @@ void BLI_buffer_resize(BLI_Buffer *buffer, int new_count)
buffer->data = buffer_realloc(buffer, buffer->alloc_count);
}
}
+ else {
+ if (buffer->flag & BLI_BUFFER_USE_CALLOC) {
+ if (new_count > buffer->count) {
+ memset(POINTER_OFFSET(buffer->data, buffer->elem_size * buffer->count), 0,
+ buffer->elem_size * (new_count - buffer->count));
+ }
+ }
+ }
+
+ buffer->count = new_count;
+}
+
+/**
+ * Similar to #BLI_buffer_resize, but use when the existing data can be:
+ * - Ignored (malloc'd)
+ * - Cleared (when BLI_BUFFER_USE_CALLOC is set)
+ */
+void BLI_buffer_reinit(BLI_Buffer *buffer, size_t new_count)
+{
+ if (UNLIKELY(new_count > buffer->alloc_count)) {
+ if ((buffer->flag & BLI_BUFFER_USE_STATIC) == 0) {
+ if (buffer->data) {
+ MEM_freeN(buffer->data);
+ }
+ }
+
+ if (buffer->alloc_count && (new_count < buffer->alloc_count * 2)) {
+ buffer->alloc_count *= 2;
+ }
+ else {
+ buffer->alloc_count = new_count;
+ }
+
+ buffer->data = buffer_alloc(buffer, new_count);
+ }
+ else {
+ if (buffer->flag & BLI_BUFFER_USE_CALLOC) {
+ memset(buffer->data, 0,
+ buffer->elem_size * new_count);
+ }
+ }
buffer->count = new_count;
}
diff --git a/source/blender/blenlib/intern/fileops.c b/source/blender/blenlib/intern/fileops.c
index bc952165b61..ef9a7c0603f 100644
--- a/source/blender/blenlib/intern/fileops.c
+++ b/source/blender/blenlib/intern/fileops.c
@@ -570,7 +570,7 @@ static int recursive_operation(const char *startfrom, const char *startto,
char *from_path = NULL, *to_path = NULL;
struct dirent **dirlist = NULL;
size_t from_alloc_len = -1, to_alloc_len = -1;
- int i, n, ret = 0;
+ int i, n = 0, ret = 0;
do { /* once */
/* ensure there's no trailing slash in file path */
diff --git a/source/blender/blenlib/intern/math_color_blend_inline.c b/source/blender/blenlib/intern/math_color_blend_inline.c
index 73a7259ddcd..048ab71c6dc 100644
--- a/source/blender/blenlib/intern/math_color_blend_inline.c
+++ b/source/blender/blenlib/intern/math_color_blend_inline.c
@@ -36,7 +36,7 @@
#ifndef __MATH_COLOR_BLEND_INLINE_C__
#define __MATH_COLOR_BLEND_INLINE_C__
-/* don't add any saturation to a completly black and white image */
+/* don't add any saturation to a completely black and white image */
#define EPS_SATURATION 0.0005f
#define EPS_ALPHA 0.0005f
@@ -72,7 +72,7 @@ MINLINE void blend_color_mix_byte(unsigned char dst[4], const unsigned char src1
}
else {
/* no op */
- copy_v4_v4_char((char *)dst, (char *)src1);
+ copy_v4_v4_uchar(dst, src1);
}
}
@@ -94,7 +94,7 @@ MINLINE void blend_color_add_byte(unsigned char dst[4], const unsigned char src1
}
else {
/* no op */
- copy_v4_v4_char((char *)dst, (char *)src1);
+ copy_v4_v4_uchar(dst, src1);
}
}
@@ -116,7 +116,7 @@ MINLINE void blend_color_sub_byte(unsigned char dst[4], const unsigned char src1
}
else {
/* no op */
- copy_v4_v4_char((char *)dst, (char *)src1);
+ copy_v4_v4_uchar(dst, src1);
}
}
@@ -139,7 +139,7 @@ MINLINE void blend_color_mul_byte(unsigned char dst[4], const unsigned char src1
}
else {
/* no op */
- copy_v4_v4_char((char *)dst, (char *)src1);
+ copy_v4_v4_uchar(dst, src1);
}
}
@@ -162,7 +162,7 @@ MINLINE void blend_color_lighten_byte(unsigned char dst[4], const unsigned char
}
else {
/* no op */
- copy_v4_v4_char((char *)dst, (char *)src1);
+ copy_v4_v4_uchar(dst, src1);
}
}
@@ -185,7 +185,7 @@ MINLINE void blend_color_darken_byte(unsigned char dst[4], const unsigned char s
}
else {
/* no op */
- copy_v4_v4_char((char *)dst, (char *)src1);
+ copy_v4_v4_uchar(dst, src1);
}
}
@@ -202,7 +202,7 @@ MINLINE void blend_color_erase_alpha_byte(unsigned char dst[4], const unsigned c
}
else {
/* no op */
- copy_v4_v4_char((char *)dst, (char *)src1);
+ copy_v4_v4_uchar(dst, src1);
}
}
@@ -219,7 +219,7 @@ MINLINE void blend_color_add_alpha_byte(unsigned char dst[4], const unsigned cha
}
else {
/* no op */
- copy_v4_v4_char((char *)dst, (char *)src1);
+ copy_v4_v4_uchar(dst, src1);
}
}
@@ -244,7 +244,7 @@ MINLINE void blend_color_overlay_byte(unsigned char dst[4], unsigned const char
}
else {
/* no op */
- copy_v4_v4_char((char *)dst, (char *)src1);
+ copy_v4_v4_uchar(dst, src1);
}
}
@@ -270,7 +270,7 @@ MINLINE void blend_color_hardlight_byte(unsigned char dst[4], unsigned const cha
}
else {
/* no op */
- copy_v4_v4_char((char *)dst, (char *)src1);
+ copy_v4_v4_uchar(dst, src1);
}
}
@@ -289,7 +289,7 @@ MINLINE void blend_color_burn_byte(unsigned char dst[4], unsigned const char src
}
else {
/* no op */
- copy_v4_v4_char((char *)dst, (char *)src1);
+ copy_v4_v4_uchar(dst, src1);
}
}
@@ -308,7 +308,7 @@ MINLINE void blend_color_linearburn_byte(unsigned char dst[4], unsigned const ch
}
else {
/* no op */
- copy_v4_v4_char((char *)dst, (char *)src1);
+ copy_v4_v4_uchar(dst, src1);
}
}
@@ -327,7 +327,7 @@ MINLINE void blend_color_dodge_byte(unsigned char dst[4], unsigned const char sr
}
else {
/* no op */
- copy_v4_v4_char((char *)dst, (char *)src1);
+ copy_v4_v4_uchar(dst, src1);
}
}
@@ -345,7 +345,7 @@ MINLINE void blend_color_screen_byte(unsigned char dst[4], unsigned const char s
}
else {
/* no op */
- copy_v4_v4_char((char *)dst, (char *)src1);
+ copy_v4_v4_uchar(dst, src1);
}
}
@@ -371,7 +371,7 @@ MINLINE void blend_color_softlight_byte(unsigned char dst[4], unsigned const cha
}
else {
/* no op */
- copy_v4_v4_char((char *)dst, (char *)src1);
+ copy_v4_v4_uchar(dst, src1);
}
}
@@ -397,7 +397,7 @@ MINLINE void blend_color_pinlight_byte(unsigned char dst[4], unsigned const char
}
else {
/* no op */
- copy_v4_v4_char((char *)dst, (char *)src1);
+ copy_v4_v4_uchar(dst, src1);
}
}
@@ -423,7 +423,7 @@ MINLINE void blend_color_linearlight_byte(unsigned char dst[4], unsigned const c
}
else {
/* no op */
- copy_v4_v4_char((char *)dst, (char *)src1);
+ copy_v4_v4_uchar(dst, src1);
}
}
@@ -455,7 +455,7 @@ MINLINE void blend_color_vividlight_byte(unsigned char dst[4], unsigned const ch
}
else {
/* no op */
- copy_v4_v4_char((char *)dst, (char *)src1);
+ copy_v4_v4_uchar(dst, src1);
}
}
@@ -475,7 +475,7 @@ MINLINE void blend_color_difference_byte(unsigned char dst[4], unsigned const ch
}
else {
/* no op */
- copy_v4_v4_char((char *)dst, (char *)src1);
+ copy_v4_v4_uchar(dst, src1);
}
}
@@ -494,7 +494,7 @@ MINLINE void blend_color_exclusion_byte(unsigned char dst[4], unsigned const cha
}
else {
/* no op */
- copy_v4_v4_char((char *)dst, (char *)src1);
+ copy_v4_v4_uchar(dst, src1);
}
}
@@ -521,7 +521,7 @@ MINLINE void blend_color_color_byte(unsigned char dst[4], unsigned const char sr
}
else {
/* no op */
- copy_v4_v4_char((char *)dst, (char *)src1);
+ copy_v4_v4_uchar(dst, src1);
}
}
@@ -547,7 +547,7 @@ MINLINE void blend_color_hue_byte(unsigned char dst[4], unsigned const char src1
}
else {
/* no op */
- copy_v4_v4_char((char *)dst, (char *)src1);
+ copy_v4_v4_uchar(dst, src1);
}
}
@@ -575,7 +575,7 @@ MINLINE void blend_color_saturation_byte(unsigned char dst[4], unsigned const ch
}
else {
/* no op */
- copy_v4_v4_char((char *)dst, (char *)src1);
+ copy_v4_v4_uchar(dst, src1);
}
}
@@ -601,7 +601,7 @@ MINLINE void blend_color_luminosity_byte(unsigned char dst[4], unsigned const ch
}
else {
/* no op */
- copy_v4_v4_char((char *)dst, (char *)src1);
+ copy_v4_v4_uchar(dst, src1);
}
}
@@ -621,7 +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 {
- copy_v4_v4_char((char *)dst, (char *)src1);
+ copy_v4_v4_uchar(dst, src1);
}
}
diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c
index 379c8524601..e5fb5533728 100644
--- a/source/blender/blenlib/intern/math_geom.c
+++ b/source/blender/blenlib/intern/math_geom.c
@@ -380,6 +380,27 @@ void closest_to_plane_v3(float r_close[3], const float plane[4], const float pt[
madd_v3_v3v3fl(r_close, pt, plane, -side / len_sq);
}
+void closest_to_plane_normalized_v3(float r_close[3], const float plane[4], const float pt[3])
+{
+ const float side = plane_point_side_v3(plane, pt);
+ BLI_ASSERT_UNIT_V3(plane);
+ madd_v3_v3v3fl(r_close, pt, plane, -side);
+}
+
+void closest_to_plane3_v3(float r_close[3], const float plane[3], const float pt[3])
+{
+ const float len_sq = len_squared_v3(plane);
+ const float side = dot_v3v3(plane, pt);
+ madd_v3_v3v3fl(r_close, pt, plane, -side / len_sq);
+}
+
+void closest_to_plane3_normalized_v3(float r_close[3], const float plane[3], const float pt[3])
+{
+ const float side = dot_v3v3(plane, pt);
+ BLI_ASSERT_UNIT_V3(plane);
+ madd_v3_v3v3fl(r_close, pt, plane, -side);
+}
+
float dist_signed_squared_to_plane_v3(const float pt[3], const float plane[4])
{
const float len_sq = len_squared_v3(plane);
@@ -476,7 +497,7 @@ float dist_to_line_v3(const float p[3], const float l1[3], const float l2[3])
* \note the distance from \a v1 & \a v3 to \a v2 doesnt matter
* (it just defines the planes).
*
- * \return the lowest squared distance to eithe of the planes.
+ * \return the lowest squared distance to either of the planes.
* where ``(return < 0.0)`` is outside.
*
* <pre>
@@ -1235,38 +1256,27 @@ bool isect_ray_tri_v3(
/**
* if clip is nonzero, will only return true if lambda is >= 0.0
* (i.e. intersection point is along positive d)
+ *
+ * \note #line_plane_factor_v3() shares logic.
*/
bool isect_ray_plane_v3(
const float p1[3], const float d[3],
- const float v0[3], const float v1[3], const float v2[3],
+ const float plane[4],
float *r_lambda, const bool clip)
{
- const float epsilon = 0.00000001f;
- float p[3], s[3], e1[3], e2[3], q[3];
- float a, f;
- /* float u, v; */ /*UNUSED*/
-
- sub_v3_v3v3(e1, v1, v0);
- sub_v3_v3v3(e2, v2, v0);
-
- cross_v3_v3v3(p, d, e2);
- a = dot_v3v3(e1, p);
- /* note: these values were 0.000001 in 2.4x but for projection snapping on
- * a human head (1BU == 1m), subsurf level 2, this gave many errors - campbell */
- if ((a > -epsilon) && (a < epsilon)) return false;
- f = 1.0f / a;
-
- sub_v3_v3v3(s, p1, v0);
-
- /* u = f * dot_v3v3(s, p); */ /*UNUSED*/
-
- cross_v3_v3v3(q, s, e1);
-
- /* v = f * dot_v3v3(d, q); */ /*UNUSED*/
-
- *r_lambda = f * dot_v3v3(e2, q);
- if (clip && (*r_lambda < 0.0f)) return false;
+ float h[3], plane_co[3];
+ float dot;
+ dot = dot_v3v3(plane, d);
+ if (dot == 0.0f) {
+ return false;
+ }
+ mul_v3_v3fl(plane_co, plane, (-plane[3] / len_squared_v3(plane)));
+ sub_v3_v3v3(h, p1, plane_co);
+ *r_lambda = -dot_v3v3(plane, h) / dot;
+ if (clip && (*r_lambda < 0.0f)) {
+ return false;
+ }
return true;
}
@@ -1535,28 +1545,90 @@ bool isect_line_plane_v3(float out[3],
}
/**
+ * Intersect three planes, return the point where all 3 meet.
+ * See Graphics Gems 1 pg 305
+ *
+ * \param plane_a, plane_b, plane_c: Planes.
+ * \param r_isect_co: The resulting intersection point.
+ */
+bool isect_plane_plane_plane_v3(
+ const float plane_a[4], const float plane_b[4], const float plane_c[4],
+ float r_isect_co[3])
+{
+ float det;
+
+ det = determinant_m3(UNPACK3(plane_a), UNPACK3(plane_b), UNPACK3(plane_c));
+
+ if (det != 0.0f) {
+ float tmp[3];
+
+ /* (plane_b.xyz.cross(plane_c.xyz) * -plane_a[3] +
+ * plane_c.xyz.cross(plane_a.xyz) * -plane_b[3] +
+ * plane_a.xyz.cross(plane_b.xyz) * -plane_c[3]) / det; */
+
+ cross_v3_v3v3(tmp, plane_c, plane_b);
+ mul_v3_v3fl(r_isect_co, tmp, plane_a[3]);
+
+ cross_v3_v3v3(tmp, plane_a, plane_c);
+ madd_v3_v3fl(r_isect_co, tmp, plane_b[3]);
+
+ cross_v3_v3v3(tmp, plane_b, plane_a);
+ madd_v3_v3fl(r_isect_co, tmp, plane_c[3]);
+
+ mul_v3_fl(r_isect_co, 1.0f / det);
+
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+/**
* Intersect two planes, return a point on the intersection and a vector
* that runs on the direction of the intersection.
- * Return error code is the same as 'isect_line_line_v3'.
*
- * \param r_isect_co The resulting intersection point.
- * \param r_isect_no The resulting vector of the intersection.
- * \param plane_a_co The point on the first plane.
- * \param plane_a_no The normal of the first plane.
- * \param plane_b_co The point on the second plane.
- * \param plane_b_no The normal of the second plane.
*
- * \note return normal isn't unit length
+ * \note this is a slightly reduced version of #isect_plane_plane_plane_v3
+ *
+ * \param plane_a, plane_b: Planes.
+ * \param r_isect_co: The resulting intersection point.
+ * \param r_isect_no: The resulting vector of the intersection.
+ *
+ * \note \a r_isect_no isn't unit length.
*/
-bool isect_plane_plane_v3(float r_isect_co[3], float r_isect_no[3],
- const float plane_a_co[3], const float plane_a_no[3],
- const float plane_b_co[3], const float plane_b_no[3])
+bool isect_plane_plane_v3(
+ const float plane_a[4], const float plane_b[4],
+ float r_isect_co[3], float r_isect_no[3])
{
- float plane_a_co_other[3];
- cross_v3_v3v3(r_isect_no, plane_a_no, plane_b_no); /* direction is simply the cross product */
- cross_v3_v3v3(plane_a_co_other, plane_a_no, r_isect_no);
- add_v3_v3(plane_a_co_other, plane_a_co);
- return isect_line_plane_v3(r_isect_co, plane_a_co, plane_a_co_other, plane_b_co, plane_b_no);
+ float det, plane_c[3];
+
+ /* direction is simply the cross product */
+ cross_v3_v3v3(plane_c, plane_a, plane_b);
+
+ /* in this case we don't need to use 'determinant_m3' */
+ det = len_squared_v3(plane_c);
+
+ if (det != 0.0f) {
+ float tmp[3];
+
+ /* (plane_b.xyz.cross(plane_c.xyz) * -plane_a[3] +
+ * plane_c.xyz.cross(plane_a.xyz) * -plane_b[3]) / det; */
+ cross_v3_v3v3(tmp, plane_c, plane_b);
+ mul_v3_v3fl(r_isect_co, tmp, plane_a[3]);
+
+ cross_v3_v3v3(tmp, plane_a, plane_c);
+ madd_v3_v3fl(r_isect_co, tmp, plane_b[3]);
+
+ mul_v3_fl(r_isect_co, 1.0f / det);
+
+ copy_v3_v3(r_isect_no, plane_c);
+
+ return true;
+ }
+ else {
+ return false;
+ }
}
/**
@@ -1574,46 +1646,67 @@ bool isect_tri_tri_epsilon_v3(
const float epsilon)
{
const float *tri_pair[2][3] = {{t_a0, t_a1, t_a2}, {t_b0, t_b1, t_b2}};
- float no_a[3], no_b[3];
- float isect_co[3], isect_no[3];
+ float plane_a[4], plane_b[4];
+ float plane_co[3], plane_no[3];
BLI_assert((r_i1 != NULL) == (r_i2 != NULL));
- normal_tri_v3(no_a, UNPACK3(tri_pair[0]));
- normal_tri_v3(no_b, UNPACK3(tri_pair[1]));
+ /* normalizing is needed for small triangles T46007 */
+ normal_tri_v3(plane_a, UNPACK3(tri_pair[0]));
+ normal_tri_v3(plane_b, UNPACK3(tri_pair[1]));
+
+ plane_a[3] = -dot_v3v3(plane_a, t_a0);
+ plane_b[3] = -dot_v3v3(plane_b, t_b0);
- if (isect_plane_plane_v3(isect_co, isect_no, t_a0, no_a, t_b0, no_b)) {
- float isect_co_other[3];
+ if (isect_plane_plane_v3(plane_a, plane_b, plane_co, plane_no) &&
+ (normalize_v3(plane_no) > epsilon))
+ {
+ /**
+ * Implementation note: its simpler to project the triangles onto the intersection plane
+ * before intersecting their edges with the ray, defined by 'isect_plane_plane_v3'.
+ * This way we can use 'line_point_factor_v3_ex' to see if an edge crosses 'co_proj',
+ * then use the factor to calculate the world-space point.
+ */
struct {
float min, max;
} range[2] = {{FLT_MAX, -FLT_MAX}, {FLT_MAX, -FLT_MAX}};
int t;
+ float co_proj[3];
- add_v3_v3v3(isect_co_other, isect_co, isect_no);
+ closest_to_plane3_normalized_v3(co_proj, plane_no, plane_co);
- /* For both triangles, find the overlap with the line defined by (isect_co, isect_co_other).
+ /* For both triangles, find the overlap with the line defined by the ray [co_proj, plane_no].
* When the ranges overlap we know the triangles do too. */
for (t = 0; t < 2; t++) {
int j, j_prev;
+ float tri_proj[3][3];
+
+ closest_to_plane3_normalized_v3(tri_proj[0], plane_no, tri_pair[t][0]);
+ closest_to_plane3_normalized_v3(tri_proj[1], plane_no, tri_pair[t][1]);
+ closest_to_plane3_normalized_v3(tri_proj[2], plane_no, tri_pair[t][2]);
for (j = 0, j_prev = 2; j < 3; j_prev = j++) {
- /* intersection point on the line intersecting both planes */
- float ix_span[3];
- /* intersection point on the triangles edge */
- float ix_tri[3];
-
- if (isect_line_line_epsilon_v3(
- isect_co, isect_co_other,
- tri_pair[t][j], tri_pair[t][j_prev],
- ix_span, ix_tri,
- epsilon) != 0)
- {
- const float edge_fac = line_point_factor_v3(ix_tri, tri_pair[t][j], tri_pair[t][j_prev]);
- if (edge_fac >= -epsilon && edge_fac <= 1.0f + epsilon) {
- const float span_fac = dist_signed_squared_to_plane3_v3(ix_tri, isect_no);
- range[t].min = min_ff(range[t].min, span_fac);
- range[t].max = max_ff(range[t].max, span_fac);
- }
+ /* note that its important to have a very small nonzero epsilon here
+ * otherwise this fails for very small faces.
+ * However if its too small, large adjacent faces will count as intersecting */
+ const float edge_fac = line_point_factor_v3_ex(co_proj, tri_proj[j_prev], tri_proj[j], 1e-10f, -1.0f);
+ /* ignore collinear lines, they are either an edge shared between 2 tri's
+ * (which runs along [co_proj, plane_no], but can be safely ignored).
+ *
+ * or a collinear edge placed away from the ray - which we don't intersect with & can ignore. */
+ if (UNLIKELY(edge_fac == -1.0f)) {
+ /* pass */
+ }
+ else if (edge_fac > 0.0f && edge_fac < 1.0f) {
+ float ix_tri[3];
+ float span_fac;
+
+ interp_v3_v3v3(ix_tri, tri_pair[t][j_prev], tri_pair[t][j], edge_fac);
+ /* the actual distance, since 'plane_no' is normalized */
+ span_fac = dot_v3v3(plane_no, ix_tri);
+
+ range[t].min = min_ff(range[t].min, span_fac);
+ range[t].max = max_ff(range[t].max, span_fac);
}
}
@@ -1626,9 +1719,9 @@ bool isect_tri_tri_epsilon_v3(
(range[0].max < range[1].min)) == 0)
{
if (r_i1 && r_i2) {
- project_plane_v3_v3v3(isect_co, isect_co, isect_no);
- madd_v3_v3v3fl(r_i1, isect_co, isect_no, sqrtf_signed(max_ff(range[0].min, range[1].min)));
- madd_v3_v3v3fl(r_i2, isect_co, isect_no, sqrtf_signed(min_ff(range[0].max, range[1].max)));
+ project_plane_v3_v3v3(plane_co, plane_co, plane_no);
+ madd_v3_v3v3fl(r_i1, plane_co, plane_no, max_ff(range[0].min, range[1].min));
+ madd_v3_v3v3fl(r_i2, plane_co, plane_no, min_ff(range[0].max, range[1].max));
}
return true;
@@ -1933,8 +2026,9 @@ int isect_line_line_epsilon_v3(
d = dot_v3v3(c, ab);
div = dot_v3v3(ab, ab);
+ /* important not to use an epsilon here, see: T45919 */
/* test zero length line */
- if (UNLIKELY(div <= epsilon)) {
+ if (UNLIKELY(div == 0.0f)) {
return 0;
}
/* test if the two lines are coplanar */
@@ -2005,8 +2099,9 @@ bool isect_line_line_strict_v3(const float v1[3], const float v2[3],
d = dot_v3v3(c, ab);
div = dot_v3v3(ab, ab);
+ /* important not to use an epsilon here, see: T45919 */
/* test zero length line */
- if (UNLIKELY(div <= epsilon)) {
+ if (UNLIKELY(div == 0.0f)) {
return false;
}
/* test if the two lines are coplanar */
@@ -2129,8 +2224,13 @@ float closest_to_line_v2(float cp[2], const float p[2], const float l1[2], const
/**
* A simplified version of #closest_to_line_v3
* we only need to return the ``lambda``
+ *
+ * \param epsilon: avoid approaching divide-by-zero.
+ * Passing a zero will just check for nonzero division.
*/
-float line_point_factor_v3(const float p[3], const float l1[3], const float l2[3])
+float line_point_factor_v3_ex(
+ const float p[3], const float l1[3], const float l2[3],
+ const float epsilon, const float fallback)
{
float h[3], u[3];
float dot;
@@ -2141,11 +2241,18 @@ float line_point_factor_v3(const float p[3], const float l1[3], const float l2[3
#else
/* better check for zero */
dot = dot_v3v3(u, u);
- return (dot != 0.0f) ? (dot_v3v3(u, h) / dot) : 0.0f;
+ return (fabsf(dot) > epsilon) ? (dot_v3v3(u, h) / dot) : fallback;
#endif
}
+float line_point_factor_v3(
+ const float p[3], const float l1[3], const float l2[3])
+{
+ return line_point_factor_v3_ex(p, l1, l2, 0.0f, 0.0f);
+}
-float line_point_factor_v2(const float p[2], const float l1[2], const float l2[2])
+float line_point_factor_v2_ex(
+ const float p[2], const float l1[2], const float l2[2],
+ const float epsilon, const float fallback)
{
float h[2], u[2];
float dot;
@@ -2156,10 +2263,15 @@ float line_point_factor_v2(const float p[2], const float l1[2], const float l2[2
#else
/* better check for zero */
dot = dot_v2v2(u, u);
- return (dot != 0.0f) ? (dot_v2v2(u, h) / dot) : 0.0f;
+ return (fabsf(dot) > epsilon) ? (dot_v2v2(u, h) / dot) : fallback;
#endif
}
+float line_point_factor_v2(const float p[2], const float l1[2], const float l2[2])
+{
+ return line_point_factor_v2_ex(p, l1, l2, 0.0f, 0.0f);
+}
+
/**
* \note #isect_line_plane_v3() shares logic
*/
@@ -3447,8 +3559,8 @@ void perspective_m4(float mat[4][4], const float left, const float right, const
mat[2][3] = -1.0f;
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.0f;
+ mat[1][0] = mat[1][2] = mat[1][3] =
+ mat[3][0] = mat[3][1] = mat[3][3] = 0.0f;
}
diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c
index 33d0fb87aca..4bf6d162970 100644
--- a/source/blender/blenlib/intern/math_matrix.c
+++ b/source/blender/blenlib/intern/math_matrix.c
@@ -516,7 +516,8 @@ void mul_v3_mat3_m4v3(float r[3], float mat[4][4], const float vec[3])
void mul_project_m4_v3(float mat[4][4], float vec[3])
{
- const float w = mul_project_m4_v3_zfac(mat, vec);
+ /* absolute value to not flip the frustum upside down behind the camera */
+ const float w = fabsf(mul_project_m4_v3_zfac(mat, vec));
mul_m4_v3(mat, vec);
vec[0] /= w;
@@ -526,7 +527,7 @@ void mul_project_m4_v3(float mat[4][4], float vec[3])
void mul_v3_project_m4_v3(float r[3], float mat[4][4], const float vec[3])
{
- const float w = mul_project_m4_v3_zfac(mat, vec);
+ const float w = fabsf(mul_project_m4_v3_zfac(mat, vec));
mul_v3_m4v3(r, mat, vec);
r[0] /= w;
@@ -536,7 +537,7 @@ void mul_v3_project_m4_v3(float r[3], float mat[4][4], const float vec[3])
void mul_v2_project_m4_v3(float r[2], float mat[4][4], const float vec[3])
{
- const float w = mul_project_m4_v3_zfac(mat, vec);
+ const float w = fabsf(mul_project_m4_v3_zfac(mat, vec));
mul_v2_m4v3(r, mat, vec);
r[0] /= w;
@@ -1247,36 +1248,74 @@ bool is_uniform_scaled_m4(float m[4][4])
return is_uniform_scaled_m3(t);
}
+void normalize_m3_ex(float mat[3][3], float r_scale[3])
+{
+ int i;
+ for (i = 0; i < 3; i++) {
+ r_scale[i] = normalize_v3(mat[i]);
+ }
+}
void normalize_m3(float mat[3][3])
{
- normalize_v3(mat[0]);
- normalize_v3(mat[1]);
- normalize_v3(mat[2]);
+ int i;
+ for (i = 0; i < 3; i++) {
+ normalize_v3(mat[i]);
+ }
}
+void normalize_m3_m3_ex(float rmat[3][3], float mat[3][3], float r_scale[3])
+{
+ int i;
+ for (i = 0; i < 3; i++) {
+ r_scale[i] = normalize_v3_v3(rmat[i], mat[i]);
+ }
+}
void normalize_m3_m3(float rmat[3][3], float mat[3][3])
{
- normalize_v3_v3(rmat[0], mat[0]);
- normalize_v3_v3(rmat[1], mat[1]);
- normalize_v3_v3(rmat[2], mat[2]);
+ int i;
+ for (i = 0; i < 3; i++) {
+ normalize_v3_v3(rmat[i], mat[i]);
+ }
}
+void normalize_m4_ex(float mat[4][4], float r_scale[3])
+{
+ int i;
+ for (i = 0; i < 3; i++) {
+ r_scale[i] = normalize_v3(mat[i]);
+ if (r_scale[i] != 0.0f) {
+ mat[i][3] /= r_scale[i];
+ }
+ }
+}
void normalize_m4(float mat[4][4])
{
- float len;
-
- len = normalize_v3(mat[0]);
- if (len != 0.0f) mat[0][3] /= len;
- len = normalize_v3(mat[1]);
- if (len != 0.0f) mat[1][3] /= len;
- len = normalize_v3(mat[2]);
- if (len != 0.0f) mat[2][3] /= len;
+ int i;
+ for (i = 0; i < 3; i++) {
+ float len = normalize_v3(mat[i]);
+ if (len != 0.0f) {
+ mat[i][3] /= len;
+ }
+ }
}
+void normalize_m4_m4_ex(float rmat[4][4], float mat[4][4], float r_scale[3])
+{
+ int i;
+ for (i = 0; i < 3; i++) {
+ r_scale[i] = normalize_v3_v3(rmat[i], mat[i]);
+ rmat[i][3] = (r_scale[i] != 0.0f) ? (mat[i][3] / r_scale[i]) : mat[i][3];
+ }
+ copy_v4_v4(rmat[3], mat[3]);
+}
void normalize_m4_m4(float rmat[4][4], float mat[4][4])
{
- copy_m4_m4(rmat, mat);
- normalize_m4(rmat);
+ int i;
+ for (i = 0; i < 3; i++) {
+ float len = normalize_v3_v3(rmat[i], mat[i]);
+ rmat[i][3] = (len != 0.0f) ? (mat[i][3] / len) : mat[i][3];
+ }
+ copy_v4_v4(rmat[3], mat[3]);
}
void adjoint_m2_m2(float m1[2][2], float m[2][2])
@@ -1521,6 +1560,34 @@ void mat4_decompose(float loc[3], float quat[4], float size[3], float wmat[4][4]
mat3_to_quat(quat, rot);
}
+/**
+ * Right polar decomposition:
+ * M = UP
+ *
+ * U is the 'rotation'-like component, the closest orthogonal matrix to M.
+ * P is the 'scaling'-like component, defined in U space.
+ *
+ * See https://en.wikipedia.org/wiki/Polar_decomposition for more.
+ */
+void mat3_polar_decompose(float mat3[3][3], float r_U[3][3], float r_P[3][3])
+{
+ /* From svd decomposition (M = WSV*), we have:
+ * U = WV*
+ * P = VSV*
+ */
+ float W[3][3], S[3][3], V[3][3], Vt[3][3];
+ float sval[3];
+
+ BLI_svd_m3(mat3, W, sval, V);
+
+ size_to_mat3(S, sval);
+
+ transpose_m3_m3(Vt, V);
+ mul_m3_m3m3(r_U, W, Vt);
+ mul_m3_series(r_P, V, S, Vt);
+}
+
+
void scale_m3_fl(float m[3][3], float scale)
{
m[0][0] = m[1][1] = m[2][2] = scale;
@@ -1660,6 +1727,75 @@ void blend_m4_m4m4(float out[4][4], float dst[4][4], float src[4][4], const floa
loc_quat_size_to_mat4(out, floc, fquat, fsize);
}
+/**
+ * A polar-decomposition-based interpolation between matrix A and matrix B.
+ *
+ * \note This code is about five times slower as the 'naive' interpolation done by \a blend_m3_m3m3
+ * (it typically remains below 2 usec on an average i74700, while \a blend_m3_m3m3 remains below 0.4 usec).
+ * However, it gives expected results even with non-uniformaly scaled matrices, see T46418 for an example.
+ *
+ * Based on "Matrix Animation and Polar Decomposition", by Ken Shoemake & Tom Duff
+ *
+ * @return R the interpolated matrix.
+ * @param A the intput matrix which is totally effective with \a t = 0.0.
+ * @param B the intput matrix which is totally effective with \a t = 1.0.
+ * @param t the interpolation factor.
+ */
+void interp_m3_m3m3(float R[3][3], float A[3][3], float B[3][3], const float t)
+{
+ /* 'Rotation' component ('U' part of polar decomposition, the closest orthogonal matrix to M3 rot/scale
+ * transformation matrix), spherically interpolated. */
+ float U_A[3][3], U_B[3][3], U[3][3];
+ float quat_A[4], quat_B[4], quat[4];
+ /* 'Scaling' component ('P' part of polar decomposition, i.e. scaling in U-defined space), linearly interpolated. */
+ float P_A[3][3], P_B[3][3], P[3][3];
+
+ int i;
+
+ mat3_polar_decompose(A, U_A, P_A);
+ mat3_polar_decompose(B, U_B, P_B);
+
+ mat3_to_quat(quat_A, U_A);
+ mat3_to_quat(quat_B, U_B);
+ interp_qt_qtqt(quat, quat_A, quat_B, t);
+ quat_to_mat3(U, quat);
+
+ for (i = 0; i < 3; i++) {
+ interp_v3_v3v3(P[i], P_A[i], P_B[i], t);
+ }
+
+ /* And we reconstruct rot/scale matrix from interpolated polar components */
+ mul_m3_m3m3(R, U, P);
+}
+
+/**
+ * Complete transform matrix interpolation, based on polar-decomposition-based interpolation from interp_m3_m3m3.
+ *
+ * @return R the interpolated matrix.
+ * @param A the intput matrix which is totally effective with \a t = 0.0.
+ * @param B the intput matrix which is totally effective with \a t = 1.0.
+ * @param t the interpolation factor.
+ */
+void interp_m4_m4m4(float R[4][4], float A[4][4], float B[4][4], const float t)
+{
+ float A3[3][3], B3[3][3], R3[3][3];
+
+ /* Location component, linearly interpolated. */
+ float loc_A[3], loc_B[3], loc[3];
+
+ copy_v3_v3(loc_A, A[3]);
+ copy_v3_v3(loc_B, B[3]);
+ interp_v3_v3v3(loc, loc_A, loc_B, t);
+
+ copy_m3_m4(A3, A);
+ copy_m3_m4(B3, B);
+
+ interp_m3_m3m3(R3, A3, B3, t);
+
+ copy_m4_m3(R, R3);
+ copy_v3_v3(R[3], loc);
+}
+
bool is_negative_m3(float mat[3][3])
{
float vec[3];
diff --git a/source/blender/blenlib/intern/math_rotation.c b/source/blender/blenlib/intern/math_rotation.c
index 5f039e89e89..575710e8d75 100644
--- a/source/blender/blenlib/intern/math_rotation.c
+++ b/source/blender/blenlib/intern/math_rotation.c
@@ -1631,7 +1631,7 @@ void mat4_to_dquat(DualQuat *dq, float basemat[4][4], float mat[4][4])
copy_m3_m4(mat3, mat);
- if (!is_orthonormal_m3(mat3) || (determinant_m4(mat) < 0.0f) || len_v3(dscale) > 1e-4f) {
+ if (!is_orthonormal_m3(mat3) || (determinant_m4(mat) < 0.0f) || len_squared_v3(dscale) > SQUARE(1e-4f)) {
/* extract R and S */
float tmp[4][4];
diff --git a/source/blender/blenlib/intern/math_solvers.c b/source/blender/blenlib/intern/math_solvers.c
index 2f962714c8c..d1dad9a6269 100644
--- a/source/blender/blenlib/intern/math_solvers.c
+++ b/source/blender/blenlib/intern/math_solvers.c
@@ -59,3 +59,16 @@ bool BLI_eigen_solve_selfadjoint_m3(const float m3[3][3], float r_eigen_values[3
return EG3_self_adjoint_eigen_solve(3, (const float *)m3, r_eigen_values, (float *)r_eigen_vectors);
}
+
+/**
+ * \brief Compute the SVD (Singular Values Decomposition) of given 3D matrix (m3 = USV*).
+ *
+ * \param m3 the matrix to decompose.
+ * \return r_U the computed left singular vector of \a m3 (NULL if not needed).
+ * \return r_S the computed singular values of \a m3 (NULL if not needed).
+ * \return r_V the computed right singular vector of \a m3 (NULL if not needed).
+ */
+void BLI_svd_m3(const float m3[3][3], float r_U[3][3], float r_S[3], float r_V[3][3])
+{
+ EG3_svd_square_matrix(3, (const float *)m3, (float *)r_U, (float *)r_S, (float *)r_V);
+}
diff --git a/source/blender/blenlib/intern/math_statistics.c b/source/blender/blenlib/intern/math_statistics.c
index 3f1bae5f58c..a8cb8e2c40d 100644
--- a/source/blender/blenlib/intern/math_statistics.c
+++ b/source/blender/blenlib/intern/math_statistics.c
@@ -39,7 +39,7 @@
/**
* \brief Compute the covariance matrix of given set of nD coordinates.
*
- * \param n the dimension of the vectors (and hence, of the covairance matrix to compute).
+ * \param n the dimension of the vectors (and hence, of the covariance matrix to compute).
* \param cos_vn the nD points to compute covariance from.
* \param nbr_cos_vn the number of nD coordinates in cos_vn.
* \param center the center (or mean point) of cos_vn. If NULL, it is assumed cos_vn is already centered.
diff --git a/source/blender/blenlib/intern/math_vector.c b/source/blender/blenlib/intern/math_vector.c
index 6da0e87355d..8d33e04241a 100644
--- a/source/blender/blenlib/intern/math_vector.c
+++ b/source/blender/blenlib/intern/math_vector.c
@@ -785,7 +785,7 @@ void minmax_v2v2_v2(float min[2], float max[2], const float vec[2])
if (max[1] < vec[1]) max[1] = vec[1];
}
-void minmax_v3v3_v3_array(float r_min[3], float r_max[3], float (*vec_arr)[3], int nbr)
+void minmax_v3v3_v3_array(float r_min[3], float r_max[3], const float (*vec_arr)[3], int nbr)
{
while (nbr--) {
minmax_v3v3_v3(r_min, r_max, *vec_arr++);
diff --git a/source/blender/blenlib/intern/math_vector_inline.c b/source/blender/blenlib/intern/math_vector_inline.c
index c21b09748c9..e625ac18685 100644
--- a/source/blender/blenlib/intern/math_vector_inline.c
+++ b/source/blender/blenlib/intern/math_vector_inline.c
@@ -97,7 +97,29 @@ MINLINE void copy_v4_fl(float r[4], float f)
r[3] = f;
}
-/* short */
+/* unsigned char */
+MINLINE void copy_v2_v2_uchar(unsigned char r[2], const unsigned char a[2])
+{
+ r[0] = a[0];
+ r[1] = a[1];
+}
+
+MINLINE void copy_v3_v3_uchar(unsigned char r[3], const unsigned char a[3])
+{
+ r[0] = a[0];
+ r[1] = a[1];
+ r[2] = a[2];
+}
+
+MINLINE void copy_v4_v4_uchar(unsigned char r[4], const unsigned char a[4])
+{
+ r[0] = a[0];
+ r[1] = a[1];
+ r[2] = a[2];
+ r[3] = a[3];
+}
+
+/* char */
MINLINE void copy_v2_v2_char(char r[2], const char a[2])
{
r[0] = a[0];
diff --git a/source/blender/blenlib/intern/memory_utils.c b/source/blender/blenlib/intern/memory_utils.c
new file mode 100644
index 00000000000..2ebb8be5bb4
--- /dev/null
+++ b/source/blender/blenlib/intern/memory_utils.c
@@ -0,0 +1,50 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenlib/intern/memory_utils.c
+ * \ingroup bli
+ * \brief Generic memory manipulation API.
+ *
+ * This is to extend on existing functions
+ * such as ``memcpy`` & ``memcmp``.
+ */
+#include <string.h>
+
+#include "BLI_sys_types.h"
+#include "BLI_utildefines.h"
+
+#include "BLI_memory_utils.h"
+
+#include "BLI_strict_flags.h"
+
+/**
+ * Check if memory is zero'd, as with memset(s, 0, nbytes)
+ */
+bool BLI_memory_is_zero(const void *s, const size_t nbytes)
+{
+ const char *s_byte = s;
+ const char *s_end = (const char *)s + nbytes;
+
+ while ((s_byte != s_end) && (*s_byte == 0)) {
+ s_byte++;
+ }
+
+ return (s_byte == s_end);
+}
diff --git a/source/blender/blenlib/intern/noise.c b/source/blender/blenlib/intern/noise.c
index 5febf720b30..4b2ad834d75 100644
--- a/source/blender/blenlib/intern/noise.c
+++ b/source/blender/blenlib/intern/noise.c
@@ -1546,7 +1546,7 @@ float BLI_gTurbulence(float noisesize, float x, float y, float z, int oct, int h
/*
* The following code is based on Ken Musgrave's explanations and sample
- * source code in the book "Texturing and Modelling: A procedural approach"
+ * source code in the book "Texturing and Modeling: A procedural approach"
*/
/*
diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c
index 3a73d4cc0c7..99e512475bb 100644
--- a/source/blender/blenlib/intern/path_util.c
+++ b/source/blender/blenlib/intern/path_util.c
@@ -191,31 +191,6 @@ int BLI_split_name_num(char *left, int *nr, const char *name, const char delim)
}
/**
- * Looks for a string of digits within name (using BLI_stringdec) and adjusts it by add.
- */
-void BLI_newname(char *name, int add)
-{
- char head[UNIQUE_NAME_MAX], tail[UNIQUE_NAME_MAX];
- int pic;
- unsigned short digits;
-
- pic = BLI_stringdec(name, head, tail, &digits);
-
- /* are we going from 100 -> 99 or from 10 -> 9 */
- if (add < 0 && digits < 4 && digits > 0) {
- int i, exp;
- exp = 1;
- for (i = digits; i > 1; i--) exp *= 10;
- if (pic >= exp && (pic + add) < exp) digits--;
- }
-
- pic += add;
-
- if (digits == 4 && pic < 0) pic = 0;
- BLI_stringenc(name, head, tail, digits, pic);
-}
-
-/**
* Ensures name is unique (according to criteria specified by caller in unique_check callback),
* incrementing its numeric suffix as necessary. Returns true if name had to be adjusted.
*
@@ -332,14 +307,15 @@ static int BLI_path_unc_prefix_len(const char *path); /* defined below in same f
/* ******************** string encoding ***************** */
-/* This is quite an ugly function... its purpose is to
- * take the dir name, make it absolute, and clean it up, replacing
- * excess file entry stuff (like /tmp/../tmp/../)
- * note that dir isn't protected for max string names...
- *
- * If relbase is NULL then its ignored
+/**
+ * Remove redundant characters from \a path and optionally make absolute.
+ *
+ * \param relbase: The path this is relative to, or ignored when NULL.
+ * \param path: Can be any input, and this function converts it to a regular full path.
+ * Also removes garbage from directory paths, like `/../` or double slashes etc.
+ *
+ * \note \a path isn't protected for max string names...
*/
-
void BLI_cleanup_path(const char *relabase, char *path)
{
ptrdiff_t a;
@@ -428,6 +404,9 @@ void BLI_cleanup_path(const char *relabase, char *path)
#endif
}
+/**
+ * Cleanup filepath ensuring a trailing slash.
+ */
void BLI_cleanup_dir(const char *relabase, char *dir)
{
BLI_cleanup_path(relabase, dir);
@@ -435,6 +414,9 @@ void BLI_cleanup_dir(const char *relabase, char *dir)
}
+/**
+ * Cleanup filepath ensuring no trailing slash.
+ */
void BLI_cleanup_file(const char *relabase, char *path)
{
BLI_cleanup_path(relabase, path);
@@ -453,6 +435,8 @@ void BLI_cleanup_file(const char *relabase, char *path)
*
* \note Space case ' ' is a bit of an edge case here - in theory it is allowed, but again can be an issue
* in some cases, so we simply replace it by an underscore too (good practice anyway).
+ * REMOVED based on popular demand (see T45900).
+ * Percent '%' char is a bit same case - not recommended to use it, but supported by all decent FS/OS around...
*
* \note On Windows, it also ensures there is no '.' (dot char) at the end of the file, this can lead to issues...
*
@@ -461,9 +445,9 @@ void BLI_cleanup_file(const char *relabase, char *path)
*/
bool BLI_filename_make_safe(char *fname)
{
- const char *invalid = "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+ const char *invalid = "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
- "/\\?%*:|\"<> ";
+ "/\\?*:|\"<>";
char *fn;
bool changed = false;
@@ -533,7 +517,7 @@ bool BLI_filename_make_safe(char *fname)
bool BLI_path_make_safe(char *path)
{
/* Simply apply BLI_filename_make_safe() over each component of the path.
- * Luckily enough, same 'sfae' rules applies to filenames and dirnames. */
+ * Luckily enough, same 'safe' rules applies to filenames and dirnames. */
char *curr_slash, *curr_path = path;
bool changed = false;
bool skip_first = false;
@@ -977,7 +961,7 @@ bool BLI_path_frame_range(char *path, int sta, int end, int digits)
*/
bool BLI_path_frame_get(char *path, int *r_frame, int *r_numdigits)
{
- if (path && *path) {
+ if (*path) {
char *file = (char *)BLI_last_slash(path);
char *c;
int len, numdigits;
@@ -1026,9 +1010,9 @@ bool BLI_path_frame_get(char *path, int *r_frame, int *r_numdigits)
return false;
}
-void BLI_path_frame_strip(char *path, bool setsharp, char *ext)
+void BLI_path_frame_strip(char *path, bool set_frame_char, char *ext)
{
- if (path && *path) {
+ if (*path) {
char *file = (char *)BLI_last_slash(path);
char *c, *suffix;
int len;
@@ -1063,15 +1047,12 @@ void BLI_path_frame_strip(char *path, bool setsharp, char *ext)
if (numdigits) {
/* replace the number with the suffix and terminate the string */
while (numdigits--) {
- if (ext) *ext++ = *suffix;
-
- if (setsharp) *c++ = '#';
- else *c++ = *suffix;
-
+ *ext++ = *suffix;
+ *c++ = set_frame_char ? '#' : *suffix;
suffix++;
}
- *c = 0;
- if (ext) *ext = 0;
+ *c = '\0';
+ *ext = '\0';
}
}
}
@@ -1087,9 +1068,14 @@ bool BLI_path_frame_check_chars(const char *path)
}
/**
- * If path begins with "//", strips that and replaces it with basepath directory. Also converts
- * a drive-letter prefix to something more sensible if this is a non-drive-letter-based system.
- * Returns true if "//" prefix expansion was done.
+ * If path begins with "//", strips that and replaces it with basepath directory.
+ *
+ * \note Also converts drive-letter prefix to something more sensible
+ * if this is a non-drive-letter-based system.
+ *
+ * \param path: The path to convert.
+ * \param basepath: The directory to base relative paths with.
+ * \return true if the path was relative (started with "//").
*/
bool BLI_path_abs(char *path, const char *basepath)
{
@@ -1202,7 +1188,7 @@ bool BLI_path_abs(char *path, const char *basepath)
* \note Should only be done with command line paths.
* this is _not_ something blenders internal paths support like the "//" prefix
*/
-bool BLI_path_cwd(char *path)
+bool BLI_path_cwd(char *path, const size_t maxlen)
{
bool wasrelative = true;
const int filelen = strlen(path);
@@ -1216,24 +1202,15 @@ bool BLI_path_cwd(char *path)
#endif
if (wasrelative) {
- char cwd[FILE_MAX] = "";
- BLI_current_working_dir(cwd, sizeof(cwd)); /* in case the full path to the blend isn't used */
-
- if (cwd[0] == '\0') {
- printf("Could not get the current working directory - $PWD for an unknown reason.\n");
- }
- else {
- /* uses the blend path relative to cwd important for loading relative linked files.
- *
- * cwd should contain c:\ etc on win32 so the relbase can be NULL
- * relbase being NULL also prevents // being misunderstood as relative to the current
- * blend file which isn't a feature we want to use in this case since were dealing
- * with a path from the command line, rather than from inside Blender */
-
+ char cwd[FILE_MAX];
+ /* in case the full path to the blend isn't used */
+ if (BLI_current_working_dir(cwd, sizeof(cwd))) {
char origpath[FILE_MAX];
BLI_strncpy(origpath, path, FILE_MAX);
-
- BLI_make_file_string(NULL, path, cwd, origpath);
+ BLI_join_dirfile(path, maxlen, cwd, origpath);
+ }
+ else {
+ printf("Could not get the current working directory - $PWD for an unknown reason.\n");
}
}
@@ -1610,17 +1587,16 @@ bool BLI_testextensie_glob(const char *str, const char *ext_fnmatch)
while (ext_step[0]) {
const char *ext_next;
- int len_ext;
+ size_t len_ext;
if ((ext_next = strchr(ext_step, ';'))) {
- len_ext = (int)(ext_next - ext_step) + 1;
+ len_ext = ext_next - ext_step + 1;
+ BLI_strncpy(pattern, ext_step, (len_ext > sizeof(pattern)) ? sizeof(pattern) : len_ext);
}
else {
- len_ext = sizeof(pattern);
+ len_ext = BLI_strncpy_rlen(pattern, ext_step, sizeof(pattern));
}
- BLI_strncpy(pattern, ext_step, len_ext);
-
if (fnmatch(pattern, str, FNM_CASEFOLD) == 0) {
return true;
}
@@ -2015,38 +1991,3 @@ void BLI_path_native_slash(char *path)
BLI_str_replace_char(path + BLI_path_unc_prefix_len(path), '\\', '/');
#endif
}
-
-
-#ifdef WITH_ICONV
-
-/**
- * Converts a string encoded in the charset named by *code to UTF-8.
- * Opens a new iconv context each time it is run, which is probably not the
- * most efficient. */
-void BLI_string_to_utf8(char *original, char *utf_8, const char *code)
-{
- size_t inbytesleft = strlen(original);
- size_t outbytesleft = 512;
- size_t rv = 0;
- iconv_t cd;
-
- if (NULL == code) {
- code = locale_charset();
- }
- cd = iconv_open("UTF-8", code);
-
- if (cd == (iconv_t)(-1)) {
- printf("iconv_open Error");
- *utf_8 = '\0';
- return;
- }
- rv = iconv(cd, &original, &inbytesleft, &utf_8, &outbytesleft);
- if (rv == (size_t) -1) {
- printf("iconv Error\n");
- iconv_close(cd);
- return;
- }
- *utf_8 = '\0';
- iconv_close(cd);
-}
-#endif // WITH_ICONV
diff --git a/source/blender/blenlib/intern/polyfill2d.c b/source/blender/blenlib/intern/polyfill2d.c
index df6caa4b65a..397082b02d2 100644
--- a/source/blender/blenlib/intern/polyfill2d.c
+++ b/source/blender/blenlib/intern/polyfill2d.c
@@ -799,7 +799,7 @@ static void polyfill_prepare(
coords_sign = (cross_poly_v2(coords, coords_tot) >= 0.0f) ? 1 : -1;
}
else {
- /* chech we're passing in correcty args */
+ /* check we're passing in correcty args */
#ifdef USE_STRICT_ASSERT
#ifndef NDEBUG
if (coords_sign == 1) {
diff --git a/source/blender/blenlib/intern/rct.c b/source/blender/blenlib/intern/rct.c
index 646613d9a29..a5f7fe2a008 100644
--- a/source/blender/blenlib/intern/rct.c
+++ b/source/blender/blenlib/intern/rct.c
@@ -474,7 +474,7 @@ void BLI_rctf_interp(rctf *rect, const rctf *rect_a, const rctf *rect_b, const f
/* BLI_rcti_interp() not needed yet */
-bool BLI_rctf_clamp_pt_v(const struct rctf *rect, float xy[2])
+bool BLI_rctf_clamp_pt_v(const rctf *rect, float xy[2])
{
bool changed = false;
if (xy[0] < rect->xmin) { xy[0] = rect->xmin; changed = true; }
@@ -484,7 +484,7 @@ bool BLI_rctf_clamp_pt_v(const struct rctf *rect, float xy[2])
return changed;
}
-bool BLI_rcti_clamp_pt_v(const struct rcti *rect, int xy[2])
+bool BLI_rcti_clamp_pt_v(const rcti *rect, int xy[2])
{
bool changed = false;
if (xy[0] < rect->xmin) { xy[0] = rect->xmin; changed = true; }
@@ -494,7 +494,96 @@ bool BLI_rcti_clamp_pt_v(const struct rcti *rect, int xy[2])
return changed;
}
-bool BLI_rctf_compare(const struct rctf *rect_a, const struct rctf *rect_b, const float limit)
+/**
+ * Clamp \a rect within \a rect_bounds, setting \a r_xy to the offset.
+ *
+ * \return true if a change is made.
+ */
+bool BLI_rctf_clamp(rctf *rect, const rctf *rect_bounds, float r_xy[2])
+{
+ bool changed = false;
+
+ r_xy[0] = 0.0f;
+ r_xy[1] = 0.0f;
+
+ if (rect->xmin < rect_bounds->xmin) {
+ float ofs = rect_bounds->xmin - rect->xmin;
+ rect->xmin += ofs;
+ rect->xmax += ofs;
+ r_xy[0] += ofs;
+ changed = true;
+ }
+
+ if (rect->xmax > rect_bounds->xmax) {
+ float ofs = rect_bounds->xmax - rect->xmax;
+ rect->xmin += ofs;
+ rect->xmax += ofs;
+ r_xy[0] += ofs;
+ changed = true;
+ }
+
+ if (rect->ymin < rect_bounds->ymin) {
+ float ofs = rect_bounds->ymin - rect->ymin;
+ rect->ymin += ofs;
+ rect->ymax += ofs;
+ r_xy[1] += ofs;
+ changed = true;
+ }
+
+ if (rect->ymax > rect_bounds->ymax) {
+ float ofs = rect_bounds->ymax - rect->ymax;
+ rect->ymin += ofs;
+ rect->ymax += ofs;
+ r_xy[1] += ofs;
+ changed = true;
+ }
+
+ return changed;
+}
+
+bool BLI_rcti_clamp(rcti *rect, const rcti *rect_bounds, int r_xy[2])
+{
+ bool changed = false;
+
+ r_xy[0] = 0;
+ r_xy[1] = 0;
+
+ if (rect->xmin < rect_bounds->xmin) {
+ int ofs = rect_bounds->xmin - rect->xmin;
+ rect->xmin += ofs;
+ rect->xmax += ofs;
+ r_xy[0] += ofs;
+ changed = true;
+ }
+
+ if (rect->xmax > rect_bounds->xmax) {
+ int ofs = rect_bounds->xmax - rect->xmax;
+ rect->xmin += ofs;
+ rect->xmax += ofs;
+ r_xy[0] += ofs;
+ changed = true;
+ }
+
+ if (rect->ymin < rect_bounds->ymin) {
+ int ofs = rect_bounds->ymin - rect->ymin;
+ rect->ymin += ofs;
+ rect->ymax += ofs;
+ r_xy[1] += ofs;
+ changed = true;
+ }
+
+ if (rect->ymax > rect_bounds->ymax) {
+ int ofs = rect_bounds->ymax - rect->ymax;
+ rect->ymin += ofs;
+ rect->ymax += ofs;
+ r_xy[1] += ofs;
+ changed = true;
+ }
+
+ return changed;
+}
+
+bool BLI_rctf_compare(const rctf *rect_a, const rctf *rect_b, const float limit)
{
if (fabsf(rect_a->xmin - rect_b->xmin) < limit)
if (fabsf(rect_a->xmax - rect_b->xmax) < limit)
@@ -505,7 +594,7 @@ bool BLI_rctf_compare(const struct rctf *rect_a, const struct rctf *rect_b, cons
return false;
}
-bool BLI_rcti_compare(const struct rcti *rect_a, const struct rcti *rect_b)
+bool BLI_rcti_compare(const rcti *rect_a, const rcti *rect_b)
{
if (rect_a->xmin == rect_b->xmin)
if (rect_a->xmax == rect_b->xmax)
diff --git a/source/blender/blenlib/intern/storage.c b/source/blender/blenlib/intern/storage.c
index 7fdf6ec8101..f7a8664c739 100644
--- a/source/blender/blenlib/intern/storage.c
+++ b/source/blender/blenlib/intern/storage.c
@@ -91,8 +91,14 @@ char *BLI_current_working_dir(char *dir, const size_t maxncpy)
{
const char *pwd = getenv("PWD");
if (pwd) {
- BLI_strncpy(dir, pwd, maxncpy);
- return dir;
+ size_t srclen = BLI_strnlen(pwd, maxncpy);
+ if (srclen != maxncpy) {
+ memcpy(dir, pwd, srclen + 1);
+ return dir;
+ }
+ else {
+ return NULL;
+ }
}
return getcwd(dir, maxncpy);
diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c
index 6cc00fc60ee..e93d2b7507a 100644
--- a/source/blender/blenlib/intern/string.c
+++ b/source/blender/blenlib/intern/string.c
@@ -756,7 +756,7 @@ void BLI_str_toupper_ascii(char *str, const size_t len)
*
* \param str
* \param pad
- * \return The number of zeto's stripped.
+ * \return The number of zeros stripped.
*/
int BLI_str_rstrip_float_zero(char *str, const char pad)
{
diff --git a/source/blender/blenlib/intern/task.c b/source/blender/blenlib/intern/task.c
index 08d40a158ca..a125bf7d8d0 100644
--- a/source/blender/blenlib/intern/task.c
+++ b/source/blender/blenlib/intern/task.c
@@ -207,7 +207,6 @@ TaskScheduler *BLI_task_scheduler_create(int num_threads)
if (pthread_create(&scheduler->threads[i], NULL, task_scheduler_thread_run, thread) != 0) {
fprintf(stderr, "TaskScheduler failed to launch thread %d/%d\n", i, num_threads);
- MEM_freeN(thread);
}
}
}
diff --git a/source/blender/blenlib/intern/timecode.c b/source/blender/blenlib/intern/timecode.c
index 4ae9249ec0d..e755a7ae52c 100644
--- a/source/blender/blenlib/intern/timecode.c
+++ b/source/blender/blenlib/intern/timecode.c
@@ -72,20 +72,20 @@ size_t BLI_timecode_string_from_time(
time = -time;
}
- if (time >= 3600) {
+ if (time >= 3600.0f) {
/* hours */
/* XXX should we only display a single digit for hours since clips are
* VERY UNLIKELY to be more than 1-2 hours max? However, that would
* go against conventions...
*/
hours = (int)time / 3600;
- time = (float)fmod(time, 3600);
+ time = fmodf(time, 3600);
}
- if (time >= 60) {
+ if (time >= 60.0f) {
/* minutes */
minutes = (int)time / 60;
- time = (float)fmod(time, 60);
+ time = fmodf(time, 60);
}
if (power <= 0) {
@@ -163,6 +163,18 @@ size_t BLI_timecode_string_from_time(
}
break;
}
+ case USER_TIMECODE_SUBRIP:
+ {
+ /* SubRip, like SMPTE milliseconds but seconds and milliseconds are separated by a comma, not a dot... */
+
+ /* precision of decimal part */
+ const int ms_dp = (power <= 0) ? (1 - power) : 1;
+ const int ms = iroundf((time - (float)seconds) * 1000.0f);
+
+ rlen = BLI_snprintf_rlen(
+ str, maxncpy, "%s%02d:%02d:%02d,%0*d", neg, hours, minutes, seconds, ms_dp, ms);
+ break;
+ }
case USER_TIMECODE_SECONDS_ONLY:
{
/* only show the original seconds display */
diff --git a/source/blender/blenlib/intern/winstuff.c b/source/blender/blenlib/intern/winstuff.c
index a67e116969e..32ab16b4b5a 100644
--- a/source/blender/blenlib/intern/winstuff.c
+++ b/source/blender/blenlib/intern/winstuff.c
@@ -93,7 +93,7 @@ void RegisterBlendExtension(void)
char RegCmd[MAX_PATH * 2];
char MBox[256];
char *blender_app;
-#ifndef WIN64
+#ifndef _WIN64
BOOL IsWOW64;
#endif
@@ -158,7 +158,7 @@ void RegisterBlendExtension(void)
BLI_getInstallationDir(InstallDir);
GetSystemDirectory(SysDir, FILE_MAXDIR);
-#ifdef WIN64
+#ifdef _WIN64
ThumbHandlerDLL = "BlendThumb64.dll";
#elif defined(__MINGW32__)
ThumbHandlerDLL = "BlendThumb.dll";
diff --git a/source/blender/blenloader/BLO_blend_defs.h b/source/blender/blenloader/BLO_blend_defs.h
index 44f0fa9aa53..a6b06a080cc 100644
--- a/source/blender/blenloader/BLO_blend_defs.h
+++ b/source/blender/blenloader/BLO_blend_defs.h
@@ -75,4 +75,6 @@ enum {
ENDB = BLEND_MAKE_ID('E', 'N', 'D', 'B'),
};
+#define BLEN_THUMB_MEMSIZE_FILE(_x, _y) (sizeof(int) * (size_t)(2 + (_x) * (_y)))
+
#endif /* __BLO_BLEND_DEFS_H__ */
diff --git a/source/blender/blenloader/BLO_readfile.h b/source/blender/blenloader/BLO_readfile.h
index 5f881c0855c..51b016a77f8 100644
--- a/source/blender/blenloader/BLO_readfile.h
+++ b/source/blender/blenloader/BLO_readfile.h
@@ -36,6 +36,7 @@
extern "C" {
#endif
+struct BlendThumbnail;
struct bScreen;
struct LinkNode;
struct Main;
@@ -43,6 +44,7 @@ struct MemFile;
struct ReportList;
struct Scene;
struct UserDef;
+struct View3D;
struct bContext;
struct BHead;
struct FileData;
@@ -69,186 +71,39 @@ typedef struct BlendFileData {
BlenFileType type;
} BlendFileData;
-/**
- * Open a blender file from a pathname. The function
- * returns NULL and sets a report in the list if
- * it cannot open the file.
- *
- * \param filepath The path of the file to open.
- * \param reports If the return value is NULL, errors
- * indicating the cause of the failure.
- * \return The data of the file.
- */
-BlendFileData *BLO_read_from_file(
- const char *filepath,
- struct ReportList *reports);
-
-/**
- * Open a blender file from memory. The function
- * returns NULL and sets a report in the list if
- * it cannot open the file.
- *
- * \param mem The file data.
- * \param memsize The length of \a mem.
- * \param reports If the return value is NULL, errors
- * indicating the cause of the failure.
- * \return The data of the file.
- */
-BlendFileData *BLO_read_from_memory(
- const void *mem, int memsize,
- struct ReportList *reports);
-
-/**
- * oldmain is old main, from which we will keep libraries, images, ..
- * file name is current file, only for retrieving library data */
-
+BlendFileData *BLO_read_from_file(const char *filepath, struct ReportList *reports);
+BlendFileData *BLO_read_from_memory(const void *mem, int memsize, struct ReportList *reports);
BlendFileData *BLO_read_from_memfile(
struct Main *oldmain, const char *filename, struct MemFile *memfile,
struct ReportList *reports);
-/**
- * Free's a BlendFileData structure and _all_ the
- * data associated with it (the userdef data, and
- * the main libblock data).
- *
- * \param bfd The structure to free.
- */
-void
-BLO_blendfiledata_free(BlendFileData *bfd);
+void BLO_blendfiledata_free(BlendFileData *bfd);
-/**
- * Open a blendhandle from a file path.
- *
- * \param filepath: The file path to open.
- * \param reports: Report errors in opening the file (can be NULL).
- * \return A handle on success, or NULL on failure.
- */
-BlendHandle *BLO_blendhandle_from_file(
- const char *filepath,
- struct ReportList *reports);
-
-/**
- * Open a blendhandle from memory.
- *
- * \param mem The data to load from.
- * \param memsize The size of the data.
- * \return A handle on success, or NULL on failure.
- */
-
-BlendHandle *BLO_blendhandle_from_memory(
- const void *mem, int memsize);
-
-/**
- * Gets the names of all the datablocks in a file
- * of a certain type (ie. All the scene names in
- * a file).
- *
- * \param bh The blendhandle to access.
- * \param ofblocktype The type of names to get.
- * \param tot_names The length of the returned list.
- * \return A BLI_linklist of strings. The string links
- * should be freed with malloc.
- */
-struct LinkNode *BLO_blendhandle_get_datablock_names(
- BlendHandle *bh,
- int ofblocktype, int *tot_names);
-
-/**
- * Gets the previews of all the datablocks in a file
- * of a certain type (ie. All the scene names in
- * a file).
- *
- * \param bh The blendhandle to access.
- * \param ofblocktype The type of names to get.
- * \param tot_prev The length of the returned list.
- * \return A BLI_linklist of PreviewImage. The PreviewImage links
- * should be freed with malloc.
- */
-struct LinkNode *BLO_blendhandle_get_previews(
- BlendHandle *bh,
- int ofblocktype, int *tot_prev);
+BlendHandle *BLO_blendhandle_from_file(const char *filepath, struct ReportList *reports);
+BlendHandle *BLO_blendhandle_from_memory(const void *mem, int memsize);
-/**
- * Gets the names of all the datablock groups in a
- * file. (ie. file contains Scene, Mesh, and Lamp
- * datablocks).
- *
- * \param bh The blendhandle to access.
- * \return A BLI_linklist of strings. The string links
- * should be freed with malloc.
- */
+struct LinkNode *BLO_blendhandle_get_datablock_names(BlendHandle *bh, int ofblocktype, int *tot_names);
+struct LinkNode *BLO_blendhandle_get_previews(BlendHandle *bh, int ofblocktype, int *tot_prev);
struct LinkNode *BLO_blendhandle_get_linkable_groups(BlendHandle *bh);
-/**
- * Close and free a blendhandle. The handle
- * becomes invalid after this call.
- *
- * \param bh The handle to close.
- */
-void
-BLO_blendhandle_close(BlendHandle *bh);
+void BLO_blendhandle_close(BlendHandle *bh);
/***/
#define BLO_GROUP_MAX 32
bool BLO_has_bfile_extension(const char *str);
-
-/**
- * \param path the full path to explode.
- * \param r_dir the string that'll contain path up to blend file itself ('library' path).
- * \param r_group the string that'll contain 'group' part of the path, if any. May be NULL.
- * \param r_name the string that'll contain data's name part of the path, if any. May be NULL.
- * \return true if path contains a blend file.
- */
bool BLO_library_path_explode(const char *path, char *r_dir, char **r_group, char **r_name);
-
-/**
- * Initialize the BlendHandle for appending or linking library data.
- *
- * \param mainvar The current main database eg G.main or CTX_data_main(C).
- * \param bh A blender file handle as returned by BLO_blendhandle_from_file or BLO_blendhandle_from_memory.
- * \param filepath Used for relative linking, copied to the lib->name
- * \return the library Main, to be passed to BLO_library_append_named_part as mainl.
- */
-struct Main *BLO_library_append_begin(
- struct Main *mainvar, BlendHandle **bh,
- const char *filepath);
-
-
-/**
- * Link/Append a named datablock from an external blend file.
- *
- * \param mainl The main database to link from (not the active one).
- * \param bh The blender file handle.
- * \param idname The name of the datablock (without the 2 char ID prefix)
- * \param idcode The kind of datablock to link.
- * \return the appended ID when found.
- */
-struct ID *BLO_library_append_named_part(
+struct Main *BLO_library_link_begin(struct Main *mainvar, BlendHandle **bh, const char *filepath);
+struct ID *BLO_library_link_named_part(struct Main *mainl, BlendHandle **bh, const short idcode, const char *name);
+struct ID *BLO_library_link_named_part_ex(
struct Main *mainl, BlendHandle **bh,
- const char *idname, const int idcode);
-
-/**
- * Link/Append a named datablock from an external blend file.
- * optionally instance the object in the scene when the flags are set.
- *
- * \param C The context, when NULL instancing object in the scene isn't done.
- * \param mainl The main database to link from (not the active one).
- * \param bh The blender file handle.
- * \param idname The name of the datablock (without the 2 char ID prefix)
- * \param idcode The kind of datablock to link.
- * \param flag Options for linking, used for instancing.
- * \return the appended ID when found.
- */
-struct ID *BLO_library_append_named_part_ex(
- const struct bContext *C, struct Main *mainl, BlendHandle **bh,
- const char *idname, const int idcode, const short flag);
-
-void BLO_library_append_end(const struct bContext *C, struct Main *mainl, BlendHandle **bh, int idcode, short flag);
+ const short idcode, const char *name, const short flag,
+ struct Scene *scene, struct View3D *v3d);
+void BLO_library_link_end(struct Main *mainl, BlendHandle **bh, short flag, struct Scene *scene, struct View3D *v3d);
-void BLO_library_append_all(struct Main *mainl, BlendHandle *bh);
+void BLO_library_link_all(struct Main *mainl, BlendHandle *bh);
void *BLO_library_read_struct(struct FileData *fd, struct BHead *bh, const char *blockname);
@@ -257,27 +112,17 @@ BlendFileData *blo_read_blendafterruntime(int file, const char *name, int actual
/* internal function but we need to expose it */
void blo_lib_link_screen_restore(struct Main *newmain, struct bScreen *curscreen, struct Scene *curscene);
-/**
- * BLO_expand_main() loops over all ID data in Main to mark relations.
- * Set (id->flag & LIB_NEED_EXPAND) to mark expanding. Flags get cleared after expanding.
- *
- * \param expand_doit_func() gets called for each ID block it finds
- */
-void BLO_main_expander(void (*expand_doit_func)(void *, struct Main *, void *));
+typedef void (*BLOExpandDoitCallback) (void *fdhandle, struct Main *mainvar, void *idv);
-/**
- * BLO_expand_main() loops over all ID data in Main to mark relations.
- * Set (id->flag & LIB_NEED_EXPAND) to mark expanding. Flags get cleared after expanding.
- *
- * \param fdhandle usually filedata, or own handle
- * \param mainvar the Main database to expand
- */
+void BLO_main_expander(BLOExpandDoitCallback expand_doit_func);
void BLO_expand_main(void *fdhandle, struct Main *mainvar);
/* 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);
+struct BlendThumbnail *BLO_thumbnail_from_file(const char *filepath);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenloader/BLO_writefile.h b/source/blender/blenloader/BLO_writefile.h
index 7a8429afec0..0d66eb743aa 100644
--- a/source/blender/blenloader/BLO_writefile.h
+++ b/source/blender/blenloader/BLO_writefile.h
@@ -33,14 +33,14 @@
* \brief external writefile function prototypes.
*/
+struct BlendThumbnail;
struct MemFile;
struct Main;
struct ReportList;
-extern int BLO_write_file(struct Main *mainvar, const char *filepath, int write_flags, struct ReportList *reports, const int *thumb);
+extern int BLO_write_file(struct Main *mainvar, const char *filepath, int write_flags,
+ struct ReportList *reports, const struct BlendThumbnail *thumb);
extern int BLO_write_file_mem(struct Main *mainvar, struct MemFile *compare, struct MemFile *current, int write_flags);
-#define BLEN_THUMB_SIZE 128
-
#endif
diff --git a/source/blender/blenloader/intern/readblenentry.c b/source/blender/blenloader/intern/readblenentry.c
index e8d7a46687f..cd6df354ca7 100644
--- a/source/blender/blenloader/intern/readblenentry.c
+++ b/source/blender/blenloader/intern/readblenentry.c
@@ -72,6 +72,13 @@ void BLO_blendhandle_print_sizes(BlendHandle *, void *);
/* Access routines used by filesel. */
+/**
+ * Open a blendhandle from a file path.
+ *
+ * \param filepath The file path to open.
+ * \param reports Report errors in opening the file (can be NULL).
+ * \return A handle on success, or NULL on failure.
+ */
BlendHandle *BLO_blendhandle_from_file(const char *filepath, ReportList *reports)
{
BlendHandle *bh;
@@ -81,6 +88,13 @@ BlendHandle *BLO_blendhandle_from_file(const char *filepath, ReportList *reports
return bh;
}
+/**
+ * Open a blendhandle from memory.
+ *
+ * \param mem The data to load from.
+ * \param memsize The size of the data.
+ * \return A handle on success, or NULL on failure.
+ */
BlendHandle *BLO_blendhandle_from_memory(const void *mem, int memsize)
{
BlendHandle *bh;
@@ -120,6 +134,14 @@ void BLO_blendhandle_print_sizes(BlendHandle *bh, void *fp)
fprintf(fp, "]\n");
}
+/**
+ * Gets the names of all the datablocks in a file of a certain type (e.g. all the scene names in a file).
+ *
+ * \param bh The blendhandle to access.
+ * \param ofblocktype The type of names to get.
+ * \param tot_names The length of the returned list.
+ * \return A BLI_linklist of strings. The string links should be freed with malloc.
+ */
LinkNode *BLO_blendhandle_get_datablock_names(BlendHandle *bh, int ofblocktype, int *tot_names)
{
FileData *fd = (FileData *) bh;
@@ -142,6 +164,14 @@ LinkNode *BLO_blendhandle_get_datablock_names(BlendHandle *bh, int ofblocktype,
return names;
}
+/**
+ * Gets the previews of all the datablocks in a file of a certain type (e.g. all the scene previews in a file).
+ *
+ * \param bh The blendhandle to access.
+ * \param ofblocktype The type of names to get.
+ * \param tot_prev The length of the returned list.
+ * \return A BLI_linklist of PreviewImage. The PreviewImage links should be freed with malloc.
+ */
LinkNode *BLO_blendhandle_get_previews(BlendHandle *bh, int ofblocktype, int *tot_prev)
{
FileData *fd = (FileData *) bh;
@@ -232,7 +262,13 @@ LinkNode *BLO_blendhandle_get_previews(BlendHandle *bh, int ofblocktype, int *to
return previews;
}
-LinkNode *BLO_blendhandle_get_linkable_groups(BlendHandle *bh)
+/**
+ * Gets the names of all the linkable datablock types available in a file. (e.g. "Scene", "Mesh", "Lamp", etc.).
+ *
+ * \param bh The blendhandle to access.
+ * \return A BLI_linklist of strings. The string links should be freed with malloc.
+ */
+LinkNode *BLO_blendhandle_get_linkable_groups(BlendHandle *bh)
{
FileData *fd = (FileData *) bh;
GSet *gathered = BLI_gset_ptr_new("linkable_groups gh");
@@ -260,6 +296,11 @@ LinkNode *BLO_blendhandle_get_linkable_groups(BlendHandle *bh)
return names;
}
+/**
+ * Close and free a blendhandle. The handle becomes invalid after this call.
+ *
+ * \param bh The handle to close.
+ */
void BLO_blendhandle_close(BlendHandle *bh)
{
FileData *fd = (FileData *) bh;
@@ -269,6 +310,14 @@ void BLO_blendhandle_close(BlendHandle *bh)
/**********/
+/**
+ * Open a blender file from a pathname. The function returns NULL
+ * and sets a report in the list if it cannot open the file.
+ *
+ * \param filepath The path of the file to open.
+ * \param reports If the return value is NULL, errors indicating the cause of the failure.
+ * \return The data of the file.
+ */
BlendFileData *BLO_read_from_file(const char *filepath, ReportList *reports)
{
BlendFileData *bfd = NULL;
@@ -284,6 +333,15 @@ BlendFileData *BLO_read_from_file(const char *filepath, ReportList *reports)
return bfd;
}
+/**
+ * Open a blender file from memory. The function returns NULL
+ * and sets a report in the list if it cannot open the file.
+ *
+ * \param mem The file data.
+ * \param memsize The length of \a mem.
+ * \param reports If the return value is NULL, errors indicating the cause of the failure.
+ * \return The data of the file.
+ */
BlendFileData *BLO_read_from_memory(const void *mem, int memsize, ReportList *reports)
{
BlendFileData *bfd = NULL;
@@ -299,11 +357,17 @@ BlendFileData *BLO_read_from_memory(const void *mem, int memsize, ReportList *re
return bfd;
}
+/**
+ * Used for undo/redo, skips part of libraries reading (assuming their data are already loaded & valid).
+ *
+ * \param oldmain old main, from which we will keep libraries and other datablocks that should not have changed.
+ * \param filename current file, only for retrieving library data.
+ */
BlendFileData *BLO_read_from_memfile(Main *oldmain, const char *filename, MemFile *memfile, ReportList *reports)
{
BlendFileData *bfd = NULL;
FileData *fd;
- ListBase mainlist;
+ ListBase old_mainlist;
fd = blo_openblendermemfile(memfile, reports);
if (fd) {
@@ -314,9 +378,9 @@ BlendFileData *BLO_read_from_memfile(Main *oldmain, const char *filename, MemFil
blo_clear_proxy_pointers_from_lib(oldmain);
/* separate libraries from old main */
- blo_split_main(&mainlist, oldmain);
+ blo_split_main(&old_mainlist, oldmain);
/* add the library pointers in oldmap lookup */
- blo_add_library_pointer_map(&mainlist, fd);
+ blo_add_library_pointer_map(&old_mainlist, fd);
/* makes lookup of existing images in old main */
blo_make_image_pointer_map(fd, oldmain);
@@ -340,25 +404,55 @@ BlendFileData *BLO_read_from_memfile(Main *oldmain, const char *filename, MemFil
/* ensures relinked sounds are not freed */
blo_end_sound_pointer_map(fd, oldmain);
- /* move libraries from old main to new main */
- if (bfd && mainlist.first != mainlist.last) {
-
- /* Library structs themselves */
- bfd->main->library = oldmain->library;
- BLI_listbase_clear(&oldmain->library);
-
- /* add the Library mainlist to the new main */
- BLI_remlink(&mainlist, oldmain);
- BLI_addhead(&mainlist, bfd->main);
+ /* Still in-use libraries have already been moved from oldmain to new mainlist,
+ * but oldmain itself shall *never* be 'transferred' to new mainlist! */
+ BLI_assert(old_mainlist.first == oldmain);
+
+ if (bfd && old_mainlist.first != old_mainlist.last) {
+ /* Even though directly used libs have been already moved to new main, indirect ones have not.
+ * This is a bit annoying, but we have no choice but to keep them all for now - means some now unused
+ * data may remain in memory, but think we'll have to live with it. */
+ Main *libmain;
+ Main *newmain = bfd->main;
+ ListBase new_mainlist = {newmain, newmain};
+
+ for (libmain = oldmain->next; libmain; libmain = libmain->next) {
+ /* Note that LIB_INDIRECT does not work with libraries themselves, so we use non-NULL parent
+ * to detect indirect-linked ones... */
+ if (libmain->curlib && (libmain->curlib->parent != NULL)) {
+ BLI_remlink(&old_mainlist, libmain);
+ BLI_addtail(&new_mainlist, libmain);
+ }
+#if 0
+ else {
+ printf("Dropped Main for lib: %s\n", libmain->curlib->id.name);
+ }
+#endif
+ }
+ /* In any case, we need to move all lib datablocks themselves - those are 'first level data',
+ * getting rid of them would imply updating spaces & co to prevent invalid pointers access. */
+ BLI_movelisttolist(&newmain->library, &oldmain->library);
+
+ blo_join_main(&new_mainlist);
}
- blo_join_main(&mainlist);
-
+
+ /* printf("Remaining mains/libs in oldmain: %d\n", BLI_listbase_count(&fd->old_mainlist) - 1); */
+
+ /* That way, libs (aka mains) we did not reuse in new undone/redone state
+ * will be cleared together with oldmain... */
+ blo_join_main(&old_mainlist);
+
blo_freefiledata(fd);
}
return bfd;
}
+/**
+ * Frees a BlendFileData structure and *all* the data associated with it (the userdef data, and the main libblock data).
+ *
+ * \param bfd The structure to free.
+ */
void BLO_blendfiledata_free(BlendFileData *bfd)
{
if (bfd->main) {
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 7bc6410316d..2c341f97a66 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -124,6 +124,7 @@
#include "BKE_global.h" // for G
#include "BKE_group.h"
#include "BKE_library.h" // for which_libbase
+#include "BKE_library_query.h"
#include "BKE_idcode.h"
#include "BKE_material.h"
#include "BKE_main.h" // for Main
@@ -618,7 +619,9 @@ static Main *blo_find_main(FileData *fd, const char *filepath, const char *relab
m = BKE_main_new();
BLI_addtail(mainlist, m);
- lib = BKE_libblock_alloc(m, ID_LI, "lib");
+ /* Add library datablock itself to 'main' Main, since libraries are **never** linked data.
+ * Fixes bug where you could end with all ID_LI datablocks having the same name... */
+ lib = BKE_libblock_alloc(mainlist->first, ID_LI, "Lib");
BLI_strncpy(lib->name, filepath, sizeof(lib->name));
BLI_strncpy(lib->filepath, name1, sizeof(lib->filepath));
@@ -851,6 +854,12 @@ BHead *blo_nextbhead(FileData *fd, BHead *thisblock)
return(bhead);
}
+/* Warning! Caller's responsability to ensure given bhead **is** and ID one! */
+const char *bhead_id_name(const FileData *fd, const BHead *bhead)
+{
+ return (const char *)POINTER_OFFSET(bhead, sizeof(*bhead) + fd->id_name_offs);
+}
+
static void decode_blender_header(FileData *fd)
{
char header[SIZEOFBLENDERHEADER], num[4];
@@ -917,6 +926,41 @@ static int read_file_dna(FileData *fd)
return 0;
}
+static int *read_file_thumbnail(FileData *fd)
+{
+ BHead *bhead;
+ int *blend_thumb = NULL;
+
+ for (bhead = blo_firstbhead(fd); bhead; bhead = blo_nextbhead(fd, bhead)) {
+ if (bhead->code == TEST) {
+ const bool do_endian_swap = (fd->flags & FD_FLAGS_SWITCH_ENDIAN) != 0;
+ int *data = (int *)(bhead + 1);
+
+ if (bhead->len < (2 * sizeof(int))) {
+ break;
+ }
+
+ if (do_endian_swap) {
+ BLI_endian_switch_int32(&data[0]);
+ BLI_endian_switch_int32(&data[1]);
+ }
+
+ if (bhead->len < BLEN_THUMB_MEMSIZE_FILE(data[0], data[1])) {
+ break;
+ }
+
+ blend_thumb = data;
+ break;
+ }
+ else if (bhead->code != REND) {
+ /* Thumbnail is stored in TEST immediately after first REND... */
+ break;
+ }
+ }
+
+ return blend_thumb;
+}
+
static int fd_read_from_file(FileData *filedata, void *buffer, unsigned int size)
{
int readsize = read(filedata->filedes, buffer, size);
@@ -1080,6 +1124,33 @@ FileData *blo_openblenderfile(const char *filepath, ReportList *reports)
}
}
+/**
+ * Same as blo_openblenderfile(), but does not reads DNA data, only header. Use it for light access
+ * (e.g. thumbnail reading).
+ */
+static FileData *blo_openblenderfile_minimal(const char *filepath)
+{
+ gzFile gzfile;
+ errno = 0;
+ gzfile = BLI_gzopen(filepath, "rb");
+
+ if (gzfile != (gzFile)Z_NULL) {
+ FileData *fd = filedata_new();
+ fd->gzfiledes = gzfile;
+ fd->read = fd_read_gzip_from_file;
+
+ decode_blender_header(fd);
+
+ if (fd->flags & FD_FLAGS_FILE_OK) {
+ return fd;
+ }
+
+ blo_freefiledata(fd);
+ }
+
+ return NULL;
+}
+
static int fd_read_gzip_from_memory(FileData *filedata, void *buffer, unsigned int size)
{
int err;
@@ -1228,12 +1299,27 @@ void blo_freefiledata(FileData *fd)
/* ************ DIV ****************** */
+/**
+ * Check whether given path ends with a blend file compatible extension (.blend, .ble or .blend.gz).
+ *
+ * \param str The path to check.
+ * \return true is this path ends with a blender file extension.
+ */
bool BLO_has_bfile_extension(const char *str)
{
const char *ext_test[4] = {".blend", ".ble", ".blend.gz", NULL};
return BLI_testextensie_array(str, ext_test);
}
+/**
+ * Try to explode given path into its 'library components' (i.e. a .blend file, id type/group, and datablock itself).
+ *
+ * \param path the full path to explode.
+ * \param r_dir the string that'll contain path up to blend file itself ('library' path).
+ * \param r_group the string that'll contain 'group' part of the path, if any. May be NULL.
+ * \param r_name the string that'll contain data's name part of the path, if any. May be NULL.
+ * \return true if path contains a blend file.
+ */
bool BLO_library_path_explode(const char *path, char *r_dir, char **r_group, char **r_name)
{
/* We might get some data names with slashes, so we have to go up in path until we find blend file itself,
@@ -1290,6 +1376,40 @@ bool BLO_library_path_explode(const char *path, char *r_dir, char **r_group, cha
return true;
}
+/**
+ * Does a very light reading of given .blend file to extract its stored thumbnail.
+ *
+ * \param filepath The path of the file to extract thumbnail from.
+ * \return The raw thumbnail
+ * (MEM-allocated, as stored in file, use BKE_main_thumbnail_to_imbuf() to convert it to ImBuf image).
+ */
+BlendThumbnail *BLO_thumbnail_from_file(const char *filepath)
+{
+ FileData *fd;
+ BlendThumbnail *data;
+ int *fd_data;
+
+ fd = blo_openblenderfile_minimal(filepath);
+ fd_data = fd ? read_file_thumbnail(fd) : NULL;
+
+ if (fd_data) {
+ const size_t sz = BLEN_THUMB_MEMSIZE(fd_data[0], fd_data[1]);
+ data = MEM_mallocN(sz, __func__);
+
+ BLI_assert((sz - sizeof(*data)) == (BLEN_THUMB_MEMSIZE_FILE(fd_data[0], fd_data[1]) - (sizeof(*fd_data) * 2)));
+ data->width = fd_data[0];
+ data->height = fd_data[1];
+ memcpy(data->rect, &fd_data[2], sz - sizeof(*data));
+ }
+ else {
+ data = NULL;
+ }
+
+ blo_freefiledata(fd);
+
+ return data;
+}
+
/* ************** OLD POINTERS ******************* */
static void *newdataadr(FileData *fd, void *adr) /* only direct databocks */
@@ -1680,9 +1800,9 @@ void blo_end_packed_pointer_map(FileData *fd, Main *oldmain)
/* undo file support: add all library pointers in lookup */
-void blo_add_library_pointer_map(ListBase *mainlist, FileData *fd)
+void blo_add_library_pointer_map(ListBase *old_mainlist, FileData *fd)
{
- Main *ptr = mainlist->first;
+ Main *ptr = old_mainlist->first;
ListBase *lbarray[MAX_LIBARRAY];
for (ptr = ptr->next; ptr; ptr = ptr->next) {
@@ -1693,6 +1813,8 @@ void blo_add_library_pointer_map(ListBase *mainlist, FileData *fd)
oldnewmap_insert(fd->libmap, id, id, GS(id->name));
}
}
+
+ fd->old_mainlist = old_mainlist;
}
@@ -4498,15 +4620,15 @@ static void direct_link_latt(FileData *fd, Lattice *lt)
/* ************ READ OBJECT ***************** */
-static void lib_link_modifiers__linkModifiers(void *userData, Object *ob,
- ID **idpoin)
+static void lib_link_modifiers__linkModifiers(
+ void *userData, Object *ob, ID **idpoin, int cd_flag)
{
FileData *fd = userData;
*idpoin = newlibadr(fd, ob->id.lib, *idpoin);
- /* hardcoded bad exception; non-object modifier data gets user count (texture, displace) */
- if (*idpoin && GS((*idpoin)->name)!=ID_OB)
+ if (*idpoin != NULL && (cd_flag & IDWALK_USER) != 0) {
(*idpoin)->us++;
+ }
}
static void lib_link_modifiers(FileData *fd, Object *ob)
{
@@ -5486,16 +5608,10 @@ static void lib_link_scene(FileData *fd, Main *main)
}
}
if (seq->clip) {
- seq->clip = newlibadr(fd, sce->id.lib, seq->clip);
- if (seq->clip) {
- seq->clip->id.us++;
- }
+ seq->clip = newlibadr_us(fd, sce->id.lib, seq->clip);
}
if (seq->mask) {
- seq->mask = newlibadr(fd, sce->id.lib, seq->mask);
- if (seq->mask) {
- seq->mask->id.us++;
- }
+ seq->mask = newlibadr_us(fd, sce->id.lib, seq->mask);
}
if (seq->scene_camera) {
seq->scene_camera = newlibadr(fd, sce->id.lib, seq->scene_camera);
@@ -6437,6 +6553,7 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc
else if (sl->spacetype == SPACE_FILE) {
SpaceFile *sfile = (SpaceFile *)sl;
sfile->op = NULL;
+ sfile->previews_timer = NULL;
}
else if (sl->spacetype == SPACE_ACTION) {
SpaceAction *saction = (SpaceAction *)sl;
@@ -6520,7 +6637,13 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc
BLI_mempool_iternew(so->treestore, &iter);
while ((tselem = BLI_mempool_iterstep(&iter))) {
- tselem->id = restore_pointer_by_name(newmain, tselem->id, USER_IGNORE);
+ /* Do not try to restore pointers to drivers/sequence/etc., can crash in undo case! */
+ if (TSE_IS_REAL_ID(tselem)) {
+ tselem->id = restore_pointer_by_name(newmain, tselem->id, USER_IGNORE);
+ }
+ else {
+ tselem->id = NULL;
+ }
}
if (so->treehash) {
/* rebuild hash table, because it depends on ids too */
@@ -6967,6 +7090,7 @@ static bool direct_link_screen(FileData *fd, bScreen *sc)
sfile->files = NULL;
sfile->layout = NULL;
sfile->op = NULL;
+ sfile->previews_timer = NULL;
sfile->params = newdataadr(fd, sfile->params);
}
else if (sl->spacetype == SPACE_CLIP) {
@@ -7079,11 +7203,7 @@ static void lib_link_speaker(FileData *fd, Main *main)
if (spk->id.flag & LIB_NEED_LINK) {
if (spk->adt) lib_link_animdata(fd, &spk->id, spk->adt);
- spk->sound= newlibadr(fd, spk->id.lib, spk->sound);
- if (spk->sound) {
- spk->sound->id.us++;
- }
-
+ spk->sound = newlibadr_us(fd, spk->id.lib, spk->sound);
spk->id.flag -= LIB_NEED_LINK;
}
}
@@ -7736,14 +7856,66 @@ static BHead *read_data_into_oldnewmap(FileData *fd, BHead *bhead, const char *a
static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, int flag, ID **r_id)
{
- /* this routine reads a libblock and its direct data. Use link functions
- * to connect it all
+ /* this routine reads a libblock and its direct data. Use link functions to connect it all
*/
ID *id;
ListBase *lb;
const char *allocname;
bool wrong_id = false;
-
+
+ /* In undo case, most libs and linked data should be kept as is from previous state (see BLO_read_from_memfile).
+ * However, some needed by the snapshot being read may have been removed in previous one, and would go missing.
+ * This leads e.g. to desappearing objects in some undo/redo case, see T34446.
+ * That means we have to carefully check whether current lib or libdata already exits in old main, if it does
+ * we merely copy it over into new main area, otherwise we have to do a full read of that bhead... */
+ if (fd->memfile && ELEM(bhead->code, ID_LI, ID_ID)) {
+ const char *idname = bhead_id_name(fd, bhead);
+
+ /* printf("Checking %s...\n", idname); */
+
+ if (bhead->code == ID_LI) {
+ Main *libmain = fd->old_mainlist->first;
+ /* Skip oldmain itself... */
+ for (libmain = libmain->next; libmain; libmain = libmain->next) {
+ /* printf("... against %s: ", libmain->curlib ? libmain->curlib->id.name : "<NULL>"); */
+ if (libmain->curlib && STREQ(idname, libmain->curlib->id.name)) {
+ Main *oldmain = fd->old_mainlist->first;
+ /* printf("FOUND!\n"); */
+ /* In case of a library, we need to re-add its main to fd->mainlist, because if we have later
+ * a missing ID_ID, we need to get the correct lib it is linked to!
+ * Order is crucial, we cannot bulk-add it in BLO_read_from_memfile() like it used to be... */
+ BLI_remlink(fd->old_mainlist, libmain);
+ BLI_remlink_safe(&oldmain->library, libmain->curlib);
+ BLI_addtail(fd->mainlist, libmain);
+ BLI_addtail(&main->library, libmain->curlib);
+
+ if (r_id) {
+ *r_id = NULL; /* Just in case... */
+ }
+ return blo_nextbhead(fd, bhead);
+ }
+ /* printf("nothing...\n"); */
+ }
+ }
+ else {
+ /* printf("... in %s (%s): ", main->curlib ? main->curlib->id.name : "<NULL>", main->curlib ? main->curlib->name : "<NULL>"); */
+ if ((id = BKE_libblock_find_name_ex(main, GS(idname), idname + 2))) {
+ /* printf("FOUND!\n"); */
+ /* Even though we found our linked ID, there is no guarantee its address is still the same... */
+ if (id != bhead->old) {
+ oldnewmap_insert(fd->libmap, bhead->old, id, GS(id->name));
+ }
+
+ /* No need to do anything else for ID_ID, it's assumed already present in its lib's main... */
+ if (r_id) {
+ *r_id = NULL; /* Just in case... */
+ }
+ return blo_nextbhead(fd, bhead);
+ }
+ /* printf("nothing...\n"); */
+ }
+ }
+
/* read libblock */
id = read_struct(fd, bhead, "lib block");
if (r_id)
@@ -7769,7 +7941,7 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, int flag, ID
if (id->flag & LIB_FAKEUSER) id->us= 1;
else id->us = 0;
id->icon_id = 0;
- id->flag &= ~(LIB_ID_RECALC|LIB_ID_RECALC_DATA|LIB_DOIT);
+ id->flag &= ~(LIB_ID_RECALC | LIB_ID_RECALC_DATA | LIB_DOIT | LIB_MISSING);
/* this case cannot be direct_linked: it's just the ID part */
if (bhead->code == ID_ID) {
@@ -8178,6 +8350,24 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath)
bfd->type = BLENFILETYPE_BLEND;
BLI_strncpy(bfd->main->name, filepath, sizeof(bfd->main->name));
+ if (G.background) {
+ /* We only read & store .blend thumbnail in background mode
+ * (because we cannot re-generate it, no OpenGL available).
+ */
+ const int *data = read_file_thumbnail(fd);
+
+ if (data) {
+ const size_t sz = BLEN_THUMB_MEMSIZE(data[0], data[1]);
+ bfd->main->blen_thumb = MEM_mallocN(sz, __func__);
+
+ BLI_assert((sz - sizeof(*bfd->main->blen_thumb)) ==
+ (BLEN_THUMB_MEMSIZE_FILE(data[0], data[1]) - (sizeof(*data) * 2)));
+ bfd->main->blen_thumb->width = data[0];
+ bfd->main->blen_thumb->height = data[1];
+ memcpy(bfd->main->blen_thumb->rect, &data[2], sz - sizeof(*bfd->main->blen_thumb));
+ }
+ }
+
while (bhead) {
switch (bhead->code) {
case DATA:
@@ -8196,26 +8386,10 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath)
bhead = NULL;
break;
- case ID_LI:
- /* skip library datablocks in undo, this works together with
- * BLO_read_from_memfile, where the old main->library is restored
- * overwriting the libraries from the memory file. previously
- * it did not save ID_LI/ID_ID blocks in this case, but they are
- * needed to make quit.blend recover them correctly. */
- if (fd->memfile)
- bhead = blo_nextbhead(fd, bhead);
- else
- bhead = read_libblock(fd, bfd->main, bhead, LIB_LOCAL, NULL);
- break;
case ID_ID:
- /* same as above */
- if (fd->memfile)
- bhead = blo_nextbhead(fd, bhead);
- else
- /* always adds to the most recently loaded
- * ID_LI block, see direct_link_library.
- * this is part of the file format definition. */
- bhead = read_libblock(fd, mainlist.last, bhead, LIB_READ+LIB_EXTERN, NULL);
+ /* Always adds to the most recently loaded ID_LI block, see direct_link_library.
+ * This is part of the file format definition. */
+ bhead = read_libblock(fd, mainlist.last, bhead, LIB_READ | LIB_EXTERN, NULL);
break;
/* in 2.50+ files, the file identifier for screens is patched, forward compatibility */
@@ -8228,10 +8402,10 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath)
}
/* do before read_libraries, but skip undo case */
- if (fd->memfile==NULL)
+ if (fd->memfile == NULL) {
do_versions(fd, NULL, bfd->main);
-
- do_versions_userdef(fd, bfd);
+ do_versions_userdef(fd, bfd);
+ }
read_libraries(fd, &mainlist);
@@ -8244,6 +8418,8 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath)
link_global(fd, bfd); /* as last */
+ fd->mainlist = NULL; /* Safety, this is local variable, shall not be used afterward. */
+
return bfd;
}
@@ -8367,11 +8543,6 @@ static BHead *find_bhead_from_idname(FileData *fd, const char *idname)
#endif
}
-const char *bhead_id_name(const FileData *fd, const BHead *bhead)
-{
- return (const char *)POINTER_OFFSET(bhead, sizeof(*bhead) + fd->id_name_offs);
-}
-
static ID *is_yet_read(FileData *fd, Main *mainvar, BHead *bhead)
{
const char *idname= bhead_id_name(fd, bhead);
@@ -8457,7 +8628,7 @@ static void expand_doit_library(void *fdhandle, Main *mainvar, void *old)
}
}
-static void (*expand_doit)(void *, Main *, void *);
+static BLOExpandDoitCallback expand_doit;
// XXX deprecated - old animation system
static void expand_ipo(FileData *fd, Main *mainvar, Ipo *ipo)
@@ -8894,8 +9065,8 @@ static void expand_armature(FileData *fd, Main *mainvar, bArmature *arm)
#endif
}
-static void expand_object_expandModifiers(void *userData, Object *UNUSED(ob),
- ID **idpoin)
+static void expand_object_expandModifiers(
+ void *userData, Object *UNUSED(ob), ID **idpoin, int UNUSED(cd_flag))
{
struct { FileData *fd; Main *mainvar; } *data= userData;
@@ -9232,11 +9403,23 @@ static void expand_gpencil(FileData *fd, Main *mainvar, bGPdata *gpd)
expand_animdata(fd, mainvar, gpd->adt);
}
-void BLO_main_expander(void (*expand_doit_func)(void *, Main *, void *))
+/**
+ * Set the callback func used over all ID data found by \a BLO_expand_main func.
+ *
+ * \param expand_doit_func Called for each ID block it finds.
+ */
+void BLO_main_expander(BLOExpandDoitCallback expand_doit_func)
{
expand_doit = expand_doit_func;
}
+/**
+ * Loop over all ID data in Main to mark relations.
+ * Set (id->flag & LIB_NEED_EXPAND) to mark expanding. Flags get cleared after expanding.
+ *
+ * \param fdhandle usually filedata, or own handle.
+ * \param mainvar the Main database to expand.
+ */
void BLO_expand_main(void *fdhandle, Main *mainvar)
{
ListBase *lbarray[MAX_LIBARRAY];
@@ -9348,101 +9531,86 @@ static bool object_in_any_scene(Main *mainvar, Object *ob)
{
Scene *sce;
- for (sce= mainvar->scene.first; sce; sce= sce->id.next) {
- if (BKE_scene_base_find(sce, ob))
- return 1;
+ for (sce = mainvar->scene.first; sce; sce = sce->id.next) {
+ if (BKE_scene_base_find(sce, ob)) {
+ return true;
+ }
}
- return 0;
+ return false;
}
-static void give_base_to_objects(Main *mainvar, Scene *sce, Library *lib, const short idcode, const bool is_link, const short active_lay)
+static void give_base_to_objects(Main *mainvar, Scene *scene, View3D *v3d, Library *lib, const short flag)
{
Object *ob;
Base *base;
- const bool is_group_append = (is_link == false && idcode == ID_GR);
+ const unsigned int active_lay = (flag & FILE_ACTIVELAY) ? BKE_screen_view3d_layer_active(v3d, scene) : 0;
+ const bool is_link = (flag & FILE_LINK) != 0;
+
+ BLI_assert(scene);
/* give all objects which are LIB_INDIRECT a base, or for a group when *lib has been set */
for (ob = mainvar->object.first; ob; ob = ob->id.next) {
- if (ob->id.flag & LIB_INDIRECT) {
- /* IF below is quite confusing!
- * if we are appending, but this object wasnt just added along with a group,
- * then this is already used indirectly in the scene somewhere else and we didnt just append it.
- *
- * (ob->id.flag & LIB_PRE_EXISTING)==0 means that this is a newly appended object - Campbell */
- if (is_group_append==0 || (ob->id.flag & LIB_PRE_EXISTING)==0) {
- bool do_it = false;
-
- if (ob->id.us == 0) {
- do_it = true;
- }
- else if (idcode==ID_GR) {
- if ((is_link == false) && (ob->id.lib == lib)) {
- if ((ob->flag & OB_FROMGROUP) && object_in_any_scene(mainvar, ob)==0) {
- do_it = true;
- }
- }
- }
- else {
- /* when appending, make sure any indirectly loaded objects
- * get a base else they cant be accessed at all [#27437] */
- if ((is_link == false) && (ob->id.lib == lib)) {
- /* we may be appending from a scene where we already
- * have a linked object which is not in any scene [#27616] */
- if ((ob->id.flag & LIB_PRE_EXISTING)==0) {
- if (object_in_any_scene(mainvar, ob)==0) {
- do_it = true;
- }
- }
- }
- }
-
- if (do_it) {
- base = MEM_callocN(sizeof(Base), "add_ext_base");
- BLI_addtail(&sce->base, base);
-
- if (active_lay) ob->lay = sce->lay;
-
- base->lay = ob->lay;
- base->object = ob;
- base->flag = ob->flag;
+ if ((ob->id.flag & LIB_INDIRECT) && (ob->id.flag & LIB_PRE_EXISTING) == 0) {
+ bool do_it = false;
- CLAMP_MIN(ob->id.us, 0);
- ob->id.us += 1;
-
- ob->id.flag -= LIB_INDIRECT;
- ob->id.flag |= LIB_EXTERN;
+ if (ob->id.us == 0) {
+ do_it = true;
+ }
+ else if (!is_link && (ob->id.lib == lib) && (object_in_any_scene(mainvar, ob) == 0)) {
+ /* When appending, make sure any indirectly loaded objects get a base, else they cant be accessed at all
+ * (see T27437). */
+ do_it = true;
+ }
+
+ if (do_it) {
+ base = MEM_callocN(sizeof(Base), __func__);
+ BLI_addtail(&scene->base, base);
+
+ if (active_lay) {
+ ob->lay = active_lay;
}
+
+ base->lay = ob->lay;
+ base->object = ob;
+ base->flag = ob->flag;
+
+ CLAMP_MIN(ob->id.us, 0);
+ ob->id.us += 1;
+
+ ob->id.flag &= ~LIB_INDIRECT;
+ ob->id.flag |= LIB_EXTERN;
}
}
}
}
-static void give_base_to_groups(Main *mainvar, Scene *scene)
+static void give_base_to_groups(
+ Main *mainvar, Scene *scene, View3D *v3d, Library *UNUSED(lib), const short UNUSED(flag))
{
Group *group;
-
+ Base *base;
+ Object *ob;
+ const unsigned int active_lay = BKE_screen_view3d_layer_active(v3d, scene);
+
/* give all objects which are tagged a base */
for (group = mainvar->group.first; group; group = group->id.next) {
if (group->id.flag & LIB_DOIT) {
- Base *base;
- Object *ob;
-
/* any indirect group should not have been tagged */
- BLI_assert((group->id.flag & LIB_INDIRECT)==0);
-
+ BLI_assert((group->id.flag & LIB_INDIRECT) == 0);
+
/* BKE_object_add(...) messes with the selection */
ob = BKE_object_add_only_object(mainvar, OB_EMPTY, group->id.name + 2);
ob->type = OB_EMPTY;
- ob->lay = scene->lay;
-
+ ob->lay = active_lay;
+
/* assign the base */
base = BKE_scene_base_add(scene, ob);
base->flag |= SELECT;
- base->object->flag= base->flag;
+ base->object->flag = base->flag;
DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
scene->basact = base;
-
+
/* assign the group */
ob->dup_group = group;
ob->transflag |= OB_DUPLIGROUP;
@@ -9451,11 +9619,30 @@ static void give_base_to_groups(Main *mainvar, Scene *scene)
}
}
+static ID *create_placeholder(Main *mainvar, const char *idname, const short flag)
+{
+ const short idcode = GS(idname);
+ ListBase *lb = which_libbase(mainvar, idcode);
+ ID *ph_id = BKE_libblock_alloc_notest(idcode);
+
+ memcpy(ph_id->name, idname, sizeof(ph_id->name));
+ BKE_libblock_init_empty(ph_id);
+ ph_id->lib = mainvar->curlib;
+ ph_id->flag = flag | LIB_MISSING;
+ ph_id->us = (flag & LIB_FAKEUSER) ? 1 : 0;
+ ph_id->icon_id = 0;
+
+ BLI_addtail(lb, ph_id);
+ id_sort_by_name(lb, ph_id);
+
+ return ph_id;
+}
+
/* returns true if the item was found
* but it may already have already been appended/linked */
-static ID *append_named_part(Main *mainl, FileData *fd, const char *idname, const short idcode)
+static ID *link_named_part(Main *mainl, FileData *fd, const short idcode, const char *name)
{
- BHead *bhead = find_bhead_from_code_name(fd, idcode, idname);
+ BHead *bhead = find_bhead_from_code_name(fd, idcode, name);
ID *id;
if (bhead) {
@@ -9491,8 +9678,10 @@ static ID *append_named_part(Main *mainl, FileData *fd, const char *idname, cons
return id;
}
-/* simple reader for copy/paste buffers */
-void BLO_library_append_all(Main *mainl, BlendHandle *bh)
+/**
+ * Simple reader for copy/paste buffers.
+ */
+void BLO_library_link_all(Main *mainl, BlendHandle *bh)
{
FileData *fd = (FileData *)(bh);
BHead *bhead;
@@ -9512,33 +9701,33 @@ void BLO_library_append_all(Main *mainl, BlendHandle *bh)
}
}
-
-static ID *append_named_part_ex(const bContext *C, Main *mainl, FileData *fd, const char *idname, const int idcode, const int flag)
+static ID *link_named_part_ex(
+ Main *mainl, FileData *fd, const short idcode, const char *name, const short flag,
+ Scene *scene, View3D *v3d)
{
- ID *id= append_named_part(mainl, fd, idname, idcode);
+ ID *id = link_named_part(mainl, fd, idcode, name);
if (id && (GS(id->name) == ID_OB)) { /* loose object: give a base */
- Scene *scene = CTX_data_scene(C); /* can be NULL */
if (scene) {
Base *base;
Object *ob;
-
- base= MEM_callocN(sizeof(Base), "app_nam_part");
+
+ base = MEM_callocN(sizeof(Base), "app_nam_part");
BLI_addtail(&scene->base, base);
-
+
ob = (Object *)id;
-
+
/* link at active layer (view3d if available in context, else scene one */
- if ((flag & FILE_ACTIVELAY)) {
- View3D *v3d = CTX_wm_view3d(C);
+ if (flag & FILE_ACTIVELAY) {
ob->lay = BKE_screen_view3d_layer_active(v3d, scene);
}
-
+
ob->mode = OB_MODE_OBJECT;
base->lay = ob->lay;
base->object = ob;
+ base->flag = ob->flag;
ob->id.us++;
-
+
if (flag & FILE_AUTOSELECT) {
base->flag |= SELECT;
base->object->flag = base->flag;
@@ -9547,47 +9736,91 @@ static ID *append_named_part_ex(const bContext *C, Main *mainl, FileData *fd, co
}
}
else if (id && (GS(id->name) == ID_GR)) {
- /* tag as needing to be instanced */
+ /* tag as needing to be instantiated */
if (flag & FILE_GROUP_INSTANCE)
id->flag |= LIB_DOIT;
}
-
+
return id;
}
-ID *BLO_library_append_named_part(Main *mainl, BlendHandle **bh, const char *idname, const int idcode)
+/**
+ * Link a named datablock from an external blend file.
+ *
+ * \param mainl The main database to link from (not the active one).
+ * \param bh The blender file handle.
+ * \param idcode The kind of datablock to link.
+ * \param name The name of the datablock (without the 2 char ID prefix).
+ * \return the linked ID when found.
+ */
+ID *BLO_library_link_named_part(Main *mainl, BlendHandle **bh, const short idcode, const char *name)
{
FileData *fd = (FileData*)(*bh);
- return append_named_part(mainl, fd, idname, idcode);
+ return link_named_part(mainl, fd, idcode, name);
}
-ID *BLO_library_append_named_part_ex(const bContext *C, Main *mainl, BlendHandle **bh, const char *idname, const int idcode, const short flag)
+/**
+ * Link a named datablock from an external blend file.
+ * Optionally instantiate the object/group in the scene when the flags are set.
+ *
+ * \param mainl The main database to link from (not the active one).
+ * \param bh The blender file handle.
+ * \param idcode The kind of datablock to link.
+ * \param name The name of the datablock (without the 2 char ID prefix).
+ * \param flag Options for linking, used for instantiating.
+ * \param scene The scene in which to instantiate objects/groups (if NULL, no instantiation is done).
+ * \param v3d The active View3D (only to define active layers for instantiated objects & groups, can be NULL).
+ * \return the linked ID when found.
+ */
+ID *BLO_library_link_named_part_ex(
+ Main *mainl, BlendHandle **bh,
+ const short idcode, const char *name, const short flag,
+ Scene *scene, View3D *v3d)
{
FileData *fd = (FileData*)(*bh);
- return append_named_part_ex(C, mainl, fd, idname, idcode, flag);
+ return link_named_part_ex(mainl, fd, idcode, name, flag, scene, v3d);
}
-static void append_id_part(FileData *fd, Main *mainvar, ID *id, ID **r_id)
+static void link_id_part(ReportList *reports, FileData *fd, Main *mainvar, ID *id, ID **r_id)
{
- BHead *bhead = find_bhead_from_idname(fd, id->name);
+ BHead *bhead = NULL;
+
+ if (fd) {
+ bhead = find_bhead_from_idname(fd, id->name);
+ }
+
+ id->flag &= ~LIB_READ;
if (bhead) {
- id->flag &= ~LIB_READ;
id->flag |= LIB_NEED_EXPAND;
// printf("read lib block %s\n", id->name);
read_libblock(fd, mainvar, bhead, id->flag, r_id);
}
+ else {
+ blo_reportf_wrap(
+ reports, RPT_WARNING,
+ TIP_("LIB ERROR: %s: '%s' missing from '%s', parent '%s'"),
+ BKE_idcode_to_name(GS(id->name)),
+ id->name + 2,
+ mainvar->curlib->filepath,
+ library_parent_filepath(mainvar->curlib));
+
+ /* Generate a placeholder for this ID (simplified version of read_libblock actually...). */
+ if (r_id) {
+ *r_id = create_placeholder(mainvar, id->name, id->flag);
+ }
+ }
}
/* common routine to append/link something from a library */
-static Main *library_append_begin(Main *mainvar, FileData **fd, const char *filepath)
+static Main *library_link_begin(Main *mainvar, FileData **fd, const char *filepath)
{
Main *mainl;
(*fd)->mainlist = MEM_callocN(sizeof(ListBase), "FileData.mainlist");
- /* clear for group instancing tag */
+ /* clear for group instantiating tag */
BKE_main_id_tag_listbase(&(mainvar->group), false);
/* make mains */
@@ -9606,77 +9839,72 @@ static Main *library_append_begin(Main *mainvar, FileData **fd, const char *file
return mainl;
}
-Main *BLO_library_append_begin(Main *mainvar, BlendHandle **bh, const char *filepath)
+/**
+ * Initialize the BlendHandle for linking library data.
+ *
+ * \param mainvar The current main database, e.g. G.main or CTX_data_main(C).
+ * \param bh A blender file handle as returned by \a BLO_blendhandle_from_file or \a BLO_blendhandle_from_memory.
+ * \param filepath Used for relative linking, copied to the \a lib->name.
+ * \return the library Main, to be passed to \a BLO_library_append_named_part as \a mainl.
+ */
+Main *BLO_library_link_begin(Main *mainvar, BlendHandle **bh, const char *filepath)
{
FileData *fd = (FileData*)(*bh);
- return library_append_begin(mainvar, &fd, filepath);
+ return library_link_begin(mainvar, &fd, filepath);
}
-
-/* Context == NULL signifies not to do any scene manipulation */
-static void library_append_end(const bContext *C, Main *mainl, FileData **fd, int idcode, short flag)
+/* scene and v3d may be NULL. */
+static void library_link_end(Main *mainl, FileData **fd, const short flag, Scene *scene, View3D *v3d)
{
Main *mainvar;
Library *curlib;
-
+
/* expander now is callback function */
BLO_main_expander(expand_doit_library);
-
+
/* make main consistent */
BLO_expand_main(*fd, mainl);
-
+
/* do this when expand found other libs */
read_libraries(*fd, (*fd)->mainlist);
-
+
curlib = mainl->curlib;
-
+
/* make the lib path relative if required */
if (flag & FILE_RELPATH) {
/* use the full path, this could have been read by other library even */
BLI_strncpy(curlib->name, curlib->filepath, sizeof(curlib->name));
-
+
/* uses current .blend file as reference */
BLI_path_rel(curlib->name, G.main->name);
}
-
+
blo_join_main((*fd)->mainlist);
mainvar = (*fd)->mainlist->first;
MEM_freeN((*fd)->mainlist);
mainl = NULL; /* blo_join_main free's mainl, cant use anymore */
-
+
lib_link_all(*fd, mainvar);
lib_verify_nodetree(mainvar, false);
fix_relpaths_library(G.main->name, mainvar); /* make all relative paths, relative to the open blend file */
-
- if (C) {
- Scene *scene = CTX_data_scene(C);
-
- /* give a base to loose objects. If group append, do it for objects too */
- if (scene) {
- const bool is_link = (flag & FILE_LINK) != 0;
- if (idcode == ID_SCE) {
- /* don't instance anything when linking in scenes, assume the scene its self instances the data */
- }
- else {
- give_base_to_objects(mainvar, scene, curlib, idcode, is_link, flag & FILE_ACTIVELAY);
-
- if (flag & FILE_GROUP_INSTANCE) {
- give_base_to_groups(mainvar, scene);
- }
- }
- }
- else {
- printf("library_append_end, scene is NULL (objects wont get bases)\n");
+
+ /* Give a base to loose objects. If group append, do it for objects too.
+ * Only directly linked objects & groups are instantiated by `BLO_library_link_named_part_ex()` & co,
+ * here we handle indirect ones and other possible edge-cases. */
+ if (scene) {
+ give_base_to_objects(mainvar, scene, v3d, curlib, flag);
+
+ if (flag & FILE_GROUP_INSTANCE) {
+ give_base_to_groups(mainvar, scene, v3d, curlib, flag);
}
}
+ else {
+ /* printf("library_append_end, scene is NULL (objects wont get bases)\n"); */
+ }
- /* clear group instancing tag */
+ /* clear group instantiating tag */
BKE_main_id_tag_listbase(&(mainvar->group), false);
-
- /* has been removed... erm, why? s..ton) */
- /* 20040907: looks like they are give base already in append_named_part(); -Nathan L */
- /* 20041208: put back. It only linked direct, not indirect objects (ton) */
-
+
/* patch to prevent switch_endian happens twice */
if ((*fd)->flags & FD_FLAGS_SWITCH_ENDIAN) {
blo_freefiledata(*fd);
@@ -9684,10 +9912,21 @@ static void library_append_end(const bContext *C, Main *mainl, FileData **fd, in
}
}
-void BLO_library_append_end(const bContext *C, struct Main *mainl, BlendHandle **bh, int idcode, short flag)
+/**
+ * Finalize linking from a given .blend file (library).
+ * Optionally instance the indirect object/group in the scene when the flags are set.
+ * \note Do not use \a bh after calling this function, it may frees it.
+ *
+ * \param mainl The main database to link from (not the active one).
+ * \param bh The blender file handle (WARNING! may be freed by this function!).
+ * \param flag Options for linking, used for instantiating.
+ * \param scene The scene in which to instantiate objects/groups (if NULL, no instantiation is done).
+ * \param v3d The active View3D (only to define active layers for instantiated objects & groups, can be NULL).
+ */
+void BLO_library_link_end(Main *mainl, BlendHandle **bh, short flag, Scene *scene, View3D *v3d)
{
FileData *fd = (FileData*)(*bh);
- library_append_end(C, mainl, &fd, idcode, flag);
+ library_link_end(mainl, &fd, flag, scene, v3d);
*bh = (BlendHandle*)fd;
}
@@ -9815,6 +10054,7 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
}
else {
mainptr->curlib->filedata = NULL;
+ mainptr->curlib->id.flag |= LIB_MISSING;
}
if (fd == NULL) {
@@ -9824,37 +10064,29 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
}
if (fd) {
do_it = true;
- a = set_listbasepointers(mainptr, lbarray);
- while (a--) {
- ID *id = lbarray[a]->first;
-
- while (id) {
- ID *idn = id->next;
- if (id->flag & LIB_READ) {
- ID *realid = NULL;
- BLI_remlink(lbarray[a], id);
-
- append_id_part(fd, mainptr, id, &realid);
- if (!realid) {
- blo_reportf_wrap(
- fd->reports, RPT_WARNING,
- TIP_("LIB ERROR: %s: '%s' missing from '%s', parent '%s'"),
- BKE_idcode_to_name(GS(id->name)),
- id->name + 2,
- mainptr->curlib->filepath,
- library_parent_filepath(mainptr->curlib));
- }
-
- change_idid_adr(mainlist, basefd, id, realid);
-
- MEM_freeN(id);
- }
- id = idn;
+ }
+ a = set_listbasepointers(mainptr, lbarray);
+ while (a--) {
+ ID *id = lbarray[a]->first;
+
+ while (id) {
+ ID *idn = id->next;
+ if (id->flag & LIB_READ) {
+ ID *realid = NULL;
+ BLI_remlink(lbarray[a], id);
+
+ link_id_part(basefd->reports, fd, mainptr, id, &realid);
+
+ BLI_assert(realid != NULL);
+
+ change_idid_adr(mainlist, basefd, id, realid);
+
+ MEM_freeN(id);
}
+ id = idn;
}
-
- BLO_expand_main(fd, mainptr);
}
+ BLO_expand_main(fd, mainptr);
}
mainptr = mainptr->next;
@@ -9862,6 +10094,7 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
}
/* test if there are unread libblocks */
+ /* XXX This code block is kept for 2.77, until we are sure it never gets reached anymore. Can be removed later. */
for (mainptr = mainl->next; mainptr; mainptr = mainptr->next) {
a = set_listbasepointers(mainptr, lbarray);
while (a--) {
@@ -9870,10 +10103,12 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
for (id = lbarray[a]->first; id; id = idn) {
idn = id->next;
if (id->flag & LIB_READ) {
+ BLI_assert(0);
BLI_remlink(lbarray[a], id);
blo_reportf_wrap(
basefd->reports, RPT_WARNING,
- TIP_("LIB ERROR: %s: '%s' unread lib block missing from '%s', parent '%s'"),
+ TIP_("LIB ERROR: %s: '%s' unread lib block missing from '%s', parent '%s' - "
+ "Please file a bug report if you see this message"),
BKE_idcode_to_name(GS(id->name)),
id->name + 2,
mainptr->curlib->filepath,
diff --git a/source/blender/blenloader/intern/readfile.h b/source/blender/blenloader/intern/readfile.h
index ed22daef9ec..f6c3b69c414 100644
--- a/source/blender/blenloader/intern/readfile.h
+++ b/source/blender/blenloader/intern/readfile.h
@@ -96,7 +96,8 @@ typedef struct FileData {
struct GHash *bhead_idname_hash;
ListBase *mainlist;
-
+ ListBase *old_mainlist; /* Used for undo. */
+
/* ick ick, used to return
* data through streamglue.
*/
@@ -139,7 +140,7 @@ void blo_make_sound_pointer_map(FileData *fd, Main *oldmain);
void blo_end_sound_pointer_map(FileData *fd, Main *oldmain);
void blo_make_packed_pointer_map(FileData *fd, Main *oldmain);
void blo_end_packed_pointer_map(FileData *fd, Main *oldmain);
-void blo_add_library_pointer_map(ListBase *mainlist, FileData *fd);
+void blo_add_library_pointer_map(ListBase *old_mainlist, FileData *fd);
void blo_freefiledata(FileData *fd);
diff --git a/source/blender/blenloader/intern/versioning_260.c b/source/blender/blenloader/intern/versioning_260.c
index 0809fc69ba2..f84427d608f 100644
--- a/source/blender/blenloader/intern/versioning_260.c
+++ b/source/blender/blenloader/intern/versioning_260.c
@@ -343,7 +343,7 @@ static void do_versions_mesh_mloopcol_swap_2_62_1(Mesh *me)
if (layer->type == CD_MLOOPCOL) {
mloopcol = (MLoopCol *)layer->data;
for (i = 0; i < me->totloop; i++, mloopcol++) {
- SWAP(char, mloopcol->r, mloopcol->b);
+ SWAP(unsigned char, mloopcol->r, mloopcol->b);
}
}
}
diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c
index c659eaf820b..3bf24d3574f 100644
--- a/source/blender/blenloader/intern/versioning_270.c
+++ b/source/blender/blenloader/intern/versioning_270.c
@@ -767,7 +767,6 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
{
SpaceImage *sima = (SpaceImage *) sl;
sima->iuser.flag |= IMA_SHOW_STEREO;
- sima->iuser.passtype = SCE_PASS_COMBINED;
break;
}
}
@@ -855,6 +854,20 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
#undef BRUSH_TORUS
}
+ if (!MAIN_VERSION_ATLEAST(main, 276, 2)) {
+ if (!DNA_struct_elem_find(fd->filesdna, "bPoseChannel", "float", "custom_scale")) {
+ Object *ob;
+
+ for (ob = main->object.first; ob; ob = ob->id.next) {
+ if (ob->pose) {
+ bPoseChannel *pchan;
+ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ pchan->custom_scale = 1.0f;
+ }
+ }
+ }
+ }
+ }
{
bScreen *screen;
for (screen = main->screen.first; screen; screen = screen->id.next) {
diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c
index 17b0f388af4..c32b3ac51cf 100644
--- a/source/blender/blenloader/intern/versioning_defaults.c
+++ b/source/blender/blenloader/intern/versioning_defaults.c
@@ -160,7 +160,7 @@ void BLO_update_defaults_startup_blend(Main *bmain)
br = (Brush *)BKE_libblock_find_name_ex(bmain, ID_BR, "Fill");
if (!br) {
- br = BKE_brush_add(bmain, "Fill");
+ br = BKE_brush_add(bmain, "Fill", OB_MODE_TEXTURE_PAINT);
br->imagepaint_tool = PAINT_TOOL_FILL;
br->ob_mode = OB_MODE_TEXTURE_PAINT;
}
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index ec18f6a6bdb..eb778048b17 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -291,11 +291,10 @@ static void ww_handle_init(eWriteWrapType ww_type, WriteWrap *r_ww)
typedef struct {
struct SDNA *sdna;
- int file;
unsigned char *buf;
MemFile *compare, *current;
- int tot, count, error, memsize;
+ int tot, count, error;
/* Wrap writing, so we can use zlib or
* other compression types later, see: G_FILE_COMPRESS
@@ -2092,7 +2091,7 @@ static void write_meshes(WriteData *wd, ListBase *idbase)
/* now fill in polys to mfaces */
/* XXX This breaks writing desing, by using temp allocated memory, which will likely generate
- * doublons in stored 'old' addresses.
+ * duplicates in stored 'old' addresses.
* This is very bad, but do not see easy way to avoid this, aside from generating those data
* outside of save process itself.
* Maybe we can live with this, though?
@@ -3704,10 +3703,11 @@ static void write_global(WriteData *wd, int fileflags, Main *mainvar)
* second are an RGBA image (unsigned char)
* note, this uses 'TEST' since new types will segfault on file load for older blender versions.
*/
-static void write_thumb(WriteData *wd, const int *img)
+static void write_thumb(WriteData *wd, const BlendThumbnail *thumb)
{
- if (img)
- writedata(wd, TEST, (2 + img[0] * img[1]) * sizeof(int), img);
+ if (thumb) {
+ writedata(wd, TEST, BLEN_THUMB_MEMSIZE_FILE(thumb->width, thumb->height), thumb);
+ }
}
/* if MemFile * there's filesave to memory */
@@ -3715,7 +3715,7 @@ static int write_file_handle(
Main *mainvar,
WriteWrap *ww,
MemFile *compare, MemFile *current,
- int write_user_block, int write_flags, const int *thumb)
+ int write_user_block, int write_flags, const BlendThumbnail *thumb)
{
BHead bhead;
ListBase mainlist;
@@ -3847,7 +3847,8 @@ static bool do_history(const char *name, ReportList *reports)
}
/* return: success (1) */
-int BLO_write_file(Main *mainvar, const char *filepath, int write_flags, ReportList *reports, const int *thumb)
+int BLO_write_file(
+ Main *mainvar, const char *filepath, int write_flags, ReportList *reports, const BlendThumbnail *thumb)
{
char tempname[FILE_MAX+1];
int err, write_user_block;
diff --git a/source/blender/blentranslation/BLT_translation.h b/source/blender/blentranslation/BLT_translation.h
index 6f24f00acfc..efd59c3fa94 100644
--- a/source/blender/blentranslation/BLT_translation.h
+++ b/source/blender/blentranslation/BLT_translation.h
@@ -106,7 +106,11 @@ const char *BLT_translate_do_new_dataname(const char *msgctxt, const char *msgid
/* Default context for operator names/labels. */
#define BLT_I18NCONTEXT_OPERATOR_DEFAULT "Operator"
-/* Mark the msgid applies to several elements (needed in some cases, as english adjectives have no plural mark. :( */
+/* Context for events/keymaps (necessary, since those often use one or two letters,
+ * easy to get collisions with other areas...). */
+#define BLT_I18NCONTEXT_UI_EVENTS "UI_Events_KeyMaps"
+
+/* Mark the msgid applies to several elements (needed in some cases, as english adjectives have no plural mark :( ). */
#define BLT_I18NCONTEXT_PLURAL "Plural"
/* ID-types contexts. */
@@ -160,6 +164,7 @@ typedef struct {
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_DEFAULT, "default_real"), \
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_DEFAULT_BPYRNA, "default"), \
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "operator_default"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_UI_EVENTS, "ui_events_keymaps"), \
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_PLURAL, "plural"), \
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_ACTION, "id_action"), \
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_ARMATURE, "id_armature"), \
diff --git a/source/blender/blentranslation/intern/blt_lang.c b/source/blender/blentranslation/intern/blt_lang.c
index cd4545275ee..1ad62fa5869 100644
--- a/source/blender/blentranslation/intern/blt_lang.c
+++ b/source/blender/blentranslation/intern/blt_lang.c
@@ -97,7 +97,7 @@ static void fill_locales(void)
BLI_join_dirfile(languages, FILE_MAX, languages_path, "languages");
line = lines = BLI_file_read_as_lines(languages);
- /* This whole "parsing" code is a bit weak, in that it expects strictly formated input file...
+ /* This whole "parsing" code is a bit weak, in that it expects strictly formatted input file...
* Should not be a problem, though, as this file is script-generated! */
/* First loop to find highest locale ID */
diff --git a/source/blender/bmesh/bmesh.h b/source/blender/bmesh/bmesh.h
index 0595a867ac2..78c814af86e 100644
--- a/source/blender/bmesh/bmesh.h
+++ b/source/blender/bmesh/bmesh.h
@@ -57,10 +57,14 @@
*
* \subsection bm_loop The Loop
*
+ * Loops can be thought of as a *face-corner*, since faces don't reference verts or edges directly.
* Each loop connects the face to one of its corner vertices,
* and also references an edge which connects this loop's vertex to the next loop's vertex.
*
- * Loops store several handy pointers:
+ * Loops allow faces to access their verts and edges,
+ * while edges and faces store their loops, allowing access in the opposite direction too.
+ *
+ * Loop pointers:
*
* - BMLoop#v - pointer to the vertex associated with this loop.
* - BMLoop#e - pointer to the edge associated with this loop,
@@ -199,18 +203,6 @@
*
* There may be a better place for this section, but adding here for now.
*
- * \subsection bm_todo_tools Tools
- *
- * Probably most of these will be bmesh operators.
- *
- * - make ngons flat.
- * - solidify (precise mode), keeps even wall thickness, re-creates outlines of offset faces with plane-plane
- * intersections.
- * - split vert (we already have in our API, just no tool).
- * - flip selected region (invert all faces about the plane defined by the selected region outline)
- * - interactive dissolve (like the knife tool but draw over edges to dissolve)
- *
- *
* \subsection bm_todo_optimize Optimizations
*
* - skip normal calc when its not needed (when calling chain of operators & for modifiers, flag as dirty)
@@ -218,11 +210,6 @@
* - ability to call BMO's with option not to create return data (will save some time)
* - binary diff UNDO, currently this uses huge amount of ram when all shapes are stored for each undo step for eg.
* - use two different iterator types for BMO map/buffer types.
- *
- *
- * \subsection bm_todo_tools_enhance Tool Enhancements
- *
- * - vert slide UV correction (like we have for edge slide)
*/
#ifdef __cplusplus
diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c
index 5bb418a5102..e67aa1da340 100644
--- a/source/blender/bmesh/intern/bmesh_core.c
+++ b/source/blender/bmesh/intern/bmesh_core.c
@@ -2016,7 +2016,7 @@ bool BM_vert_splice_check_double(BMVert *v_a, BMVert *v_b)
*
* \return Success
*
- * \warning This does't work for collapsing edges,
+ * \warning This doesn't work for collapsing edges,
* where \a v and \a vtarget are connected by an edge
* (assert checks for this case).
*/
@@ -2395,6 +2395,8 @@ void bmesh_edge_separate(
* Disconnects a face from its vertex fan at loop \a l_sep
*
* \return The newly created BMVert
+ *
+ * \note Will be a no-op and return original vertex if only two edges at that vertex.
*/
BMVert *bmesh_urmv_loop(BMesh *bm, BMLoop *l_sep)
{
@@ -2406,8 +2408,10 @@ BMVert *bmesh_urmv_loop(BMesh *bm, BMLoop *l_sep)
/* peel the face from the edge radials on both sides of the
* loop vert, disconnecting the face from its fan */
- bmesh_edge_separate(bm, l_sep->e, l_sep, false);
- bmesh_edge_separate(bm, l_sep->prev->e, l_sep->prev, false);
+ if (!BM_edge_is_boundary(l_sep->e))
+ bmesh_edge_separate(bm, l_sep->e, l_sep, false);
+ if (!BM_edge_is_boundary(l_sep->prev->e))
+ bmesh_edge_separate(bm, l_sep->prev->e, l_sep->prev, false);
/* do inline, below */
#if 0
diff --git a/source/blender/bmesh/intern/bmesh_marking.c b/source/blender/bmesh/intern/bmesh_marking.c
index 17b6d1d99e7..cd3c8325831 100644
--- a/source/blender/bmesh/intern/bmesh_marking.c
+++ b/source/blender/bmesh/intern/bmesh_marking.c
@@ -102,6 +102,7 @@ static bool bm_vert_is_edge_select_any(const BMVert *v)
}
#endif
+#if 0
static bool bm_edge_is_face_select_any_other(BMLoop *l_first)
{
const BMLoop *l_iter = l_first;
@@ -114,6 +115,7 @@ static bool bm_edge_is_face_select_any_other(BMLoop *l_first)
}
return false;
}
+#endif
#if 0
static bool bm_edge_is_face_select_any(const BMEdge *e)
@@ -498,6 +500,20 @@ void BM_face_select_set(BMesh *bm, BMFace *f, const bool select)
BM_elem_flag_disable(f, BM_ELEM_SELECT);
bm->totfacesel -= 1;
}
+ /**
+ * \note This allows a temporarily invalid state - where for eg
+ * an edge bay be de-selected, but an adjacent face remains selected.
+ *
+ * Rely on #BM_mesh_select_mode_flush to correct these cases.
+ */
+#if 1
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ BM_vert_select_set(bm, l_iter->v, false);
+ BM_edge_select_set(bm, l_iter->e, false);
+ } while ((l_iter = l_iter->next) != l_first);
+#else
+ /* disabled, see T46494 */
/* flush down to edges */
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
@@ -515,6 +531,7 @@ void BM_face_select_set(BMesh *bm, BMFace *f, const bool select)
BM_vert_select_set(bm, l_iter->v, false);
}
} while ((l_iter = l_iter->next) != l_first);
+#endif
}
}
diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c
index 2c4a98b0b7e..9036e882b0b 100644
--- a/source/blender/bmesh/intern/bmesh_mesh.c
+++ b/source/blender/bmesh/intern/bmesh_mesh.c
@@ -1438,6 +1438,24 @@ int BM_mesh_elem_count(BMesh *bm, const char htype)
}
/**
+ * Special case: Python uses custom-data layers to hold PyObject references.
+ * These have to be kept in-place, else the PyObject's we point to, wont point back to us.
+ *
+ * \note ``ele_src`` Is a duplicate, so we don't need to worry about getting in a feedback loop.
+ *
+ * \note If there are other customdata layers which need this functionality, it should be generalized.
+ * However #BM_mesh_remap is currently the only place where this is done.
+ */
+static void bm_mesh_remap_cd_update(
+ BMHeader *ele_dst, BMHeader *ele_src,
+ const int cd_elem_pyptr)
+{
+ void **pyptr_dst_p = BM_ELEM_CD_GET_VOID_P(((BMElem *)ele_dst), cd_elem_pyptr);
+ void **pyptr_src_p = BM_ELEM_CD_GET_VOID_P(((BMElem *)ele_src), cd_elem_pyptr);
+ *pyptr_dst_p = *pyptr_src_p;
+}
+
+/**
* Remaps the vertices, edges and/or faces of the bmesh as indicated by vert/edge/face_idx arrays
* (xxx_idx[org_index] = new_index).
*
@@ -1477,6 +1495,7 @@ void BM_mesh_remap(
BMVert **verts_pool, *verts_copy, **vep;
int i, totvert = bm->totvert;
const unsigned int *new_idx;
+ const int cd_vert_pyptr = CustomData_get_offset(&bm->vdata, CD_BM_ELEM_PYPTR);
/* Init the old-to-new vert pointers mapping */
vptr_map = BLI_ghash_ptr_new_ex("BM_mesh_remap vert pointers mapping", bm->totvert);
@@ -1498,6 +1517,9 @@ void BM_mesh_remap(
*new_vep = *ve;
/* printf("mapping vert from %d to %d (%p/%p to %p)\n", i, *new_idx, *vep, verts_pool[i], new_vep);*/
BLI_ghash_insert(vptr_map, *vep, new_vep);
+ if (cd_vert_pyptr != -1) {
+ bm_mesh_remap_cd_update(&(*vep)->head, &new_vep->head, cd_vert_pyptr);
+ }
}
bm->elem_index_dirty |= BM_VERT;
bm->elem_table_dirty |= BM_VERT;
@@ -1510,6 +1532,7 @@ void BM_mesh_remap(
BMEdge **edges_pool, *edges_copy, **edp;
int i, totedge = bm->totedge;
const unsigned int *new_idx;
+ const int cd_edge_pyptr = CustomData_get_offset(&bm->edata, CD_BM_ELEM_PYPTR);
/* Init the old-to-new vert pointers mapping */
eptr_map = BLI_ghash_ptr_new_ex("BM_mesh_remap edge pointers mapping", bm->totedge);
@@ -1530,6 +1553,9 @@ void BM_mesh_remap(
*new_edp = *ed;
BLI_ghash_insert(eptr_map, *edp, new_edp);
/* printf("mapping edge from %d to %d (%p/%p to %p)\n", i, *new_idx, *edp, edges_pool[i], new_edp);*/
+ if (cd_edge_pyptr != -1) {
+ bm_mesh_remap_cd_update(&(*edp)->head, &new_edp->head, cd_edge_pyptr);
+ }
}
bm->elem_index_dirty |= BM_EDGE;
bm->elem_table_dirty |= BM_EDGE;
@@ -1542,6 +1568,7 @@ void BM_mesh_remap(
BMFace **faces_pool, *faces_copy, **fap;
int i, totface = bm->totface;
const unsigned int *new_idx;
+ const int cd_poly_pyptr = CustomData_get_offset(&bm->pdata, CD_BM_ELEM_PYPTR);
/* Init the old-to-new vert pointers mapping */
fptr_map = BLI_ghash_ptr_new_ex("BM_mesh_remap face pointers mapping", bm->totface);
@@ -1561,6 +1588,9 @@ void BM_mesh_remap(
BMFace *new_fap = faces_pool[*new_idx];
*new_fap = *fa;
BLI_ghash_insert(fptr_map, *fap, new_fap);
+ if (cd_poly_pyptr != -1) {
+ bm_mesh_remap_cd_update(&(*fap)->head, &new_fap->head, cd_poly_pyptr);
+ }
}
bm->elem_index_dirty |= BM_FACE | BM_LOOP;
@@ -1573,8 +1603,11 @@ void BM_mesh_remap(
/* Verts' pointers, only edge pointers... */
if (eptr_map) {
BM_ITER_MESH (ve, &iter, bm, BM_VERTS_OF_MESH) {
-/* printf("Vert e: %p -> %p\n", ve->e, BLI_ghash_lookup(eptr_map, (const void *)ve->e));*/
- ve->e = BLI_ghash_lookup(eptr_map, (const void *)ve->e);
+/* printf("Vert e: %p -> %p\n", ve->e, BLI_ghash_lookup(eptr_map, ve->e));*/
+ if (ve->e) {
+ ve->e = BLI_ghash_lookup(eptr_map, ve->e);
+ BLI_assert(ve->e);
+ }
}
}
@@ -1583,24 +1616,30 @@ void BM_mesh_remap(
if (vptr_map || eptr_map) {
BM_ITER_MESH (ed, &iter, bm, BM_EDGES_OF_MESH) {
if (vptr_map) {
-/* printf("Edge v1: %p -> %p\n", ed->v1, BLI_ghash_lookup(vptr_map, (const void *)ed->v1));*/
-/* printf("Edge v2: %p -> %p\n", ed->v2, BLI_ghash_lookup(vptr_map, (const void *)ed->v2));*/
- ed->v1 = BLI_ghash_lookup(vptr_map, (const void *)ed->v1);
- ed->v2 = BLI_ghash_lookup(vptr_map, (const void *)ed->v2);
+/* printf("Edge v1: %p -> %p\n", ed->v1, BLI_ghash_lookup(vptr_map, ed->v1));*/
+/* printf("Edge v2: %p -> %p\n", ed->v2, BLI_ghash_lookup(vptr_map, ed->v2));*/
+ ed->v1 = BLI_ghash_lookup(vptr_map, ed->v1);
+ ed->v2 = BLI_ghash_lookup(vptr_map, ed->v2);
+ BLI_assert(ed->v1);
+ BLI_assert(ed->v2);
}
if (eptr_map) {
/* printf("Edge v1_disk_link prev: %p -> %p\n", ed->v1_disk_link.prev,*/
-/* BLI_ghash_lookup(eptr_map, (const void *)ed->v1_disk_link.prev));*/
+/* BLI_ghash_lookup(eptr_map, ed->v1_disk_link.prev));*/
/* printf("Edge v1_disk_link next: %p -> %p\n", ed->v1_disk_link.next,*/
-/* BLI_ghash_lookup(eptr_map, (const void *)ed->v1_disk_link.next));*/
+/* BLI_ghash_lookup(eptr_map, ed->v1_disk_link.next));*/
/* printf("Edge v2_disk_link prev: %p -> %p\n", ed->v2_disk_link.prev,*/
-/* BLI_ghash_lookup(eptr_map, (const void *)ed->v2_disk_link.prev));*/
+/* BLI_ghash_lookup(eptr_map, ed->v2_disk_link.prev));*/
/* printf("Edge v2_disk_link next: %p -> %p\n", ed->v2_disk_link.next,*/
-/* BLI_ghash_lookup(eptr_map, (const void *)ed->v2_disk_link.next));*/
- ed->v1_disk_link.prev = BLI_ghash_lookup(eptr_map, (const void *)ed->v1_disk_link.prev);
- ed->v1_disk_link.next = BLI_ghash_lookup(eptr_map, (const void *)ed->v1_disk_link.next);
- ed->v2_disk_link.prev = BLI_ghash_lookup(eptr_map, (const void *)ed->v2_disk_link.prev);
- ed->v2_disk_link.next = BLI_ghash_lookup(eptr_map, (const void *)ed->v2_disk_link.next);
+/* BLI_ghash_lookup(eptr_map, ed->v2_disk_link.next));*/
+ ed->v1_disk_link.prev = BLI_ghash_lookup(eptr_map, ed->v1_disk_link.prev);
+ ed->v1_disk_link.next = BLI_ghash_lookup(eptr_map, ed->v1_disk_link.next);
+ ed->v2_disk_link.prev = BLI_ghash_lookup(eptr_map, ed->v2_disk_link.prev);
+ ed->v2_disk_link.next = BLI_ghash_lookup(eptr_map, ed->v2_disk_link.next);
+ BLI_assert(ed->v1_disk_link.prev);
+ BLI_assert(ed->v1_disk_link.next);
+ BLI_assert(ed->v2_disk_link.prev);
+ BLI_assert(ed->v2_disk_link.next);
}
}
}
@@ -1609,20 +1648,57 @@ void BM_mesh_remap(
BM_ITER_MESH (fa, &iter, bm, BM_FACES_OF_MESH) {
BM_ITER_ELEM (lo, &iterl, fa, BM_LOOPS_OF_FACE) {
if (vptr_map) {
-/* printf("Loop v: %p -> %p\n", lo->v, BLI_ghash_lookup(vptr_map, (const void *)lo->v));*/
- lo->v = BLI_ghash_lookup(vptr_map, (const void *)lo->v);
+/* printf("Loop v: %p -> %p\n", lo->v, BLI_ghash_lookup(vptr_map, lo->v));*/
+ lo->v = BLI_ghash_lookup(vptr_map, lo->v);
+ BLI_assert(lo->v);
}
if (eptr_map) {
-/* printf("Loop e: %p -> %p\n", lo->e, BLI_ghash_lookup(eptr_map, (const void *)lo->e));*/
- lo->e = BLI_ghash_lookup(eptr_map, (const void *)lo->e);
+/* printf("Loop e: %p -> %p\n", lo->e, BLI_ghash_lookup(eptr_map, lo->e));*/
+ lo->e = BLI_ghash_lookup(eptr_map, lo->e);
+ BLI_assert(lo->e);
}
if (fptr_map) {
-/* printf("Loop f: %p -> %p\n", lo->f, BLI_ghash_lookup(fptr_map, (const void *)lo->f));*/
- lo->f = BLI_ghash_lookup(fptr_map, (const void *)lo->f);
+/* printf("Loop f: %p -> %p\n", lo->f, BLI_ghash_lookup(fptr_map, lo->f));*/
+ lo->f = BLI_ghash_lookup(fptr_map, lo->f);
+ BLI_assert(lo->f);
}
}
}
+ /* Selection history */
+ {
+ BMEditSelection *ese;
+ for (ese = bm->selected.first; ese; ese = ese->next) {
+ switch (ese->htype) {
+ case BM_VERT:
+ if (vptr_map) {
+ ese->ele = BLI_ghash_lookup(vptr_map, ese->ele);
+ BLI_assert(ese->ele);
+ }
+ break;
+ case BM_EDGE:
+ if (eptr_map) {
+ ese->ele = BLI_ghash_lookup(eptr_map, ese->ele);
+ BLI_assert(ese->ele);
+ }
+ break;
+ case BM_FACE:
+ if (fptr_map) {
+ ese->ele = BLI_ghash_lookup(fptr_map, ese->ele);
+ BLI_assert(ese->ele);
+ }
+ break;
+ }
+ }
+ }
+
+ if (fptr_map) {
+ if (bm->act_face) {
+ bm->act_face = BLI_ghash_lookup(fptr_map, bm->act_face);
+ BLI_assert(bm->act_face);
+ }
+ }
+
if (vptr_map)
BLI_ghash_free(vptr_map, NULL, NULL);
if (eptr_map)
diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c
index 3e814948ade..f3496b31255 100644
--- a/source/blender/bmesh/intern/bmesh_opdefines.c
+++ b/source/blender/bmesh/intern/bmesh_opdefines.c
@@ -262,7 +262,7 @@ static BMOpDefine bmo_bisect_edges_def = {
/* slots_in */
{{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */
{"cuts", BMO_OP_SLOT_INT}, /* number of cuts */
- {"edge_percents", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_FLT}},
+ {"edge_percents", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_FLT}},
{{'\0'}},
},
/* slots_out */
@@ -322,7 +322,7 @@ static BMOpDefine bmo_find_doubles_def = {
{{'\0'}},
},
/* slots_out */
- {{"targetmap.out", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
+ {{"targetmap.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
{{'\0'}},
},
bmo_find_doubles_exec,
@@ -401,7 +401,7 @@ static BMOpDefine bmo_pointmerge_facedata_def = {
"pointmerge_facedata",
/* slots_in */
{{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */
- {"vert_snap", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE}}, /* snap vertex */
+ {"vert_snap", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | (int)BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE}}, /* snap vertex */
{{'\0'}},
},
{{{'\0'}}}, /* no output */
@@ -474,7 +474,7 @@ static BMOpDefine bmo_weld_verts_def = {
"weld_verts",
/* slots_in */
/* maps welded vertices to verts they should weld to */
- {{"targetmap", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
+ {{"targetmap", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
{{'\0'}},
},
{{{'\0'}}}, /* no output */
@@ -819,8 +819,8 @@ static BMOpDefine bmo_transform_def = {
static BMOpDefine bmo_object_load_bmesh_def = {
"object_load_bmesh",
/* slots_in */
- {{"scene", BMO_OP_SLOT_PTR, {BMO_OP_SLOT_SUBTYPE_PTR_SCENE}},
- {"object", BMO_OP_SLOT_PTR, {BMO_OP_SLOT_SUBTYPE_PTR_OBJECT}},
+ {{"scene", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_SCENE}},
+ {"object", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_OBJECT}},
{{'\0'}},
},
{{{'\0'}}}, /* no output */
@@ -839,9 +839,9 @@ static BMOpDefine bmo_bmesh_to_mesh_def = {
/* slots_in */
{
/* pointer to a mesh structure to fill in */
- {"mesh", BMO_OP_SLOT_PTR, {BMO_OP_SLOT_SUBTYPE_PTR_MESH}},
+ {"mesh", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_MESH}},
/* pointer to an object structure */
- {"object", BMO_OP_SLOT_PTR, {BMO_OP_SLOT_SUBTYPE_PTR_OBJECT}},
+ {"object", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_OBJECT}},
{"skip_tessface", BMO_OP_SLOT_BOOL}, /* don't calculate mfaces */
{{'\0'}},
},
@@ -861,9 +861,9 @@ static BMOpDefine bmo_mesh_to_bmesh_def = {
/* slots_in */
{
/* pointer to a Mesh structure */
- {"mesh", BMO_OP_SLOT_PTR, {BMO_OP_SLOT_SUBTYPE_PTR_MESH}},
+ {"mesh", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_MESH}},
/* pointer to an Object structure */
- {"object", BMO_OP_SLOT_PTR, {BMO_OP_SLOT_SUBTYPE_PTR_OBJECT}},
+ {"object", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_OBJECT}},
{"use_shapekey", BMO_OP_SLOT_BOOL}, /* load active shapekey coordinates into verts */
{{'\0'}},
},
@@ -1035,7 +1035,7 @@ static BMOpDefine bmo_extrude_face_region_def = {
"extrude_face_region",
/* slots_in */
{{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* edges and faces */
- {"edges_exclude", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_EMPTY}},
+ {"edges_exclude", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_EMPTY}},
{"use_keep_orig", BMO_OP_SLOT_BOOL}, /* keep original geometry */
{"use_select_history", BMO_OP_SLOT_BOOL}, /* pass to duplicate */
{{'\0'}},
@@ -1170,7 +1170,7 @@ static BMOpDefine bmo_triangulate_def = {
/* slots_out */
{{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}},
{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},
- {"face_map.out", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
+ {"face_map.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
{{'\0'}},
},
bmo_triangulate_exec,
@@ -1215,8 +1215,8 @@ static BMOpDefine bmo_subdivide_edges_def = {
{"along_normal", BMO_OP_SLOT_FLT},
{"cuts", BMO_OP_SLOT_INT},
{"seed", BMO_OP_SLOT_INT},
- {"custom_patterns", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL}}, /* uses custom pointers */
- {"edge_percents", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_FLT}},
+ {"custom_patterns", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL}}, /* uses custom pointers */
+ {"edge_percents", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_FLT}},
{"quad_corner_type", BMO_OP_SLOT_INT}, /* quad corner type, see bmesh_operators.h */
{"use_grid_fill", BMO_OP_SLOT_BOOL}, /* fill in fully-selected faces with a grid */
@@ -1322,7 +1322,7 @@ static BMOpDefine bmo_duplicate_def = {
/* slots_in */
{{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
/* destination bmesh, if NULL will use current on */
- {"dest", BMO_OP_SLOT_PTR, {BMO_OP_SLOT_SUBTYPE_PTR_BMESH}},
+ {"dest", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_BMESH}},
{"use_select_history", BMO_OP_SLOT_BOOL},
{{'\0'}},
},
@@ -1331,11 +1331,11 @@ static BMOpDefine bmo_duplicate_def = {
{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
/* facemap maps from source faces to dupe
* faces, and from dupe faces to source faces */
- {"vert_map.out", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
- {"edge_map.out", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
- {"face_map.out", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
- {"boundary_map.out", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
- {"isovert_map.out", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
+ {"vert_map.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
+ {"edge_map.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
+ {"face_map.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
+ {"boundary_map.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
+ {"isovert_map.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
{{'\0'}},
},
bmo_duplicate_exec,
@@ -1354,14 +1354,14 @@ static BMOpDefine bmo_split_def = {
/* slots_in */
{{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
/* destination bmesh, if NULL will use current one */
- {"dest", BMO_OP_SLOT_PTR, {BMO_OP_SLOT_SUBTYPE_PTR_BMESH}},
+ {"dest", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_BMESH}},
{"use_only_faces", BMO_OP_SLOT_BOOL}, /* when enabled. don't duplicate loose verts/edges */
{{'\0'}},
},
/* slots_out */
{{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
- {"boundary_map.out", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
- {"isovert_map.out", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
+ {"boundary_map.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
+ {"isovert_map.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
{{'\0'}},
},
bmo_split_exec,
diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c
index 09284ea3549..1a8ea1e3a0d 100644
--- a/source/blender/bmesh/intern/bmesh_queries.c
+++ b/source/blender/bmesh/intern/bmesh_queries.c
@@ -317,7 +317,7 @@ float BM_loop_point_side_of_loop_test(const BMLoop *l, const float co[3])
* Check if a point is inside the edge defined by a loop
* (within the plane defined by the loops edge & face normal).
*
- * \return signed, squared distablce to the edge plane, less than 0.0 when outside.
+ * \return signed, squared distance to the edge plane, less than 0.0 when outside.
*/
float BM_loop_point_side_of_edge_test(const BMLoop *l, const float co[3])
{
diff --git a/source/blender/bmesh/operators/bmo_extrude.c b/source/blender/bmesh/operators/bmo_extrude.c
index 435b9e60949..3eae98b3c46 100644
--- a/source/blender/bmesh/operators/bmo_extrude.c
+++ b/source/blender/bmesh/operators/bmo_extrude.c
@@ -137,7 +137,7 @@ void bmo_extrude_discrete_faces_exec(BMesh *bm, BMOperator *op)
* This function won't crash if its not but won't work right either.
* \a e_b is the new edge.
*
- * \note The edge this face comes from needs to be from the first and second verts fo the face.
+ * \note The edge this face comes from needs to be from the first and second verts to the face.
* The caller must ensure this else we will copy from the wrong source.
*/
static void bm_extrude_copy_face_loop_attributes(BMesh *bm, BMFace *f)
@@ -728,9 +728,9 @@ static void solidify_add_thickness(BMesh *bm, const float dist)
if (BMO_elem_flag_test(bm, f, FACE_MARK)) {
/* array for passing verts to angle_poly_v3 */
- float *face_angles = BLI_buffer_resize_data(&face_angles_buf, float, f->len);
+ float *face_angles = BLI_buffer_reinit_data(&face_angles_buf, float, f->len);
/* array for receiving angles from angle_poly_v3 */
- float **verts = BLI_buffer_resize_data(&verts_buf, float *, f->len);
+ float **verts = BLI_buffer_reinit_data(&verts_buf, float *, f->len);
BM_ITER_ELEM_INDEX (l, &loopIter, f, BM_LOOPS_OF_FACE, i) {
verts[i] = l->v->co;
diff --git a/source/blender/bmesh/operators/bmo_inset.c b/source/blender/bmesh/operators/bmo_inset.c
index 6664bf6dc46..118a19d3082 100644
--- a/source/blender/bmesh/operators/bmo_inset.c
+++ b/source/blender/bmesh/operators/bmo_inset.c
@@ -208,14 +208,11 @@ static void bm_loop_customdata_merge(
*/
const void *data_src;
- CustomData_data_add(
+ CustomData_data_mix_value(
type,
BM_ELEM_CD_GET_VOID_P(l_a_inner_inset, offset),
- BM_ELEM_CD_GET_VOID_P(l_b_inner_inset, offset));
- CustomData_data_multiply(
- type,
- BM_ELEM_CD_GET_VOID_P(l_a_inner_inset, offset),
- 0.5f);
+ BM_ELEM_CD_GET_VOID_P(l_b_inner_inset, offset),
+ CDT_MIX_MIX, 0.5f);
CustomData_data_copy_value(
type,
BM_ELEM_CD_GET_VOID_P(l_a_inner_inset, offset),
diff --git a/source/blender/bmesh/operators/bmo_planar_faces.c b/source/blender/bmesh/operators/bmo_planar_faces.c
index 4e3ac58a813..2856d3d18a6 100644
--- a/source/blender/bmesh/operators/bmo_planar_faces.c
+++ b/source/blender/bmesh/operators/bmo_planar_faces.c
@@ -21,7 +21,7 @@
/** \file blender/bmesh/operators/bmo_planar_faces.c
* \ingroup bmesh
*
- * Iternatively flatten 4+ sided faces.
+ * Iteratively flatten 4+ sided faces.
*/
#include "MEM_guardedalloc.h"
@@ -117,7 +117,7 @@ void bmo_planar_faces_exec(BMesh *bm, BMOperator *op)
}
va = *va_p;
- closest_to_plane_v3(co, plane, l_iter->v->co);
+ closest_to_plane_normalized_v3(co, plane, l_iter->v->co);
va->co_tot += 1;
interp_v3_v3v3(va->co, va->co, co, 1.0f / (float)va->co_tot);
diff --git a/source/blender/bmesh/operators/bmo_subdivide.c b/source/blender/bmesh/operators/bmo_subdivide.c
index 45e3c8d193d..38fa2cfdcc8 100644
--- a/source/blender/bmesh/operators/bmo_subdivide.c
+++ b/source/blender/bmesh/operators/bmo_subdivide.c
@@ -163,6 +163,85 @@ static BMEdge *connect_smallest_face(BMesh *bm, BMVert *v_a, BMVert *v_b, BMFace
return NULL;
}
+
+/**
+ * Specialized slerp that uses a sphere defined by each points normal.
+ */
+static void interp_slerp_co_no_v3(
+ const float co_a[3], const float no_a[3],
+ const float co_b[3], const float no_b[3],
+ const float no_dir[3], /* caller already knows, avoid normalize */
+ float fac,
+ float r_co[3])
+{
+ /* center of the sphere defined by both normals */
+ float center[3];
+
+ BLI_assert(len_squared_v3v3(no_a, no_b) != 0);
+
+ /* calculate sphere 'center' */
+ {
+ /* use point on plane to */
+ float plane_a[4], plane_b[4], plane_c[4];
+ float no_mid[3], no_ortho[3];
+ /* pass this as an arg instead */
+#if 0
+ float no_dir[3];
+#endif
+
+ float v_a_no_ortho[3], v_b_no_ortho[3];
+
+ add_v3_v3v3(no_mid, no_a, no_b);
+ normalize_v3(no_mid);
+
+#if 0
+ sub_v3_v3v3(no_dir, co_a, co_b);
+ normalize_v3(no_dir);
+#endif
+
+ /* axis of slerp */
+ cross_v3_v3v3(no_ortho, no_mid, no_dir);
+ normalize_v3(no_ortho);
+
+ /* create planes */
+ cross_v3_v3v3(v_a_no_ortho, no_ortho, no_a);
+ cross_v3_v3v3(v_b_no_ortho, no_ortho, no_b);
+ project_v3_plane(v_a_no_ortho, no_ortho, v_a_no_ortho);
+ project_v3_plane(v_b_no_ortho, no_ortho, v_b_no_ortho);
+
+ plane_from_point_normal_v3(plane_a, co_a, v_a_no_ortho);
+ plane_from_point_normal_v3(plane_b, co_b, v_b_no_ortho);
+ plane_from_point_normal_v3(plane_c, co_b, no_ortho);
+
+ /* find the sphere center from 3 planes */
+ if (isect_plane_plane_plane_v3(plane_a, plane_b, plane_c, center)) {
+ /* pass */
+ }
+ else {
+ mid_v3_v3v3(center, co_a, co_b);
+ }
+ }
+
+ /* calculate the final output 'r_co' */
+ {
+ float ofs_a[3], ofs_b[3], ofs_slerp[3];
+ float dist_a, dist_b;
+
+ sub_v3_v3v3(ofs_a, co_a, center);
+ sub_v3_v3v3(ofs_b, co_b, center);
+
+ dist_a = normalize_v3(ofs_a);
+ dist_b = normalize_v3(ofs_b);
+
+ if (interp_v3_v3v3_slerp(ofs_slerp, ofs_a, ofs_b, fac)) {
+ madd_v3_v3v3fl(r_co, center, ofs_slerp, interpf(dist_b, dist_a, fac));
+ }
+ else {
+ interp_v3_v3v3(r_co, co_a, co_b, fac);
+ }
+ }
+}
+
/* calculates offset for co, based on fractal, sphere or smooth settings */
static void alter_co(
BMVert *v, BMEdge *UNUSED(e_orig),
@@ -179,32 +258,72 @@ static void alter_co(
mul_v3_fl(co, params->smooth);
}
else if (params->use_smooth) {
- /* we calculate an offset vector vec1[], to be added to *co */
- float dir[3], tvec[3];
- float fac, len, val;
+ /* calculating twice and blending gives smoother results,
+ * removing visible seams. */
+#define USE_SPHERE_DUAL_BLEND
- sub_v3_v3v3(dir, v_a->co, v_b->co);
- len = (float)M_SQRT1_2 * normalize_v3(dir);
+ const float eps_unit_vec = 1e-5f;
+ float smooth;
+ float no_dir[3];
- /* cosine angle */
- fac = dot_v3v3(dir, v_a->no);
- mul_v3_v3fl(tvec, v_a->no, fac);
+#ifdef USE_SPHERE_DUAL_BLEND
+ float no_reflect[3], co_a[3], co_b[3];
+#endif
- /* cosine angle */
- fac = -dot_v3v3(dir, v_b->no);
- madd_v3_v3fl(tvec, v_b->no, fac);
+ sub_v3_v3v3(no_dir, v_a->co, v_b->co);
+ normalize_v3(no_dir);
- /* falloff for multi subdivide */
- val = fabsf(1.0f - 2.0f * fabsf(0.5f - perc));
- val = bmesh_subd_falloff_calc(params->smooth_falloff, val);
+#ifndef USE_SPHERE_DUAL_BLEND
+ if (len_squared_v3v3(v_a->no, v_b->no) < eps_unit_vec) {
+ interp_v3_v3v3(co, v_a->co, v_b->co, perc);
+ }
+ else {
+ interp_slerp_co_no_v3(v_a->co, v_a->no, v_b->co, v_b->no, no_dir, perc, co);
+ }
+#else
+ /* sphere-a */
+ reflect_v3_v3v3(no_reflect, v_a->no, no_dir);
+ if (len_squared_v3v3(v_a->no, no_reflect) < eps_unit_vec) {
+ interp_v3_v3v3(co_a, v_a->co, v_b->co, perc);
+ }
+ else {
+ interp_slerp_co_no_v3(v_a->co, v_a->no, v_b->co, no_reflect, no_dir, perc, co_a);
+ }
+
+ /* sphere-b */
+ reflect_v3_v3v3(no_reflect, v_b->no, no_dir);
+ if (len_squared_v3v3(v_b->no, no_reflect) < eps_unit_vec) {
+ interp_v3_v3v3(co_b, v_a->co, v_b->co, perc);
+ }
+ else {
+ interp_slerp_co_no_v3(v_a->co, no_reflect, v_b->co, v_b->no, no_dir, perc, co_b);
+ }
+
+ /* blend both spheres */
+ interp_v3_v3v3(co, co_a, co_b, perc);
+#endif /* USE_SPHERE_DUAL_BLEND */
+
+ /* apply falloff */
+ if (params->smooth_falloff == SUBD_FALLOFF_LIN) {
+ smooth = 1.0f;
+ }
+ else {
+ smooth = fabsf(1.0f - 2.0f * fabsf(0.5f - perc));
+ smooth = 1.0f + bmesh_subd_falloff_calc(params->smooth_falloff, smooth);
+ }
if (params->use_smooth_even) {
- val *= shell_v3v3_mid_normalized_to_dist(v_a->no, v_b->no);
+ smooth *= shell_v3v3_mid_normalized_to_dist(v_a->no, v_b->no);
}
- mul_v3_fl(tvec, params->smooth * val * len);
+ smooth *= params->smooth;
+ if (smooth != 1.0f) {
+ float co_flat[3];
+ interp_v3_v3v3(co_flat, v_a->co, v_b->co, perc);
+ interp_v3_v3v3(co, co_flat, co, smooth);
+ }
- add_v3_v3(co, tvec);
+#undef USE_SPHERE_DUAL_BLEND
}
if (params->use_fractal) {
diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c
index e20d4e61d01..5a7788c0b62 100644
--- a/source/blender/bmesh/tools/bmesh_bevel.c
+++ b/source/blender/bmesh/tools/bmesh_bevel.c
@@ -348,7 +348,7 @@ static EdgeHalf *next_bev(BevVert *bv, EdgeHalf *from_e)
/* Return a good representative face (for materials, etc.) for faces
* created around/near BoundVert v.
* Sometimes care about a second choice, if there is one.
- * If r_fother paramenter is non-NULL and there is another, different,
+ * If r_fother parameter is non-NULL and there is another, different,
* possible frep, return the other one in that parameter. */
static BMFace *boundvert_rep_face(BoundVert *v, BMFace **r_fother)
{
@@ -823,7 +823,7 @@ static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f, bool e
if (!ff)
continue;
plane_from_point_normal_v3(plane, v->co, ff->no);
- closest_to_plane_v3(dropco, plane, meetco);
+ closest_to_plane_normalized_v3(dropco, plane, meetco);
if (point_between_edges(dropco, v, ff, e, e->next)) {
copy_v3_v3(meetco, dropco);
break;
@@ -2947,7 +2947,7 @@ static void bevel_build_rings(BevelParams *bp, BMesh *bm, BevVert *bv)
BLI_array_append(ve, v == vm->boundstart ? NULL : frep_e);
}
else {
- BLI_array_append(vf, frep);
+ BLI_array_append(vf, boundvert_rep_face(v, NULL));
BLI_array_append(ve, NULL);
}
} while ((v = v->next) != vm->boundstart);
@@ -4032,7 +4032,7 @@ static float find_superellipse_chord_u(float u0, float d2goal, float r)
* Return the u's in *r_params, which should point to an array of size n+1. */
static void find_even_superellipse_params(int n, float r, float *r_params)
{
- float d2low, d2high, d2, d2final, u;
+ float d2low, d2high, d2 = 0.0f, d2final, u;
int i, j, n2;
const int maxiters = 40;
const float d2tol = 1e-6f;
diff --git a/source/blender/bmesh/tools/bmesh_intersect.c b/source/blender/bmesh/tools/bmesh_intersect.c
index 169ad49195c..19cf2d29aff 100644
--- a/source/blender/bmesh/tools/bmesh_intersect.c
+++ b/source/blender/bmesh/tools/bmesh_intersect.c
@@ -1000,7 +1000,7 @@ bool BM_mesh_intersect(
if (BM_vert_in_edge(e, v_prev)) {
v_prev = BM_edge_split(bm, e, v_prev, NULL, CLAMPIS(fac, 0.0f, 1.0f));
- BLI_assert( BM_vert_in_edge(e, v_end));
+ BLI_assert(BM_vert_in_edge(e, v_end));
if (!BM_edge_exists(v_prev, vi) &&
!BM_vert_splice_check_double(v_prev, vi) &&
@@ -1017,6 +1017,7 @@ bool BM_mesh_intersect(
}
}
}
+ UNUSED_VARS_NDEBUG(v_end);
}
}
#endif
diff --git a/source/blender/collada/AnimationImporter.cpp b/source/blender/collada/AnimationImporter.cpp
index e5f7bb2eb89..1bcf51f9d1f 100644
--- a/source/blender/collada/AnimationImporter.cpp
+++ b/source/blender/collada/AnimationImporter.cpp
@@ -153,15 +153,13 @@ void AnimationImporter::animation_to_fcurves(COLLADAFW::AnimationCurve *curve)
calchandles_fcurve(fcu);
fcurves.push_back(fcu);
+ unused_curves.push_back(fcu);
}
}
break;
default:
fprintf(stderr, "Output dimension of %d is not yet supported (animation id = %s)\n", (int)dim, curve->getOriginalId().c_str());
}
-
- for (std::vector<FCurve *>::iterator it = fcurves.begin(); it != fcurves.end(); it++)
- unused_curves.push_back(*it);
}
@@ -175,6 +173,11 @@ void AnimationImporter::fcurve_deg_to_rad(FCurve *cu)
}
}
+void AnimationImporter::fcurve_is_used(FCurve *fcu)
+{
+ unused_curves.erase(std::remove(unused_curves.begin(), unused_curves.end(), fcu), unused_curves.end());
+}
+
void AnimationImporter::add_fcurves_to_object(Object *ob, std::vector<FCurve *>& curves, char *rna_path, int array_index, Animation *animated)
{
@@ -225,6 +228,7 @@ void AnimationImporter::add_fcurves_to_object(Object *ob, std::vector<FCurve *>&
/* add F-Curve to group */
action_groups_add_channel(act, grp, fcu);
+ fcurve_is_used(fcu);
}
#if 0
@@ -235,10 +239,8 @@ void AnimationImporter::add_fcurves_to_object(Object *ob, std::vector<FCurve *>&
}
else {
BLI_addtail(&act->curves, fcu);
+ fcurve_is_used(fcu);
}
-
- // curve is used, so remove it from unused_curves
- unused_curves.erase(std::remove(unused_curves.begin(), unused_curves.end(), fcu), unused_curves.end());
}
}
@@ -438,7 +440,7 @@ void AnimationImporter::modify_fcurve(std::vector<FCurve *> *curves, const char
if (array_index == -1) fcu->array_index = i;
else fcu->array_index = array_index;
- unused_curves.erase(std::remove(unused_curves.begin(), unused_curves.end(), fcu), unused_curves.end());
+ fcurve_is_used(fcu);
}
}
@@ -448,7 +450,7 @@ void AnimationImporter::unused_fcurve(std::vector<FCurve *> *curves)
std::vector<FCurve *>::iterator it;
for (it = curves->begin(); it != curves->end(); it++) {
FCurve *fcu = *it;
- unused_curves.erase(std::remove(unused_curves.begin(), unused_curves.end(), fcu), unused_curves.end());
+ fcurve_is_used(fcu);
}
}
@@ -621,6 +623,7 @@ void AnimationImporter:: Assign_color_animations(const COLLADAFW::UniqueId& list
for (iter = animcurves.begin(); iter != animcurves.end(); iter++) {
FCurve *fcu = *iter;
BLI_addtail(AnimCurves, fcu);
+ fcurve_is_used(fcu);
}
}
@@ -660,6 +663,7 @@ void AnimationImporter:: Assign_float_animations(const COLLADAFW::UniqueId& list
/** XXX What About animtype "rotation" ? */
BLI_addtail(AnimCurves, fcu);
+ fcurve_is_used(fcu);
}
}
}
@@ -705,6 +709,7 @@ void AnimationImporter::Assign_lens_animations(const COLLADAFW::UniqueId& listid
}
BLI_addtail(AnimCurves, fcu);
+ fcurve_is_used(fcu);
}
}
}
@@ -840,8 +845,10 @@ void AnimationImporter::apply_matrix_curves(Object *ob, std::vector<FCurve *>& a
add_bone_fcurve(ob, node, newcu[i]);
else
BLI_addtail(curves, newcu[i]);
+ // fcurve_is_used(newcu[i]); // never added to unused
}
+
if (is_joint) {
bPoseChannel *chan = BKE_pose_channel_find_name(ob->pose, bone_name);
chan->rotmode = ROT_MODE_QUAT;
@@ -891,8 +898,6 @@ void AnimationImporter::translate_Animations(COLLADAFW::Node *node,
std::multimap<COLLADAFW::UniqueId, Object *>& object_map,
std::map<COLLADAFW::UniqueId, const COLLADAFW::Object *> FW_object_map)
{
- AnimationImporter::AnimMix *animType = get_animation_type(node, FW_object_map);
-
bool is_joint = node->getType() == COLLADAFW::Node::JOINT;
COLLADAFW::UniqueId uid = node->getUniqueId();
COLLADAFW::Node *root = root_map.find(uid) == root_map.end() ? node : root_map[uid];
@@ -908,6 +913,8 @@ void AnimationImporter::translate_Animations(COLLADAFW::Node *node,
return;
}
+
+ AnimationImporter::AnimMix *animType = get_animation_type(node, FW_object_map);
bAction *act;
if ( (animType->transform) != 0) {
@@ -966,6 +973,7 @@ void AnimationImporter::translate_Animations(COLLADAFW::Node *node,
FCurve *fcu = *iter;
BLI_addtail(AnimCurves, fcu);
+ fcurve_is_used(fcu);
}
}
@@ -1108,6 +1116,8 @@ void AnimationImporter::translate_Animations(COLLADAFW::Node *node,
}
}
}
+
+ delete animType;
}
void AnimationImporter::add_bone_animation_sampled(Object *ob, std::vector<FCurve *>& animcurves, COLLADAFW::Node *root, COLLADAFW::Node *node, COLLADAFW::Transformation *tm)
@@ -1233,6 +1243,7 @@ void AnimationImporter::add_bone_animation_sampled(Object *ob, std::vector<FCurv
// add curves
for (int i = 0; i < totcu; i++) {
add_bone_fcurve(ob, node, newcu[i]);
+ // fcurve_is_used(newcu[i]); // never added to unused
}
bPoseChannel *chan = BKE_pose_channel_find_name(ob->pose, bone_name);
@@ -1832,7 +1843,7 @@ bool AnimationImporter::evaluate_animation(COLLADAFW::Transformation *tm, float
i++;
j = 0;
}
- unused_curves.erase(std::remove(unused_curves.begin(), unused_curves.end(), *it), unused_curves.end());
+ fcurve_is_used(*it);
}
COLLADAFW::Matrix tm(matrix);
diff --git a/source/blender/collada/AnimationImporter.h b/source/blender/collada/AnimationImporter.h
index 565fe183d02..15dee8ff5f4 100644
--- a/source/blender/collada/AnimationImporter.h
+++ b/source/blender/collada/AnimationImporter.h
@@ -85,7 +85,10 @@ private:
void fcurve_deg_to_rad(FCurve *cu);
+ void fcurve_is_used(FCurve *fcu);
+
void add_fcurves_to_object(Object *ob, std::vector<FCurve*>& curves, char *rna_path, int array_index, Animation *animated);
+
int typeFlag;
diff --git a/source/blender/collada/ArmatureImporter.cpp b/source/blender/collada/ArmatureImporter.cpp
index 6ddce75ec33..fd08e1ebfab 100644
--- a/source/blender/collada/ArmatureImporter.cpp
+++ b/source/blender/collada/ArmatureImporter.cpp
@@ -255,9 +255,13 @@ void ArmatureImporter::connect_bone_chains(bArmature *armature, Bone *parentbone
{
BoneExtended *dominant_child = NULL;
int maxlen = 0;
- Bone *child = (Bone *)parentbone->childbase.first;
- if (child && (import_settings->find_chains || child->next==NULL) )
- {
+ Bone *child;
+
+ if (parentbone == NULL)
+ return;
+
+ child = (Bone *)parentbone->childbase.first;
+ if (child && (import_settings->find_chains || child->next==NULL)) {
for (; child; child = child->next) {
BoneExtended *be = extended_bones[child->name];
if (be != NULL) {
diff --git a/source/blender/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp
index 0aff5147060..674a79f0fe7 100644
--- a/source/blender/collada/DocumentImporter.cpp
+++ b/source/blender/collada/DocumentImporter.cpp
@@ -136,11 +136,14 @@ bool DocumentImporter::import()
const std::string encodedFilename = bc_url_encode(mFilename);
if (!root.loadDocument(encodedFilename)) {
fprintf(stderr, "COLLADAFW::Root::loadDocument() returned false on 1st pass\n");
+ delete ehandler;
return false;
}
- if (errorHandler.hasError())
+ if (errorHandler.hasError()) {
+ delete ehandler;
return false;
+ }
/** TODO set up scene graph and such here */
@@ -151,10 +154,10 @@ bool DocumentImporter::import()
if (!root2.loadDocument(encodedFilename)) {
fprintf(stderr, "COLLADAFW::Root::loadDocument() returned false on 2nd pass\n");
+ delete ehandler;
return false;
}
-
-
+
delete ehandler;
return true;
@@ -223,6 +226,7 @@ void DocumentImporter::finish()
for (unsigned int i = 0; i < roots.getCount(); i++) {
std::vector<Object *> *objects_done = write_node(roots[i], NULL, sce, NULL, false);
objects_to_scale->insert(objects_to_scale->end(), objects_done->begin(), objects_done->end());
+ delete objects_done;
}
// update scene
@@ -275,6 +279,8 @@ void DocumentImporter::finish()
}
bc_match_scale(objects_to_scale, unit_converter, !this->import_settings->import_units);
+
+ delete objects_to_scale;
}
@@ -499,6 +505,9 @@ std::vector<Object *> *DocumentImporter::write_node(COLLADAFW::Node *node, COLLA
std::string id = node->getOriginalId();
std::string name = node->getName();
+ // if node has child nodes write them
+ COLLADAFW::NodePointerArray &child_nodes = node->getChildNodes();
+
std::vector<Object *> *objects_done = new std::vector<Object *>();
std::vector<Object *> *root_objects = new std::vector<Object *>();
@@ -524,7 +533,7 @@ std::vector<Object *> *DocumentImporter::write_node(COLLADAFW::Node *node, COLLA
if (parent_node == NULL) {
// for skeletons without root node all has been done above.
// Skeletons with root node are handled further down.
- return root_objects;
+ goto finally;
}
}
else {
@@ -638,7 +647,9 @@ std::vector<Object *> *DocumentImporter::write_node(COLLADAFW::Node *node, COLLA
// XXX: if there're multiple instances, only one is stored
- if (!ob) return root_objects;
+ if (!ob) {
+ goto finally;
+ }
for (std::vector<Object *>::iterator it = objects_done->begin(); it != objects_done->end(); ++it) {
ob = *it;
@@ -673,9 +684,6 @@ std::vector<Object *> *DocumentImporter::write_node(COLLADAFW::Node *node, COLLA
}
}
- // if node has child nodes write them
- COLLADAFW::NodePointerArray &child_nodes = node->getChildNodes();
-
if (objects_done->size() > 0) {
ob = *objects_done->begin();
}
@@ -684,9 +692,15 @@ std::vector<Object *> *DocumentImporter::write_node(COLLADAFW::Node *node, COLLA
}
for (unsigned int i = 0; i < child_nodes.getCount(); i++) {
- write_node(child_nodes[i], node, sce, ob, is_library_node);
+ std::vector<Object *> *child_objects;
+ child_objects = write_node(child_nodes[i], node, sce, ob, is_library_node);
+ delete child_objects;
}
+
+finally:
+ delete objects_done;
+
return root_objects;
}
@@ -725,7 +739,9 @@ bool DocumentImporter::writeLibraryNodes(const COLLADAFW::LibraryNodes *libraryN
const COLLADAFW::NodePointerArray& nodes = libraryNodes->getNodes();
for (unsigned int i = 0; i < nodes.getCount(); i++) {
- write_node(nodes[i], NULL, sce, NULL, true);
+ std::vector<Object *> *child_objects;
+ child_objects = write_node(nodes[i], NULL, sce, NULL, true);
+ delete child_objects;
}
return true;
diff --git a/source/blender/compositor/intern/COM_CompositorContext.h b/source/blender/compositor/intern/COM_CompositorContext.h
index d7ec653f480..3cc6e9d4ac8 100644
--- a/source/blender/compositor/intern/COM_CompositorContext.h
+++ b/source/blender/compositor/intern/COM_CompositorContext.h
@@ -24,7 +24,6 @@
#define _COM_CompositorContext_h
#include <vector>
-#include "BKE_text.h"
#include <string>
#include "DNA_node_types.h"
#include "DNA_color_types.h"
diff --git a/source/blender/compositor/intern/COM_ExecutionGroup.cpp b/source/blender/compositor/intern/COM_ExecutionGroup.cpp
index 5cb757d7dcb..184c381f42a 100644
--- a/source/blender/compositor/intern/COM_ExecutionGroup.cpp
+++ b/source/blender/compositor/intern/COM_ExecutionGroup.cpp
@@ -40,7 +40,6 @@
#include "MEM_guardedalloc.h"
#include "BLI_math.h"
#include "BLI_string.h"
-#include "BKE_global.h"
#include "PIL_time.h"
#include "WM_api.h"
#include "WM_types.h"
diff --git a/source/blender/compositor/intern/COM_ExecutionSystem.cpp b/source/blender/compositor/intern/COM_ExecutionSystem.cpp
index caeaa07d9f9..143528e68b1 100644
--- a/source/blender/compositor/intern/COM_ExecutionSystem.cpp
+++ b/source/blender/compositor/intern/COM_ExecutionSystem.cpp
@@ -36,8 +36,6 @@ extern "C" {
#include "COM_ReadBufferOperation.h"
#include "COM_Debug.h"
-#include "BKE_global.h"
-
#ifdef WITH_CXX_GUARDEDALLOC
#include "MEM_guardedalloc.h"
#endif
diff --git a/source/blender/compositor/intern/COM_MemoryBuffer.cpp b/source/blender/compositor/intern/COM_MemoryBuffer.cpp
index 2dbf0a6aa46..7ee5e2f7c57 100644
--- a/source/blender/compositor/intern/COM_MemoryBuffer.cpp
+++ b/source/blender/compositor/intern/COM_MemoryBuffer.cpp
@@ -195,59 +195,30 @@ void MemoryBuffer::addPixel(int x, int y, const float color[4])
}
}
-typedef struct ReadEWAData {
- MemoryBuffer *buffer;
- PixelSampler sampler;
- float ufac, vfac;
-} ReadEWAData;
-
static void read_ewa_pixel_sampled(void *userdata, int x, int y, float result[4])
{
- ReadEWAData *data = (ReadEWAData *) userdata;
- switch (data->sampler) {
- case COM_PS_NEAREST:
- data->buffer->read(result, x, y);
- break;
- case COM_PS_BILINEAR:
- data->buffer->readBilinear(result,
- (float)x + data->ufac,
- (float)y + data->vfac);
- break;
- case COM_PS_BICUBIC:
- /* TOOD(sergey): no readBicubic method yet */
- data->buffer->readBilinear(result,
- (float)x + data->ufac,
- (float)y + data->vfac);
- break;
- default:
- zero_v4(result);
- break;
- }
+ MemoryBuffer *buffer = (MemoryBuffer *) userdata;
+ buffer->read(result, x, y);
}
-void MemoryBuffer::readEWA(float *result, const float uv[2], const float derivatives[2][2], PixelSampler sampler)
+void MemoryBuffer::readEWA(float *result, const float uv[2], const float derivatives[2][2])
{
BLI_assert(this->m_datatype == COM_DT_COLOR);
- ReadEWAData data;
- data.buffer = this;
- data.sampler = sampler;
- data.ufac = uv[0] - floorf(uv[0]);
- data.vfac = uv[1] - floorf(uv[1]);
-
- int width = this->getWidth(), height = this->getHeight();
+ float inv_width = 1.0f / (float)this->getWidth(),
+ inv_height = 1.0f / (float)this->getHeight();
/* TODO(sergey): Render pipeline uses normalized coordinates and derivatives,
* but compositor uses pixel space. For now let's just divide the values and
* switch compositor to normalized space for EWA later.
*/
- float uv_normal[2] = {uv[0] / width, uv[1] / height};
- float du_normal[2] = {derivatives[0][0] / width, derivatives[0][1] / height};
- float dv_normal[2] = {derivatives[1][0] / width, derivatives[1][1] / height};
+ float uv_normal[2] = {uv[0] * inv_width, uv[1] * inv_height};
+ float du_normal[2] = {derivatives[0][0] * inv_width, derivatives[0][1] * inv_height};
+ float dv_normal[2] = {derivatives[1][0] * inv_width, derivatives[1][1] * inv_height};
BLI_ewa_filter(this->getWidth(), this->getHeight(),
false,
true,
uv_normal, du_normal, dv_normal,
read_ewa_pixel_sampled,
- &data,
+ this,
result);
}
diff --git a/source/blender/compositor/intern/COM_MemoryBuffer.h b/source/blender/compositor/intern/COM_MemoryBuffer.h
index 0b5fc21e69e..de8c14e1a66 100644
--- a/source/blender/compositor/intern/COM_MemoryBuffer.h
+++ b/source/blender/compositor/intern/COM_MemoryBuffer.h
@@ -262,7 +262,7 @@ public:
BLI_bilinear_interpolation_fl(this->m_buffer, result, this->m_width, this->m_height, this->m_num_channels, u, v);
}
- void readEWA(float *result, const float uv[2], const float derivatives[2][2], PixelSampler sampler);
+ void readEWA(float *result, const float uv[2], const float derivatives[2][2]);
/**
* @brief is this MemoryBuffer a temporarily buffer (based on an area, not on a chunk)
diff --git a/source/blender/compositor/intern/COM_Node.h b/source/blender/compositor/intern/COM_Node.h
index 6046af24c55..559ca46ae8b 100644
--- a/source/blender/compositor/intern/COM_Node.h
+++ b/source/blender/compositor/intern/COM_Node.h
@@ -24,7 +24,6 @@
#define __COM_NODE_H__
#include "DNA_node_types.h"
-#include "BKE_text.h"
#include <vector>
#include <string>
#include <algorithm>
diff --git a/source/blender/compositor/intern/COM_SocketReader.h b/source/blender/compositor/intern/COM_SocketReader.h
index 7ba208ebbf6..ab8a3c06ef5 100644
--- a/source/blender/compositor/intern/COM_SocketReader.h
+++ b/source/blender/compositor/intern/COM_SocketReader.h
@@ -93,8 +93,7 @@ protected:
*/
virtual void executePixelFiltered(float /*output*/[4],
float /*x*/, float /*y*/,
- float /*dx*/[2], float /*dy*/[2],
- PixelSampler /*sampler*/) {}
+ float /*dx*/[2], float /*dy*/[2]) {}
public:
inline void readSampled(float result[4], float x, float y, PixelSampler sampler) {
@@ -103,8 +102,8 @@ public:
inline void read(float result[4], int x, int y, void *chunkData) {
executePixel(result, x, y, chunkData);
}
- inline void readFiltered(float result[4], float x, float y, float dx[2], float dy[2], PixelSampler sampler) {
- executePixelFiltered(result, x, y, dx, dy, sampler);
+ inline void readFiltered(float result[4], float x, float y, float dx[2], float dy[2]) {
+ executePixelFiltered(result, x, y, dx, dy);
}
virtual void *initializeTileData(rcti * /*rect*/) { return 0; }
diff --git a/source/blender/compositor/intern/COM_WorkScheduler.h b/source/blender/compositor/intern/COM_WorkScheduler.h
index 71c5f859418..27afdf6efd0 100644
--- a/source/blender/compositor/intern/COM_WorkScheduler.h
+++ b/source/blender/compositor/intern/COM_WorkScheduler.h
@@ -59,7 +59,7 @@ public:
* @brief schedule a chunk of a group to be calculated.
* An execution group schedules a chunk in the WorkScheduler
* when ExecutionGroup.isOpenCL is set the work will be handled by a OpenCLDevice
- * otherwide the work is scheduled for an CPUDevice
+ * otherwise the work is scheduled for an CPUDevice
* @see ExecutionGroup.execute
* @param group the execution group
* @param chunkNumber the number of the chunk in the group to be executed
diff --git a/source/blender/compositor/intern/COM_compositor.cpp b/source/blender/compositor/intern/COM_compositor.cpp
index 7f7fc141aca..397540e8e2f 100644
--- a/source/blender/compositor/intern/COM_compositor.cpp
+++ b/source/blender/compositor/intern/COM_compositor.cpp
@@ -25,9 +25,7 @@ extern "C" {
#include "BKE_node.h"
#include "BLI_threads.h"
}
-#include "BKE_main.h"
#include "BKE_scene.h"
-#include "BKE_global.h"
#include "COM_compositor.h"
#include "COM_ExecutionSystem.h"
diff --git a/source/blender/compositor/nodes/COM_ChannelMatteNode.cpp b/source/blender/compositor/nodes/COM_ChannelMatteNode.cpp
index b04f86dea08..cc573274c34 100644
--- a/source/blender/compositor/nodes/COM_ChannelMatteNode.cpp
+++ b/source/blender/compositor/nodes/COM_ChannelMatteNode.cpp
@@ -33,41 +33,45 @@ ChannelMatteNode::ChannelMatteNode(bNode *editorNode) : Node(editorNode)
void ChannelMatteNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const
{
bNode *node = this->getbNode();
-
+
NodeInput *inputSocketImage = this->getInputSocket(0);
NodeOutput *outputSocketImage = this->getOutputSocket(0);
NodeOutput *outputSocketMatte = this->getOutputSocket(1);
-
- NodeOperation *convert = NULL;
+
+ NodeOperation *convert = NULL, *inv_convert = NULL;
/* colorspace */
switch (node->custom1) {
case CMP_NODE_CHANNEL_MATTE_CS_RGB:
break;
case CMP_NODE_CHANNEL_MATTE_CS_HSV: /* HSV */
convert = new ConvertRGBToHSVOperation();
+ inv_convert = new ConvertHSVToRGBOperation();
break;
case CMP_NODE_CHANNEL_MATTE_CS_YUV: /* YUV */
convert = new ConvertRGBToYUVOperation();
+ inv_convert = new ConvertYUVToRGBOperation();
break;
case CMP_NODE_CHANNEL_MATTE_CS_YCC: /* YCC */
convert = new ConvertRGBToYCCOperation();
((ConvertRGBToYCCOperation *)convert)->setMode(0); /* BLI_YCC_ITU_BT601 */
+ inv_convert = new ConvertYCCToRGBOperation();
+ ((ConvertYCCToRGBOperation *)inv_convert)->setMode(0); /* BLI_YCC_ITU_BT601 */
break;
default:
break;
}
-
+
ChannelMatteOperation *operation = new ChannelMatteOperation();
/* pass the ui properties to the operation */
operation->setSettings((NodeChroma *)node->storage, node->custom2);
converter.addOperation(operation);
-
+
SetAlphaOperation *operationAlpha = new SetAlphaOperation();
converter.addOperation(operationAlpha);
-
- if (convert) {
+
+ if (convert != NULL) {
converter.addOperation(convert);
-
+
converter.mapInputSocket(inputSocketImage, convert->getInputSocket(0));
converter.addLink(convert->getOutputSocket(), operation->getInputSocket(0));
converter.addLink(convert->getOutputSocket(), operationAlpha->getInputSocket(0));
@@ -76,11 +80,18 @@ void ChannelMatteNode::convertToOperations(NodeConverter &converter, const Compo
converter.mapInputSocket(inputSocketImage, operation->getInputSocket(0));
converter.mapInputSocket(inputSocketImage, operationAlpha->getInputSocket(0));
}
-
+
converter.mapOutputSocket(outputSocketMatte, operation->getOutputSocket(0));
-
converter.addLink(operation->getOutputSocket(), operationAlpha->getInputSocket(1));
- converter.mapOutputSocket(outputSocketImage, operationAlpha->getOutputSocket());
-
- converter.addPreview(operationAlpha->getOutputSocket());
+
+ if (inv_convert != NULL) {
+ converter.addOperation(inv_convert);
+ converter.addLink(operationAlpha->getOutputSocket(0), inv_convert->getInputSocket(0));
+ converter.mapOutputSocket(outputSocketImage, inv_convert->getOutputSocket());
+ converter.addPreview(inv_convert->getOutputSocket());
+ }
+ else {
+ converter.mapOutputSocket(outputSocketImage, operationAlpha->getOutputSocket());
+ converter.addPreview(operationAlpha->getOutputSocket());
+ }
}
diff --git a/source/blender/compositor/nodes/COM_DistanceMatteNode.cpp b/source/blender/compositor/nodes/COM_DistanceMatteNode.cpp
index 5f3feda5de7..99061cf8824 100644
--- a/source/blender/compositor/nodes/COM_DistanceMatteNode.cpp
+++ b/source/blender/compositor/nodes/COM_DistanceMatteNode.cpp
@@ -66,6 +66,8 @@ void DistanceMatteNode::convertToOperations(NodeConverter &converter, const Comp
ConvertRGBToYCCOperation *operationYCCImage = new ConvertRGBToYCCOperation();
ConvertRGBToYCCOperation *operationYCCMatte = new ConvertRGBToYCCOperation();
+ operationYCCImage->setMode(0); /* BLI_YCC_ITU_BT601 */
+ operationYCCMatte->setMode(0); /* BLI_YCC_ITU_BT601 */
converter.addOperation(operationYCCImage);
converter.addOperation(operationYCCMatte);
@@ -79,10 +81,20 @@ void DistanceMatteNode::convertToOperations(NodeConverter &converter, const Comp
operation = matte;
}
+ converter.mapOutputSocket(outputSocketMatte, operation->getOutputSocket(0));
converter.addLink(operation->getOutputSocket(), operationAlpha->getInputSocket(1));
- converter.mapOutputSocket(outputSocketMatte, operation->getOutputSocket());
- converter.mapOutputSocket(outputSocketImage, operationAlpha->getOutputSocket());
-
- converter.addPreview(operationAlpha->getOutputSocket());
+ if (storage->channel != 1) {
+ ConvertYCCToRGBOperation *inv_convert = new ConvertYCCToRGBOperation();
+ inv_convert->setMode(0); /* BLI_YCC_ITU_BT601 */
+
+ converter.addOperation(inv_convert);
+ converter.addLink(operationAlpha->getOutputSocket(0), inv_convert->getInputSocket(0));
+ converter.mapOutputSocket(outputSocketImage, inv_convert->getOutputSocket());
+ converter.addPreview(inv_convert->getOutputSocket());
+ }
+ else {
+ converter.mapOutputSocket(outputSocketImage, operationAlpha->getOutputSocket());
+ converter.addPreview(operationAlpha->getOutputSocket());
+ }
}
diff --git a/source/blender/compositor/nodes/COM_ImageNode.cpp b/source/blender/compositor/nodes/COM_ImageNode.cpp
index 572e63a2ced..facd422c217 100644
--- a/source/blender/compositor/nodes/COM_ImageNode.cpp
+++ b/source/blender/compositor/nodes/COM_ImageNode.cpp
@@ -40,19 +40,19 @@ ImageNode::ImageNode(bNode *editorNode) : Node(editorNode)
}
NodeOperation *ImageNode::doMultilayerCheck(NodeConverter &converter, RenderLayer *rl, Image *image, ImageUser *user,
- int framenumber, int outputsocketIndex, int passtype, int view, DataType datatype) const
+ int framenumber, int outputsocketIndex, int passindex, int view, DataType datatype) const
{
NodeOutput *outputSocket = this->getOutputSocket(outputsocketIndex);
MultilayerBaseOperation *operation = NULL;
switch (datatype) {
case COM_DT_VALUE:
- operation = new MultilayerValueOperation(passtype, view);
+ operation = new MultilayerValueOperation(passindex, view);
break;
case COM_DT_VECTOR:
- operation = new MultilayerVectorOperation(passtype, view);
+ operation = new MultilayerVectorOperation(passindex, view);
break;
case COM_DT_COLOR:
- operation = new MultilayerColorOperation(passtype, view);
+ operation = new MultilayerColorOperation(passindex, view);
break;
default:
break;
@@ -124,20 +124,21 @@ void ImageNode::convertToOperations(NodeConverter &converter, const CompositorCo
}
if (rpass) {
+ int passindex = BLI_findindex(&rl->passes, rpass);
switch (rpass->channels) {
case 1:
operation = doMultilayerCheck(converter, rl, image, imageuser, framenumber, index,
- rpass->passtype, view, COM_DT_VALUE);
+ passindex, view, COM_DT_VALUE);
break;
/* using image operations for both 3 and 4 channels (RGB and RGBA respectively) */
/* XXX any way to detect actual vector images? */
case 3:
operation = doMultilayerCheck(converter, rl, image, imageuser, framenumber, index,
- rpass->passtype, view, COM_DT_VECTOR);
+ passindex, view, COM_DT_VECTOR);
break;
case 4:
operation = doMultilayerCheck(converter, rl, image, imageuser, framenumber, index,
- rpass->passtype, view, COM_DT_COLOR);
+ passindex, view, COM_DT_COLOR);
break;
default:
/* dummy operation is added below */
diff --git a/source/blender/compositor/operations/COM_CurveBaseOperation.cpp b/source/blender/compositor/operations/COM_CurveBaseOperation.cpp
index 408395bfcf0..9bb5ac88343 100644
--- a/source/blender/compositor/operations/COM_CurveBaseOperation.cpp
+++ b/source/blender/compositor/operations/COM_CurveBaseOperation.cpp
@@ -34,14 +34,25 @@ CurveBaseOperation::CurveBaseOperation() : NodeOperation()
{
this->m_curveMapping = NULL;
}
+
+CurveBaseOperation::~CurveBaseOperation()
+{
+ if (this->m_curveMapping) {
+ curvemapping_free(this->m_curveMapping);
+ this->m_curveMapping = NULL;
+ }
+}
+
void CurveBaseOperation::initExecution()
{
curvemapping_initialize(this->m_curveMapping);
}
void CurveBaseOperation::deinitExecution()
{
- curvemapping_free(this->m_curveMapping);
- this->m_curveMapping = NULL;
+ if (this->m_curveMapping) {
+ curvemapping_free(this->m_curveMapping);
+ this->m_curveMapping = NULL;
+ }
}
void CurveBaseOperation::setCurveMapping(CurveMapping *mapping)
diff --git a/source/blender/compositor/operations/COM_CurveBaseOperation.h b/source/blender/compositor/operations/COM_CurveBaseOperation.h
index 6bfce26f532..154eb18e387 100644
--- a/source/blender/compositor/operations/COM_CurveBaseOperation.h
+++ b/source/blender/compositor/operations/COM_CurveBaseOperation.h
@@ -33,6 +33,7 @@ protected:
CurveMapping *m_curveMapping;
public:
CurveBaseOperation();
+ ~CurveBaseOperation();
/**
* Initialize the execution
diff --git a/source/blender/compositor/operations/COM_DisplaceOperation.cpp b/source/blender/compositor/operations/COM_DisplaceOperation.cpp
index 6dfef8a0a11..9b3377e887a 100644
--- a/source/blender/compositor/operations/COM_DisplaceOperation.cpp
+++ b/source/blender/compositor/operations/COM_DisplaceOperation.cpp
@@ -60,7 +60,7 @@ void DisplaceOperation::executePixelSampled(float output[4], float x, float y, P
}
else {
/* EWA filtering (without nearest it gets blurry with NO distortion) */
- this->m_inputColorProgram->readFiltered(output, uv[0], uv[1], deriv[0], deriv[1], COM_PS_BILINEAR);
+ this->m_inputColorProgram->readFiltered(output, uv[0], uv[1], deriv[0], deriv[1]);
}
}
diff --git a/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp
index 37d59229e50..7c4132238e3 100644
--- a/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp
+++ b/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp
@@ -273,7 +273,7 @@ void GaussianBlurReferenceOperation::executePixel(float output[4], int x, int y,
float *gausstaby, *gausstabcentx;
int i, j;
float *src;
- register float sum, val;
+ float sum, val;
float rval, gval, bval, aval;
int imgx = getWidth();
int imgy = getHeight();
diff --git a/source/blender/compositor/operations/COM_IDMaskOperation.cpp b/source/blender/compositor/operations/COM_IDMaskOperation.cpp
index a021f07d2a7..68e681c1326 100644
--- a/source/blender/compositor/operations/COM_IDMaskOperation.cpp
+++ b/source/blender/compositor/operations/COM_IDMaskOperation.cpp
@@ -38,7 +38,9 @@ void IDMaskOperation::executePixelSampled(float output[4], float x, float y, Pix
float inputValue[4];
this->m_inputProgram->readSampled(inputValue, x, y, sampler);
- const float a = (inputValue[0] == this->m_objectIndex) ? 1.0f : 0.0f;
+ /* 'round' since sampling may adjust value slightly.
+ * ID-mask input are originally integers too. */
+ const float a = (roundf(inputValue[0]) == this->m_objectIndex) ? 1.0f : 0.0f;
output[0] = a;
}
diff --git a/source/blender/compositor/operations/COM_MapUVOperation.cpp b/source/blender/compositor/operations/COM_MapUVOperation.cpp
index ffa48ce3956..d091675286d 100644
--- a/source/blender/compositor/operations/COM_MapUVOperation.cpp
+++ b/source/blender/compositor/operations/COM_MapUVOperation.cpp
@@ -53,7 +53,7 @@ void MapUVOperation::executePixelSampled(float output[4], float x, float y, Pixe
}
/* EWA filtering */
- this->m_inputColorProgram->readFiltered(output, uv[0], uv[1], deriv[0], deriv[1], COM_PS_BILINEAR);
+ this->m_inputColorProgram->readFiltered(output, uv[0], uv[1], deriv[0], deriv[1]);
/* UV to alpha threshold */
const float threshold = this->m_alpha * 0.05f;
diff --git a/source/blender/compositor/operations/COM_MovieDistortionOperation.h b/source/blender/compositor/operations/COM_MovieDistortionOperation.h
index 577712eda56..85f075ab65a 100644
--- a/source/blender/compositor/operations/COM_MovieDistortionOperation.h
+++ b/source/blender/compositor/operations/COM_MovieDistortionOperation.h
@@ -36,9 +36,9 @@ extern "C" {
class DistortionCache {
private:
- float m_k1;
- float m_k2;
- float m_k3;
+ short m_distortion_model;
+ float m_k1, m_k2, m_k3;
+ float m_division_k1, m_division_k2;
float m_principal_x;
float m_principal_y;
float m_pixel_aspect;
@@ -59,9 +59,12 @@ public:
bool inverted,
const int margin[2])
{
+ this->m_distortion_model = movieclip->tracking.camera.distortion_model;
this->m_k1 = movieclip->tracking.camera.k1;
this->m_k2 = movieclip->tracking.camera.k2;
this->m_k3 = movieclip->tracking.camera.k3;
+ this->m_division_k1 = movieclip->tracking.camera.division_k1;
+ this->m_division_k2 = movieclip->tracking.camera.division_k2;
this->m_principal_x = movieclip->tracking.camera.principal[0];
this->m_principal_y = movieclip->tracking.camera.principal[1];
this->m_pixel_aspect = movieclip->tracking.camera.pixel_aspect;
@@ -101,9 +104,12 @@ public:
int calibration_width, int claibration_height,
bool inverted)
{
- return this->m_k1 == movieclip->tracking.camera.k1 &&
+ return this->m_distortion_model == movieclip->tracking.camera.distortion_model &&
+ this->m_k1 == movieclip->tracking.camera.k1 &&
this->m_k2 == movieclip->tracking.camera.k2 &&
this->m_k3 == movieclip->tracking.camera.k3 &&
+ this->m_division_k1 == movieclip->tracking.camera.division_k1 &&
+ this->m_division_k2 == movieclip->tracking.camera.division_k2 &&
this->m_principal_x == movieclip->tracking.camera.principal[0] &&
this->m_principal_y == movieclip->tracking.camera.principal[1] &&
this->m_pixel_aspect == movieclip->tracking.camera.pixel_aspect &&
diff --git a/source/blender/compositor/operations/COM_MultilayerImageOperation.cpp b/source/blender/compositor/operations/COM_MultilayerImageOperation.cpp
index 00be3b1cdde..b57dd4e32c3 100644
--- a/source/blender/compositor/operations/COM_MultilayerImageOperation.cpp
+++ b/source/blender/compositor/operations/COM_MultilayerImageOperation.cpp
@@ -27,9 +27,9 @@ extern "C" {
# include "IMB_imbuf_types.h"
}
-MultilayerBaseOperation::MultilayerBaseOperation(int passtype, int view) : BaseImageOperation()
+MultilayerBaseOperation::MultilayerBaseOperation(int passindex, int view) : BaseImageOperation()
{
- this->m_passtype = passtype;
+ this->m_passId = passindex;
this->m_view = view;
}
@@ -39,7 +39,7 @@ ImBuf *MultilayerBaseOperation::getImBuf()
int view = this->m_imageUser->view;
this->m_imageUser->view = this->m_view;
- this->m_imageUser->passtype = this->m_passtype;
+ this->m_imageUser->pass = this->m_passId;
if (BKE_image_multilayer_index(this->m_image->rr, this->m_imageUser)) {
ImBuf *ibuf = BaseImageOperation::getImBuf();
diff --git a/source/blender/compositor/operations/COM_MultilayerImageOperation.h b/source/blender/compositor/operations/COM_MultilayerImageOperation.h
index 2e140577d74..46a9319c373 100644
--- a/source/blender/compositor/operations/COM_MultilayerImageOperation.h
+++ b/source/blender/compositor/operations/COM_MultilayerImageOperation.h
@@ -29,7 +29,7 @@
class MultilayerBaseOperation : public BaseImageOperation {
private:
- int m_passtype;
+ int m_passId;
int m_view;
RenderLayer *m_renderlayer;
protected:
@@ -38,13 +38,13 @@ public:
/**
* Constructor
*/
- MultilayerBaseOperation(int passtype, int view);
+ MultilayerBaseOperation(int passindex, int view);
void setRenderLayer(RenderLayer *renderlayer) { this->m_renderlayer = renderlayer; }
};
class MultilayerColorOperation : public MultilayerBaseOperation {
public:
- MultilayerColorOperation(int passtype, int view) : MultilayerBaseOperation(passtype, view) {
+ MultilayerColorOperation(int passindex, int view) : MultilayerBaseOperation(passindex, view) {
this->addOutputSocket(COM_DT_COLOR);
}
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
@@ -52,7 +52,7 @@ public:
class MultilayerValueOperation : public MultilayerBaseOperation {
public:
- MultilayerValueOperation(int passtype, int view) : MultilayerBaseOperation(passtype, view) {
+ MultilayerValueOperation(int passindex, int view) : MultilayerBaseOperation(passindex, view) {
this->addOutputSocket(COM_DT_VALUE);
}
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
@@ -60,7 +60,7 @@ public:
class MultilayerVectorOperation : public MultilayerBaseOperation {
public:
- MultilayerVectorOperation(int passtype, int view) : MultilayerBaseOperation(passtype, view) {
+ MultilayerVectorOperation(int passindex, int view) : MultilayerBaseOperation(passindex, view) {
this->addOutputSocket(COM_DT_VECTOR);
}
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
diff --git a/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.cpp b/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.cpp
index d7d1c9c0c93..1145abd076a 100644
--- a/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.cpp
+++ b/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.cpp
@@ -108,8 +108,7 @@ void PlaneDistortWarpImageOperation::executePixelSampled(float output[4], float
warpCoord(x, y, this->m_samples[0].perspectiveMatrix, uv, deriv);
m_pixelReader->readFiltered(output,
uv[0], uv[1],
- deriv[0], deriv[1],
- COM_PS_BILINEAR);
+ deriv[0], deriv[1]);
}
else {
zero_v4(output);
@@ -118,8 +117,7 @@ void PlaneDistortWarpImageOperation::executePixelSampled(float output[4], float
warpCoord(x, y, this->m_samples[sample].perspectiveMatrix, uv, deriv);
m_pixelReader->readFiltered(color,
uv[0], uv[1],
- deriv[0], deriv[1],
- COM_PS_BILINEAR);
+ deriv[0], deriv[1]);
add_v4_v4(output, color);
}
mul_v4_fl(output, 1.0f / (float)this->m_motion_blur_samples);
diff --git a/source/blender/compositor/operations/COM_ReadBufferOperation.cpp b/source/blender/compositor/operations/COM_ReadBufferOperation.cpp
index bf0f24e06be..6dbe132257a 100644
--- a/source/blender/compositor/operations/COM_ReadBufferOperation.cpp
+++ b/source/blender/compositor/operations/COM_ReadBufferOperation.cpp
@@ -89,7 +89,7 @@ void ReadBufferOperation::executePixelExtend(float output[4], float x, float y,
}
}
-void ReadBufferOperation::executePixelFiltered(float output[4], float x, float y, float dx[2], float dy[2], PixelSampler sampler)
+void ReadBufferOperation::executePixelFiltered(float output[4], float x, float y, float dx[2], float dy[2])
{
if (m_single_value) {
/* write buffer has a single value stored at (0,0) */
@@ -98,7 +98,7 @@ void ReadBufferOperation::executePixelFiltered(float output[4], float x, float y
else {
const float uv[2] = { x, y };
const float deriv[2][2] = { {dx[0], dx[1]}, {dy[0], dy[1]} };
- m_buffer->readEWA(output, uv, deriv, sampler);
+ m_buffer->readEWA(output, uv, deriv);
}
}
diff --git a/source/blender/compositor/operations/COM_ReadBufferOperation.h b/source/blender/compositor/operations/COM_ReadBufferOperation.h
index 7e5bc55a8ca..cd706ed0b75 100644
--- a/source/blender/compositor/operations/COM_ReadBufferOperation.h
+++ b/source/blender/compositor/operations/COM_ReadBufferOperation.h
@@ -43,7 +43,7 @@ public:
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
void executePixelExtend(float output[4], float x, float y, PixelSampler sampler,
MemoryBufferExtend extend_x, MemoryBufferExtend extend_y);
- void executePixelFiltered(float output[4], float x, float y, float dx[2], float dy[2], PixelSampler sampler);
+ void executePixelFiltered(float output[4], float x, float y, float dx[2], float dy[2]);
const bool isReadBufferOperation() const { return true; }
void setOffset(unsigned int offset) { this->m_offset = offset; }
unsigned int getOffset() const { return this->m_offset; }
diff --git a/source/blender/compositor/operations/COM_RenderLayersProg.cpp b/source/blender/compositor/operations/COM_RenderLayersProg.cpp
index 1a7e775113b..2a45690a9f2 100644
--- a/source/blender/compositor/operations/COM_RenderLayersProg.cpp
+++ b/source/blender/compositor/operations/COM_RenderLayersProg.cpp
@@ -150,6 +150,7 @@ void RenderLayersBaseProg::executePixelSampled(float output[4], float x, float y
expected_element_size = 4;
}
else {
+ expected_element_size = 0;
BLI_assert(!"Something horribly wrong just happened");
}
BLI_assert(expected_element_size == actual_element_size);
diff --git a/source/blender/depsgraph/DEG_depsgraph.h b/source/blender/depsgraph/DEG_depsgraph.h
index b91f99ecd20..f37ba71ab65 100644
--- a/source/blender/depsgraph/DEG_depsgraph.h
+++ b/source/blender/depsgraph/DEG_depsgraph.h
@@ -193,6 +193,8 @@ void DEG_evaluate_on_refresh(struct EvaluationContext *eval_ctx,
Depsgraph *graph,
struct Scene *scene);
+bool DEG_needs_eval(Depsgraph *graph);
+
/* Editors Integration -------------------------- */
/* Mechanism to allow editors to be informed of depsgraph updates,
@@ -203,10 +205,16 @@ typedef void (*DEG_EditorUpdateIDCb)(struct Main *bmain, struct ID *id);
typedef void (*DEG_EditorUpdateSceneCb)(struct Main *bmain,
struct Scene *scene,
int updated);
+typedef void (*DEG_EditorUpdateScenePreCb)(struct Main *bmain,
+ struct Scene *scene,
+ bool time);
/* Set callbacks which are being called when depsgraph changes. */
void DEG_editors_set_update_cb(DEG_EditorUpdateIDCb id_func,
- DEG_EditorUpdateSceneCb scene_func);
+ DEG_EditorUpdateSceneCb scene_func,
+ DEG_EditorUpdateScenePreCb scene_pre_func);
+
+void DEG_editors_update_pre(struct Main *bmain, struct Scene *scene, bool time);
#ifdef __cplusplus
} /* extern "C" */
diff --git a/source/blender/depsgraph/intern/depsgraph.cc b/source/blender/depsgraph/intern/depsgraph.cc
index 12b3a36b33e..dedb6e322ba 100644
--- a/source/blender/depsgraph/intern/depsgraph.cc
+++ b/source/blender/depsgraph/intern/depsgraph.cc
@@ -58,11 +58,12 @@ extern "C" {
static DEG_EditorUpdateIDCb deg_editor_update_id_cb = NULL;
static DEG_EditorUpdateSceneCb deg_editor_update_scene_cb = NULL;
+static DEG_EditorUpdateScenePreCb deg_editor_update_scene_pre_cb = NULL;
Depsgraph::Depsgraph()
: root_node(NULL),
need_update(false),
- layers((1 << 20) - 1)
+ layers(0)
{
BLI_spin_init(&lock);
}
@@ -355,11 +356,16 @@ DepsRelation *Depsgraph::add_new_relation(OperationDepsNode *from,
DepsRelation *rel = OBJECT_GUARDED_NEW(DepsRelation, from, to, type, description);
/* TODO(sergey): Find a better place for this. */
#ifdef WITH_OPENSUBDIV
- if (type == DEPSREL_TYPE_GEOMETRY_EVAL) {
+ ComponentDepsNode *comp_node = from->owner;
+ if (comp_node->type == DEPSNODE_TYPE_GEOMETRY) {
IDDepsNode *id_to = to->owner->owner;
- if ((id_to->eval_flags & DAG_EVAL_NEED_CPU) == 0) {
- id_to->tag_update(this);
- id_to->eval_flags |= DAG_EVAL_NEED_CPU;
+ IDDepsNode *id_from = from->owner->owner;
+ Object *object_to = (Object *)id_to->id;
+ if (id_to != id_from && (object_to->recalc & OB_RECALC_ALL)) {
+ if ((id_from->eval_flags & DAG_EVAL_NEED_CPU) == 0) {
+ id_from->tag_update(this);
+ id_from->eval_flags |= DAG_EVAL_NEED_CPU;
+ }
}
}
#endif
@@ -464,10 +470,19 @@ void DEG_graph_free(Depsgraph *graph)
/* Set callbacks which are being called when depsgraph changes. */
void DEG_editors_set_update_cb(DEG_EditorUpdateIDCb id_func,
- DEG_EditorUpdateSceneCb scene_func)
+ DEG_EditorUpdateSceneCb scene_func,
+ DEG_EditorUpdateScenePreCb scene_pre_func)
{
deg_editor_update_id_cb = id_func;
deg_editor_update_scene_cb = scene_func;
+ deg_editor_update_scene_pre_cb = scene_pre_func;
+}
+
+void DEG_editors_update_pre(Main *bmain, Scene *scene, bool time)
+{
+ if (deg_editor_update_scene_pre_cb != NULL) {
+ deg_editor_update_scene_pre_cb(bmain, scene, time);
+ }
}
void deg_editors_id_update(Main *bmain, ID *id)
diff --git a/source/blender/depsgraph/intern/depsgraph_build.h b/source/blender/depsgraph/intern/depsgraph_build.h
index 4088a3289ef..c5b04ec299c 100644
--- a/source/blender/depsgraph/intern/depsgraph_build.h
+++ b/source/blender/depsgraph/intern/depsgraph_build.h
@@ -108,7 +108,7 @@ struct DepsgraphNodeBuilder {
void build_object_constraints(Scene *scene, Object *ob);
void build_pose_constraints(Object *ob, bPoseChannel *pchan);
void build_rigidbody(Scene *scene);
- void build_particles(Object *ob);
+ void build_particles(Scene *scene, Object *ob);
void build_animdata(ID *id);
OperationDepsNode *build_driver(ID *id, FCurve *fcurve);
void build_ik_pose(Scene *scene, Object *ob, bPoseChannel *pchan, bConstraint *con);
diff --git a/source/blender/depsgraph/intern/depsgraph_build_nodes.cc b/source/blender/depsgraph/intern/depsgraph_build_nodes.cc
index 31e32ac3e75..4463df61f91 100644
--- a/source/blender/depsgraph/intern/depsgraph_build_nodes.cc
+++ b/source/blender/depsgraph/intern/depsgraph_build_nodes.cc
@@ -448,7 +448,7 @@ void DepsgraphNodeBuilder::build_object(Scene *scene, Base *base, Object *ob)
/* particle systems */
if (ob->particlesystem.first) {
- build_particles(ob);
+ build_particles(scene, ob);
}
/* grease pencil */
@@ -676,7 +676,7 @@ void DepsgraphNodeBuilder::build_rigidbody(Scene *scene)
}
}
-void DepsgraphNodeBuilder::build_particles(Object *ob)
+void DepsgraphNodeBuilder::build_particles(Scene *scene, Object *ob)
{
/**
* Particle Systems Nodes
@@ -707,7 +707,7 @@ void DepsgraphNodeBuilder::build_particles(Object *ob)
/* this particle system */
// TODO: for now, this will just be a placeholder "ubereval" node
add_operation_node(psys_comp,
- DEPSOP_TYPE_EXEC, function_bind(BKE_particle_system_eval, _1, ob, psys),
+ DEPSOP_TYPE_EXEC, function_bind(BKE_particle_system_eval, _1, scene, ob, psys),
DEG_OPCODE_PSYS_EVAL,
psys->name);
}
diff --git a/source/blender/depsgraph/intern/depsgraph_build_relations.cc b/source/blender/depsgraph/intern/depsgraph_build_relations.cc
index 649105a0df2..c348adaaf53 100644
--- a/source/blender/depsgraph/intern/depsgraph_build_relations.cc
+++ b/source/blender/depsgraph/intern/depsgraph_build_relations.cc
@@ -812,6 +812,10 @@ void DepsgraphRelationBuilder::build_driver(ID *id, FCurve *fcu)
ComponentKey geometry_key(shape_key->from, DEPSNODE_TYPE_GEOMETRY);
add_relation(driver_key, geometry_key, DEPSREL_TYPE_DRIVER, "[Driver -> ShapeKey Geom]");
}
+ else if (strstr(fcu->rna_path, "key_blocks[")) {
+ ComponentKey geometry_key(id, DEPSNODE_TYPE_GEOMETRY);
+ add_relation(driver_key, geometry_key, DEPSREL_TYPE_DRIVER, "[Driver -> ShapeKey Geom]");
+ }
else {
if (GS(id->name) == ID_OB) {
/* assume that driver affects a transform... */
diff --git a/source/blender/depsgraph/intern/depsgraph_debug.cc b/source/blender/depsgraph/intern/depsgraph_debug.cc
index 59351495df0..7f3f328502f 100644
--- a/source/blender/depsgraph/intern/depsgraph_debug.cc
+++ b/source/blender/depsgraph/intern/depsgraph_debug.cc
@@ -59,8 +59,6 @@ extern "C" {
/* ****************** */
/* Graphviz Debugging */
-static SpinLock lock;
-
#define NL "\r\n"
/* Only one should be enabled, defines whether graphviz nodes
@@ -345,9 +343,11 @@ static void deg_debug_graphviz_node_fillcolor(const DebugContext &ctx,
#endif
static void deg_debug_graphviz_relation_color(const DebugContext &ctx,
- const DepsRelation *UNUSED(rel))
+ const DepsRelation *rel)
{
- const char *defaultcolor = "black";
+ const char *color_default = "black";
+ const char *color_error = "red4";
+ const char *color = color_default;
#if 0 /* disabled for now, edge colors are hardly distinguishable */
int color = deg_debug_relation_type_color_index(rel->type);
if (color < 0) {
@@ -357,7 +357,10 @@ static void deg_debug_graphviz_relation_color(const DebugContext &ctx,
deg_debug_fprintf(ctx, "\"%s\"", deg_debug_colors_dark[color % deg_debug_max_colors]);
}
#else
- deg_debug_fprintf(ctx, "%s", defaultcolor);
+ if (rel->flag & DEPSREL_FLAG_CYCLIC)
+ color = color_error;
+
+ deg_debug_fprintf(ctx, "%s", color);
#endif
}
@@ -439,6 +442,7 @@ static void deg_debug_graphviz_node_cluster_begin(const DebugContext &ctx,
deg_debug_fprintf(ctx, "label=<%s>;" NL, name.c_str());
deg_debug_fprintf(ctx, "fontname=\"%s\";" NL, deg_debug_graphviz_fontname);
deg_debug_fprintf(ctx, "fontsize=%f;" NL, deg_debug_graphviz_node_label_size);
+ deg_debug_fprintf(ctx, "margin=\"%d\";" NL, 16);
deg_debug_fprintf(ctx, "style="); deg_debug_graphviz_node_style(ctx, node); deg_debug_fprintf(ctx, ";" NL);
deg_debug_fprintf(ctx, "color="); deg_debug_graphviz_node_color(ctx, node); deg_debug_fprintf(ctx, ";" NL);
deg_debug_fprintf(ctx, "fillcolor="); deg_debug_graphviz_node_fillcolor(ctx, node); deg_debug_fprintf(ctx, ";" NL);
@@ -592,6 +596,8 @@ static void deg_debug_graphviz_node_relations(const DebugContext &ctx,
{
DEPSNODE_RELATIONS_ITER_BEGIN(node->inlinks, rel)
{
+ float penwidth = 2.0f;
+
const DepsNode *tail = rel->to; /* same as node */
const DepsNode *head = rel->from;
deg_debug_fprintf(ctx, "// %s -> %s\n",
@@ -602,9 +608,20 @@ static void deg_debug_graphviz_node_relations(const DebugContext &ctx,
deg_debug_fprintf(ctx, "\"node_%p\"", tail);
deg_debug_fprintf(ctx, "[");
+ /* XXX labels on relations are not very helpful:
+ * - they tend to appear too far away to be associated with the edge lines
+ * - names are mostly redundant, reflecting simply their from/to nodes
+ * - no behavior or typing of relations themselves to justify labels
+ */
+#if 0
deg_debug_fprintf(ctx, "label=\"%s\"", rel->name);
deg_debug_fprintf(ctx, ",fontname=\"%s\"", deg_debug_graphviz_fontname);
+#else
+ /* Note: without label an id seem necessary to avoid bugs in graphviz/dot */
+ deg_debug_fprintf(ctx, "id=\"%s\"", rel->name);
+#endif
deg_debug_fprintf(ctx, ",color="); deg_debug_graphviz_relation_color(ctx, rel);
+ deg_debug_fprintf(ctx, ",penwidth=\"%f\"", penwidth);
/* NOTE: edge from node to own cluster is not possible and gives graphviz
* warning, avoid this here by just linking directly to the invisible
* placeholder node
diff --git a/source/blender/depsgraph/intern/depsgraph_eval.cc b/source/blender/depsgraph/intern/depsgraph_eval.cc
index 0a1563e7704..e8065766332 100644
--- a/source/blender/depsgraph/intern/depsgraph_eval.cc
+++ b/source/blender/depsgraph/intern/depsgraph_eval.cc
@@ -392,3 +392,8 @@ void DEG_evaluate_on_framechange(EvaluationContext *eval_ctx,
/* Perform recalculation updates. */
DEG_evaluate_on_refresh_ex(eval_ctx, graph, layers);
}
+
+bool DEG_needs_eval(Depsgraph *graph)
+{
+ return graph->entry_tags.size() != 0;
+}
diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c
index 8853422df8f..bdf5291dcc7 100644
--- a/source/blender/editors/animation/anim_filter.c
+++ b/source/blender/editors/animation/anim_filter.c
@@ -2016,7 +2016,7 @@ typedef struct tAnimFilterModifiersContext {
/* dependency walker callback for modifier dependencies */
-static void animfilter_modifier_idpoin_cb(void *afm_ptr, Object *ob, ID **idpoin)
+static void animfilter_modifier_idpoin_cb(void *afm_ptr, Object *ob, ID **idpoin, int UNUSED(cd_flag))
{
tAnimFilterModifiersContext *afm = (tAnimFilterModifiersContext *)afm_ptr;
ID *owner_id = &ob->id;
diff --git a/source/blender/editors/animation/keyframes_general.c b/source/blender/editors/animation/keyframes_general.c
index 3642c07b758..f0d9c48eb5e 100644
--- a/source/blender/editors/animation/keyframes_general.c
+++ b/source/blender/editors/animation/keyframes_general.c
@@ -955,6 +955,7 @@ short paste_animedit_keys(bAnimContext *ac, ListBase *anim_data,
aci = animcopybuf.first;
paste_animedit_keys_fcurve(fcu, aci, offset, merge_mode, false);
+ ale->update |= ANIM_UPDATE_DEFAULT;
}
else {
/* from selected channels
diff --git a/source/blender/editors/armature/armature_select.c b/source/blender/editors/armature/armature_select.c
index f4575105426..dbbdae280f2 100644
--- a/source/blender/editors/armature/armature_select.c
+++ b/source/blender/editors/armature/armature_select.c
@@ -929,7 +929,7 @@ static int armature_select_hierarchy_exec(bContext *C, wmOperator *op)
ob = obedit;
arm = (bArmature *)ob->data;
- ebone_active = arm->act_edbone;
+ ebone_active = arm->act_edbone;
if (ebone_active == NULL) {
return OPERATOR_CANCELLED;
}
diff --git a/source/blender/editors/armature/armature_utils.c b/source/blender/editors/armature/armature_utils.c
index 09284860ec4..61ed7fdc41b 100644
--- a/source/blender/editors/armature/armature_utils.c
+++ b/source/blender/editors/armature/armature_utils.c
@@ -477,48 +477,78 @@ EditBone *make_boneList(ListBase *edbo, ListBase *bones, EditBone *parent, Bone
return eBoneAct;
}
-/* nasty stuff for converting roll in editbones into bones */
-/* also sets restposition in armature (arm_mat) */
-static void fix_bonelist_roll(ListBase *bonelist, ListBase *editbonelist)
+/* This function:
+ * - sets local head/tail rest locations using parent bone's arm_mat.
+ * - calls BKE_armature_where_is_bone() which uses parent's transform (arm_mat) to define this bone's transform.
+ * - fixes (converts) EditBone roll into Bone roll.
+ * - calls again BKE_armature_where_is_bone(), since roll fiddling may have changed things for our bone...
+ * Note that order is crucial here, we can only handle child if all its parents in chain have already been handled
+ * (this is ensured by recursive process). */
+static void armature_finalize_restpose(ListBase *bonelist, ListBase *editbonelist)
{
Bone *curBone;
EditBone *ebone;
- float premat[3][3];
- float postmat[3][3];
- float difmat[3][3];
- float imat[3][3];
-
+
for (curBone = bonelist->first; curBone; curBone = curBone->next) {
- /* sets local matrix and arm_mat (restpos) */
- BKE_armature_where_is_bone(curBone, curBone->parent);
-
+ /* Set bone's local head/tail.
+ * Note that it's important to use final parent's restpose (arm_mat) here, instead of setting those values
+ * from editbone's matrix (see T46010). */
+ if (curBone->parent) {
+ float parmat_inv[4][4];
+
+ invert_m4_m4(parmat_inv, curBone->parent->arm_mat);
+
+ /* Get the new head and tail */
+ sub_v3_v3v3(curBone->head, curBone->arm_head, curBone->parent->arm_tail);
+ sub_v3_v3v3(curBone->tail, curBone->arm_tail, curBone->parent->arm_tail);
+
+ mul_mat3_m4_v3(parmat_inv, curBone->head);
+ mul_mat3_m4_v3(parmat_inv, curBone->tail);
+ }
+ else {
+ copy_v3_v3(curBone->head, curBone->arm_head);
+ copy_v3_v3(curBone->tail, curBone->arm_tail);
+ }
+
+ /* Set local matrix and arm_mat (restpose).
+ * Do not recurse into children here, armature_finalize_restpose() is already recursive. */
+ BKE_armature_where_is_bone(curBone, curBone->parent, false);
+
/* Find the associated editbone */
- for (ebone = editbonelist->first; ebone; ebone = ebone->next)
- if (ebone->temp.bone == curBone)
- break;
-
- if (ebone) {
- /* Get the ebone premat */
- ED_armature_ebone_to_mat3(ebone, premat);
-
- /* Get the bone postmat */
- copy_m3_m4(postmat, curBone->arm_mat);
-
- invert_m3_m3(imat, premat);
- mul_m3_m3m3(difmat, imat, postmat);
+ for (ebone = editbonelist->first; ebone; ebone = ebone->next) {
+ if (ebone->temp.bone == curBone) {
+ float premat[3][3];
+ float postmat[3][3];
+ float difmat[3][3];
+ float imat[3][3];
+
+ /* Get the ebone premat and its inverse. */
+ ED_armature_ebone_to_mat3(ebone, premat);
+ invert_m3_m3(imat, premat);
+
+ /* Get the bone postmat. */
+ copy_m3_m4(postmat, curBone->arm_mat);
+
+ mul_m3_m3m3(difmat, imat, postmat);
+
#if 0
- printf("Bone %s\n", curBone->name);
- print_m4("premat", premat);
- print_m4("postmat", postmat);
- print_m4("difmat", difmat);
- printf("Roll = %f\n", RAD2DEGF(-atan2(difmat[2][0], difmat[2][2])));
+ printf("Bone %s\n", curBone->name);
+ print_m4("premat", premat);
+ print_m4("postmat", postmat);
+ print_m4("difmat", difmat);
+ printf("Roll = %f\n", RAD2DEGF(-atan2(difmat[2][0], difmat[2][2])));
#endif
- curBone->roll = -atan2f(difmat[2][0], difmat[2][2]);
-
- /* and set restposition again */
- BKE_armature_where_is_bone(curBone, curBone->parent);
+
+ curBone->roll = -atan2f(difmat[2][0], difmat[2][2]);
+
+ /* and set restposition again */
+ BKE_armature_where_is_bone(curBone, curBone->parent, false);
+ break;
+ }
}
- fix_bonelist_roll(&curBone->childbase, editbonelist);
+
+ /* Recurse into children... */
+ armature_finalize_restpose(&curBone->childbase, editbonelist);
}
}
@@ -535,9 +565,9 @@ void ED_armature_from_edit(bArmature *arm)
/* remove zero sized bones, this gives unstable restposes */
for (eBone = arm->edbo->first; eBone; eBone = neBone) {
- float len = len_v3v3(eBone->head, eBone->tail);
+ float len_sq = len_squared_v3v3(eBone->head, eBone->tail);
neBone = eBone->next;
- if (len <= 0.000001f) { /* FLT_EPSILON is too large? */
+ if (len_sq <= SQUARE(0.000001f)) { /* FLT_EPSILON is too large? */
EditBone *fBone;
/* Find any bones that refer to this bone */
@@ -587,48 +617,29 @@ void ED_armature_from_edit(bArmature *arm)
newBone->prop = IDP_CopyProperty(eBone->prop);
}
- /* Fix parenting in a separate pass to ensure ebone->bone connections
- * are valid at this point */
+ /* Fix parenting in a separate pass to ensure ebone->bone connections are valid at this point.
+ * Do not set bone->head/tail here anymore, using EditBone data for that is not OK since our later fiddling
+ * with parent's arm_mat (for roll conversion) may have some small but visible impact on locations (T46010). */
for (eBone = arm->edbo->first; eBone; eBone = eBone->next) {
newBone = eBone->temp.bone;
if (eBone->parent) {
newBone->parent = eBone->parent->temp.bone;
BLI_addtail(&newBone->parent->childbase, newBone);
-
- {
- float M_parentRest[3][3];
- float iM_parentRest[3][3];
-
- /* Get the parent's matrix (rotation only) */
- ED_armature_ebone_to_mat3(eBone->parent, M_parentRest);
-
- /* Invert the parent matrix */
- invert_m3_m3(iM_parentRest, M_parentRest);
-
- /* Get the new head and tail */
- sub_v3_v3v3(newBone->head, eBone->head, eBone->parent->tail);
- sub_v3_v3v3(newBone->tail, eBone->tail, eBone->parent->tail);
-
- mul_m3_v3(iM_parentRest, newBone->head);
- mul_m3_v3(iM_parentRest, newBone->tail);
- }
}
/* ...otherwise add this bone to the armature's bonebase */
else {
- copy_v3_v3(newBone->head, eBone->head);
- copy_v3_v3(newBone->tail, eBone->tail);
BLI_addtail(&arm->bonebase, newBone);
}
}
- /* Make a pass through the new armature to fix rolling */
- /* also builds restposition again (like BKE_armature_where_is) */
- fix_bonelist_roll(&arm->bonebase, arm->edbo);
+ /* Finalize definition of restpose data (roll, bone_mat, arm_mat, head/tail...). */
+ armature_finalize_restpose(&arm->bonebase, arm->edbo);
/* so all users of this armature should get rebuilt */
for (obt = G.main->object.first; obt; obt = obt->id.next) {
- if (obt->data == arm)
+ if (obt->data == arm) {
BKE_pose_rebuild(obt, arm);
+ }
}
DAG_id_tag_update(&arm->id, 0);
diff --git a/source/blender/editors/armature/editarmature_sketch.c b/source/blender/editors/armature/editarmature_sketch.c
index c0098a3726a..e4c3f73dd94 100644
--- a/source/blender/editors/armature/editarmature_sketch.c
+++ b/source/blender/editors/armature/editarmature_sketch.c
@@ -436,7 +436,7 @@ static float sk_clampPointSize(SK_Point *pt, float size)
static void sk_drawPoint(GLUquadric *quad, SK_Point *pt, float size)
{
- glTranslatef(pt->p[0], pt->p[1], pt->p[2]);
+ glTranslate3fv(pt->p);
gluSphere(quad, sk_clampPointSize(pt, size), 8, 8);
}
@@ -455,7 +455,7 @@ static void sk_drawEdge(GLUquadric *quad, SK_Point *pt0, SK_Point *pt1, float si
angle = angle_normalized_v3v3(vec2, vec1);
- glRotatef(angle * (float)(180.0 / M_PI) + 180.0f, axis[0], axis[1], axis[2]);
+ glRotate3fv(angle * (float)(180.0 / M_PI) + 180.0f, axis);
gluCylinder(quad, sk_clampPointSize(pt1, size), sk_clampPointSize(pt0, size), length, 8, 8);
}
@@ -475,7 +475,7 @@ static void sk_drawNormal(GLUquadric *quad, SK_Point *pt, float size, float heig
angle = angle_normalized_v3v3(vec2, pt->no);
- glRotatef(angle * (float)(180.0 / M_PI), axis[0], axis[1], axis[2]);
+ glRotate3fv(angle * (float)(180.0 / M_PI), axis);
glColor3f(0, 1, 1);
gluCylinder(quad, sk_clampPointSize(pt, size), 0, sk_clampPointSize(pt, height), 10, 2);
@@ -2112,7 +2112,7 @@ static void sk_drawSketch(Scene *scene, View3D *UNUSED(v3d), SK_Sketch *sketch,
glColor3fv(colors[index]);
glPushMatrix();
- glTranslatef(p->p[0], p->p[1], p->p[2]);
+ glTranslate3fv(p->p);
gluSphere(quad, 0.02, 8, 8);
glPopMatrix();
}
diff --git a/source/blender/editors/curve/editcurve_select.c b/source/blender/editors/curve/editcurve_select.c
index cbb533a0440..34ac3b8bb97 100644
--- a/source/blender/editors/curve/editcurve_select.c
+++ b/source/blender/editors/curve/editcurve_select.c
@@ -999,20 +999,22 @@ void CURVE_OT_select_less(wmOperatorType *ot)
/********************** select random *********************/
-static void curve_select_random(ListBase *editnurb, float randfac, bool select)
+static void curve_select_random(ListBase *editnurb, float randfac, int seed, bool select)
{
Nurb *nu;
BezTriple *bezt;
BPoint *bp;
int a;
+ RNG *rng = BLI_rng_new_srandom(seed);
+
for (nu = editnurb->first; nu; nu = nu->next) {
if (nu->type == CU_BEZIER) {
bezt = nu->bezt;
a = nu->pntsu;
while (a--) {
if (!bezt->hide) {
- if (BLI_frand() < randfac) {
+ if (BLI_rng_get_float(rng) < randfac) {
select_beztriple(bezt, select, SELECT, VISIBLE);
}
}
@@ -1025,7 +1027,7 @@ static void curve_select_random(ListBase *editnurb, float randfac, bool select)
while (a--) {
if (!bp->hide) {
- if (BLI_frand() < randfac) {
+ if (BLI_rng_get_float(rng) < randfac) {
select_bpoint(bp, select, SELECT, VISIBLE);
}
}
@@ -1033,6 +1035,8 @@ static void curve_select_random(ListBase *editnurb, float randfac, bool select)
}
}
}
+
+ BLI_rng_free(rng);
}
static int curve_select_random_exec(bContext *C, wmOperator *op)
@@ -1041,8 +1045,9 @@ static int curve_select_random_exec(bContext *C, wmOperator *op)
ListBase *editnurb = object_editcurve_get(obedit);
const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT);
const float randfac = RNA_float_get(op->ptr, "percent") / 100.0f;
+ const int seed = RNA_int_get(op->ptr, "seed");
- curve_select_random(editnurb, randfac, select);
+ curve_select_random(editnurb, randfac, seed, select);
BKE_curve_nurb_vert_active_validate(obedit->data);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
@@ -1065,9 +1070,7 @@ void CURVE_OT_select_random(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- RNA_def_float_percentage(ot->srna, "percent", 50.f, 0.0f, 100.0f,
- "Percent", "Percentage of elements to select randomly", 0.0f, 100.0f);
- WM_operator_properties_select_action_simple(ot, SEL_SELECT);
+ WM_operator_properties_select_random(ot);
}
/********************* every nth number of point *******************/
@@ -1725,4 +1728,4 @@ void CURVE_OT_shortest_path_pick(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/** \} */ \ No newline at end of file
+/** \} */
diff --git a/source/blender/editors/gpencil/drawgpencil.c b/source/blender/editors/gpencil/drawgpencil.c
index ff8984ae329..6b71c0ac053 100644
--- a/source/blender/editors/gpencil/drawgpencil.c
+++ b/source/blender/editors/gpencil/drawgpencil.c
@@ -398,7 +398,7 @@ static void gp_draw_stroke_point(bGPDspoint *points, short thickness, short dfla
gluQuadricDrawStyle(qobj, GLU_FILL);
/* need to translate drawing position, but must reset after too! */
- glTranslatef(co[0], co[1], 0.0);
+ glTranslate2fv(co);
gluDisk(qobj, 0.0, thickness, 32, 1);
glTranslatef(-co[0], -co[1], 0.0);
diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c
index 184482eeacb..df88da073ca 100644
--- a/source/blender/editors/gpencil/gpencil_paint.c
+++ b/source/blender/editors/gpencil/gpencil_paint.c
@@ -756,7 +756,7 @@ static short gp_stroke_eraser_splitdel(bGPDframe *gpf, bGPDstroke *gps, int i)
else if (i == gps->totpoints - 2) {
/* allocate new points array, and assign most of the old stroke there */
gps->totpoints--;
- gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
+ gps->points = MEM_mallocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
memcpy(gps->points, pt_tmp, sizeof(bGPDspoint) * gps->totpoints);
/* free temp buffer */
@@ -770,7 +770,7 @@ static short gp_stroke_eraser_splitdel(bGPDframe *gpf, bGPDstroke *gps, int i)
else if (i == 0) {
/* allocate new points array, and assign most of the old stroke there */
gps->totpoints--;
- gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
+ gps->points = MEM_mallocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
memcpy(gps->points, pt_tmp + 1, sizeof(bGPDspoint) * gps->totpoints);
/* We must adjust timings!
@@ -807,7 +807,7 @@ static short gp_stroke_eraser_splitdel(bGPDframe *gpf, bGPDstroke *gps, int i)
BLI_insertlinkafter(&gpf->strokes, gps, gsn);
gsn->totpoints = gps->totpoints - i;
- gsn->points = MEM_callocN(sizeof(bGPDspoint) * gsn->totpoints, "gp_stroke_points");
+ gsn->points = MEM_mallocN(sizeof(bGPDspoint) * gsn->totpoints, "gp_stroke_points");
memcpy(gsn->points, pt_tmp + i, sizeof(bGPDspoint) * gsn->totpoints);
/* We must adjust timings of this new stroke!
@@ -831,8 +831,8 @@ static short gp_stroke_eraser_splitdel(bGPDframe *gpf, bGPDstroke *gps, int i)
/* adjust existing stroke */
gps->totpoints = i;
- gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
- memcpy(gps->points, pt_tmp, sizeof(bGPDspoint) * i);
+ gps->points = MEM_mallocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
+ memcpy(gps->points, pt_tmp, sizeof(bGPDspoint) * gps->totpoints);
/* free temp buffer */
MEM_freeN(pt_tmp);
diff --git a/source/blender/editors/include/BIF_gl.h b/source/blender/editors/include/BIF_gl.h
index 49c808e4f01..58da0b5d695 100644
--- a/source/blender/editors/include/BIF_gl.h
+++ b/source/blender/editors/include/BIF_gl.h
@@ -34,6 +34,7 @@
#define __BIF_GL_H__
#include "GPU_glew.h"
+#include "BLI_utildefines.h"
/*
* these should be phased out. cpack should be replaced in
@@ -85,5 +86,24 @@ void cpack(unsigned int x);
#define GLA_PIXEL_OFS 0.375f
+
+BLI_INLINE void glTranslate3iv(const int vec[3]) { glTranslatef(UNPACK3_EX((const float), vec, )); }
+BLI_INLINE void glTranslate2iv(const int vec[2]) { glTranslatef(UNPACK2_EX((const float), vec, ), 0.0f); }
+BLI_INLINE void glTranslate3fv(const float vec[3]) { glTranslatef(UNPACK3(vec)); }
+BLI_INLINE void glTranslate2fv(const float vec[2]) { glTranslatef(UNPACK2(vec), 0.0f); }
+BLI_INLINE void glTranslate3dv(const double vec[3]) { glTranslated(UNPACK3(vec)); }
+BLI_INLINE void glTranslate2dv(const double vec[2]) { glTranslated(UNPACK2(vec), 0.0f); }
+
+BLI_INLINE void glScale3iv(const int vec[3]) { glTranslatef(UNPACK3_EX((const float), vec, )); }
+BLI_INLINE void glScale2iv(const int vec[2]) { glTranslatef(UNPACK2_EX((const float), vec, ), 0.0f); }
+BLI_INLINE void glScale3fv(const float vec[3]) { glScalef(UNPACK3(vec)); }
+BLI_INLINE void glScale2fv(const float vec[2]) { glScalef(UNPACK2(vec), 0.0); }
+BLI_INLINE void glScale3dv(const double vec[3]) { glScaled(UNPACK3(vec)); }
+BLI_INLINE void glScale2dv(const double vec[2]) { glScaled(UNPACK2(vec), 0.0); }
+
+/* v2 versions don't make much sense for rotation */
+BLI_INLINE void glRotate3fv(const float angle, const float vec[3]) { glRotatef(angle, UNPACK3(vec)); }
+BLI_INLINE void glRotate3dv(const double angle, const double vec[3]) { glRotated(angle, UNPACK3(vec)); }
+
#endif /* #ifdef __BIF_GL_H__ */
diff --git a/source/blender/editors/include/ED_image.h b/source/blender/editors/include/ED_image.h
index f49d4b508c6..4c4cec2ee29 100644
--- a/source/blender/editors/include/ED_image.h
+++ b/source/blender/editors/include/ED_image.h
@@ -59,8 +59,8 @@ void ED_space_image_get_uv_aspect(struct SpaceImage *sima, float *aspx, float *a
void ED_space_image_scopes_update(const struct bContext *C, struct SpaceImage *sima, struct ImBuf *ibuf, bool use_view_settings);
-void ED_space_image_paint_update(struct wmWindowManager *wm, struct ToolSettings *settings);
-void ED_space_image_uv_sculpt_update(struct wmWindowManager *wm, struct ToolSettings *settings);
+void ED_space_image_paint_update(struct wmWindowManager *wm, struct Scene *scene);
+void ED_space_image_uv_sculpt_update(struct wmWindowManager *wm, struct Scene *scene);
void ED_image_get_uv_aspect(struct Image *ima, struct ImageUser *iuser, float *aspx, float *aspy);
void ED_image_mouse_pos(struct SpaceImage *sima, struct ARegion *ar, const int mval[2], float co[2]);
diff --git a/source/blender/editors/include/ED_render.h b/source/blender/editors/include/ED_render.h
index 1898b9cb5d1..707d7c6c693 100644
--- a/source/blender/editors/include/ED_render.h
+++ b/source/blender/editors/include/ED_render.h
@@ -49,6 +49,7 @@ void ED_render_id_flush_update(struct Main *bmain, struct ID *id);
void ED_render_engine_changed(struct Main *bmain);
void ED_render_engine_area_exit(struct Main *bmain, struct ScrArea *sa);
void ED_render_scene_update(struct Main *bmain, struct Scene *scene, int updated);
+void ED_render_scene_update_pre(struct Main *bmain, struct Scene *scene, bool time);
void ED_viewport_render_kill_jobs(struct wmWindowManager *wm, struct Main *bmain, bool free_database);
struct Scene *ED_render_job_get_scene(const struct bContext *C);
diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h
index 6c9150cbb74..2a7d79c9d1c 100644
--- a/source/blender/editors/include/ED_screen.h
+++ b/source/blender/editors/include/ED_screen.h
@@ -69,7 +69,7 @@ void ED_region_header_init(struct ARegion *ar);
void ED_region_header(const struct bContext *C, struct ARegion *ar);
void ED_region_toggle_hidden(struct bContext *C, struct ARegion *ar);
void ED_region_info_draw(struct ARegion *ar, const char *text, float fill_color[4], const bool full_redraw);
-void ED_region_image_metadata_draw(int x, int y, struct ImBuf *ibuf, rctf frame, float zoomx, float zoomy);
+void ED_region_image_metadata_draw(int x, int y, struct ImBuf *ibuf, const rctf *frame, float zoomx, float zoomy);
void ED_region_grid_draw(struct ARegion *ar, float zoomx, float zoomy);
void ED_region_draw_backdrop_view3d(const struct bContext *C, struct Object *camera, const float alpha,
const float width, const float height, const float x, const float y,
diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h
index 080820e67a1..17db1cb8548 100644
--- a/source/blender/editors/include/ED_transform.h
+++ b/source/blender/editors/include/ED_transform.h
@@ -135,7 +135,7 @@ void BIF_createTransformOrientation(struct bContext *C, struct ReportList *repor
void BIF_selectTransformOrientation(struct bContext *C, struct TransformOrientation *ts);
void BIF_selectTransformOrientationValue(struct bContext *C, int orientation);
-void ED_getTransformOrientationMatrix(const struct bContext *C, float orientation_mat[3][3], const bool activeOnly);
+void ED_getTransformOrientationMatrix(const struct bContext *C, float orientation_mat[3][3], const short around);
int BIF_countTransformOrientation(const struct bContext *C);
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index 84e09910c85..97696c8fd47 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -329,15 +329,20 @@ bool ED_view3d_context_activate(struct bContext *C);
void ED_view3d_draw_offscreen_init(struct Scene *scene, struct View3D *v3d);
void ED_view3d_draw_offscreen(
struct Scene *scene, struct View3D *v3d, struct ARegion *ar, int winx, int winy, float viewmat[4][4],
- float winmat[4][4], bool do_bgpic, bool do_sky, bool is_persp,
- struct GPUOffScreen *ofs,
+ float winmat[4][4], bool do_bgpic, bool do_sky, bool is_persp, const char *viewname,
struct GPUFX *fx, struct GPUFXSettings *fx_settings,
- const char *viewname);
-
-struct ImBuf *ED_view3d_draw_offscreen_imbuf(struct Scene *scene, struct View3D *v3d, struct ARegion *ar, int sizex, int sizey, unsigned int flag,
- bool draw_background, int alpha_mode, const char *viewname, char err_out[256]);
-struct ImBuf *ED_view3d_draw_offscreen_imbuf_simple(struct Scene *scene, struct Object *camera, int width, int height, unsigned int flag, int drawtype,
- bool use_solid_tex, bool use_gpencil, bool draw_background, int alpha_mode, const char *viewname, char err_out[256]);
+ struct GPUOffScreen *ofs);
+
+struct ImBuf *ED_view3d_draw_offscreen_imbuf(
+ struct Scene *scene, struct View3D *v3d, struct ARegion *ar, int sizex, int sizey,
+ unsigned int flag, bool draw_background,
+ int alpha_mode, int samples, const char *viewname,
+ struct GPUOffScreen *ofs, char err_out[256]);
+struct ImBuf *ED_view3d_draw_offscreen_imbuf_simple(
+ struct Scene *scene, struct Object *camera, int width, int height,
+ unsigned int flag, int drawtype, bool use_solid_tex, bool use_gpencil, bool draw_background,
+ int alpha_mode, int samples, const char *viewname,
+ struct GPUOffScreen *ofs, char err_out[256]);
struct Base *ED_view3d_give_base_under_cursor(struct bContext *C, const int mval[2]);
void ED_view3d_quadview_update(struct ScrArea *sa, struct ARegion *ar, bool do_clip);
diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h
index 32f45b222aa..286235e95eb 100644
--- a/source/blender/editors/include/UI_icons.h
+++ b/source/blender/editors/include/UI_icons.h
@@ -374,8 +374,8 @@ DEF_ICON(MESH_MONKEY)
DEF_ICON(MESH_CYLINDER)
DEF_ICON(MESH_TORUS)
DEF_ICON(MESH_CONE)
+DEF_ICON(MESH_CAPSULE)
#ifndef DEF_ICON_BLANK_SKIP
- DEF_ICON(BLANK610)
DEF_ICON(BLANK611)
#endif
DEF_ICON(LAMP_POINT)
@@ -702,14 +702,12 @@ DEF_ICON(MANIPUL)
DEF_ICON(SNAP_OFF)
DEF_ICON(SNAP_ON)
DEF_ICON(SNAP_NORMAL)
-DEF_ICON(SNAP_INCREMENT)
+DEF_ICON(SNAP_GRID)
DEF_ICON(SNAP_VERTEX)
DEF_ICON(SNAP_EDGE)
DEF_ICON(SNAP_FACE)
DEF_ICON(SNAP_VOLUME)
-#ifndef DEF_ICON_BLANK_SKIP
- DEF_ICON(BLANK220)
-#endif
+DEF_ICON(SNAP_INCREMENT)
DEF_ICON(STICKY_UVS_LOC)
DEF_ICON(STICKY_UVS_DISABLE)
DEF_ICON(STICKY_UVS_VERT)
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 3fb41069449..8125ab4297e 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -1050,6 +1050,8 @@ void UI_butstore_unregister(uiButStore *bs_handle, uiBut **but_p);
/* Float precision helpers */
#define UI_PRECISION_FLOAT_MAX 7
+/* For float buttons the 'step' (or a1), is scaled */
+#define UI_PRECISION_FLOAT_SCALE 0.01f
/* Typical UI text */
#define UI_FSTYLE_WIDGET (const uiFontStyle *)&(UI_style_get()->widget)
diff --git a/source/blender/editors/include/UI_view2d.h b/source/blender/editors/include/UI_view2d.h
index 43a55845d49..7335233a215 100644
--- a/source/blender/editors/include/UI_view2d.h
+++ b/source/blender/editors/include/UI_view2d.h
@@ -155,7 +155,7 @@ void UI_view2d_curRect_reset(struct View2D *v2d);
void UI_view2d_sync(struct bScreen *screen, struct ScrArea *sa, struct View2D *v2dcur, int flag);
void UI_view2d_totRect_set(struct View2D *v2d, int width, int height);
-void UI_view2d_totRect_set_resize(struct View2D *v2d, int width, int height, int resize);
+void UI_view2d_totRect_set_resize(struct View2D *v2d, int width, int height, bool resize);
/* per tab offsets, returns 1 if tab changed */
bool UI_view2d_tab_set(struct View2D *v2d, int tab);
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 4c42d5bac99..0ee4a30d005 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -375,9 +375,11 @@ static void ui_block_bounds_calc_popup(
wmWindow *window, uiBlock *block,
eBlockBoundsCalc bounds_calc, const int xy[2])
{
- int startx, starty, endx, endy, width, height, oldwidth, oldheight;
+ int width, height, oldwidth, oldheight;
int oldbounds, xmax, ymax;
const int margin = UI_SCREEN_MARGIN;
+ rcti rect, rect_bounds;
+ int ofs_dummy[2];
oldbounds = block->bounds;
@@ -412,27 +414,18 @@ static void ui_block_bounds_calc_popup(
/* offset block based on mouse position, user offset is scaled
* along in case we resized the block in ui_block_bounds_calc_text */
- startx = xy[0] + block->rect.xmin + (block->mx * width) / oldwidth;
- starty = xy[1] + block->rect.ymin + (block->my * height) / oldheight;
+ rect.xmin = xy[0] + block->rect.xmin + (block->mx * width) / oldwidth;
+ rect.ymin = xy[1] + block->rect.ymin + (block->my * height) / oldheight;
+ rect.xmax = rect.xmin + width;
+ rect.ymax = rect.ymin + height;
- if (startx < margin)
- startx = margin;
- if (starty < margin)
- starty = margin;
+ rect_bounds.xmin = margin;
+ rect_bounds.ymin = margin;
+ rect_bounds.xmax = xmax - margin;
+ rect_bounds.ymax = ymax - UI_POPUP_MENU_TOP;
- endx = startx + width;
- endy = starty + height;
-
- if (endx > xmax) {
- endx = xmax - margin;
- startx = endx - width;
- }
- if (endy > ymax - margin) {
- endy = ymax - margin;
- starty = endy - height;
- }
-
- ui_block_translate(block, startx - block->rect.xmin, starty - block->rect.ymin);
+ BLI_rcti_clamp(&rect, &rect_bounds, ofs_dummy);
+ ui_block_translate(block, rect.xmin - block->rect.xmin, rect.ymin - block->rect.ymin);
/* now recompute bounds and safety */
ui_block_bounds_calc(block);
@@ -1849,6 +1842,16 @@ bool ui_but_is_rna_valid(uiBut *but)
}
}
+/**
+ * Checks if the button supports ctrl+mousewheel cycling
+ */
+bool ui_but_supports_cycling(const uiBut *but)
+{
+ return ((ELEM(but->type, UI_BTYPE_ROW, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER, UI_BTYPE_LISTBOX)) ||
+ (but->type == UI_BTYPE_MENU && ui_but_menu_step_poll(but)) ||
+ (but->type == UI_BTYPE_COLOR && but->a1 != -1));
+}
+
double ui_but_value_get(uiBut *but)
{
PropertyRNA *prop;
@@ -2121,14 +2124,32 @@ static void ui_get_but_string_unit(uiBut *but, char *str, int len_max, double va
static float ui_get_but_step_unit(uiBut *but, float step_default)
{
int unit_type = RNA_SUBTYPE_UNIT_VALUE(UI_but_unit_type_get(but));
- double step;
-
- step = bUnit_ClosestScalar(ui_get_but_scale_unit(but, step_default), but->block->unit->system, unit_type);
+ const double step_orig = step_default * UI_PRECISION_FLOAT_SCALE;
+ /* Scaling up 'step_origg ' here is a bit arbitrary, its just giving better scales from user POV */
+ const double scale_step = ui_get_but_scale_unit(but, step_orig * 10);
+ const double step = bUnit_ClosestScalar(scale_step, but->block->unit->system, unit_type);
/* -1 is an error value */
if (step != -1.0) {
+ const double scale_unit = ui_get_but_scale_unit(but, 1.0);
+ const double step_unit = bUnit_ClosestScalar(scale_unit, but->block->unit->system, unit_type);
+ double step_final;
+
BLI_assert(step > 0.0);
- return (float)(step / ui_get_but_scale_unit(but, 1.0));
+
+ step_final = (step / scale_unit) / (double)UI_PRECISION_FLOAT_SCALE;
+
+ if (step == step_unit) {
+ /* Logic here is to scale by the original 'step_orig'
+ * only when the unit step matches the scaled step.
+ *
+ * This is needed for units that don't have a wide range of scales (degrees for eg.).
+ * Without this we can't select between a single degree, or a 10th of a degree.
+ */
+ step_final *= step_orig;
+ }
+
+ return (float)step_final;
}
else {
return step_default;
@@ -2172,8 +2193,14 @@ void ui_but_string_get_ex(uiBut *but, char *str, const size_t maxlen, const int
str[0] = '\0';
}
else if (buf && buf != str) {
+ BLI_assert(maxlen <= buf_len + 1);
/* string was too long, we have to truncate */
- memcpy(str, buf, MIN2(maxlen, (size_t)(buf_len + 1)));
+ if (ui_but_is_utf8(but)) {
+ BLI_strncpy_utf8(str, buf, maxlen);
+ }
+ else {
+ BLI_strncpy(str, buf, maxlen);
+ }
MEM_freeN((void *)buf);
}
}
@@ -3170,6 +3197,20 @@ void ui_block_cm_to_scene_linear_v3(uiBlock *block, float pixel[3])
IMB_colormanagement_display_to_scene_linear_v3(pixel, display);
}
+void ui_block_cm_to_display_space_range(uiBlock *block, float *min, float *max)
+{
+ struct ColorManagedDisplay *display = ui_block_cm_display_get(block);
+ float pixel[3];
+
+ copy_v3_fl(pixel, *min);
+ IMB_colormanagement_scene_linear_to_display_v3(pixel, display);
+ *min = min_fff(UNPACK3(pixel));
+
+ copy_v3_fl(pixel, *max);
+ IMB_colormanagement_scene_linear_to_display_v3(pixel, display);
+ *max = max_fff(UNPACK3(pixel));
+}
+
static uiSubBut *ui_def_subbut(
uiBut *but, const int type,
uiSubButAlign alignment,
diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c
index 0193c1b3a7c..968b3ea1934 100644
--- a/source/blender/editors/interface/interface_draw.c
+++ b/source/blender/editors/interface/interface_draw.c
@@ -675,8 +675,8 @@ void ui_draw_but_HISTOGRAM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol)
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
- glColor4f(0.f, 0.f, 0.f, 0.3f);
+
+ UI_ThemeColor4(TH_PREVIEW_BACK);
UI_draw_roundbox_corner_set(UI_CNR_ALL);
UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f);
@@ -762,8 +762,8 @@ void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol),
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
- glColor4f(0.f, 0.f, 0.f, 0.3f);
+
+ UI_ThemeColor4(TH_PREVIEW_BACK);
UI_draw_roundbox_corner_set(UI_CNR_ALL);
UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f);
@@ -981,8 +981,8 @@ void ui_draw_but_VECTORSCOPE(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wco
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
- glColor4f(0.f, 0.f, 0.f, 0.3f);
+
+ UI_ThemeColor4(TH_PREVIEW_BACK);
UI_draw_roundbox_corner_set(UI_CNR_ALL);
UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f);
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 5d2b6e3c9c6..b2688619e7a 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -138,6 +138,8 @@ static bool ui_mouse_motion_keynav_test(struct uiKeyNavLock *keynav, const wmEve
#define MENU_TOWARDS_MARGIN 20 /* margin in pixels */
#define MENU_TOWARDS_WIGGLE_ROOM 64 /* tolerance in pixels */
+/* drag-lock distance threshold in pixels */
+#define BUTTON_DRAGLOCK_THRESH 3
typedef enum uiButtonActivateType {
BUTTON_ACTIVATE_OVER,
@@ -530,6 +532,30 @@ static bool ui_but_is_cursor_warp(uiBut *but)
return false;
}
+/**
+ * Ignore mouse movements within some horizontal pixel threshold before starting to drag
+ */
+static bool ui_but_dragedit_update_mval(uiHandleButtonData *data, int mx)
+{
+ if (mx == data->draglastx)
+ return false;
+
+ if (data->draglock) {
+ if (ABS(mx - data->dragstartx) <= BUTTON_DRAGLOCK_THRESH) {
+ return false;
+ }
+#ifdef USE_DRAG_MULTINUM
+ if (ELEM(data->multi_data.init, BUTTON_MULTI_INIT_UNSET, BUTTON_MULTI_INIT_SETUP)) {
+ return false;
+ }
+#endif
+ data->draglock = false;
+ data->dragstartx = mx; /* ignore mouse movement within drag-lock */
+ }
+
+ return true;
+}
+
static float ui_mouse_scale_warp_factor(const bool shift)
{
return shift ? 0.05f : 1.0f;
@@ -3949,8 +3975,12 @@ static float ui_numedit_apply_snapf(
/* snapping by 10's for float buttons is quite annoying (location, scale...),
* but allow for rotations */
if (softrange >= 21.0f) {
+ UnitSettings *unit = but->block->unit;
int unit_type = UI_but_unit_type_get(but);
- if (!ELEM(unit_type, PROP_UNIT_ROTATION)) {
+ if ((unit_type == PROP_UNIT_ROTATION) && (unit->system_rotation != USER_UNIT_ROT_RADIANS)) {
+ /* pass (degrees)*/
+ }
+ else {
softrange = 20.0f;
}
}
@@ -4006,23 +4036,10 @@ static bool ui_numedit_but_NUM(
int lvalue, temp;
bool changed = false;
const bool is_float = ui_but_is_float(but);
-
- if (mx == data->draglastx)
- return changed;
-
- /* drag-lock - prevent unwanted scroll adjustments */
- /* change value (now 3) to adjust threshold in pixels */
- if (data->draglock) {
- if (abs(mx - data->dragstartx) <= 3)
- return changed;
-#ifdef USE_DRAG_MULTINUM
- if (ELEM(data->multi_data.init, BUTTON_MULTI_INIT_UNSET, BUTTON_MULTI_INIT_SETUP)) {
- return changed;
- }
-#endif
- data->draglock = false;
- data->dragstartx = mx; /* ignore mouse movement within drag-lock */
+ /* prevent unwanted drag adjustments */
+ if (ui_but_dragedit_update_mval(data, mx) == false) {
+ return changed;
}
softmin = but->softmin;
@@ -4319,6 +4336,13 @@ static bool ui_numedit_but_SLI(
/* note, 'offs' is really from the widget drawing rounded corners see 'widget_numslider' */
float offs;
+ /* prevent unwanted drag adjustments */
+ if ((but->type != UI_BTYPE_SCROLL) &&
+ (ui_but_dragedit_update_mval(data, mx) == false))
+ {
+ return changed;
+ }
+
softmin = but->softmin;
softmax = but->softmax;
softrange = softmax - softmin;
@@ -4498,6 +4522,10 @@ static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
}
}
else {
+#ifdef USE_CONT_MOUSE_CORRECT
+ /* reset! */
+ copy_v2_fl(data->ungrab_mval, FLT_MAX);
+#endif
click = 1;
}
}
@@ -5187,11 +5215,16 @@ static bool ui_numedit_but_HSVCUBE(
hsv[2] = y;
break;
case UI_GRAD_V_ALT:
+ {
/* vertical 'value' strip */
-
+ float min = but->softmin, max = but->softmax;
+ if (use_display_colorspace) {
+ ui_block_cm_to_display_space_range(but->block, &min, &max);
+ }
/* exception only for value strip - use the range set in but->min/max */
- hsv[2] = y * (but->softmax - but->softmin) + but->softmin;
+ hsv[2] = y * (max - min) + min;
break;
+ }
default:
BLI_assert(0);
break;
@@ -5690,7 +5723,9 @@ static int ui_do_but_COLORBAND(bContext *C, uiBlock *block, uiBut *but, uiHandle
{
ColorBand *coba;
CBData *cbd;
- int mx, my, a, xco, mindist = 12;
+ /* ignore zoom-level for mindist */
+ int mindist = (50 * UI_DPI_FAC) * block->aspect;
+ int mx, my, a, xco;
mx = event->x;
my = event->y;
@@ -6664,30 +6699,44 @@ static bool ui_but_menu(bContext *C, uiBut *but)
int w = uiLayoutGetWidth(layout);
wmKeyMap *km;
wmKeyMapItem *kmi = NULL;
- int kmi_id = WM_key_event_operator_id(C, but->optype->idname, but->opcontext, prop, true, &km);
+ /* We want to know if this op has a shortcut, be it hotkey or not. */
+ int kmi_id = WM_key_event_operator_id(C, but->optype->idname, but->opcontext, prop, false, &km);
if (kmi_id)
kmi = WM_keymap_item_find_id(km, kmi_id);
- /* keyboard shortcuts */
- if ((kmi) && ISKEYBOARD(kmi->type)) {
+ /* We do have a shortcut, but only keyboard ones are editbale that way... */
+ if (kmi) {
+ if (ISKEYBOARD(kmi->type)) {
+#if 0 /* would rather use a block but, but gets weirdly positioned... */
+ uiDefBlockBut(block, menu_change_shortcut, but, "Change Shortcut",
+ 0, 0, uiLayoutGetWidth(layout), UI_UNIT_Y, "");
+#endif
- /* would rather use a block but, but gets weirdly positioned... */
- //uiDefBlockBut(block, menu_change_shortcut, but, "Change Shortcut", 0, 0, uiLayoutGetWidth(layout), UI_UNIT_Y, "");
-
- but2 = uiDefIconTextBut(block, UI_BTYPE_BUT, 0, 0, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Change Shortcut"),
- 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
- UI_but_func_set(but2, popup_change_shortcut_func, but, NULL);
+ but2 = uiDefIconTextBut(block, UI_BTYPE_BUT, 0, ICON_NONE,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Change Shortcut"),
+ 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
+ UI_but_func_set(but2, popup_change_shortcut_func, but, NULL);
- but2 = uiDefIconTextBut(block, UI_BTYPE_BUT, 0, 0, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove Shortcut"),
- 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
- UI_but_func_set(but2, remove_shortcut_func, but, NULL);
+ but2 = uiDefIconTextBut(block, UI_BTYPE_BUT, 0, ICON_NONE,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove Shortcut"),
+ 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
+ UI_but_func_set(but2, remove_shortcut_func, but, NULL);
+ }
+ else {
+ but2 = uiDefIconTextBut(block, UI_BTYPE_BUT, 0, ICON_NONE, IFACE_("Non-Keyboard Shortcut"),
+ 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0,
+ TIP_("Only keyboard shortcuts can be edited that way, "
+ "please use User Preferences otherwise"));
+ UI_but_flag_enable(but2, UI_BUT_DISABLED);
+ }
is_first_item = false;
}
/* only show 'add' if there's a suitable key map for it to go in */
else if (WM_keymap_guess_opname(C, but->optype->idname)) {
- but2 = uiDefIconTextBut(block, UI_BTYPE_BUT, 0, 0, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add Shortcut"),
+ but2 = uiDefIconTextBut(block, UI_BTYPE_BUT, 0, ICON_NONE,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add Shortcut"),
0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
UI_but_func_set(but2, popup_add_shortcut_func, but, NULL);
@@ -7442,7 +7491,7 @@ static uiSubBut *ui_subbut_find_mouse_over(const ARegion *ar, const uiBut *but,
}
-static uiBut *ui_list_find_mouse_over(ARegion *ar, int x, int y)
+static uiBut *ui_list_find_mouse_over_ex(ARegion *ar, int x, int y)
{
uiBlock *block;
uiBut *but;
@@ -7466,6 +7515,11 @@ static uiBut *ui_list_find_mouse_over(ARegion *ar, int x, int y)
return NULL;
}
+static uiBut *ui_list_find_mouse_over(ARegion *ar, const wmEvent *event)
+{
+ return ui_list_find_mouse_over_ex(ar, event->x, event->y);
+}
+
/* ****************** button state handling **************************/
static bool button_modal_state(uiHandleButtonState state)
@@ -8353,21 +8407,15 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but)
return retval;
}
-static int ui_handle_list_event(bContext *C, const wmEvent *event, ARegion *ar)
+static int ui_handle_list_event(bContext *C, const wmEvent *event, ARegion *ar, uiBut *listbox)
{
- uiBut *but;
uiList *ui_list;
uiListDyn *dyn_data;
int retval = WM_UI_HANDLER_CONTINUE;
int type = event->type, val = event->val;
int mx, my;
- but = ui_list_find_mouse_over(ar, event->x, event->y);
- if (!but) {
- return retval;
- }
-
- ui_list = but->custom_data;
+ ui_list = listbox->custom_data;
if (!ui_list || !ui_list->dyn_data) {
return retval;
}
@@ -8375,7 +8423,7 @@ static int ui_handle_list_event(bContext *C, const wmEvent *event, ARegion *ar)
mx = event->x;
my = event->y;
- ui_window_to_block(ar, but->block, &mx, &my);
+ ui_window_to_block(ar, listbox->block, &mx, &my);
/* convert pan to scrollwheel */
if (type == MOUSEPAN) {
@@ -8391,7 +8439,7 @@ static int ui_handle_list_event(bContext *C, const wmEvent *event, ARegion *ar)
if (ELEM(type, UPARROWKEY, DOWNARROWKEY) ||
((ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->ctrl)))
{
- const int value_orig = RNA_property_int_get(&but->rnapoin, but->rnaprop);
+ const int value_orig = RNA_property_int_get(&listbox->rnapoin, listbox->rnaprop);
int value, min, max, inc;
/* activate up/down the list */
@@ -8444,14 +8492,14 @@ static int ui_handle_list_event(bContext *C, const wmEvent *event, ARegion *ar)
CLAMP(value, 0, dyn_data->items_len - 1);
- RNA_property_int_range(&but->rnapoin, but->rnaprop, &min, &max);
+ RNA_property_int_range(&listbox->rnapoin, listbox->rnaprop, &min, &max);
CLAMP(value, min, max);
if (value != value_orig) {
- RNA_property_int_set(&but->rnapoin, but->rnaprop, value);
- RNA_property_update(C, &but->rnapoin, but->rnaprop);
+ RNA_property_int_set(&listbox->rnapoin, listbox->rnaprop, value);
+ RNA_property_update(C, &listbox->rnapoin, listbox->rnaprop);
- ui_apply_but_undo(but);
+ ui_apply_but_undo(listbox);
ui_list->flag |= UILST_SCROLL_TO_ACTIVE_ITEM;
ED_region_tag_redraw(ar);
@@ -8871,7 +8919,7 @@ static int ui_handle_menu_event(
/* check if mouse is inside block */
inside = BLI_rctf_isect_pt(&block->rect, mx, my);
- inside_title = inside && ((my + UI_MENU_TITLE_HEIGHT) > block->rect.ymax);
+ inside_title = inside && ((my + (UI_UNIT_Y * 1.5f)) > block->rect.ymax);
/* if there's an active modal button, don't check events or outside, except for search menu */
but = ui_but_find_active_in_region(ar);
@@ -9776,7 +9824,7 @@ static int ui_tab_region_handler(bContext *C, const wmEvent *event, ARegion *ar)
static int ui_region_handler(bContext *C, const wmEvent *event, void *UNUSED(userdata))
{
ARegion *ar;
- uiBut *but;
+ uiBut *but, *listbox;
int retval;
/* here we handle buttons at the region level, non-modal */
@@ -9789,14 +9837,15 @@ static int ui_region_handler(bContext *C, const wmEvent *event, void *UNUSED(use
/* either handle events for already activated button or try to activate */
but = ui_but_find_active_in_region(ar);
+ listbox = ui_list_find_mouse_over(ar, event);
- retval = ui_handler_panel_region(C, event, ar);
+ retval = ui_handler_panel_region(C, event, ar, listbox ? listbox : but);
if (retval == WM_UI_HANDLER_CONTINUE)
retval = ui_tab_region_handler(C, event, ar);
- if (retval == WM_UI_HANDLER_CONTINUE)
- retval = ui_handle_list_event(C, event, ar);
+ if (retval == WM_UI_HANDLER_CONTINUE && listbox)
+ retval = ui_handle_list_event(C, event, ar, listbox);
if (retval == WM_UI_HANDLER_CONTINUE) {
if (but)
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index ac946606a9a..811b3583c5d 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -521,6 +521,7 @@ extern bool ui_but_is_unit(const uiBut *but) ATTR_WARN_UNUSED_RESULT;
extern bool ui_but_is_compatible(const uiBut *but_a, const uiBut *but_b) ATTR_WARN_UNUSED_RESULT;
extern bool ui_but_is_rna_valid(uiBut *but) ATTR_WARN_UNUSED_RESULT;
extern bool ui_but_is_utf8(const uiBut *but) ATTR_WARN_UNUSED_RESULT;
+extern bool ui_but_supports_cycling(const uiBut *but) ATTR_WARN_UNUSED_RESULT;
extern int ui_but_is_pushed_ex(uiBut *but, double *value) ATTR_WARN_UNUSED_RESULT;
extern int ui_but_is_pushed(uiBut *but) ATTR_WARN_UNUSED_RESULT;
@@ -533,6 +534,7 @@ extern void ui_block_align_calc(uiBlock *block);
extern struct ColorManagedDisplay *ui_block_cm_display_get(uiBlock *block);
void ui_block_cm_to_display_space_v3(uiBlock *block, float pixel[3]);
void ui_block_cm_to_scene_linear_v3(uiBlock *block, float pixel[3]);
+void ui_block_cm_to_display_space_range(uiBlock *block, float *min, float *max);
/* interface_regions.c */
@@ -641,11 +643,14 @@ uiPopupBlockHandle *ui_popup_menu_create(
void ui_popup_block_free(struct bContext *C, uiPopupBlockHandle *handle);
-int ui_but_menu_step(uiBut *but, int step);
+int ui_but_menu_step(uiBut *but, int step);
+bool ui_but_menu_step_poll(const uiBut *but);
/* interface_panel.c */
-extern int ui_handler_panel_region(struct bContext *C, const struct wmEvent *event, struct ARegion *ar);
+extern int ui_handler_panel_region(
+ struct bContext *C, const struct wmEvent *event,
+ struct ARegion *ar, const uiBut *active_but);
extern void ui_draw_aligned_panel(struct uiStyle *style, uiBlock *block, const rcti *rect, const bool show_pin);
/* interface_draw.c */
@@ -716,6 +721,8 @@ void ui_draw_preview_item(struct uiFontStyle *fstyle, rcti *rect, const char *na
#define UI_TEXT_MARGIN_X 0.4f
#define UI_POPUP_MARGIN (UI_DPI_FAC * 12)
+/* margin at top of screen for popups */
+#define UI_POPUP_MENU_TOP (int)(8 * UI_DPI_FAC)
/* interface_style.c */
void uiStyleInit(void);
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index 99a44f265ec..593138869a8 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -3455,6 +3455,10 @@ void uiLayoutOperatorButs(
/* XXX, could give some nicer feedback or not show redo panel at all? */
uiItemL(layout, IFACE_("* Redo Unsupported *"), ICON_NONE);
}
+ else {
+ /* useful for macros where only one of the steps can't be re-done */
+ UI_block_lock_clear(uiLayoutGetBlock(layout));
+ }
/* menu */
if (op->type->flag & OPTYPE_PRESET) {
diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c
index 076412d475f..d9f4689748f 100644
--- a/source/blender/editors/interface/interface_panel.c
+++ b/source/blender/editors/interface/interface_panel.c
@@ -1942,7 +1942,7 @@ void UI_panel_category_draw_all(ARegion *ar, const char *category_id_active)
/* XXX should become modal keymap */
/* AKey is opening/closing panels, independent of button state now */
-int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar)
+int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar, const uiBut *active_but)
{
uiBlock *block;
Panel *pa;
@@ -1970,20 +1970,26 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar)
/* first check if the mouse is in the tab region */
if (event->ctrl || (event->mval[0] < ((PanelCategoryDyn *)ar->panels_category.first)->rect.xmax)) {
- const char *category = UI_panel_category_active_get(ar, false);
- if (LIKELY(category)) {
- PanelCategoryDyn *pc_dyn = UI_panel_category_find(ar, category);
- if (LIKELY(pc_dyn)) {
- pc_dyn = (event->type == WHEELDOWNMOUSE) ? pc_dyn->next : pc_dyn->prev;
- if (pc_dyn) {
- /* intentionally don't reset scroll in this case,
- * this allows for quick browsing between tabs */
- UI_panel_category_active_set(ar, pc_dyn->idname);
- ED_region_tag_redraw(ar);
+ if (active_but && ui_but_supports_cycling(active_but)) {
+ /* skip - exception to make cycling buttons
+ * using ctrl+mousewheel work in tabbed regions */
+ }
+ else {
+ const char *category = UI_panel_category_active_get(ar, false);
+ if (LIKELY(category)) {
+ PanelCategoryDyn *pc_dyn = UI_panel_category_find(ar, category);
+ if (LIKELY(pc_dyn)) {
+ pc_dyn = (event->type == WHEELDOWNMOUSE) ? pc_dyn->next : pc_dyn->prev;
+ if (pc_dyn) {
+ /* intentionally don't reset scroll in this case,
+ * this allows for quick browsing between tabs */
+ UI_panel_category_active_set(ar, pc_dyn->idname);
+ ED_region_tag_redraw(ar);
+ }
}
}
+ retval = WM_UI_HANDLER_BREAK;
}
- retval = WM_UI_HANDLER_BREAK;
}
}
}
diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c
index 24e6e17a89e..bfaf03cdce0 100644
--- a/source/blender/editors/interface/interface_regions.c
+++ b/source/blender/editors/interface/interface_regions.c
@@ -70,7 +70,6 @@
#include "interface_intern.h"
-#define MENU_TOP (int)(8 * UI_DPI_FAC)
#define MENU_PADDING (int)(0.2f * UI_UNIT_Y)
#define MENU_BORDER (int)(0.3f * U.widget_unit)
@@ -107,15 +106,22 @@ static int rna_property_enum_step(const bContext *C, PointerRNA *ptr, PropertyRN
return value;
}
-int ui_but_menu_step(uiBut *but, int direction)
+bool ui_but_menu_step_poll(const uiBut *but)
{
+ BLI_assert(but->type == UI_BTYPE_MENU);
+
/* currenly only RNA buttons */
- if ((but->rnaprop == NULL) || (RNA_property_type(but->rnaprop) != PROP_ENUM)) {
- printf("%s: cannot cycle button '%s'\n", __func__, but->str);
- return 0;
+ return (but->rnaprop && RNA_property_type(but->rnaprop) == PROP_ENUM);
+}
+
+int ui_but_menu_step(uiBut *but, int direction)
+{
+ if (ui_but_menu_step_poll(but)) {
+ return rna_property_enum_step(but->block->evil_C, &but->rnapoin, but->rnaprop, direction);
}
- return rna_property_enum_step(but->block->evil_C, &but->rnapoin, but->rnaprop, direction);
+ printf("%s: cannot cycle button '%s'\n", __func__, but->str);
+ return 0;
}
/******************** Creating Temporary regions ******************/
@@ -148,13 +154,14 @@ static void ui_region_temp_remove(bContext *C, bScreen *sc, ARegion *ar)
#define UI_TIP_PAD_FAC 1.3f
#define UI_TIP_PADDING (int)(UI_TIP_PAD_FAC * UI_UNIT_Y)
+#define UI_TIP_MAXWIDTH 600
#define MAX_TOOLTIP_LINES 8
typedef struct uiTooltipData {
rcti bbox;
uiFontStyle fstyle;
- char lines[MAX_TOOLTIP_LINES][512];
- char header[512], active_info[512];
+ char lines[MAX_TOOLTIP_LINES][2048];
+ char header[2048], active_info[2048];
struct {
enum {
UI_TIP_STYLE_NORMAL = 0,
@@ -171,6 +178,14 @@ typedef struct uiTooltipData {
} color_id : 4;
int is_pad : 1;
} format[MAX_TOOLTIP_LINES];
+
+ struct {
+ unsigned int x_pos; /* x cursor position at the end of the last line */
+ unsigned int lines; /* number of lines, 1 or more with word-wrap */
+ } line_geom[MAX_TOOLTIP_LINES];
+
+ int wrap_width;
+
int totline;
int toth, lineh;
} uiTooltipData;
@@ -250,38 +265,48 @@ static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *ar)
rgb_tint(alert_color, 0.0f, 0.8f, tone_bg, 0.1f); /* red */
/* draw text */
+ BLF_wordwrap(data->fstyle.uifont_id, data->wrap_width);
+ BLF_wordwrap(blf_mono_font, data->wrap_width);
bbox.xmin += 0.5f * pad_px; /* add padding to the text */
- bbox.ymax -= 0.5f * (BLI_rcti_size_y(&bbox) - data->toth);
- bbox.ymin = bbox.ymax - data->lineh;
+ bbox.ymax -= 0.25f * pad_px;
for (i = 0; i < data->totline; i++) {
+ bbox.ymin = bbox.ymax - (data->lineh * data->line_geom[i].lines);
if (data->format[i].style == UI_TIP_STYLE_HEADER) {
/* draw header and active data (is done here to be able to change color) */
uiFontStyle fstyle_header = data->fstyle;
- float xofs;
+ float xofs, yofs;
/* override text-style */
fstyle_header.shadow = 1;
fstyle_header.shadowcolor = rgb_to_grayscale(tip_colors[UI_TIP_LC_MAIN]);
fstyle_header.shadx = fstyle_header.shady = 0;
fstyle_header.shadowalpha = 1.0f;
+ fstyle_header.word_wrap = true;
UI_fontstyle_set(&fstyle_header);
glColor3fv(tip_colors[UI_TIP_LC_MAIN]);
UI_fontstyle_draw(&fstyle_header, &bbox, data->header);
- xofs = BLF_width(fstyle_header.uifont_id, data->header, sizeof(data->header));
+ /* offset to the end of the last line */
+ xofs = data->line_geom[i].x_pos;
+ yofs = data->lineh * (data->line_geom[i].lines - 1);
bbox.xmin += xofs;
+ bbox.ymax -= yofs;
glColor3fv(tip_colors[UI_TIP_LC_ACTIVE]);
- UI_fontstyle_draw(&data->fstyle, &bbox, data->active_info);
+ fstyle_header.shadow = 0;
+ UI_fontstyle_draw(&fstyle_header, &bbox, data->active_info);
+ /* undo offset */
bbox.xmin -= xofs;
+ bbox.ymax += yofs;
}
else if (data->format[i].style == UI_TIP_STYLE_MONO) {
uiFontStyle fstyle_mono = data->fstyle;
fstyle_mono.uifont_id = blf_mono_font;
+ fstyle_mono.word_wrap = true;
UI_fontstyle_set(&fstyle_mono);
/* XXX, needed because we dont have mono in 'U.uifonts' */
@@ -290,22 +315,26 @@ static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *ar)
UI_fontstyle_draw(&fstyle_mono, &bbox, data->lines[i]);
}
else {
+ uiFontStyle fstyle_normal = data->fstyle;
BLI_assert(data->format[i].style == UI_TIP_STYLE_NORMAL);
+ fstyle_normal.word_wrap = true;
+
/* draw remaining data */
- UI_fontstyle_set(&data->fstyle);
+ UI_fontstyle_set(&fstyle_normal);
glColor3fv(tip_colors[data->format[i].color_id]);
- UI_fontstyle_draw(&data->fstyle, &bbox, data->lines[i]);
+ UI_fontstyle_draw(&fstyle_normal, &bbox, data->lines[i]);
}
+
+ bbox.ymax -= data->lineh * data->line_geom[i].lines;
+
if ((i + 1 != data->totline) && data->format[i + 1].is_pad) {
- bbox.ymax -= data->lineh * UI_TIP_PAD_FAC;
- bbox.ymin -= data->lineh * UI_TIP_PAD_FAC;
- }
- else {
- bbox.ymax -= data->lineh;
- bbox.ymin -= data->lineh;
+ bbox.ymax -= data->lineh * (UI_TIP_PAD_FAC - 1);
}
}
+ BLF_disable(data->fstyle.uifont_id, BLF_WORD_WRAP);
+ BLF_disable(blf_mono_font, BLF_WORD_WRAP);
+
if (multisample_enabled)
glEnable(GL_MULTISAMPLE_ARB);
}
@@ -331,10 +360,11 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but)
char buf[512];
/* aspect values that shrink text are likely unreadable */
const float aspect = min_ff(1.0f, but->block->aspect);
- float fonth, fontw;
- int winx, ofsx, ofsy, w = 0, h, i;
+ int fonth, fontw;
+ int winx, ofsx, ofsy, h, i;
rctf rect_fl;
rcti rect_i;
+ int font_flag = 0;
uiStringInfo but_tip = {BUT_GET_TIP, NULL};
uiStringInfo enum_label = {BUT_GET_RNAENUM_LABEL, NULL};
@@ -513,9 +543,10 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but)
}
if (data_path) {
+ const char *data_delim = (data_path[0] == '[') ? "" : ".";
BLI_snprintf(data->lines[data->totline], sizeof(data->lines[0]),
- "%s.%s", /* no need to translate */
- id_path, data_path);
+ "%s%s%s", /* no need to translate */
+ id_path, data_delim, data_path);
MEM_freeN(data_path);
}
else if (prop) {
@@ -570,6 +601,17 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but)
UI_fontstyle_set(&data->fstyle);
+ data->wrap_width = min_ii(UI_TIP_MAXWIDTH * U.pixelsize / aspect, WM_window_pixels_x(win) - (UI_TIP_PADDING * 2));
+
+ font_flag |= BLF_WORD_WRAP;
+ if (data->fstyle.kerning == 1) {
+ font_flag |= BLF_KERNING_DEFAULT;
+ }
+ BLF_enable(data->fstyle.uifont_id, font_flag);
+ BLF_enable(blf_mono_font, font_flag);
+ BLF_wordwrap(data->fstyle.uifont_id, data->wrap_width);
+ BLF_wordwrap(blf_mono_font, data->wrap_width);
+
/* these defines tweaked depending on font */
#define TIP_BORDER_X (16.0f / aspect)
#define TIP_BORDER_Y (6.0f / aspect)
@@ -577,33 +619,43 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but)
h = BLF_height_max(data->fstyle.uifont_id);
for (i = 0, fontw = 0, fonth = 0; i < data->totline; i++) {
+ struct ResultBLF info;
+ int w, x_pos = 0;
+
if (data->format[i].style == UI_TIP_STYLE_HEADER) {
- w = BLF_width(data->fstyle.uifont_id, data->header, sizeof(data->header));
- if (enum_label.strinfo)
- w += BLF_width(data->fstyle.uifont_id, data->active_info, sizeof(data->active_info));
+ w = BLF_width_ex(data->fstyle.uifont_id, data->header, sizeof(data->header), &info);
+ if (enum_label.strinfo) {
+ x_pos = info.width + (U.widget_unit / 2);
+ w = max_ii(w, x_pos + BLF_width(data->fstyle.uifont_id, data->active_info, sizeof(data->active_info)));
+ }
}
else if (data->format[i].style == UI_TIP_STYLE_MONO) {
BLF_size(blf_mono_font, data->fstyle.points * U.pixelsize, U.dpi);
- w = BLF_width(blf_mono_font, data->lines[i], sizeof(data->lines[i]));
+ w = BLF_width_ex(blf_mono_font, data->lines[i], sizeof(data->lines[i]), &info);
}
else {
BLI_assert(data->format[i].style == UI_TIP_STYLE_NORMAL);
- w = BLF_width(data->fstyle.uifont_id, data->lines[i], sizeof(data->lines[i]));
+
+ w = BLF_width_ex(data->fstyle.uifont_id, data->lines[i], sizeof(data->lines[i]), &info);
}
- fontw = max_ff(fontw, (float)w);
+ fontw = max_ii(fontw, w);
+ fonth += h * info.lines;
if ((i + 1 != data->totline) && data->format[i + 1].is_pad) {
- fonth += h * UI_TIP_PAD_FAC;
- }
- else {
- fonth += h;
+ fonth += h * (UI_TIP_PAD_FAC - 1);
}
+
+ data->line_geom[i].lines = info.lines;
+ data->line_geom[i].x_pos = x_pos;
}
//fontw *= aspect;
+ BLF_disable(data->fstyle.uifont_id, font_flag);
+ BLF_disable(blf_mono_font, font_flag);
+
ar->regiondata = data;
data->toth = fonth;
@@ -769,7 +821,7 @@ bool UI_search_item_add(uiSearchItems *items, const char *name, void *poin, int
int UI_searchbox_size_y(void)
{
- return SEARCH_ITEMS * UI_UNIT_Y + 2 * MENU_TOP;
+ return SEARCH_ITEMS * UI_UNIT_Y + 2 * UI_POPUP_MENU_TOP;
}
int UI_searchbox_size_x(void)
@@ -845,13 +897,13 @@ static void ui_searchbox_butrect(rcti *r_rect, uiSearchboxData *data, int itemnr
}
/* list view */
else {
- int buth = (BLI_rcti_size_y(&data->bbox) - 2 * MENU_TOP) / SEARCH_ITEMS;
+ int buth = (BLI_rcti_size_y(&data->bbox) - 2 * UI_POPUP_MENU_TOP) / SEARCH_ITEMS;
*r_rect = data->bbox;
r_rect->xmin = data->bbox.xmin + 3.0f;
r_rect->xmax = data->bbox.xmax - 3.0f;
- r_rect->ymax = data->bbox.ymax - MENU_TOP - itemnr * buth;
+ r_rect->ymax = data->bbox.ymax - UI_POPUP_MENU_TOP - itemnr * buth;
r_rect->ymin = r_rect->ymax - buth;
}
@@ -1591,8 +1643,8 @@ static void ui_popup_block_clip(wmWindow *window, uiBlock *block)
if (block->rect.ymin < width)
block->rect.ymin = width;
- if (block->rect.ymax > winy - MENU_TOP)
- block->rect.ymax = winy - MENU_TOP;
+ if (block->rect.ymax > winy - UI_POPUP_MENU_TOP)
+ block->rect.ymax = winy - UI_POPUP_MENU_TOP;
/* ensure menu items draw inside left/right boundary */
for (bt = block->buttons.first; bt; bt = bt->next) {
@@ -1779,7 +1831,7 @@ uiBlock *ui_popup_block_refresh(
ar->winrct.xmin = block->rect.xmin - margin;
ar->winrct.xmax = block->rect.xmax + margin;
ar->winrct.ymin = block->rect.ymin - margin;
- ar->winrct.ymax = block->rect.ymax + MENU_TOP;
+ ar->winrct.ymax = block->rect.ymax + UI_POPUP_MENU_TOP;
ui_block_translate(block, -ar->winrct.xmin, -ar->winrct.ymin);
}
diff --git a/source/blender/editors/interface/interface_style.c b/source/blender/editors/interface/interface_style.c
index 8dca148ffe6..25a187c43ad 100644
--- a/source/blender/editors/interface/interface_style.c
+++ b/source/blender/editors/interface/interface_style.c
@@ -152,13 +152,34 @@ void UI_fontstyle_draw_ex(
const uiFontStyle *fs, const rcti *rect, const char *str,
size_t len, float *r_xofs, float *r_yofs)
{
- float height;
int xofs = 0, yofs;
+ int font_flag = BLF_CLIPPING;
UI_fontstyle_set(fs);
- height = BLF_ascender(fs->uifont_id);
- yofs = ceil(0.5f * (BLI_rcti_size_y(rect) - height));
+ /* set the flag */
+ if (fs->shadow) {
+ font_flag |= BLF_SHADOW;
+ BLF_shadow(fs->uifont_id, fs->shadow, fs->shadowcolor, fs->shadowcolor, fs->shadowcolor, fs->shadowalpha);
+ BLF_shadow_offset(fs->uifont_id, fs->shadx, fs->shady);
+ }
+ if (fs->kerning == 1) {
+ font_flag |= BLF_KERNING_DEFAULT;
+ }
+ if (fs->word_wrap == 1) {
+ font_flag |= BLF_WORD_WRAP;
+ }
+
+ BLF_enable(fs->uifont_id, font_flag);
+
+ if (fs->word_wrap == 1) {
+ /* draw from boundbox top */
+ yofs = BLI_rcti_size_y(rect) - BLF_height_max(fs->uifont_id);
+ }
+ else {
+ /* draw from boundbox center */
+ yofs = ceil(0.5f * (BLI_rcti_size_y(rect) - BLF_ascender(fs->uifont_id)));
+ }
if (fs->align == UI_STYLE_TEXT_CENTER) {
xofs = floor(0.5f * (BLI_rcti_size_x(rect) - BLF_width(fs->uifont_id, str, len)));
@@ -173,24 +194,11 @@ void UI_fontstyle_draw_ex(
/* clip is very strict, so we give it some space */
BLF_clipping(fs->uifont_id, rect->xmin - 2, rect->ymin - 4, rect->xmax + 1, rect->ymax + 4);
- BLF_enable(fs->uifont_id, BLF_CLIPPING);
BLF_position(fs->uifont_id, rect->xmin + xofs, rect->ymin + yofs, 0.0f);
- if (fs->shadow) {
- BLF_enable(fs->uifont_id, BLF_SHADOW);
- BLF_shadow(fs->uifont_id, fs->shadow, fs->shadowcolor, fs->shadowcolor, fs->shadowcolor, fs->shadowalpha);
- BLF_shadow_offset(fs->uifont_id, fs->shadx, fs->shady);
- }
-
- if (fs->kerning == 1)
- BLF_enable(fs->uifont_id, BLF_KERNING_DEFAULT);
-
BLF_draw(fs->uifont_id, str, len);
- BLF_disable(fs->uifont_id, BLF_CLIPPING);
- if (fs->shadow)
- BLF_disable(fs->uifont_id, BLF_SHADOW);
- if (fs->kerning == 1)
- BLF_disable(fs->uifont_id, BLF_KERNING_DEFAULT);
+
+ BLF_disable(fs->uifont_id, font_flag);
*r_xofs = xofs;
*r_yofs = yofs;
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index f4618d8e5ff..e69fbf7fb8f 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -3486,7 +3486,8 @@ void uiTemplateReportsBanner(uiLayout *layout, bContext *C)
ui_abs = uiLayoutAbsolute(layout, false);
block = uiLayoutGetBlock(ui_abs);
- width = BLF_width(style->widget.uifont_id, report->message, report->len);
+ UI_fontstyle_set(&style->widgetlabel);
+ width = BLF_width(style->widgetlabel.uifont_id, report->message, report->len);
width = min_ii((int)(rti->widthfac * width), width);
width = max_ii(width, 10);
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index a7592276256..008f129904b 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -206,7 +206,7 @@ void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y
/* for each AA step */
for (j = 0; j < WIDGET_AA_JITTER; j++) {
- glTranslatef(jit[j][0], jit[j][1], 0.0f);
+ glTranslate2fv(jit[j]);
glDrawArrays(GL_TRIANGLES, 0, 3);
glTranslatef(-jit[j][0], -jit[j][1], 0.0f);
}
@@ -229,7 +229,7 @@ void ui_draw_anti_roundbox(int mode, float minx, float miny, float maxx, float m
glColor4fv(color);
for (j = 0; j < WIDGET_AA_JITTER; j++) {
- glTranslatef(jit[j][0], jit[j][1], 0.0f);
+ glTranslate2fv(jit[j]);
UI_draw_roundbox_gl_mode(mode, minx, miny, maxx, maxy, rad);
glTranslatef(-jit[j][0], -jit[j][1], 0.0f);
}
@@ -816,7 +816,7 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol)
for (j = 0; j < WIDGET_AA_JITTER; j++) {
unsigned char emboss[4];
- glTranslatef(jit[j][0], jit[j][1], 0.0f);
+ glTranslate2fv(jit[j]);
/* outline */
glColor4ubv(tcol);
@@ -850,7 +850,7 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol)
/* for each AA step */
for (j = 0; j < WIDGET_AA_JITTER; j++) {
- glTranslatef(jit[j][0], jit[j][1], 0.0f);
+ glTranslate2fv(jit[j]);
if (wtb->tria1.tot) {
glColor4ubv(tcol);
@@ -2910,8 +2910,11 @@ static void ui_draw_but_HSV_v(uiBut *but, const rcti *rect)
/* map v from property range to [0,1] */
if (but->a1 == UI_GRAD_V_ALT) {
- float range = but->softmax - but->softmin;
- v = (v - but->softmin) / range;
+ float min = but->softmin, max = but->softmax;
+ if (color_profile) {
+ ui_block_cm_to_display_space_range(but->block, &min, &max);
+ }
+ v = (v - min) / (max - min);
}
widget_init(&wtb);
diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c
index 02f4eb171a4..c19cef6fadc 100644
--- a/source/blender/editors/interface/resources.c
+++ b/source/blender/editors/interface/resources.c
@@ -1083,7 +1083,7 @@ void ui_theme_init_default(void)
rgba_char_args_set(btheme->tima.face, 255, 255, 255, 10);
rgba_char_args_set(btheme->tima.face_select, 255, 133, 0, 60);
rgba_char_args_set(btheme->tima.editmesh_active, 255, 255, 255, 128);
- rgba_char_args_set_fl(btheme->tima.preview_back, 0.45, 0.45, 0.45, 1.0);
+ rgba_char_args_set_fl(btheme->tima.preview_back, 0.0, 0.0, 0.0, 0.3);
rgba_char_args_set_fl(btheme->tima.preview_stitch_face, 0.5, 0.5, 0.0, 0.2);
rgba_char_args_set_fl(btheme->tima.preview_stitch_edge, 1.0, 0.0, 1.0, 0.2);
rgba_char_args_set_fl(btheme->tima.preview_stitch_vert, 0.0, 0.0, 1.0, 0.2);
@@ -2492,10 +2492,10 @@ void init_userdef_do_versions(void)
ThemeSpace *ts;
for (ts = UI_THEMESPACE_START(btheme); ts != UI_THEMESPACE_END(btheme); ts++) {
- rgba_char_args_set(ts->tabs.tab_active, 114, 114, 114, 255);
- rgba_char_args_set(ts->tabs.tab_inactive, 83, 83, 83, 255);
- rgba_char_args_set(ts->tabs.tab_back, 64, 64, 64, 255);
- rgba_char_args_set(ts->tabs.tab_outline, 60, 60, 60, 255);
+ rgba_char_args_set(ts->tab_active, 114, 114, 114, 255);
+ rgba_char_args_set(ts->tab_inactive, 83, 83, 83, 255);
+ rgba_char_args_set(ts->tab_back, 64, 64, 64, 255);
+ rgba_char_args_set(ts->tab_outline, 60, 60, 60, 255);
}
}
}
@@ -2633,7 +2633,14 @@ void init_userdef_do_versions(void)
U.node_margin = 80;
}
- if (!USER_VERSION_ATLEAST(275, 6)) {
+ if (!USER_VERSION_ATLEAST(276, 1)) {
+ bTheme *btheme;
+ for (btheme = U.themes.first; btheme; btheme = btheme->next) {
+ rgba_char_args_set_fl(btheme->tima.preview_back, 0.0f, 0.0f, 0.0f, 0.3f);
+ }
+ }
+
+ if (!USER_VERSION_ATLEAST(276, 2)) {
bTheme *btheme;
ThemeSpace *ts;
@@ -2662,7 +2669,7 @@ void init_userdef_do_versions(void)
}
}
- if (!USER_VERSION_ATLEAST(275, 6)) {
+ if (!USER_VERSION_ATLEAST(276, 2)) {
bTheme *btheme;
ThemeSpace *ts;
@@ -2682,7 +2689,7 @@ void init_userdef_do_versions(void)
}
}
- if (!USER_VERSION_ATLEAST(275, 5)) {
+ if (!USER_VERSION_ATLEAST(276, 2)) {
bTheme *btheme;
for (btheme = U.themes.first; btheme; btheme = btheme->next) {
rgba_char_args_set_fl(btheme->tui.xaxis, 1.0f, 0.27f, 0.27f, 1.0f); /* red */
diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c
index 2c56ef0aecb..d966cedc133 100644
--- a/source/blender/editors/interface/view2d.c
+++ b/source/blender/editors/interface/view2d.c
@@ -63,7 +63,7 @@
#include "interface_intern.h"
-static void ui_view2d_curRect_validate_resize(View2D *v2d, int resize, int mask_scrollers);
+static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize, bool mask_scrollers);
/* *********************************************************************** */
@@ -116,7 +116,7 @@ static int view2d_scroll_mapped(int scroll)
}
/* called each time cur changes, to dynamically update masks */
-static void view2d_masks(View2D *v2d, int check_scrollers)
+static void view2d_masks(View2D *v2d, bool check_scrollers)
{
int scroll;
@@ -372,7 +372,7 @@ void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy)
* 'cur' is not allowed to be: larger than max, smaller than min, or outside of 'tot'
*/
// XXX pre2.5 -> this used to be called test_view2d()
-static void ui_view2d_curRect_validate_resize(View2D *v2d, int resize, int mask_scrollers)
+static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize, bool mask_scrollers)
{
float totwidth, totheight, curwidth, curheight, width, height;
float winx, winy;
@@ -476,7 +476,7 @@ static void ui_view2d_curRect_validate_resize(View2D *v2d, int resize, int mask_
/* check if we should restore aspect ratio (if view size changed) */
if (v2d->keepzoom & V2D_KEEPASPECT) {
bool do_x = false, do_y = false, do_cur /* , do_win */ /* UNUSED */;
- float /* curRatio, */ /* UNUSED */ winRatio;
+ float curRatio, winRatio;
/* when a window edge changes, the aspect ratio can't be used to
* find which is the best new 'cur' rect. thats why it stores 'old'
@@ -484,7 +484,7 @@ static void ui_view2d_curRect_validate_resize(View2D *v2d, int resize, int mask_
if (winx != v2d->oldwinx) do_x = true;
if (winy != v2d->oldwiny) do_y = true;
- /* curRatio = height / width; */ /* UNUSED */
+ curRatio = height / width;
winRatio = winy / winx;
/* both sizes change (area/region maximized) */
@@ -494,7 +494,7 @@ static void ui_view2d_curRect_validate_resize(View2D *v2d, int resize, int mask_
if (fabsf(winx - v2d->oldwinx) > fabsf(winy - v2d->oldwiny)) do_y = false;
else do_x = false;
}
- else if (winRatio > 1.0f) {
+ else if (winRatio > curRatio) {
do_x = false;
}
else {
@@ -903,7 +903,7 @@ void UI_view2d_curRect_reset(View2D *v2d)
/* ------------------ */
/* Change the size of the maximum viewable area (i.e. 'tot' rect) */
-void UI_view2d_totRect_set_resize(View2D *v2d, int width, int height, int resize)
+void UI_view2d_totRect_set_resize(View2D *v2d, int width, int height, bool resize)
{
// int scroll = view2d_scroll_mapped(v2d->scroll);
diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c
index 726678cd4e8..2ebdf467ceb 100644
--- a/source/blender/editors/interface/view2d_ops.c
+++ b/source/blender/editors/interface/view2d_ops.c
@@ -616,15 +616,20 @@ static int view_zoom_poll(bContext *C)
/* check if there's a region in context to work with */
if (ar == NULL)
- return 0;
+ return false;
+
+ /* Do not show that in 3DView context. */
+ if (CTX_wm_region_view3d(C))
+ return false;
+
v2d = &ar->v2d;
/* check that 2d-view is zoomable */
if ((v2d->keepzoom & V2D_LOCKZOOM_X) && (v2d->keepzoom & V2D_LOCKZOOM_Y))
- return 0;
+ return false;
/* view is zoomable */
- return 1;
+ return true;
}
/* apply transform to view (i.e. adjust 'cur' rect) */
diff --git a/source/blender/editors/mask/mask_add.c b/source/blender/editors/mask/mask_add.c
index 2dae9561d4e..822bb429f9e 100644
--- a/source/blender/editors/mask/mask_add.c
+++ b/source/blender/editors/mask/mask_add.c
@@ -74,7 +74,7 @@ bool ED_mask_find_nearest_diff_point(const bContext *C,
MaskSplinePoint *point = NULL;
float dist_best_sq = FLT_MAX, co[2];
int width, height;
- float u;
+ float u = 0.0f;
float scalex, scaley;
ED_mask_get_size(sa, &width, &height);
diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c
index 929c4f74b2f..bf8630ff843 100644
--- a/source/blender/editors/mask/mask_ops.c
+++ b/source/blender/editors/mask/mask_ops.c
@@ -516,7 +516,7 @@ static bool spline_under_mouse_get(const bContext *C,
MaskLayer *mask_layer;
int width, height;
float pixel_co[2];
- float closest_dist_squared;
+ float closest_dist_squared = 0.0f;
MaskLayer *closest_layer = NULL;
MaskSpline *closest_spline = NULL;
bool undistort = false;
@@ -2209,7 +2209,7 @@ static int mask_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
}
if (end >= start) {
int tot_point;
- int tot_point_shape_start;
+ int tot_point_shape_start = 0;
MaskSpline *new_spline = BKE_mask_spline_add(mask_layer);
MaskSplinePoint *new_point;
int b;
diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c
index 787b79f0d6e..621155bc696 100644
--- a/source/blender/editors/mesh/editmesh_knife.c
+++ b/source/blender/editors/mesh/editmesh_knife.c
@@ -209,6 +209,8 @@ typedef struct KnifeTool_OpData {
bool is_ortho;
float ortho_extent;
+ float ortho_extent_center[3];
+
float clipsta, clipend;
enum {
@@ -226,14 +228,8 @@ typedef struct KnifeTool_OpData {
/* use to check if we're currently dragging an angle snapped line */
bool is_angle_snapping;
-
- enum {
- ANGLE_FREE,
- ANGLE_0,
- ANGLE_45,
- ANGLE_90,
- ANGLE_135
- } angle_snapping;
+ bool angle_snapping;
+ float angle;
const float (*cagecos)[3];
} KnifeTool_OpData;
@@ -941,98 +937,66 @@ static void knife_finish_cut(KnifeTool_OpData *kcd)
static void knifetool_draw_angle_snapping(const KnifeTool_OpData *kcd)
{
- bglMats mats;
- double u[3], u1[2], u2[2], v1[3], v2[3], dx, dy;
- double wminx, wminy, wmaxx, wmaxy;
-
- /* make u the window coords of prevcage */
- view3d_get_transformation(kcd->ar, kcd->vc.rv3d, kcd->ob, &mats);
- gluProject(kcd->prev.cage[0], kcd->prev.cage[1], kcd->prev.cage[2],
- mats.modelview, mats.projection, mats.viewport,
- &u[0], &u[1], &u[2]);
-
- /* make u1, u2 the points on window going through u at snap angle */
- wminx = kcd->ar->winrct.xmin;
- wmaxx = kcd->ar->winrct.xmin + kcd->ar->winx;
- wminy = kcd->ar->winrct.ymin;
- wmaxy = kcd->ar->winrct.ymin + kcd->ar->winy;
-
- switch (kcd->angle_snapping) {
- case ANGLE_0:
- u1[0] = wminx;
- u2[0] = wmaxx;
- u1[1] = u2[1] = u[1];
- break;
- case ANGLE_90:
- u1[0] = u2[0] = u[0];
- u1[1] = wminy;
- u2[1] = wmaxy;
- break;
- case ANGLE_45:
- /* clip against left or bottom */
- dx = u[0] - wminx;
- dy = u[1] - wminy;
- if (dy > dx) {
- u1[0] = wminx;
- u1[1] = u[1] - dx;
- }
- else {
- u1[0] = u[0] - dy;
- u1[1] = wminy;
- }
- /* clip against right or top */
- dx = wmaxx - u[0];
- dy = wmaxy - u[1];
- if (dy > dx) {
- u2[0] = wmaxx;
- u2[1] = u[1] + dx;
- }
- else {
- u2[0] = u[0] + dy;
- u2[1] = wmaxy;
- }
- break;
- case ANGLE_135:
- /* clip against right or bottom */
- dx = wmaxx - u[0];
- dy = u[1] - wminy;
- if (dy > dx) {
- u1[0] = wmaxx;
- u1[1] = u[1] - dx;
- }
- else {
- u1[0] = u[0] + dy;
- u1[1] = wminy;
- }
- /* clip against left or top */
- dx = u[0] - wminx;
- dy = wmaxy - u[1];
- if (dy > dx) {
- u2[0] = wminx;
- u2[1] = u[1] + dx;
- }
- else {
- u2[0] = u[0] - dy;
- u2[1] = wmaxy;
+ float v1[3], v2[3];
+ float planes[4][4];
+
+ planes_from_projmat(
+ (float (*)[4])kcd->projmat,
+ planes[2], planes[0], planes[3], planes[1], NULL, NULL);
+
+ /* ray-cast all planes */
+ {
+ float ray_dir[3];
+ float ray_hit_best[2][3] = {{UNPACK3(kcd->prev.cage)}, {UNPACK3(kcd->curr.cage)}};
+ float lambda_best[2] = {-FLT_MAX, FLT_MAX};
+ int i;
+
+ /* we (sometimes) need the lines to be at the same depth before projecting */
+#if 0
+ sub_v3_v3v3(ray_dir, kcd->curr.cage, kcd->prev.cage);
+#else
+ {
+ float curr_cage_adjust[3];
+ float co_depth[3];
+
+ copy_v3_v3(co_depth, kcd->prev.cage);
+ mul_m4_v3(kcd->ob->obmat, co_depth);
+ ED_view3d_win_to_3d(kcd->ar, co_depth, kcd->curr.mval, curr_cage_adjust);
+ mul_m4_v3(kcd->ob->imat, curr_cage_adjust);
+
+ sub_v3_v3v3(ray_dir, curr_cage_adjust, kcd->prev.cage);
+ }
+#endif
+
+ for (i = 0; i < 4; i++) {
+ float ray_hit[3];
+ float lambda_test;
+ if (isect_ray_plane_v3(kcd->prev.cage, ray_dir, planes[i], &lambda_test, false)) {
+ madd_v3_v3v3fl(ray_hit, kcd->prev.cage, ray_dir, lambda_test);
+ if (lambda_test < 0.0f) {
+ if (lambda_test > lambda_best[0]) {
+ copy_v3_v3(ray_hit_best[0], ray_hit);
+ lambda_best[0] = lambda_test;
+ }
+ }
+ else {
+ if (lambda_test < lambda_best[1]) {
+ copy_v3_v3(ray_hit_best[1], ray_hit);
+ lambda_best[1] = lambda_test;
+ }
+ }
}
- break;
- default:
- return;
- }
+ }
- /* unproject u1 and u2 back into object space */
- gluUnProject(u1[0], u1[1], 0.0,
- mats.modelview, mats.projection, mats.viewport,
- &v1[0], &v1[1], &v1[2]);
- gluUnProject(u2[0], u2[1], 0.0,
- mats.modelview, mats.projection, mats.viewport,
- &v2[0], &v2[1], &v2[2]);
+ copy_v3_v3(v1, ray_hit_best[0]);
+ copy_v3_v3(v2, ray_hit_best[1]);
+ }
UI_ThemeColor(TH_TRANSFORM);
glLineWidth(2.0);
glBegin(GL_LINES);
- glVertex3dv(v1);
- glVertex3dv(v2);
+ glVertex3fv(v1);
+ glVertex3fv(v2);
glEnd();
}
@@ -1065,7 +1029,7 @@ static void knifetool_draw(const bContext *C, ARegion *UNUSED(ar), void *arg)
glMultMatrixf(kcd->ob->obmat);
if (kcd->mode == MODE_DRAGGING) {
- if (kcd->angle_snapping != ANGLE_FREE)
+ if (kcd->is_angle_snapping)
knifetool_draw_angle_snapping(kcd);
glColor3ubv(kcd->colors.line);
@@ -1281,20 +1245,29 @@ static bool knife_ray_intersect_face(
return false;
}
-/* Calculate maximum excursion from (0,0,0) of mesh */
+/**
+ * Calculate the center and maximum excursion of mesh.
+ */
static void calc_ortho_extent(KnifeTool_OpData *kcd)
{
BMIter iter;
BMVert *v;
BMesh *bm = kcd->em->bm;
- float max_xyz = 0.0f;
- int i;
+ float min[3], max[3];
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- for (i = 0; i < 3; i++)
- max_xyz = max_ff(max_xyz, fabsf(v->co[i]));
+ INIT_MINMAX(min, max);
+
+ if (kcd->cagecos) {
+ minmax_v3v3_v3_array(min, max, kcd->cagecos, bm->totvert);
+ }
+ else {
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ minmax_v3v3_v3(min, max, v->co);
+ }
}
- kcd->ortho_extent = max_xyz;
+
+ kcd->ortho_extent = len_v3v3(min, max) / 2;
+ mid_v3_v3v3(kcd->ortho_extent_center, min, max);
}
static BMElem *bm_elem_from_knife_vert(KnifeVert *kfv, KnifeEdge **r_kfe)
@@ -1482,14 +1455,20 @@ static bool point_is_visible(
/* Clip the line (v1, v2) to planes perpendicular to it and distances d from
* the closest point on the line to the origin */
-static void clip_to_ortho_planes(float v1[3], float v2[3], float d)
+static void clip_to_ortho_planes(float v1[3], float v2[3], const float center[3], const float d)
{
- float closest[3];
- const float origin[3] = {0.0f, 0.0f, 0.0f};
+ float closest[3], dir[3];
+
+ sub_v3_v3v3(dir, v1, v2);
+ normalize_v3(dir);
+
+ /* could be v1 or v2 */
+ sub_v3_v3(v1, center);
+ project_plane_v3_v3v3(closest, v1, dir);
+ add_v3_v3(closest, center);
- closest_to_line_v3(closest, origin, v1, v2);
- dist_ensure_v3_v3fl(v1, closest, d);
- dist_ensure_v3_v3fl(v2, closest, d);
+ madd_v3_v3v3fl(v1, closest, dir, d);
+ madd_v3_v3v3fl(v2, closest, dir, -d);
}
static void set_linehit_depth(KnifeTool_OpData *kcd, KnifeLineHit *lh)
@@ -1573,8 +1552,8 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
if (kcd->is_ortho && (kcd->vc.rv3d->persp != RV3D_CAMOB)) {
if (kcd->ortho_extent == 0.0f)
calc_ortho_extent(kcd);
- clip_to_ortho_planes(v1, v3, kcd->ortho_extent + 10.0f);
- clip_to_ortho_planes(v2, v4, kcd->ortho_extent + 10.0f);
+ clip_to_ortho_planes(v1, v3, kcd->ortho_extent_center, kcd->ortho_extent + 10.0f);
+ clip_to_ortho_planes(v2, v4, kcd->ortho_extent_center, kcd->ortho_extent + 10.0f);
}
/* First use bvh tree to find faces, knife edges, and knife verts that might
@@ -2124,42 +2103,41 @@ static KnifeVert *knife_find_closest_vert(KnifeTool_OpData *kcd, float p[3], flo
return NULL;
}
+/**
+ * Snaps a 2d vector to an angle, relative to \a v_ref.
+ */
+static float snap_v2_angle(float r[2], const float v[2], const float v_ref[2], float angle_snap)
+{
+ float m2[2][2];
+ float v_unit[2];
+ float angle, angle_delta;
+
+ BLI_ASSERT_UNIT_V2(v_ref);
+
+ normalize_v2_v2(v_unit, v);
+ angle = angle_signed_v2v2(v_unit, v_ref);
+ angle_delta = (roundf(angle / angle_snap) * angle_snap) - angle;
+ rotate_m2(m2, angle_delta);
+
+ mul_v2_m2v2(r, m2, v);
+ return angle + angle_delta;
+}
+
/* update both kcd->curr.mval and kcd->mval to snap to required angle */
static bool knife_snap_angle(KnifeTool_OpData *kcd)
{
- float dx, dy;
- float w, abs_tan;
+ const float dvec_ref[2] = {0.0f, 1.0f};
+ float dvec[2], dvec_snap[2];
+ float snap_step = DEG2RADF(45);
- dx = kcd->curr.mval[0] - kcd->prev.mval[0];
- dy = kcd->curr.mval[1] - kcd->prev.mval[1];
- if (dx == 0.0f && dy == 0.0f)
+ sub_v2_v2v2(dvec, kcd->curr.mval, kcd->prev.mval);
+ if (is_zero_v2(dvec)) {
return false;
-
- if (dx == 0.0f) {
- kcd->angle_snapping = ANGLE_90;
- kcd->curr.mval[0] = kcd->prev.mval[0];
}
- w = dy / dx;
- abs_tan = fabsf(w);
- if (abs_tan <= 0.4142f) { /* tan(22.5 degrees) = 0.4142 */
- kcd->angle_snapping = ANGLE_0;
- kcd->curr.mval[1] = kcd->prev.mval[1];
- }
- else if (abs_tan < 2.4142f) { /* tan(67.5 degrees) = 2.4142 */
- if (w > 0) {
- kcd->angle_snapping = ANGLE_45;
- kcd->curr.mval[1] = kcd->prev.mval[1] + dx;
- }
- else {
- kcd->angle_snapping = ANGLE_135;
- kcd->curr.mval[1] = kcd->prev.mval[1] - dx;
- }
- }
- else {
- kcd->angle_snapping = ANGLE_90;
- kcd->curr.mval[0] = kcd->prev.mval[0];
- }
+ kcd->angle = snap_v2_angle(dvec_snap, dvec, dvec_ref, snap_step);
+
+ add_v2_v2v2(kcd->curr.mval, kcd->prev.mval, dvec_snap);
copy_v2_v2(kcd->mval, kcd->curr.mval);
@@ -2175,7 +2153,7 @@ static int knife_update_active(KnifeTool_OpData *kcd)
/* view matrix may have changed, reproject */
knife_project_v2(kcd, kcd->prev.cage, kcd->prev.mval);
- if (kcd->angle_snapping != ANGLE_FREE && kcd->mode == MODE_DRAGGING) {
+ if (kcd->angle_snapping && (kcd->mode == MODE_DRAGGING)) {
kcd->is_angle_snapping = knife_snap_angle(kcd);
}
else {
diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c
index 50257d250dc..593e27ff69d 100644
--- a/source/blender/editors/mesh/editmesh_loopcut.c
+++ b/source/blender/editors/mesh/editmesh_loopcut.c
@@ -401,7 +401,7 @@ static void ringsel_finish(bContext *C, wmOperator *op)
{
RingSelOpData *lcd = op->customdata;
const int cuts = RNA_int_get(op->ptr, "number_cuts");
- const float smoothness = 0.292f * RNA_float_get(op->ptr, "smoothness");
+ const float smoothness = RNA_float_get(op->ptr, "smoothness");
const int smooth_falloff = RNA_enum_get(op->ptr, "falloff");
#ifdef BMW_EDGERING_NGON
const bool use_only_quads = false;
@@ -430,8 +430,9 @@ static void ringsel_finish(bContext *C, wmOperator *op)
cuts, seltype, SUBD_CORNER_PATH, 0, true,
use_only_quads, 0);
- /* when used in a macro tessface is already re-recalculated */
- EDBM_update_generic(em, (is_macro == false), true);
+ /* when used in a macro the tessfaces will be recalculated anyway,
+ * this is needed here because modifiers depend on updated tessellation, see T45920 */
+ EDBM_update_generic(em, true, true);
if (is_single) {
/* de-select endpoints */
diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c
index eac5e3fece0..1169c91bf66 100644
--- a/source/blender/editors/mesh/editmesh_select.c
+++ b/source/blender/editors/mesh/editmesh_select.c
@@ -2013,7 +2013,7 @@ void EDBM_selectmode_set(BMEditMesh *em)
/**
* Expand & Contract the Selection
- * (used when chaning modes and Ctrl key held)
+ * (used when changing modes and Ctrl key held)
*
* Flush the selection up:
* - vert -> edge
@@ -2389,6 +2389,15 @@ static bool select_linked_delimit_test(
return false;
}
+static void select_linked_delimit_validate(BMesh *bm, int *delimit)
+{
+ if ((*delimit) & BMO_DELIM_UV) {
+ if (!CustomData_has_layer(&bm->ldata, CD_MLOOPUV)) {
+ (*delimit) &= ~BMO_DELIM_UV;
+ }
+ }
+}
+
static void select_linked_delimit_begin(BMesh *bm, short selectmode, int delimit)
{
struct DelimitData delimit_data = {0};
@@ -2441,7 +2450,9 @@ static int edbm_select_linked_exec(bContext *C, wmOperator *op)
BMIter iter;
BMWalker walker;
- const int delimit = RNA_enum_get(op->ptr, "delimit");
+ int delimit = RNA_enum_get(op->ptr, "delimit");
+
+ select_linked_delimit_validate(bm, &delimit);
if (delimit) {
select_linked_delimit_begin(em->bm, em->selectmode, delimit);
@@ -2607,6 +2618,8 @@ static void edbm_select_linked_pick_ex(
BMesh *bm = em->bm;
BMWalker walker;
+ select_linked_delimit_validate(bm, &delimit);
+
if (delimit) {
select_linked_delimit_begin(bm, em->selectmode, delimit);
}
@@ -3538,13 +3551,16 @@ static int edbm_select_random_exec(bContext *C, wmOperator *op)
BMEditMesh *em = BKE_editmesh_from_object(obedit);
const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT);
const float randfac = RNA_float_get(op->ptr, "percent") / 100.0f;
+ const int seed = RNA_int_get(op->ptr, "seed");
BMIter iter;
+ RNG *rng = BLI_rng_new_srandom(seed);
+
if (em->selectmode & SCE_SELECT_VERTEX) {
BMVert *eve;
BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
- if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN) && BLI_frand() < randfac) {
+ if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN) && BLI_rng_get_float(rng) < randfac) {
BM_vert_select_set(em->bm, eve, select);
}
}
@@ -3552,7 +3568,7 @@ static int edbm_select_random_exec(bContext *C, wmOperator *op)
else if (em->selectmode & SCE_SELECT_EDGE) {
BMEdge *eed;
BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
- if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && BLI_frand() < randfac) {
+ if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && BLI_rng_get_float(rng) < randfac) {
BM_edge_select_set(em->bm, eed, select);
}
}
@@ -3560,12 +3576,14 @@ static int edbm_select_random_exec(bContext *C, wmOperator *op)
else {
BMFace *efa;
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && BLI_frand() < randfac) {
+ if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && BLI_rng_get_float(rng) < randfac) {
BM_face_select_set(em->bm, efa, select);
}
}
}
+ BLI_rng_free(rng);
+
if (select) {
/* was EDBM_select_flush, but it over select in edge/face mode */
EDBM_selectmode_flush(em);
@@ -3594,9 +3612,7 @@ void MESH_OT_select_random(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* props */
- RNA_def_float_percentage(ot->srna, "percent", 50.0f, 0.0f, 100.0f,
- "Percent", "Percentage of elements to select randomly", 0.0f, 100.0f);
- WM_operator_properties_select_action_simple(ot, SEL_SELECT);
+ WM_operator_properties_select_random(ot);
}
static int edbm_select_ungrouped_poll(bContext *C)
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index d3937188358..67c23a9f7a1 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -85,7 +85,7 @@ static int edbm_subdivide_exec(bContext *C, wmOperator *op)
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BKE_editmesh_from_object(obedit);
const int cuts = RNA_int_get(op->ptr, "number_cuts");
- float smooth = 0.292f * RNA_float_get(op->ptr, "smoothness");
+ float smooth = RNA_float_get(op->ptr, "smoothness");
const float fractal = RNA_float_get(op->ptr, "fractal") / 2.5f;
const float along_normal = RNA_float_get(op->ptr, "fractal_along_normal");
@@ -96,7 +96,7 @@ static int edbm_subdivide_exec(bContext *C, wmOperator *op)
}
BM_mesh_esubdivide(em->bm, BM_ELEM_SELECT,
- smooth, SUBD_FALLOFF_INVSQUARE, false,
+ smooth, SUBD_FALLOFF_LIN, false,
fractal, along_normal,
cuts,
SUBDIV_SELECT_ORIG, RNA_enum_get(op->ptr, "quadcorner"),
diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c
index d521b2c01e5..c101b416169 100644
--- a/source/blender/editors/mesh/editmesh_utils.c
+++ b/source/blender/editors/mesh/editmesh_utils.c
@@ -671,7 +671,7 @@ UvVertMap *BM_uv_vert_map_create(
float (*tf_uv)[2];
if (use_winding) {
- tf_uv = (float (*)[2])BLI_buffer_resize_data(&tf_uv_buf, vec2f, efa->len);
+ tf_uv = (float (*)[2])BLI_buffer_reinit_data(&tf_uv_buf, vec2f, efa->len);
}
BM_ITER_ELEM_INDEX(l, &liter, efa, BM_LOOPS_OF_FACE, i) {
@@ -823,7 +823,7 @@ UvElementMap *BM_uv_element_map_create(
float (*tf_uv)[2];
if (use_winding) {
- tf_uv = (float (*)[2])BLI_buffer_resize_data(&tf_uv_buf, vec2f, efa->len);
+ tf_uv = (float (*)[2])BLI_buffer_reinit_data(&tf_uv_buf, vec2f, efa->len);
}
BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
diff --git a/source/blender/editors/mesh/mesh_navmesh.c b/source/blender/editors/mesh/mesh_navmesh.c
index 1c36826b882..85868da0b15 100644
--- a/source/blender/editors/mesh/mesh_navmesh.c
+++ b/source/blender/editors/mesh/mesh_navmesh.c
@@ -84,6 +84,7 @@ static void createVertsTrisData(bContext *C, LinkNode *obs,
for (oblink = obs; oblink; oblink = oblink->next) {
ob = (Object *) oblink->link;
dm = mesh_create_derived_no_virtual(scene, ob, NULL, CD_MASK_MESH);
+ DM_ensure_tessface(dm);
BLI_linklist_prepend(&dms, dm);
nverts += dm->getNumVerts(dm);
diff --git a/source/blender/editors/metaball/mball_edit.c b/source/blender/editors/metaball/mball_edit.c
index 42eda235276..de725d391f7 100644
--- a/source/blender/editors/metaball/mball_edit.c
+++ b/source/blender/editors/metaball/mball_edit.c
@@ -372,17 +372,22 @@ static int select_random_metaelems_exec(bContext *C, wmOperator *op)
MetaBall *mb = (MetaBall *)obedit->data;
MetaElem *ml;
const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT);
- float percent = RNA_float_get(op->ptr, "percent") / 100.0f;
+ const float randfac = RNA_float_get(op->ptr, "percent") / 100.0f;
+ const int seed = RNA_int_get(op->ptr, "seed");
+ RNG *rng = BLI_rng_new_srandom(seed);
+
for (ml = mb->editelems->first; ml; ml = ml->next) {
- if (BLI_frand() < percent) {
+ if (BLI_rng_get_float(rng) < randfac) {
if (select)
ml->flag |= SELECT;
else
ml->flag &= ~SELECT;
}
}
-
+
+ BLI_rng_free(rng);
+
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, mb);
return OPERATOR_FINISHED;
@@ -404,9 +409,7 @@ void MBALL_OT_select_random_metaelems(struct wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- RNA_def_float_percentage(ot->srna, "percent", 50.f, 0.0f, 100.0f,
- "Percent", "Percentage of elements to select randomly", 0.0f, 100.0f);
- WM_operator_properties_select_action_simple(ot, SEL_SELECT);
+ WM_operator_properties_select_random(ot);
}
/***************************** Duplicate operator *****************************/
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index 615fbb527b3..269700c3aef 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -1195,89 +1195,16 @@ void OBJECT_OT_delete(wmOperatorType *ot)
/**************************** Copy Utilities ******************************/
/* after copying objects, copied data should get new pointers */
-static void copy_object_set_idnew(bContext *C, int dupflag)
+static void copy_object_set_idnew(bContext *C)
{
Main *bmain = CTX_data_main(C);
- Material *ma, *mao;
- ID *id;
- int a;
- /* XXX check object pointers */
CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
{
- BKE_object_relink(ob);
+ BKE_libblock_relink(&ob->id);
}
CTX_DATA_END;
- /* materials */
- if (dupflag & USER_DUP_MAT) {
- mao = bmain->mat.first;
- while (mao) {
- if (mao->id.newid) {
- ma = (Material *)mao->id.newid;
-
- if (dupflag & USER_DUP_TEX) {
- for (a = 0; a < MAX_MTEX; a++) {
- if (ma->mtex[a]) {
- id = (ID *)ma->mtex[a]->tex;
- if (id) {
- ID_NEW_US(ma->mtex[a]->tex)
- else
- ma->mtex[a]->tex = BKE_texture_copy(ma->mtex[a]->tex);
- id->us--;
- }
- }
- }
- }
-#if 0 // XXX old animation system
- id = (ID *)ma->ipo;
- if (id) {
- ID_NEW_US(ma->ipo)
- else
- ma->ipo = copy_ipo(ma->ipo);
- id->us--;
- }
-#endif // XXX old animation system
- }
- mao = mao->id.next;
- }
- }
-
-#if 0 // XXX old animation system
- /* lamps */
- if (dupflag & USER_DUP_IPO) {
- Lamp *la = bmain->lamp.first;
- while (la) {
- if (la->id.newid) {
- Lamp *lan = (Lamp *)la->id.newid;
- id = (ID *)lan->ipo;
- if (id) {
- ID_NEW_US(lan->ipo)
- else
- lan->ipo = copy_ipo(lan->ipo);
- id->us--;
- }
- }
- la = la->id.next;
- }
- }
-
- /* ipos */
- ipo = bmain->ipo.first;
- while (ipo) {
- if (ipo->id.lib == NULL && ipo->id.newid) {
- Ipo *ipon = (Ipo *)ipo->id.newid;
- IpoCurve *icu;
- for (icu = ipon->curve.first; icu; icu = icu->next) {
- if (icu->driver) {
- ID_NEW(icu->driver->ob);
- }
- }
- }
- ipo = ipo->id.next;
- }
-#endif // XXX old animation system
-
set_sca_new_poins();
BKE_main_id_clear_newpoins(bmain);
@@ -1468,7 +1395,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
if (parent_gh)
BLI_ghash_free(parent_gh, NULL, NULL);
- copy_object_set_idnew(C, 0);
+ copy_object_set_idnew(C);
free_object_duplilist(lb);
@@ -2023,9 +1950,6 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
ID_NEW_US2(obn->data)
else {
obn->data = BKE_mesh_copy(obn->data);
- if (obn->fluidsimSettings) {
- obn->fluidsimSettings->orgMesh = (Mesh *)obn->data;
- }
didit = 1;
}
id->us--;
@@ -2190,7 +2114,7 @@ Base *ED_object_add_duplicate(Main *bmain, Scene *scene, Base *base, int dupflag
ob = basen->object;
/* link own references to the newly duplicated data [#26816] */
- BKE_object_relink(ob);
+ BKE_libblock_relink(&ob->id);
set_sca_new_poins_ob(ob);
/* DAG_relations_tag_update(bmain); */ /* caller must do */
@@ -2235,7 +2159,7 @@ static int duplicate_exec(bContext *C, wmOperator *op)
}
CTX_DATA_END;
- copy_object_set_idnew(C, dupflag);
+ copy_object_set_idnew(C);
DAG_relations_tag_update(bmain);
@@ -2320,7 +2244,7 @@ static int add_named_exec(bContext *C, wmOperator *op)
ED_base_object_select(basen, BA_SELECT);
ED_base_object_activate(C, basen);
- copy_object_set_idnew(C, dupflag);
+ copy_object_set_idnew(C);
DAG_relations_tag_update(bmain);
diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c
index bd847fcd712..ecaa05ace99 100644
--- a/source/blender/editors/object/object_bake.c
+++ b/source/blender/editors/object/object_bake.c
@@ -215,7 +215,7 @@ static DerivedMesh *multiresbake_create_loresdm(Scene *scene, Object *ob, int *l
tmp_mmd.simple = true;
}
- DM_set_only_copy(cddm, CD_MASK_BAREMESH | CD_MASK_MFACE | CD_MASK_MTFACE);
+ DM_set_only_copy(cddm, CD_MASK_BAREMESH);
tmp_mmd.lvl = *lvl;
tmp_mmd.sculptlvl = *lvl;
@@ -283,23 +283,6 @@ static void clear_single_image(Image *image, ClearFlag flag)
}
}
-static void clear_images(MTFace *mtface, int totface, ClearFlag flag)
-{
- int a;
-
- for (a = 0; a < totface; a++) {
- mtface[a].tpage->id.flag &= ~LIB_DOIT;
- }
-
- for (a = 0; a < totface; a++) {
- clear_single_image(mtface[a].tpage, flag);
- }
-
- for (a = 0; a < totface; a++) {
- mtface[a].tpage->id.flag &= ~LIB_DOIT;
- }
-}
-
static void clear_images_poly(MTexPoly *mtpoly, int totpoly, ClearFlag flag)
{
int a;
@@ -342,7 +325,6 @@ static int multiresbake_image_exec_locked(bContext *C, wmOperator *op)
clear_flag = CLEAR_DISPLACEMENT;
}
- clear_images(me->mtface, me->totface, clear_flag);
clear_images_poly(me->mtpoly, me->totpoly, clear_flag);
}
CTX_DATA_END;
@@ -440,7 +422,7 @@ static void multiresbake_startjob(void *bkv, short *stop, short *do_update, floa
if (bkj->bake_clear) { /* clear images */
for (data = bkj->data.first; data; data = data->next) {
DerivedMesh *dm = data->lores_dm;
- MTFace *mtface = CustomData_get_layer(&dm->faceData, CD_MTFACE);
+ MTexPoly *mtexpoly = CustomData_get_layer(&dm->polyData, CD_MTEXPOLY);
ClearFlag clear_flag = 0;
if (bkj->mode == RE_BAKE_NORMALS) {
@@ -450,7 +432,7 @@ static void multiresbake_startjob(void *bkv, short *stop, short *do_update, floa
clear_flag = CLEAR_DISPLACEMENT;
}
- clear_images(mtface, dm->getNumTessFaces(dm), clear_flag);
+ clear_images_poly(mtexpoly, dm->getNumPolys(dm), clear_flag);
}
}
diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c
index b382fbafcfd..9090bffcbfc 100644
--- a/source/blender/editors/object/object_bake_api.c
+++ b/source/blender/editors/object/object_bake_api.c
@@ -563,7 +563,7 @@ static int bake(
Object *ob_cage = NULL;
BakeHighPolyData *highpoly = NULL;
- int tot_highpoly;
+ int tot_highpoly = 0;
char restrict_flag_low = ob_low->restrictflag;
char restrict_flag_cage = 0;
@@ -689,7 +689,6 @@ static int bake(
/* get the mesh as it arrives in the renderer */
me_low = BKE_mesh_new_from_object(bmain, scene, ob_low, 1, 2, 0, 0);
BKE_mesh_split_faces(me_low);
- BKE_mesh_tessface_ensure(me_low);
/* populate the pixel array with the face data */
if ((is_selected_to_active && (ob_cage == NULL) && is_cage) == false)
@@ -706,8 +705,7 @@ static int bake(
if (ob_cage) {
me_cage = BKE_mesh_new_from_object(bmain, scene, ob_cage, 1, 2, 0, 0);
BKE_mesh_split_faces(me_cage);
- BKE_mesh_tessface_ensure(me_cage);
- if (me_low->totface != me_cage->totface) {
+ if ((me_low->totpoly != me_cage->totpoly) || (me_low->totloop != me_cage->totloop)) {
BKE_report(reports, RPT_ERROR,
"Invalid cage object, the cage mesh must have the same number "
"of faces as the active object");
@@ -740,7 +738,6 @@ static int bake(
/* get the cage mesh as it arrives in the renderer */
me_cage = BKE_mesh_new_from_object(bmain, scene, ob_low, 1, 2, 0, 0);
BKE_mesh_split_faces(me_cage);
- BKE_mesh_tessface_ensure(me_cage);
RE_bake_pixels_populate(me_cage, pixel_array_low, num_pixels, &bake_images, uv_layer);
}
@@ -769,7 +766,6 @@ static int bake(
highpoly[i].me = BKE_mesh_new_from_object(bmain, scene, highpoly[i].ob, 1, 2, 0, 0);
highpoly[i].ob->restrictflag &= ~OB_RESTRICT_RENDER;
BKE_mesh_split_faces(highpoly[i].me);
- BKE_mesh_tessface_ensure(highpoly[i].me);
/* lowpoly to highpoly transformation matrix */
copy_m4_m4(highpoly[i].obmat, highpoly[i].ob->obmat);
@@ -873,7 +869,6 @@ cage_cleanup:
me_nores = BKE_mesh_new_from_object(bmain, scene, ob_low, 1, 2, 0, 0);
BKE_mesh_split_faces(me_nores);
- BKE_mesh_tessface_ensure(me_nores);
RE_bake_pixels_populate(me_nores, pixel_array_low, num_pixels, &bake_images, uv_layer);
RE_bake_normal_world_to_tangent(pixel_array_low, num_pixels, depth, result, me_nores, normal_swizzle, ob_low->obmat);
diff --git a/source/blender/editors/object/object_data_transfer.c b/source/blender/editors/object/object_data_transfer.c
index 90c3f0026ac..95e1204e122 100644
--- a/source/blender/editors/object/object_data_transfer.c
+++ b/source/blender/editors/object/object_data_transfer.c
@@ -183,7 +183,8 @@ static EnumPropertyItem *dt_layers_select_src_itemf(
}
/* Note: DT_layers_select_dst_items enum is from rna_modifier.c */
-static EnumPropertyItem *dt_layers_select_dst_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free)
+static EnumPropertyItem *dt_layers_select_dst_itemf(
+ bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free)
{
EnumPropertyItem *item = NULL;
int totitem = 0;
@@ -208,6 +209,26 @@ static EnumPropertyItem *dt_layers_select_dst_itemf(bContext *C, PointerRNA *ptr
return item;
}
+static EnumPropertyItem *dt_layers_select_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *prop, bool *r_free)
+{
+ const bool reverse_transfer = RNA_boolean_get(ptr, "use_reverse_transfer");
+
+ if (STREQ(RNA_property_identifier(prop), "layers_select_dst")) {
+ if (reverse_transfer) {
+ return dt_layers_select_src_itemf(C, ptr, prop, r_free);
+ }
+ else {
+ return dt_layers_select_dst_itemf(C, ptr, prop, r_free);
+ }
+ }
+ else if (reverse_transfer) {
+ return dt_layers_select_dst_itemf(C, ptr, prop, r_free);
+ }
+ else {
+ return dt_layers_select_src_itemf(C, ptr, prop, r_free);
+ }
+}
+
/* Note: DT_mix_mode_items enum is from rna_modifier.c */
static EnumPropertyItem *dt_mix_mode_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free)
{
@@ -530,7 +551,7 @@ void OBJECT_OT_data_transfer(wmOperatorType *ot)
/* Properties.*/
prop = RNA_def_boolean(ot->srna, "use_reverse_transfer", false, "Reverse Transfer",
"Transfer from selected objects to active one");
- RNA_def_property_flag(prop, PROP_HIDDEN);
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
RNA_def_boolean(ot->srna, "use_freeze", false, "Freeze Operator",
"Prevent changes to settings to re-run the operator, "
@@ -574,11 +595,11 @@ void OBJECT_OT_data_transfer(wmOperatorType *ot)
/* How to handle multi-layers types of data. */
prop = RNA_def_enum(ot->srna, "layers_select_src", DT_layers_select_src_items, DT_LAYERS_ACTIVE_SRC,
"Source Layers Selection", "Which layers to transfer, in case of multi-layers types");
- RNA_def_property_enum_funcs_runtime(prop, NULL, NULL, dt_layers_select_src_itemf);
+ RNA_def_property_enum_funcs_runtime(prop, NULL, NULL, dt_layers_select_itemf);
prop = RNA_def_enum(ot->srna, "layers_select_dst", DT_layers_select_dst_items, DT_LAYERS_ACTIVE_DST,
"Destination Layers Matching", "How to match source and destination layers");
- RNA_def_property_enum_funcs_runtime(prop, NULL, NULL, dt_layers_select_dst_itemf);
+ RNA_def_property_enum_funcs_runtime(prop, NULL, NULL, dt_layers_select_itemf);
prop = RNA_def_enum(ot->srna, "mix_mode", DT_mix_mode_items, CDT_MIX_TRANSFER, "Mix Mode",
"How to affect destination elements with source values");
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index 5b39a76c2a5..05a55a8996b 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -576,7 +576,7 @@ static int editmode_toggle_exec(bContext *C, wmOperator *op)
{
const int mode_flag = OB_MODE_EDIT;
const bool is_mode_set = (CTX_data_edit_object(C) != NULL);
- ToolSettings *toolsettings = CTX_data_tool_settings(C);
+ Scene *scene = CTX_data_scene(C);
if (!is_mode_set) {
Object *ob = CTX_data_active_object(C);
@@ -590,7 +590,7 @@ static int editmode_toggle_exec(bContext *C, wmOperator *op)
else
ED_object_editmode_exit(C, EM_FREEDATA | EM_FREEUNDO | EM_WAITCURSOR); /* had EM_DO_UNDO but op flag calls undo too [#24685] */
- ED_space_image_uv_sculpt_update(CTX_wm_manager(C), toolsettings);
+ ED_space_image_uv_sculpt_update(CTX_wm_manager(C), scene);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/object/object_lattice.c b/source/blender/editors/object/object_lattice.c
index 76d9facf701..410b15581df 100644
--- a/source/blender/editors/object/object_lattice.c
+++ b/source/blender/editors/object/object_lattice.c
@@ -192,9 +192,13 @@ static int lattice_select_random_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
Lattice *lt = ((Lattice *)obedit->data)->editlatt->latt;
+
const float randfac = RNA_float_get(op->ptr, "percent") / 100.0f;
+ const int seed = RNA_int_get(op->ptr, "seed");
const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT);
+ RNG *rng = BLI_rng_new_srandom(seed);
+
int tot;
BPoint *bp;
@@ -202,7 +206,7 @@ static int lattice_select_random_exec(bContext *C, wmOperator *op)
bp = lt->def;
while (tot--) {
if (!bp->hide) {
- if (BLI_frand() < randfac) {
+ if (BLI_rng_get_float(rng) < randfac) {
bpoint_select_set(bp, select);
}
}
@@ -213,6 +217,8 @@ static int lattice_select_random_exec(bContext *C, wmOperator *op)
lt->actbp = LT_ACTBP_NONE;
}
+ BLI_rng_free(rng);
+
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_FINISHED;
@@ -233,9 +239,7 @@ void LATTICE_OT_select_random(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* props */
- RNA_def_float_percentage(ot->srna, "percent", 50.f, 0.0f, 100.0f,
- "Percent", "Percentage of elements to select randomly", 0.f, 100.0f);
- WM_operator_properties_select_action_simple(ot, SEL_SELECT);
+ WM_operator_properties_select_random(ot);
}
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index e21f58d8a38..3d030f1a770 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -1794,7 +1794,7 @@ static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const in
/* object and group pointers */
for (base = FIRSTBASE; base; base = base->next) {
- BKE_object_relink(base->object);
+ BKE_libblock_relink(&base->object->id);
}
set_sca_new_poins();
diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c
index 83334e4e6a3..2f2eece8018 100644
--- a/source/blender/editors/object/object_select.c
+++ b/source/blender/editors/object/object_select.c
@@ -854,47 +854,47 @@ static int object_select_grouped_exec(bContext *C, wmOperator *op)
switch (type) {
case OBJECT_GRPSEL_CHILDREN_RECURSIVE:
- changed = select_grouped_children(C, ob, true);
+ changed |= select_grouped_children(C, ob, true);
break;
case OBJECT_GRPSEL_CHILDREN:
- changed = select_grouped_children(C, ob, false);
+ changed |= select_grouped_children(C, ob, false);
break;
case OBJECT_GRPSEL_PARENT:
- changed = select_grouped_parent(C);
+ changed |= select_grouped_parent(C);
break;
case OBJECT_GRPSEL_SIBLINGS:
- changed = select_grouped_siblings(C, ob);
+ changed |= select_grouped_siblings(C, ob);
break;
case OBJECT_GRPSEL_TYPE:
- changed = select_grouped_type(C, ob);
+ changed |= select_grouped_type(C, ob);
break;
case OBJECT_GRPSEL_LAYER:
- changed = select_grouped_layer(C, ob);
+ changed |= select_grouped_layer(C, ob);
break;
case OBJECT_GRPSEL_GROUP:
- changed = select_grouped_group(C, ob);
+ changed |= select_grouped_group(C, ob);
break;
case OBJECT_GRPSEL_HOOK:
- changed = select_grouped_object_hooks(C, ob);
+ changed |= select_grouped_object_hooks(C, ob);
break;
case OBJECT_GRPSEL_PASS:
- changed = select_grouped_index_object(C, ob);
+ changed |= select_grouped_index_object(C, ob);
break;
case OBJECT_GRPSEL_COLOR:
- changed = select_grouped_color(C, ob);
+ changed |= select_grouped_color(C, ob);
break;
case OBJECT_GRPSEL_PROPERTIES:
- changed = select_grouped_gameprops(C, ob);
+ changed |= select_grouped_gameprops(C, ob);
break;
case OBJECT_GRPSEL_KEYINGSET:
- changed = select_grouped_keyingset(C, ob, op->reports);
+ changed |= select_grouped_keyingset(C, ob, op->reports);
break;
case OBJECT_GRPSEL_LAMP_TYPE:
if (ob->type != OB_LAMP) {
BKE_report(op->reports, RPT_ERROR, "Active object must be a lamp");
break;
}
- changed = select_grouped_lamptype(C, ob);
+ changed |= select_grouped_lamptype(C, ob);
break;
default:
break;
@@ -1179,19 +1179,22 @@ void OBJECT_OT_select_mirror(wmOperatorType *ot)
static int object_select_random_exec(bContext *C, wmOperator *op)
{
- float percent;
+ const float randfac = RNA_float_get(op->ptr, "percent") / 100.0f;
+ const int seed = RNA_int_get(op->ptr, "seed");
const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT);
- percent = RNA_float_get(op->ptr, "percent") / 100.0f;
-
+ RNG *rng = BLI_rng_new_srandom(seed);
+
CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
{
- if (BLI_frand() < percent) {
+ if (BLI_rng_get_float(rng) < randfac) {
ED_base_object_select(base, select);
}
}
CTX_DATA_END;
-
+
+ BLI_rng_free(rng);
+
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
return OPERATOR_FINISHED;
@@ -1213,6 +1216,5 @@ void OBJECT_OT_select_random(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- RNA_def_float_percentage(ot->srna, "percent", 50.f, 0.0f, 100.0f, "Percent", "Percentage of objects to select randomly", 0.f, 100.0f);
- WM_operator_properties_select_action_simple(ot, SEL_SELECT);
+ WM_operator_properties_select_random(ot);
}
diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c
index 340b662c0ef..ac1f13ee59c 100644
--- a/source/blender/editors/object/object_transform.c
+++ b/source/blender/editors/object/object_transform.c
@@ -382,7 +382,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 (ELEM(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, OB_FONT)) {
ID *obdata = ob->data;
if (ID_REAL_USERS(obdata) > 1) {
BKE_reportf(reports, RPT_ERROR,
@@ -418,6 +418,15 @@ static int apply_objects_internal(bContext *C, ReportList *reports, bool apply_l
changed = false;
}
}
+
+ if (ob->type == OB_FONT) {
+ if (apply_rot || apply_loc) {
+ BKE_reportf(reports, RPT_ERROR,
+ "Font's can only have scale applied: \"%s\"",
+ ob->id.name + 2);
+ changed = false;
+ }
+ }
}
CTX_DATA_END;
@@ -496,6 +505,22 @@ static int apply_objects_internal(bContext *C, ReportList *reports, bool apply_l
scale = mat3_to_scale(rsmat);
BKE_curve_transform_ex(cu, mat, true, scale);
}
+ else if (ob->type == OB_FONT) {
+ Curve *cu = ob->data;
+ int i;
+
+ scale = mat3_to_scale(rsmat);
+
+ for (i = 0; i < cu->totbox; i++) {
+ TextBox *tb = &cu->tb[i];
+ tb->x *= scale;
+ tb->y *= scale;
+ tb->w *= scale;
+ tb->h *= scale;
+ }
+
+ cu->fsize *= scale;
+ }
else if (ob->type == OB_CAMERA) {
MovieClip *clip = BKE_object_movieclip_get(scene, ob, false);
diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c
index d52031ecc03..352c90e805a 100644
--- a/source/blender/editors/object/object_vgroup.c
+++ b/source/blender/editors/object/object_vgroup.c
@@ -246,7 +246,7 @@ bool ED_vgroup_parray_alloc(ID *id, MDeformVert ***dvert_arr, int *dvert_tot, co
/**
* For use with tools that use ED_vgroup_parray_alloc with \a use_vert_sel == true.
- * This finds the unselected mirror deform verts and copys the weights to them from the selected.
+ * This finds the unselected mirror deform verts and copies the weights to them from the selected.
*
* \note \a dvert_array has mirrored weights filled in, incase cleanup operations are needed on both.
*/
@@ -1213,8 +1213,8 @@ static void getVerticalAndHorizontalChange(const float norm[3], float d, const f
plane_from_point_normal_v3(plane, coord, norm);
- closest_to_plane_v3(projA, plane, start);
- closest_to_plane_v3(projB, plane, end);
+ closest_to_plane_normalized_v3(projA, plane, start);
+ closest_to_plane_normalized_v3(projB, plane, end);
/* (vertical and horizontal refer to the plane's y and xz respectively)
* vertical distance */
dists[index] = dot_v3v3(norm, end) + d;
diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c
index 892545a8efd..32cd1f7a1ce 100644
--- a/source/blender/editors/physics/particle_edit.c
+++ b/source/blender/editors/physics/particle_edit.c
@@ -1634,7 +1634,10 @@ static int select_random_exec(bContext *C, wmOperator *op)
int p;
int k;
- const float randf = RNA_float_get (op->ptr, "percent") / 100.0f;
+ const float randfac = RNA_float_get (op->ptr, "percent") / 100.0f;
+ const int seed = RNA_int_get(op->ptr, "seed");
+ const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT);
+ RNG *rng;
type = RNA_enum_get(op->ptr, "type");
@@ -1644,10 +1647,12 @@ static int select_random_exec(bContext *C, wmOperator *op)
ob = CTX_data_active_object(C);
edit = PE_get_current(scene, ob);
+ rng = BLI_rng_new_srandom(seed);
+
switch (type) {
case RAN_HAIR:
LOOP_VISIBLE_POINTS {
- int flag = (BLI_frand() < randf) ? SEL_SELECT : SEL_DESELECT;
+ int flag = ((BLI_rng_get_float(rng) < randfac) == select) ? SEL_SELECT : SEL_DESELECT;
LOOP_KEYS {
select_action_apply (point, key, flag);
}
@@ -1656,13 +1661,15 @@ static int select_random_exec(bContext *C, wmOperator *op)
case RAN_POINTS:
LOOP_VISIBLE_POINTS {
LOOP_VISIBLE_KEYS {
- int flag = (BLI_frand() < randf) ? SEL_SELECT : SEL_DESELECT;
+ int flag = ((BLI_rng_get_float(rng) < randfac) == select) ? SEL_SELECT : SEL_DESELECT;
select_action_apply (point, key, flag);
}
}
break;
}
+ BLI_rng_free(rng);
+
PE_update_selection(data.scene, data.ob, 1);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, data.ob);
@@ -1684,9 +1691,7 @@ void PARTICLE_OT_select_random(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
/* properties */
- RNA_def_float_percentage (ot->srna, "percent", 50.0f, 0.0f, 100.0f, "Percent",
- "Percentage (mean) of elements in randomly selected set",
- 0.0f, 100.0f);
+ WM_operator_properties_select_random(ot);
ot->prop = RNA_def_enum (ot->srna, "type", select_random_type_items, RAN_HAIR,
"Type", "Select either hair or points");
}
diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c
index 327ce060df9..337e7e99929 100644
--- a/source/blender/editors/physics/particle_object.c
+++ b/source/blender/editors/physics/particle_object.c
@@ -1095,6 +1095,7 @@ static bool copy_particle_systems_to_object(Scene *scene, Object *ob_from, Parti
break;
default:
/* should not happen */
+ from_mat = to_mat = NULL;
BLI_assert(false);
break;
}
diff --git a/source/blender/editors/render/render_intern.h b/source/blender/editors/render/render_intern.h
index 54429f9f066..26f313cb3fe 100644
--- a/source/blender/editors/render/render_intern.h
+++ b/source/blender/editors/render/render_intern.h
@@ -93,7 +93,7 @@ void render_view3d_update(struct RenderEngine *engine, const struct bContext *C)
void render_view3d_draw(struct RenderEngine *engine, const struct bContext *C);
/* render_view.c */
-struct ScrArea *render_view_open(struct bContext *C, int mx, int my);
+struct ScrArea *render_view_open(struct bContext *C, int mx, int my, struct ReportList *reports);
void RENDER_OT_view_show(struct wmOperatorType *ot);
void RENDER_OT_view_cancel(struct wmOperatorType *ot);
diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c
index 75ee6d17307..164b8fa1c9a 100644
--- a/source/blender/editors/render/render_internal.c
+++ b/source/blender/editors/render/render_internal.c
@@ -190,7 +190,7 @@ static void image_buffer_rect_update(RenderJob *rj, RenderResult *rr, ImBuf *ibu
* - sergey -
*/
/* TODO(sergey): Need to check has_combined here? */
- if (iuser->passtype == SCE_PASS_COMBINED) {
+ if (iuser->pass == 0) {
RenderView *rv;
size_t view_id = BKE_scene_multiview_view_id_get(&scene->r, viewname);
rv = RE_RenderViewGetById(rr, view_id);
@@ -525,6 +525,7 @@ static void render_image_update_pass_and_layer(RenderJob *rj, RenderResult *rr,
}
}
+ iuser->pass = sima->iuser.pass;
iuser->layer = sima->iuser.layer;
RE_ReleaseResult(rj->re);
@@ -876,7 +877,7 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
// store spare
/* ensure at least 1 area shows result */
- sa = render_view_open(C, event->x, event->y);
+ sa = render_view_open(C, event->x, event->y, op->reports);
jobflag = WM_JOB_EXCL_RENDER | WM_JOB_PRIORITY | WM_JOB_PROGRESS;
@@ -898,7 +899,6 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
rj->write_still = is_write_still && !is_animation;
rj->iuser.scene = scene;
rj->iuser.ok = 1;
- rj->iuser.passtype = SCE_PASS_COMBINED;
rj->reports = op->reports;
rj->orig_layer = 0;
rj->last_layer = 0;
diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c
index c718dfa9229..51c4e8bc16e 100644
--- a/source/blender/editors/render/render_opengl.c
+++ b/source/blender/editors/render/render_opengl.c
@@ -96,6 +96,7 @@ typedef struct OGLRender {
ImageUser iuser;
GPUOffScreen *ofs;
+ int ofs_samples;
GPUFX *fx;
int sizex, sizey;
int write_still;
@@ -228,13 +229,8 @@ static void screen_opengl_views_setup(OGLRender *oglrender)
}
BLI_lock_thread(LOCK_DRAW_IMAGE);
- if (is_multiview && BKE_scene_multiview_is_stereo3d(rd)) {
- oglrender->ima->flag |= IMA_IS_STEREO;
- }
- else {
- oglrender->ima->flag &= ~IMA_IS_STEREO;
+ if (!(is_multiview && BKE_scene_multiview_is_stereo3d(rd)))
oglrender->iuser.flag &= ~IMA_SHOW_STEREO;
- }
BLI_unlock_thread(LOCK_DRAW_IMAGE);
/* will only work for non multiview correctly */
@@ -279,6 +275,9 @@ static void screen_opengl_render_doit(OGLRender *oglrender, RenderResult *rr)
&context);
context.view_id = BKE_scene_multiview_view_id_get(&scene->r, viewname);
+ context.gpu_offscreen = oglrender->ofs;
+ context.gpu_samples = oglrender->ofs_samples;
+
ibuf = BKE_sequencer_give_ibuf(&context, CFRA, chanshown);
if (ibuf) {
@@ -375,63 +374,23 @@ static void screen_opengl_render_doit(OGLRender *oglrender, RenderResult *rr)
rect = MEM_mallocN(sizex * sizey * sizeof(unsigned char) * 4, "offscreen rect");
- if ((scene->r.mode & R_OSA) == 0) {
- ED_view3d_draw_offscreen(
- scene, v3d, ar, sizex, sizey, NULL, winmat,
- draw_bgpic, draw_sky, is_persp,
- oglrender->ofs, oglrender->fx, &fx_settings, viewname);
- GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, rect);
- }
- else {
- /* simple accumulation, less hassle then FSAA FBO's */
- static float jit_ofs[32][2];
- float winmat_jitter[4][4];
- int *accum_buffer = MEM_mallocN(sizex * sizey * sizeof(int) * 4, "accum1");
- int i, j;
-
- BLI_jitter_init(jit_ofs, scene->r.osa);
-
- /* first sample buffer, also initializes 'rv3d->persmat' */
- ED_view3d_draw_offscreen(
- scene, v3d, ar, sizex, sizey, NULL, winmat,
- draw_bgpic, draw_sky, is_persp,
- oglrender->ofs, oglrender->fx, &fx_settings, viewname);
- GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, rect);
-
- for (i = 0; i < sizex * sizey * 4; i++)
- accum_buffer[i] = rect[i];
-
- /* skip the first sample */
- for (j = 1; j < scene->r.osa; j++) {
- copy_m4_m4(winmat_jitter, winmat);
- window_translate_m4(winmat_jitter, rv3d->persmat,
- (jit_ofs[j][0] * 2.0f) / sizex,
- (jit_ofs[j][1] * 2.0f) / sizey);
-
- ED_view3d_draw_offscreen(
- scene, v3d, ar, sizex, sizey, NULL, winmat_jitter,
- draw_bgpic, draw_sky, is_persp,
- oglrender->ofs, oglrender->fx, &fx_settings, viewname);
- GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, rect);
-
- for (i = 0; i < sizex * sizey * 4; i++)
- accum_buffer[i] += rect[i];
- }
-
- for (i = 0; i < sizex * sizey * 4; i++)
- rect[i] = accum_buffer[i] / scene->r.osa;
-
- MEM_freeN(accum_buffer);
- }
+ ED_view3d_draw_offscreen(
+ scene, v3d, ar, sizex, sizey, NULL, winmat,
+ draw_bgpic, draw_sky, is_persp, viewname,
+ oglrender->fx, &fx_settings,
+ oglrender->ofs);
+ GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, rect);
GPU_offscreen_unbind(oglrender->ofs, true); /* unbind */
}
else {
/* shouldnt suddenly give errors mid-render but possible */
char err_out[256] = "unknown";
- ImBuf *ibuf_view = ED_view3d_draw_offscreen_imbuf_simple(scene, scene->camera, oglrender->sizex, oglrender->sizey,
- IB_rect, OB_SOLID, false, true, true,
- (draw_sky) ? R_ADDSKY : R_ALPHAPREMUL, viewname, err_out);
+ ImBuf *ibuf_view = ED_view3d_draw_offscreen_imbuf_simple(
+ scene, scene->camera, oglrender->sizex, oglrender->sizey,
+ IB_rect, OB_SOLID, false, true, true,
+ (draw_sky) ? R_ADDSKY : R_ALPHAPREMUL, oglrender->ofs_samples, viewname,
+ oglrender->ofs, err_out);
camera = scene->camera;
if (ibuf_view) {
@@ -541,6 +500,7 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op)
GPUOffScreen *ofs;
OGLRender *oglrender;
int sizex, sizey;
+ const int samples = (scene->r.mode & R_OSA) ? scene->r.osa : 0;
bool is_view_context = RNA_boolean_get(op->ptr, "view_context");
const bool is_animation = RNA_boolean_get(op->ptr, "animation");
const bool is_sequencer = RNA_boolean_get(op->ptr, "sequencer");
@@ -585,7 +545,7 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op)
sizey = (scene->r.size * scene->r.ysch) / 100;
/* corrects render size with actual size, not every card supports non-power-of-two dimensions */
- ofs = GPU_offscreen_create(sizex, sizey, err_out);
+ ofs = GPU_offscreen_create(sizex, sizey, samples, err_out);
if (!ofs) {
BKE_reportf(op->reports, RPT_ERROR, "Failed to create OpenGL off-screen buffer, %s", err_out);
@@ -597,6 +557,7 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op)
op->customdata = oglrender;
oglrender->ofs = ofs;
+ oglrender->ofs_samples = samples;
oglrender->sizex = sizex;
oglrender->sizey = sizey;
oglrender->bmain = CTX_data_main(C);
@@ -706,7 +667,7 @@ static void screen_opengl_render_cancel(bContext *C, wmOperator *op)
}
/* share between invoke and exec */
-static int screen_opengl_render_anim_initialize(bContext *C, wmOperator *op)
+static bool screen_opengl_render_anim_initialize(bContext *C, wmOperator *op)
{
/* initialize animation */
OGLRender *oglrender;
@@ -722,9 +683,16 @@ static int screen_opengl_render_anim_initialize(bContext *C, wmOperator *op)
size_t i, width, height;
BKE_scene_multiview_videos_dimensions_get(&scene->r, oglrender->sizex, oglrender->sizey, &width, &height);
- oglrender->movie_ctx_arr = MEM_mallocN(sizeof(void *) * oglrender->totvideos, "Movies");
oglrender->mh = BKE_movie_handle_get(scene->r.im_format.imtype);
+ if (oglrender->mh == NULL) {
+ BKE_report(oglrender->reports, RPT_ERROR, "Movie format unsupported");
+ screen_opengl_render_end(C, oglrender);
+ return false;
+ }
+
+ oglrender->movie_ctx_arr = MEM_mallocN(sizeof(void *) * oglrender->totvideos, "Movies");
+
for (i = 0; i < oglrender->totvideos; i++) {
const char *suffix = BKE_scene_multiview_view_id_suffix_get(&scene->r, i);
@@ -733,7 +701,7 @@ static int screen_opengl_render_anim_initialize(bContext *C, wmOperator *op)
oglrender->sizey, oglrender->reports, PRVRANGEON != 0, suffix))
{
screen_opengl_render_end(C, oglrender);
- return 0;
+ return false;
}
}
}
@@ -742,7 +710,7 @@ static int screen_opengl_render_anim_initialize(bContext *C, wmOperator *op)
oglrender->nfra = PSFRA;
scene->r.cfra = PSFRA;
- return 1;
+ return true;
}
static bool screen_opengl_render_anim_step(bContext *C, wmOperator *op)
@@ -904,7 +872,7 @@ static int screen_opengl_render_invoke(bContext *C, wmOperator *op, const wmEven
}
oglrender = op->customdata;
- render_view_open(C, event->x, event->y);
+ render_view_open(C, event->x, event->y, op->reports);
/* view may be changed above (R_OUTPUT_WINDOW) */
oglrender->win = CTX_wm_window(C);
diff --git a/source/blender/editors/render/render_update.c b/source/blender/editors/render/render_update.c
index dedcbb144aa..f11a8177bf8 100644
--- a/source/blender/editors/render/render_update.c
+++ b/source/blender/editors/render/render_update.c
@@ -52,6 +52,7 @@
#include "BKE_material.h"
#include "BKE_node.h"
#include "BKE_paint.h"
+#include "BKE_scene.h"
#include "GPU_material.h"
#include "GPU_buffers.h"
@@ -142,6 +143,23 @@ void ED_render_scene_update(Main *bmain, Scene *scene, int updated)
recursive_check = false;
}
+void ED_render_scene_update_pre(Main *bmain, Scene *scene, bool time)
+{
+ /* Blender internal might access to the data which is gonna to be freed
+ * by the scene update functions. This applies for example to simulation
+ * data like smoke and fire.
+ */
+ if (time && !BKE_scene_use_new_shading_nodes(scene)) {
+ bScreen *sc;
+ ScrArea *sa;
+ for (sc = bmain->screen.first; sc; sc = sc->id.next) {
+ for (sa = sc->areabase.first; sa; sa = sa->next) {
+ ED_render_engine_area_exit(bmain, sa);
+ }
+ }
+ }
+}
+
void ED_render_engine_area_exit(Main *bmain, ScrArea *sa)
{
/* clear all render engines in this area */
diff --git a/source/blender/editors/render/render_view.c b/source/blender/editors/render/render_view.c
index f6690296890..4e36303d829 100644
--- a/source/blender/editors/render/render_view.c
+++ b/source/blender/editors/render/render_view.c
@@ -38,6 +38,7 @@
#include "BKE_image.h"
#include "BKE_global.h"
#include "BKE_screen.h"
+#include "BKE_report.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -125,7 +126,7 @@ static ScrArea *find_area_image_empty(bContext *C)
/********************** open image editor for render *************************/
/* new window uses x,y to set position */
-ScrArea *render_view_open(bContext *C, int mx, int my)
+ScrArea *render_view_open(bContext *C, int mx, int my, ReportList *reports)
{
wmWindow *win = CTX_wm_window(C);
Scene *scene = CTX_data_scene(C);
@@ -155,7 +156,10 @@ ScrArea *render_view_open(bContext *C, int mx, int my)
rect.ymax = rect.ymin + sizey;
/* changes context! */
- WM_window_open_temp(C, &rect, WM_WINDOW_RENDER);
+ if (WM_window_open_temp(C, &rect, WM_WINDOW_RENDER) == NULL) {
+ BKE_report(reports, RPT_ERROR, "Failed to open window!");
+ return NULL;
+ }
sa = CTX_wm_area(C);
}
@@ -292,7 +296,7 @@ void RENDER_OT_view_cancel(struct wmOperatorType *ot)
/************************* show render viewer *****************/
-static int render_view_show_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
+static int render_view_show_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
wmWindow *wincur = CTX_wm_window(C);
@@ -341,7 +345,7 @@ static int render_view_show_invoke(bContext *C, wmOperator *UNUSED(op), const wm
}
}
else {
- render_view_open(C, event->x, event->y);
+ render_view_open(C, event->x, event->y, op->reports);
}
}
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index 03df6b17acd..3e0bbd47eda 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -2116,9 +2116,9 @@ static const char *meta_data_list[] =
{
"File",
"Strip",
- "Note",
"Date",
"RenderTime",
+ "Note",
"Marker",
"Time",
"Frame",
@@ -2139,7 +2139,15 @@ static void metadata_draw_imbuf(ImBuf *ibuf, const rctf *rect, int fontid, const
short i;
int len;
const float height = BLF_height_max(fontid);
- const float vertical_offset = height + (0.1f * U.widget_unit);
+ const float margin = height / 8;
+ const float vertical_offset = (height + margin);
+
+ /* values taking margins into account */
+ const float descender = BLF_descender(fontid);
+ const float xmin = (rect->xmin + margin);
+ const float xmax = (rect->xmax - margin);
+ const float ymin = (rect->ymin + margin) - descender;
+ const float ymax = (rect->ymax - margin) - descender;
if (is_top) {
for (i = 0; i < 4; i++) {
@@ -2148,8 +2156,7 @@ static void metadata_draw_imbuf(ImBuf *ibuf, const rctf *rect, int fontid, const
bool do_newline = false;
len = BLI_snprintf_rlen(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[0]);
if (metadata_is_valid(ibuf, temp_str, 0, len)) {
- BLF_position(fontid, rect->xmin + (0.2f * U.widget_unit),
- rect->ymax - vertical_offset, 0.0f);
+ BLF_position(fontid, xmin, ymax - vertical_offset, 0.0f);
BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX);
do_newline = true;
}
@@ -2157,30 +2164,40 @@ static void metadata_draw_imbuf(ImBuf *ibuf, const rctf *rect, int fontid, const
len = BLI_snprintf_rlen(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[1]);
if (metadata_is_valid(ibuf, temp_str, 1, len)) {
line_width = BLF_width(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX);
- BLF_position(fontid, rect->xmax - line_width - (0.2f * U.widget_unit),
- rect->ymax - vertical_offset, 0.0f);
+ BLF_position(fontid, xmax - line_width, ymax - vertical_offset, 0.0f);
BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX);
do_newline = true;
}
if (do_newline)
ofs_y += vertical_offset;
- }
- else if (i == 1) {
+ } /* Strip */
+ else if (i == 1 || i == 2) {
len = BLI_snprintf_rlen(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[i + 1]);
if (metadata_is_valid(ibuf, temp_str, i + 1, len)) {
- BLF_position(fontid, rect->xmin + (0.2f * U.widget_unit),
- rect->ymax - vertical_offset - ofs_y, 0.0f);
+ BLF_position(fontid, xmin, ymax - vertical_offset - ofs_y, 0.0f);
BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX);
ofs_y += vertical_offset;
}
+ } /* Note (wrapped) */
+ else if (i == 3) {
+ len = BLI_snprintf_rlen(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[i + 1]);
+ if (metadata_is_valid(ibuf, temp_str, i + 1, len)) {
+ struct ResultBLF info;
+ BLF_enable(fontid, BLF_WORD_WRAP);
+ BLF_wordwrap(fontid, ibuf->x - (margin * 2));
+ BLF_position(fontid, xmin, ymax - vertical_offset - ofs_y, 0.0f);
+ BLF_draw_ex(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX, &info);
+ BLF_wordwrap(fontid, 0);
+ BLF_disable(fontid, BLF_WORD_WRAP);
+ ofs_y += vertical_offset * info.lines;
+ }
}
else {
len = BLI_snprintf_rlen(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[i + 1]);
if (metadata_is_valid(ibuf, temp_str, i + 1, len)) {
line_width = BLF_width(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX);
- BLF_position(fontid, rect->xmax - line_width - (0.2f * U.widget_unit),
- rect->ymax - vertical_offset - ofs_y, 0.0f);
+ BLF_position(fontid, xmax - line_width, ymax - vertical_offset - ofs_y, 0.0f);
BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX);
ofs_y += vertical_offset;
}
@@ -2192,8 +2209,7 @@ static void metadata_draw_imbuf(ImBuf *ibuf, const rctf *rect, int fontid, const
for (i = 5; i < 10; i++) {
len = BLI_snprintf_rlen(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[i]);
if (metadata_is_valid(ibuf, temp_str, i, len)) {
- BLF_position(fontid, rect->xmin + (0.2f * U.widget_unit) + ofs_x,
- rect->ymin + (0.3f * U.widget_unit), 0.0f);
+ BLF_position(fontid, xmin + ofs_x, ymin, 0.0f);
BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX);
ofs_x += BLF_width(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX) + UI_UNIT_X;
@@ -2204,9 +2220,10 @@ static void metadata_draw_imbuf(ImBuf *ibuf, const rctf *rect, int fontid, const
static float metadata_box_height_get(ImBuf *ibuf, int fontid, const bool is_top)
{
+ const float height = BLF_height_max(fontid);
+ const float margin = (height / 8);
char str[MAX_METADATA_STR] = "";
short i, count = 0;
- const float height = BLF_height_max(fontid) + 0.1f * U.widget_unit;
if (is_top) {
if (metadata_is_valid(ibuf, str, 0, 0) || metadata_is_valid(ibuf, str, 1, 0)) {
@@ -2214,7 +2231,23 @@ static float metadata_box_height_get(ImBuf *ibuf, int fontid, const bool is_top)
}
for (i = 2; i < 5; i++) {
if (metadata_is_valid(ibuf, str, i, 0)) {
- count++;
+ if (i == 4) {
+ struct {
+ struct ResultBLF info;
+ rctf rect;
+ } wrap;
+
+ BLF_enable(fontid, BLF_WORD_WRAP);
+ BLF_wordwrap(fontid, ibuf->x - (margin * 2));
+ BLF_boundbox_ex(fontid, str, sizeof(str), &wrap.rect, &wrap.info);
+ BLF_wordwrap(fontid, 0);
+ BLF_disable(fontid, BLF_WORD_WRAP);
+
+ count += wrap.info.lines;
+ }
+ else {
+ count++;
+ }
}
}
}
@@ -2227,7 +2260,7 @@ static float metadata_box_height_get(ImBuf *ibuf, int fontid, const bool is_top)
}
if (count) {
- return (height * count + (0.1f * U.widget_unit));
+ return (height + margin) * count;
}
return 0;
@@ -2235,7 +2268,7 @@ static float metadata_box_height_get(ImBuf *ibuf, int fontid, const bool is_top)
#undef MAX_METADATA_STR
-void ED_region_image_metadata_draw(int x, int y, ImBuf *ibuf, rctf frame, float zoomx, float zoomy)
+void ED_region_image_metadata_draw(int x, int y, ImBuf *ibuf, const rctf *frame, float zoomx, float zoomy)
{
float box_y;
rctf rect;
@@ -2251,7 +2284,7 @@ void ED_region_image_metadata_draw(int x, int y, ImBuf *ibuf, rctf frame, float
glTranslatef(x, y, 0.0f);
glScalef(zoomx, zoomy, 1.0f);
- BLF_size(blf_mono_font, style->widgetlabel.points * 1.5f, U.dpi);
+ BLF_size(blf_mono_font, style->widgetlabel.points * 1.5f * U.pixelsize, U.dpi);
/* *** upper box*** */
@@ -2262,7 +2295,7 @@ void ED_region_image_metadata_draw(int x, int y, ImBuf *ibuf, rctf frame, float
UI_ThemeColor(TH_METADATA_BG);
/* set up rect */
- BLI_rctf_init(&rect, frame.xmin, frame.xmax, frame.ymax, frame.ymax + box_y);
+ BLI_rctf_init(&rect, frame->xmin, frame->xmax, frame->ymax, frame->ymax + box_y);
/* draw top box */
glRectf(rect.xmin, rect.ymin, rect.xmax, rect.ymax);
@@ -2284,7 +2317,7 @@ void ED_region_image_metadata_draw(int x, int y, ImBuf *ibuf, rctf frame, float
UI_ThemeColor(TH_METADATA_BG);
/* set up box rect */
- BLI_rctf_init(&rect, frame.xmin, frame.xmax, frame.ymin - box_y, frame.ymin);
+ BLI_rctf_init(&rect, frame->xmin, frame->xmax, frame->ymin - box_y, frame->ymin);
/* draw top box */
glRectf(rect.xmin, rect.ymin, rect.xmax, rect.ymax);
@@ -2373,7 +2406,7 @@ void ED_region_draw_backdrop_view3d(const bContext *C, struct Object *camera, co
BKE_scene_update_for_newframe(bmain->eval_ctx, bmain, scene, scene->lay);
ibuf = ED_view3d_draw_offscreen_imbuf_simple(scene, camera, width, height, IB_rect,
OB_SOLID, false, false, false,
- R_ADDSKY, NULL, err_out);
+ R_ADDSKY, 0, NULL, NULL, err_out);
if (ibuf == NULL)
return;
diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c
index f4c4af9d031..f46486601af 100644
--- a/source/blender/editors/screen/screen_edit.c
+++ b/source/blender/editors/screen/screen_edit.c
@@ -42,6 +42,7 @@
#include "BKE_context.h"
#include "BKE_depsgraph.h"
+#include "BKE_image.h"
#include "BKE_global.h"
#include "BKE_library.h"
#include "BKE_main.h"
@@ -1554,8 +1555,8 @@ bool ED_screen_set(bContext *C, bScreen *sc)
}
/* Always do visible update since it's possible new screen will
- * have different layers visible in 3D viewpots. This is possible
- * because of view3d.lock_camera_and_layers option.
+ * have different layers visible in 3D view-ports.
+ * This is possible because of view3d.lock_camera_and_layers option.
*/
DAG_on_visible_update(bmain, false);
}
@@ -1783,6 +1784,8 @@ ScrArea *ED_screen_full_newspace(bContext *C, ScrArea *sa, int type)
*/
void ED_screen_full_prevspace(bContext *C, ScrArea *sa, const bool was_prev_temp)
{
+ BLI_assert(sa->full);
+
if (sa->flag & AREA_FLAG_STACKED_FULLSCREEN) {
/* stacked fullscreen -> only go back to previous screen and don't toggle out of fullscreen */
ED_area_prevspace(C, sa);
@@ -2185,7 +2188,7 @@ bool ED_screen_stereo3d_required(bScreen *screen)
/* images should always show in stereo, even if
* the file doesn't have views enabled */
sima = sa->spacedata.first;
- if (sima->image && (sima->image->flag & IMA_IS_STEREO) &&
+ if (sima->image && BKE_image_is_stereo(sima->image) &&
(sima->iuser.flag & IMA_SHOW_STEREO))
{
return true;
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index 7806c1a0eac..5222bbcc9ba 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -992,6 +992,11 @@ static int area_dupli_invoke(bContext *C, wmOperator *op, const wmEvent *event)
rect.ymax = rect.ymin + BLI_rcti_size_y(&rect) / U.pixelsize;
newwin = WM_window_open(C, &rect);
+ if (newwin == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Failed to open window!");
+ goto finally;
+ }
+
*newwin->stereo3d_format = *win->stereo3d_format;
/* allocs new screen and adds to newly created window, using window size */
@@ -1005,11 +1010,18 @@ static int area_dupli_invoke(bContext *C, wmOperator *op, const wmEvent *event)
/* screen, areas init */
WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
-
+
+
+finally:
if (event->type == EVT_ACTIONZONE_AREA)
actionzone_exit(op);
- return OPERATOR_FINISHED;
+ if (newwin) {
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
static void SCREEN_OT_area_dupli(wmOperatorType *ot)
@@ -2356,7 +2368,7 @@ static void SCREEN_OT_marker_jump(wmOperatorType *ot)
static bool screen_set_is_ok(bScreen *screen, bScreen *screen_prev)
{
return ((screen->winid == 0) &&
- /* in typical useage these should have a nonzero winid
+ /* in typical usage these should have a nonzero winid
* (all temp screens should be used, or closed & freed). */
(screen->temp == false) &&
(screen->state == SCREENNORMAL) &&
@@ -2376,7 +2388,7 @@ static int screen_set_exec(bContext *C, wmOperator *op)
int delta = RNA_int_get(op->ptr, "delta");
/* temp screens are for userpref or render display */
- if (screen->temp || (sa->full && sa->full->temp)) {
+ if (screen->temp || (sa && sa->full && sa->full->temp)) {
return OPERATOR_CANCELLED;
}
@@ -3845,7 +3857,7 @@ static void SCREEN_OT_back_to_previous(struct wmOperatorType *ot)
/* *********** show user pref window ****** */
-static int userpref_show_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
+static int userpref_show_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
wmWindow *win = CTX_wm_window(C);
rcti rect;
@@ -3862,9 +3874,13 @@ static int userpref_show_invoke(bContext *C, wmOperator *UNUSED(op), const wmEve
rect.ymax = rect.ymin + sizey;
/* changes context! */
- WM_window_open_temp(C, &rect, WM_WINDOW_USERPREFS);
-
- return OPERATOR_FINISHED;
+ if (WM_window_open_temp(C, &rect, WM_WINDOW_USERPREFS) != NULL) {
+ return OPERATOR_FINISHED;
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "Failed to open window!");
+ return OPERATOR_CANCELLED;
+ }
}
diff --git a/source/blender/editors/screen/screendump.c b/source/blender/editors/screen/screendump.c
index e23ac1710e3..a701fc9ccb7 100644
--- a/source/blender/editors/screen/screendump.c
+++ b/source/blender/editors/screen/screendump.c
@@ -354,6 +354,10 @@ static void screenshot_startjob(void *sjv, short *stop, short *do_update, float
if (BKE_imtype_is_movie(rd.im_format.imtype)) {
mh = BKE_movie_handle_get(sj->scene->r.im_format.imtype);
+ if (mh == NULL) {
+ printf("Movie format unsupported\n");
+ return;
+ }
sj->movie_ctx = mh->context_create();
sj->movie_handle = mh;
diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c
index e4cad389004..e19756c6a35 100644
--- a/source/blender/editors/sculpt_paint/paint_cursor.c
+++ b/source/blender/editors/sculpt_paint/paint_cursor.c
@@ -644,9 +644,9 @@ static void paint_draw_tex_overlay(UnifiedPaintSettings *ups, Brush *brush,
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
if (primary)
- glTranslatef(brush->stencil_pos[0], brush->stencil_pos[1], 0);
+ glTranslate2fv(brush->stencil_pos);
else
- glTranslatef(brush->mask_stencil_pos[0], brush->mask_stencil_pos[1], 0);
+ glTranslate2fv(brush->mask_stencil_pos);
glRotatef(RAD2DEGF(mtex->rot), 0, 0, 1);
glMatrixMode(GL_TEXTURE);
}
@@ -725,7 +725,7 @@ static void paint_draw_cursor_overlay(UnifiedPaintSettings *ups, Brush *brush,
do_pop = true;
glPushMatrix();
glLoadIdentity();
- glTranslatef(center[0], center[1], 0);
+ glTranslate2fv(center);
glScalef(ups->size_pressure_value, ups->size_pressure_value, 1);
glTranslatef(-center[0], -center[1], 0);
}
@@ -756,7 +756,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 = ELEM(mode, PAINT_TEXTURE_PROJECTIVE, PAINT_TEXTURE_2D, PAINT_VERTEX) ? true : false;
+ bool col = ELEM(mode, ePaintTextureProjective, ePaintTexture2D, ePaintVertex) ? true : false;
OverlayControlFlags flags = BKE_paint_get_overlay_flags();
/* save lots of GL state
* TODO: check on whether all of these are needed? */
@@ -782,7 +782,7 @@ static void paint_draw_alpha_overlay(UnifiedPaintSettings *ups, Brush *brush,
paint_draw_cursor_overlay(ups, brush, vc, x, y, zoom);
}
else {
- if (!(flags & PAINT_OVERLAY_OVERRIDE_PRIMARY) && (mode != PAINT_WEIGHT))
+ if (!(flags & PAINT_OVERLAY_OVERRIDE_PRIMARY) && (mode != ePaintWeight))
paint_draw_tex_overlay(ups, brush, vc, x, y, zoom, false, true);
if (!(flags & PAINT_OVERLAY_OVERRIDE_CURSOR))
paint_draw_cursor_overlay(ups, brush, vc, x, y, zoom);
@@ -958,7 +958,7 @@ static void paint_cursor_on_hit(UnifiedPaintSettings *ups, Brush *brush, ViewCon
static bool ommit_cursor_drawing(Paint *paint, PaintMode mode, Brush *brush)
{
if (paint->flags & PAINT_SHOW_BRUSH) {
- if (ELEM(mode, PAINT_TEXTURE_2D, PAINT_TEXTURE_PROJECTIVE) && brush->imagepaint_tool == PAINT_TOOL_FILL) {
+ if (ELEM(mode, ePaintTexture2D, ePaintTextureProjective) && brush->imagepaint_tool == PAINT_TOOL_FILL) {
return true;
}
return false;
@@ -1014,7 +1014,7 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
/* TODO: as sculpt and other paint modes are unified, this
* special mode of drawing will go away */
- if ((mode == PAINT_SCULPT) && vc.obact->sculpt) {
+ if ((mode == ePaintSculpt) && vc.obact->sculpt) {
float location[3];
int pixel_radius;
bool hit;
@@ -1056,7 +1056,7 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
glColor4f(outline_col[0], outline_col[1], outline_col[2], outline_alpha);
/* draw brush outline */
- glTranslatef(translation[0], translation[1], 0);
+ glTranslate2fv(translation);
/* draw an inner brush */
if (ups->stroke_active && BKE_brush_use_size_pressure(scene, brush)) {
diff --git a/source/blender/editors/sculpt_paint/paint_curve.c b/source/blender/editors/sculpt_paint/paint_curve.c
index ebe5268ec5c..2f27db835f5 100644
--- a/source/blender/editors/sculpt_paint/paint_curve.c
+++ b/source/blender/editors/sculpt_paint/paint_curve.c
@@ -134,12 +134,12 @@ static void paintcurve_undo_begin(bContext *C, wmOperator *op, PaintCurve *pc)
UndoCurve *uc;
switch (mode) {
- case PAINT_TEXTURE_2D:
- case PAINT_TEXTURE_PROJECTIVE:
+ case ePaintTexture2D:
+ case ePaintTextureProjective:
undo_stack_id = UNDO_PAINT_IMAGE;
break;
- case PAINT_SCULPT:
+ case ePaintSculpt:
undo_stack_id = UNDO_PAINT_MESH;
break;
@@ -737,17 +737,17 @@ static int paintcurve_draw_exec(bContext *C, wmOperator *UNUSED(op))
const char *name;
switch (mode) {
- case PAINT_TEXTURE_2D:
- case PAINT_TEXTURE_PROJECTIVE:
+ case ePaintTexture2D:
+ case ePaintTextureProjective:
name = "PAINT_OT_image_paint";
break;
- case PAINT_WEIGHT:
+ case ePaintWeight:
name = "PAINT_OT_weight_paint";
break;
- case PAINT_VERTEX:
+ case ePaintVertex:
name = "PAINT_OT_vertex_paint";
break;
- case PAINT_SCULPT:
+ case ePaintSculpt:
name = "SCULPT_OT_brush_stroke";
break;
default:
@@ -777,7 +777,7 @@ static int paintcurve_cursor_invoke(bContext *C, wmOperator *UNUSED(op), const w
PaintMode mode = BKE_paintmode_get_active_from_context(C);
switch (mode) {
- case PAINT_TEXTURE_2D:
+ case ePaintTexture2D:
{
ARegion *ar = CTX_wm_region(C);
SpaceImage *sima = CTX_wm_space_image(C);
diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c
index 64e0aa822df..f0c9c023876 100644
--- a/source/blender/editors/sculpt_paint/paint_image.c
+++ b/source/blender/editors/sculpt_paint/paint_image.c
@@ -1045,8 +1045,9 @@ static void toggle_paint_cursor(bContext *C, int enable)
* purpose is to make sure the paint cursor is shown if paint
* mode is enabled in the image editor. the paint poll will
* ensure that the cursor is hidden when not in paint mode */
-void ED_space_image_paint_update(wmWindowManager *wm, ToolSettings *settings)
+void ED_space_image_paint_update(wmWindowManager *wm, Scene *scene)
{
+ ToolSettings *settings = scene->toolsettings;
wmWindow *win;
ScrArea *sa;
ImagePaintSettings *imapaint = &settings->imapaint;
@@ -1059,7 +1060,7 @@ void ED_space_image_paint_update(wmWindowManager *wm, ToolSettings *settings)
enabled = true;
if (enabled) {
- BKE_paint_init(&settings->unified_paint_settings, &imapaint->paint, PAINT_CURSOR_TEXTURE_PAINT);
+ BKE_paint_init(scene, ePaintTexture2D, PAINT_CURSOR_TEXTURE_PAINT);
paint_cursor_start_explicit(&imapaint->paint, wm, image_paint_poll);
}
@@ -1212,7 +1213,7 @@ static int sample_color_exec(bContext *C, wmOperator *op)
RNA_int_get_array(op->ptr, "location", location);
use_palette = RNA_boolean_get(op->ptr, "palette");
- paint_sample_color(C, ar, location[0], location[1], mode == PAINT_TEXTURE_PROJECTIVE, use_palette);
+ paint_sample_color(C, ar, location[0], location[1], mode == ePaintTextureProjective, use_palette);
if (show_cursor) {
paint->flags |= PAINT_SHOW_BRUSH;
@@ -1250,7 +1251,7 @@ static int sample_color_invoke(bContext *C, wmOperator *op, const wmEvent *event
RNA_int_set_array(op->ptr, "location", event->mval);
- paint_sample_color(C, ar, event->mval[0], event->mval[1], mode == PAINT_TEXTURE_PROJECTIVE, false);
+ paint_sample_color(C, ar, event->mval[0], event->mval[1], mode == ePaintTextureProjective, false);
WM_cursor_modal_set(win, BC_EYEDROPPER_CURSOR);
WM_event_add_notifier(C, NC_BRUSH | NA_EDITED, brush);
@@ -1289,7 +1290,7 @@ 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], mode == PAINT_TEXTURE_PROJECTIVE, false);
+ paint_sample_color(C, ar, event->mval[0], event->mval[1], mode == ePaintTextureProjective, false);
WM_event_add_notifier(C, NC_BRUSH | NA_EDITED, brush);
break;
}
@@ -1298,7 +1299,7 @@ static int sample_color_modal(bContext *C, wmOperator *op, const wmEvent *event)
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);
+ paint_sample_color(C, ar, event->mval[0], event->mval[1], mode == ePaintTextureProjective, true);
if (!data->sample_palette) {
data->sample_palette = true;
sample_color_update_header(data, C);
@@ -1416,7 +1417,7 @@ static int texture_paint_toggle_exec(bContext *C, wmOperator *op)
ob->mode |= mode_flag;
- BKE_paint_init(&scene->toolsettings->unified_paint_settings, &imapaint->paint, PAINT_CURSOR_TEXTURE_PAINT);
+ BKE_paint_init(scene, ePaintTextureProjective, PAINT_CURSOR_TEXTURE_PAINT);
if (U.glreslimit != 0)
GPU_free_images();
diff --git a/source/blender/editors/sculpt_paint/paint_image_2d.c b/source/blender/editors/sculpt_paint/paint_image_2d.c
index 03a96fb149a..c5a066e9b14 100644
--- a/source/blender/editors/sculpt_paint/paint_image_2d.c
+++ b/source/blender/editors/sculpt_paint/paint_image_2d.c
@@ -1601,6 +1601,7 @@ void paint_2d_gradient_fill(
break;
}
case BRUSH_GRADIENT_RADIAL:
+ default:
{
f = len_v2(p) / line_len;
break;
@@ -1629,6 +1630,7 @@ void paint_2d_gradient_fill(
break;
}
case BRUSH_GRADIENT_RADIAL:
+ default:
{
f = len_v2(p) / line_len;
break;
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c
index 2b0aba9e3fb..565f8a51610 100644
--- a/source/blender/editors/sculpt_paint/paint_image_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_image_proj.c
@@ -298,6 +298,7 @@ typedef struct ProjPaintState {
float cloneOffset[2];
float projectMat[4][4]; /* Projection matrix, use for getting screen coords */
+ float projectMatInv[4][4]; /* inverse of projectMat */
float viewDir[3]; /* View vector, use for do_backfacecull and for ray casting with an ortho viewport */
float viewPos[3]; /* View location in object relative 3D space, so can compare to verts */
float clipsta, clipend;
@@ -1247,6 +1248,55 @@ static void screen_px_from_persp(
}
+/**
+ * Set a direction vector based on a screen location.
+ * (use for perspective view, else we can simply use `ps->viewDir`)
+ *
+ * Similar functionality to #ED_view3d_win_to_vector
+ *
+ * \param r_dir: Resulting direction (length is undefined).
+ */
+static void screen_px_to_vector_persp(
+ int winx, int winy, const float projmat_inv[4][4], const float view_pos[3],
+ const float co_px[2],
+ float r_dir[3])
+{
+ r_dir[0] = 2.0f * (co_px[0] / winx) - 1.0f;
+ r_dir[1] = 2.0f * (co_px[1] / winy) - 1.0f;
+ r_dir[2] = -0.5f;
+ mul_project_m4_v3((float(*)[4])projmat_inv, r_dir);
+ sub_v3_v3(r_dir, view_pos);
+}
+
+/**
+ * Special function to return the factor to a point along a line in pixel space.
+ *
+ * This is needed since we can't use #line_point_factor_v2 for perspective screen-space coords.
+ *
+ * \param p: 2D screen-space location.
+ * \param v1, v2: 3D object-space locations.
+ */
+static float screen_px_line_point_factor_v2_persp(
+ const ProjPaintState *ps,
+ const float p[2],
+ const float v1[3], const float v2[3])
+{
+ const float zero[3] = {0};
+ float v1_proj[3], v2_proj[3];
+ float dir[3];
+
+ screen_px_to_vector_persp(ps->winx, ps->winy, ps->projectMatInv, ps->viewPos, p, dir);
+
+ sub_v3_v3v3(v1_proj, v1, ps->viewPos);
+ sub_v3_v3v3(v2_proj, v2, ps->viewPos);
+
+ project_plane_v3_v3v3(v1_proj, v1_proj, dir);
+ project_plane_v3_v3v3(v2_proj, v2_proj, dir);
+
+ return line_point_factor_v2(zero, v1_proj, v2_proj);
+}
+
+
static void project_face_pixel(
const float *lt_tri_uv[3], ImBuf *ibuf_other, const float w[3],
unsigned char rgba_ub[4], float rgba_f[4])
@@ -2680,8 +2730,15 @@ static void project_paint_face_init(
line_clip_rect2f(clip_rect, bucket_bounds, vCoSS[fidx1], vCoSS[fidx2], bucket_clip_edges[0], bucket_clip_edges[1]))
{
if (len_squared_v2v2(vCoSS[fidx1], vCoSS[fidx2]) > FLT_EPSILON) { /* avoid div by zero */
- fac1 = line_point_factor_v2(bucket_clip_edges[0], vCoSS[fidx1], vCoSS[fidx2]);
- fac2 = line_point_factor_v2(bucket_clip_edges[1], vCoSS[fidx1], vCoSS[fidx2]);
+
+ if (is_ortho) {
+ fac1 = line_point_factor_v2(bucket_clip_edges[0], vCoSS[fidx1], vCoSS[fidx2]);
+ fac2 = line_point_factor_v2(bucket_clip_edges[1], vCoSS[fidx1], vCoSS[fidx2]);
+ }
+ else {
+ fac1 = screen_px_line_point_factor_v2_persp(ps, bucket_clip_edges[0], vCo[fidx1], vCo[fidx2]);
+ fac2 = screen_px_line_point_factor_v2_persp(ps, bucket_clip_edges[1], vCo[fidx1], vCo[fidx2]);
+ }
interp_v2_v2v2(seam_subsection[0], lt_uv_pxoffset[fidx1], lt_uv_pxoffset[fidx2], fac1);
interp_v2_v2v2(seam_subsection[1], lt_uv_pxoffset[fidx1], lt_uv_pxoffset[fidx2], fac2);
@@ -2695,7 +2752,7 @@ static void project_paint_face_init(
interp_v3_v3v3(edge_verts_inset_clip[1], insetCos[fidx1], insetCos[fidx2], fac2);
- if (pixel_bounds_uv(seam_subsection, &bounds_px, ibuf->x, ibuf->y)) {
+ if (pixel_bounds_uv((const float (*)[2])seam_subsection, &bounds_px, ibuf->x, ibuf->y)) {
/* bounds between the seam rect and the uvspace bucket pixels */
has_isect = 0;
@@ -3104,6 +3161,7 @@ static void proj_paint_state_viewport_init(
mul_m4_m4m4(ps->projectMat, winmat, vmat);
}
+ invert_m4_m4(ps->projectMatInv, ps->projectMat);
/* viewDir - object relative */
copy_m3_m4(mat, viewinv);
@@ -3559,34 +3617,6 @@ static bool project_paint_winclip(
}
#endif //PROJ_DEBUG_WINCLIP
-/* Return true if face should be culled, false otherwise */
-static bool project_paint_backface_cull(
- const ProjPaintState *ps, const MLoopTri *lt,
- const ProjPaintFaceCoSS *coSS)
-{
- if (ps->do_backfacecull) {
- if (ps->do_mask_normal) {
- const int lt_vtri[3] = { PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt) };
- /* Since we are interpolating the normals of faces, we want to make
- * sure all the verts are pointing away from the view,
- * not just the face */
- if ((ps->vertFlags[lt_vtri[0]] & PROJ_VERT_CULL) &&
- (ps->vertFlags[lt_vtri[1]] & PROJ_VERT_CULL) &&
- (ps->vertFlags[lt_vtri[2]] & PROJ_VERT_CULL))
- {
- return true;
- }
- }
- else {
- if ((line_point_side_v2(coSS->v1, coSS->v2, coSS->v3) < 0.0f) != ps->is_flip_object) {
- return true;
- }
-
- }
- }
-
- return false;
-}
static void project_paint_build_proj_ima(
ProjPaintState *ps, MemArena *arena,
@@ -3631,6 +3661,7 @@ static void project_paint_prepare_all_faces(
TexPaintSlot *slot = NULL;
const MLoopTri *lt;
int image_index = -1, tri_index;
+ int prev_poly = -1;
for (tri_index = 0, lt = ps->dm_mlooptri; tri_index < ps->dm_totlooptri; tri_index++, lt++) {
bool is_face_sel;
@@ -3691,8 +3722,37 @@ static void project_paint_prepare_all_faces(
#endif //PROJ_DEBUG_WINCLIP
- if (project_paint_backface_cull(ps, lt, &coSS)) {
- continue;
+ /* backface culls individual triangles but mask normal will use polygon */
+ if (ps->do_backfacecull) {
+ if (ps->do_mask_normal) {
+ if (prev_poly != lt->poly) {
+ int iloop;
+ bool culled = true;
+ const MPoly *poly = ps->dm_mpoly + lt->poly;
+ int poly_loops = poly->totloop;
+ prev_poly = lt->poly;
+ for (iloop = 0; iloop < poly_loops; iloop++) {
+ if (!(ps->vertFlags[ps->dm_mloop[poly->loopstart + iloop].v] & PROJ_VERT_CULL)) {
+ culled = false;
+ break;
+ }
+ }
+
+ if (culled) {
+ /* poly loops - 2 is number of triangles for poly,
+ * but counter gets incremented when continuing, so decrease by 3 */
+ int poly_tri = poly_loops - 3;
+ tri_index += poly_tri;
+ lt += poly_tri;
+ continue;
+ }
+ }
+ }
+ else {
+ if ((line_point_side_v2(coSS.v1, coSS.v2, coSS.v3) < 0.0f) != ps->is_flip_object) {
+ continue;
+ }
+ }
}
}
@@ -4264,7 +4324,7 @@ static void do_projectpaint_soften(ProjPaintState *ps, ProjPixel *projPixel, flo
}
else {
premul_float_to_straight_uchar(rgba_ub, rgba);
- blend_color_interpolate_byte(rgba_ub, rgba_ub, projPixel->pixel.ch_pt, mask);
+ blend_color_interpolate_byte(rgba_ub, projPixel->pixel.ch_pt, rgba_ub, mask);
}
BLI_linklist_prepend_arena(softenPixels, (void *)projPixel, softenArena);
}
@@ -4472,6 +4532,7 @@ static void *do_projectpaint_thread(void *ph_v)
break;
}
case BRUSH_GRADIENT_RADIAL:
+ default:
{
f = len_v2(p) / line_len;
break;
@@ -5338,7 +5399,10 @@ static int texture_paint_image_from_view_exec(bContext *C, wmOperator *op)
if (w > maxsize) w = maxsize;
if (h > maxsize) h = maxsize;
- ibuf = ED_view3d_draw_offscreen_imbuf(scene, CTX_wm_view3d(C), CTX_wm_region(C), w, h, IB_rect, false, R_ALPHAPREMUL, NULL, err_out);
+ ibuf = ED_view3d_draw_offscreen_imbuf(
+ scene, CTX_wm_view3d(C), CTX_wm_region(C),
+ w, h, IB_rect, false, R_ALPHAPREMUL, 0, NULL,
+ NULL, err_out);
if (!ibuf) {
/* Mostly happens when OpenGL offscreen buffer was failed to create, */
/* but could be other reasons. Should be handled in the future. nazgul */
@@ -5352,7 +5416,7 @@ static int texture_paint_image_from_view_exec(bContext *C, wmOperator *op)
IMB_freeImBuf(ibuf);
if (image) {
- /* now for the trickyness. store the view projection here!
+ /* now for the trickiness. store the view projection here!
* re-projection will reuse this */
View3D *v3d = CTX_wm_view3d(C);
RegionView3D *rv3d = CTX_wm_region_view3d(C);
diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c
index eebd49895ef..05eda4da63b 100644
--- a/source/blender/editors/sculpt_paint/paint_ops.c
+++ b/source/blender/editors/sculpt_paint/paint_ops.c
@@ -66,11 +66,12 @@ static int brush_add_exec(bContext *C, wmOperator *UNUSED(op))
Paint *paint = BKE_paint_get_active_from_context(C);
Brush *br = BKE_paint_brush(paint);
Main *bmain = CTX_data_main(C);
+ PaintMode mode = BKE_paintmode_get_active_from_context(C);
if (br)
br = BKE_brush_copy(br);
else
- br = BKE_brush_add(bmain, "Brush");
+ br = BKE_brush_add(bmain, "Brush", BKE_paint_object_mode_from_paint_mode(mode));
BKE_paint_brush_set(paint, br);
@@ -201,11 +202,11 @@ static int palette_color_add_exec(bContext *C, wmOperator *UNUSED(op))
color = BKE_palette_color_add(palette);
palette->active_color = BLI_listbase_count(&palette->colors) - 1;
- if (ELEM(mode, PAINT_TEXTURE_PROJECTIVE, PAINT_TEXTURE_2D, PAINT_VERTEX)) {
+ if (ELEM(mode, ePaintTextureProjective, ePaintTexture2D, ePaintVertex)) {
copy_v3_v3(color->rgb, BKE_brush_color_get(scene, brush));
color->value = 0.0;
}
- else if (mode == PAINT_WEIGHT) {
+ else if (mode == ePaintWeight) {
zero_v3(color->rgb);
color->value = brush->weight;
}
@@ -431,9 +432,8 @@ static int brush_generic_tool_set(Main *bmain, Paint *paint, const int tool,
brush = brush_tool_cycle(bmain, brush_orig, tool, tool_offset, ob_mode);
if (!brush && brush_tool(brush_orig, tool_offset) != tool && create_missing) {
- brush = BKE_brush_add(bmain, tool_name);
+ brush = BKE_brush_add(bmain, tool_name, ob_mode);
brush_tool_set(brush, tool_offset, tool);
- brush->ob_mode = ob_mode;
brush->toggle_brush = brush_orig;
}
diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c
index a6d80953178..b1ddf1172c8 100644
--- a/source/blender/editors/sculpt_paint/paint_stroke.c
+++ b/source/blender/editors/sculpt_paint/paint_stroke.c
@@ -194,7 +194,7 @@ static void paint_draw_line_cursor(bContext *C, int x, int y, void *customdata)
static bool paint_tool_require_location(Brush *brush, PaintMode mode)
{
switch (mode) {
- case PAINT_SCULPT:
+ case ePaintSculpt:
if (ELEM(brush->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_ROTATE,
SCULPT_TOOL_SNAKE_HOOK, SCULPT_TOOL_THUMB))
{
@@ -224,6 +224,7 @@ static bool paint_brush_update(bContext *C,
bool location_sampled = false;
bool location_success = false;
bool do_random = false;
+ bool do_random_mask = 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.
@@ -271,9 +272,11 @@ static bool paint_brush_update(bContext *C,
}
if (paint_supports_dynamic_tex_coords(brush, mode)) {
- if (((brush->mtex.brush_map_mode == MTEX_MAP_MODE_VIEW) ||
- (brush->mtex.brush_map_mode == MTEX_MAP_MODE_AREA) ||
- (brush->mtex.brush_map_mode == MTEX_MAP_MODE_RANDOM)))
+
+ if (ELEM(brush->mtex.brush_map_mode,
+ MTEX_MAP_MODE_VIEW,
+ MTEX_MAP_MODE_AREA,
+ MTEX_MAP_MODE_RANDOM))
{
do_random = true;
}
@@ -286,6 +289,15 @@ static bool paint_brush_update(bContext *C,
/* take care of mask texture, if any */
if (brush->mask_mtex.tex) {
+
+ if (ELEM(brush->mask_mtex.brush_map_mode,
+ MTEX_MAP_MODE_VIEW,
+ MTEX_MAP_MODE_AREA,
+ MTEX_MAP_MODE_RANDOM))
+ {
+ do_random_mask = true;
+ }
+
if (brush->mask_mtex.brush_map_mode == MTEX_MAP_MODE_RANDOM)
BKE_brush_randomize_texture_coords(ups, true);
else {
@@ -358,7 +370,9 @@ static bool paint_brush_update(bContext *C,
ups->brush_rotation += -brush->mtex.random_angle / 2.0f +
brush->mtex.random_angle * BLI_frand();
}
+ }
+ if (do_random_mask) {
if (brush->mask_mtex.brush_angle_mode & MTEX_ANGLE_RANDOM) {
ups->brush_rotation_sec += -brush->mask_mtex.random_angle / 2.0f +
brush->mask_mtex.random_angle * BLI_frand();
@@ -389,7 +403,7 @@ static bool paint_stroke_use_jitter(PaintMode mode, Brush *brush, bool invert)
/* jitter-ed brush gives weird and unpredictable result for this
* kinds of stroke, so manually disable jitter usage (sergey) */
use_jitter &= (brush->flag & (BRUSH_DRAG_DOT | BRUSH_ANCHORED)) == 0;
- use_jitter &= (!ELEM(mode, PAINT_TEXTURE_2D, PAINT_TEXTURE_PROJECTIVE) ||
+ use_jitter &= (!ELEM(mode, ePaintTexture2D, ePaintTextureProjective) ||
!(invert && brush->imagepaint_tool == PAINT_TOOL_CLONE));
@@ -760,13 +774,13 @@ bool paint_supports_dynamic_size(Brush *br, PaintMode mode)
return false;
switch (mode) {
- case PAINT_SCULPT:
+ case ePaintSculpt:
if (sculpt_is_grab_tool(br))
return false;
break;
- case PAINT_TEXTURE_2D: /* fall through */
- case PAINT_TEXTURE_PROJECTIVE:
+ case ePaintTexture2D: /* fall through */
+ case ePaintTextureProjective:
if ((br->imagepaint_tool == PAINT_TOOL_FILL) &&
(br->flag & BRUSH_USE_GRADIENT))
{
@@ -789,7 +803,7 @@ bool paint_supports_smooth_stroke(Brush *br, PaintMode mode)
}
switch (mode) {
- case PAINT_SCULPT:
+ case ePaintSculpt:
if (sculpt_is_grab_tool(br))
return false;
break;
@@ -802,7 +816,7 @@ bool paint_supports_smooth_stroke(Brush *br, PaintMode mode)
bool paint_supports_texture(PaintMode mode)
{
/* omit: PAINT_WEIGHT, PAINT_SCULPT_UV, PAINT_INVALID */
- return ELEM(mode, PAINT_SCULPT, PAINT_VERTEX, PAINT_TEXTURE_PROJECTIVE, PAINT_TEXTURE_2D);
+ return ELEM(mode, ePaintSculpt, ePaintVertex, ePaintTextureProjective, ePaintTexture2D);
}
/* return true if the brush size can change during paint (normally used for pressure) */
@@ -812,7 +826,7 @@ bool paint_supports_dynamic_tex_coords(Brush *br, PaintMode mode)
return false;
switch (mode) {
- case PAINT_SCULPT:
+ case ePaintSculpt:
if (sculpt_is_grab_tool(br))
return false;
break;
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index 23f388d2a58..8daad9deea9 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -1956,7 +1956,7 @@ static int wpaint_mode_toggle_exec(bContext *C, wmOperator *op)
paint_cursor_start(C, weight_paint_poll);
- BKE_paint_init(&scene->toolsettings->unified_paint_settings, &wp->paint, PAINT_CURSOR_WEIGHT_PAINT);
+ BKE_paint_init(scene, ePaintWeight, PAINT_CURSOR_WEIGHT_PAINT);
/* weight paint specific */
ED_mesh_mirror_spatial_table(ob, NULL, NULL, 's');
@@ -2564,7 +2564,7 @@ static int vpaint_mode_toggle_exec(bContext *C, wmOperator *op)
paint_cursor_start(C, vertex_paint_poll);
- BKE_paint_init(&scene->toolsettings->unified_paint_settings, &vp->paint, PAINT_CURSOR_VERTEX_PAINT);
+ BKE_paint_init(scene, ePaintVertex, PAINT_CURSOR_VERTEX_PAINT);
}
/* update modifier stack for mapping requirements */
@@ -2675,7 +2675,7 @@ static bool vpaint_stroke_test_start(bContext *C, struct wmOperator *op, const f
brush->mtex.tex;
/* are we painting onto a modified mesh?,
- * if not we can skip face map trickyness */
+ * if not we can skip face map trickiness */
if (vertex_paint_use_fast_update_check(ob)) {
vpd->use_fast_update = true;
/* printf("Fast update!\n");*/
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 3800271e0cb..07511e1924e 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -4062,7 +4062,7 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob,
* brush coord/pressure/etc.
* It's more an events design issue, which doesn't split coordinate/pressure/angle
* changing events. We should avoid this after events system re-design */
- if (paint_supports_dynamic_size(brush, PAINT_SCULPT) || cache->first_time) {
+ if (paint_supports_dynamic_size(brush, ePaintSculpt) || cache->first_time) {
cache->pressure = RNA_float_get(ptr, "pressure");
}
@@ -4079,7 +4079,7 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob,
}
}
- if (BKE_brush_use_size_pressure(scene, brush) && paint_supports_dynamic_size(brush, PAINT_SCULPT)) {
+ if (BKE_brush_use_size_pressure(scene, brush) && paint_supports_dynamic_size(brush, ePaintSculpt)) {
cache->radius = cache->initial_radius * cache->pressure;
}
else {
@@ -4217,7 +4217,10 @@ static float sculpt_raycast_init(ViewContext *vc, const float mouse[2], float ra
sub_v3_v3v3(ray_normal, ray_end, ray_start);
dist = normalize_v3(ray_normal);
- if (!rv3d->is_persp) {
+ if ((rv3d->is_persp == false) &&
+ /* if the ray is clipped, don't adjust its start/end */
+ ((rv3d->rflag & RV3D_CLIPPING) == 0))
+ {
BKE_pbvh_raycast_project_ray_root(ob->sculpt->pbvh, original, ray_start, ray_end, ray_normal);
/* recalculate the normal */
@@ -5141,7 +5144,7 @@ static int sculpt_mode_toggle_exec(bContext *C, wmOperator *op)
"Object has negative scale, sculpting may be unpredictable");
}
- BKE_paint_init(&ts->unified_paint_settings, &ts->sculpt->paint, PAINT_CURSOR_SCULPT);
+ BKE_paint_init(scene, ePaintSculpt, PAINT_CURSOR_SCULPT);
paint_cursor_start(C, sculpt_poll_view3d);
}
diff --git a/source/blender/editors/sculpt_paint/sculpt_uv.c b/source/blender/editors/sculpt_paint/sculpt_uv.c
index e01d8a6bd17..405ac3f6808 100644
--- a/source/blender/editors/sculpt_paint/sculpt_uv.c
+++ b/source/blender/editors/sculpt_paint/sculpt_uv.c
@@ -224,8 +224,9 @@ static void brush_drawcursor_uvsculpt(bContext *C, int x, int y, void *UNUSED(cu
}
-void ED_space_image_uv_sculpt_update(wmWindowManager *wm, ToolSettings *settings)
+void ED_space_image_uv_sculpt_update(wmWindowManager *wm, Scene *scene)
{
+ ToolSettings *settings = scene->toolsettings;
if (settings->use_uv_sculpt) {
if (!settings->uvsculpt) {
settings->uvsculpt = MEM_callocN(sizeof(*settings->uvsculpt), "UV Smooth paint");
@@ -236,7 +237,7 @@ void ED_space_image_uv_sculpt_update(wmWindowManager *wm, ToolSettings *settings
settings->uvsculpt->paint.flags |= PAINT_SHOW_BRUSH;
}
- BKE_paint_init(&settings->unified_paint_settings, &settings->uvsculpt->paint, PAINT_CURSOR_SCULPT);
+ BKE_paint_init(scene, ePaintSculptUV, PAINT_CURSOR_SCULPT);
settings->uvsculpt->paint.paint_cursor = WM_paint_cursor_activate(wm, uv_sculpt_brush_poll,
brush_drawcursor_uvsculpt, NULL);
diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c
index b2e046ee24b..e351fb57d9a 100644
--- a/source/blender/editors/space_action/action_edit.c
+++ b/source/blender/editors/space_action/action_edit.c
@@ -223,7 +223,7 @@ static bool get_keyframe_extents(bAnimContext *ac, float *min, float *max, const
float tmin, tmax;
/* get range and apply necessary scaling before processing */
- if (calc_fcurve_range(fcu, &tmin, &tmax, onlySel, true)) {
+ if (calc_fcurve_range(fcu, &tmin, &tmax, onlySel, false)) {
if (adt) {
tmin = BKE_nla_tweakedit_remap(adt, tmin, NLATIME_CONVERT_MAP);
@@ -237,7 +237,7 @@ static bool get_keyframe_extents(bAnimContext *ac, float *min, float *max, const
}
}
}
-
+
/* free memory */
ANIM_animdata_freelist(&anim_data);
}
@@ -275,8 +275,12 @@ static int actkeys_previewrange_exec(bContext *C, wmOperator *UNUSED(op))
/* set the range directly */
get_keyframe_extents(&ac, &min, &max, false);
scene->r.flag |= SCER_PRV_RANGE;
- scene->r.psfra = iroundf(min);
- scene->r.pefra = iroundf(max);
+ scene->r.psfra = floorf(min);
+ scene->r.pefra = ceilf(max);
+
+ if (scene->r.psfra == scene->r.pefra) {
+ scene->r.pefra = scene->r.psfra + 1;
+ }
/* set notifier that things have changed */
// XXX err... there's nothing for frame ranges yet, but this should do fine too
diff --git a/source/blender/editors/space_buttons/buttons_texture.c b/source/blender/editors/space_buttons/buttons_texture.c
index b56ff850c35..6bdcee8aaef 100644
--- a/source/blender/editors/space_buttons/buttons_texture.c
+++ b/source/blender/editors/space_buttons/buttons_texture.c
@@ -539,6 +539,9 @@ static void template_texture_select(bContext *C, void *user_p, void *UNUSED(arg)
if (user->ptr.data == part->mtex[a])
part->texact = a;
}
+
+ if (sbuts && tex)
+ sbuts->preview = 1;
}
ct->user = user;
diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c
index 74a9eb480b7..40505d28d39 100644
--- a/source/blender/editors/space_clip/clip_draw.c
+++ b/source/blender/editors/space_clip/clip_draw.c
@@ -286,7 +286,6 @@ static void draw_movieclip_buffer(const bContext *C, SpaceClip *sc, ARegion *ar,
MovieClip *clip = ED_space_clip_get_clip(sc);
int filter = GL_LINEAR;
int x, y;
- rctf frame;
/* find window pixel coordinates of origin */
UI_view2d_view_to_region(&ar->v2d, 0.0f, 0.0f, &x, &y);
@@ -314,10 +313,12 @@ static void draw_movieclip_buffer(const bContext *C, SpaceClip *sc, ARegion *ar,
/* reset zoom */
glPixelZoom(1.0f, 1.0f);
- BLI_rctf_init(&frame, 0.0f, ibuf->x, 0.0f, ibuf->y);
- if (sc->flag & SC_SHOW_METADATA)
- ED_region_image_metadata_draw(x, y, ibuf, frame, zoomx * width / ibuf->x, zoomy * height / ibuf->y);
+ if (sc->flag & SC_SHOW_METADATA) {
+ rctf frame;
+ BLI_rctf_init(&frame, 0.0f, ibuf->x, 0.0f, ibuf->y);
+ ED_region_image_metadata_draw(x, y, ibuf, &frame, zoomx * width / ibuf->x, zoomy * height / ibuf->y);
+ }
if (ibuf->planes == 32)
glDisable(GL_BLEND);
@@ -521,7 +522,7 @@ static void draw_marker_outline(SpaceClip *sc, MovieTrackingTrack *track, MovieT
/* pattern and search outline */
glPushMatrix();
- glTranslatef(marker_pos[0], marker_pos[1], 0);
+ glTranslate2fv(marker_pos);
if (!tiny)
glLineWidth(3.0f);
@@ -653,7 +654,7 @@ static void draw_marker_areas(SpaceClip *sc, MovieTrackingTrack *track, MovieTra
/* pattern */
glPushMatrix();
- glTranslatef(marker_pos[0], marker_pos[1], 0);
+ glTranslate2fv(marker_pos);
if (tiny) {
glLineStipple(3, 0xaaaa);
@@ -806,7 +807,7 @@ static void draw_marker_slide_zones(SpaceClip *sc, MovieTrackingTrack *track, Mo
}
glPushMatrix();
- glTranslatef(marker_pos[0], marker_pos[1], 0);
+ glTranslate2fv(marker_pos);
dx = 6.0f / width / sc->zoom;
dy = 6.0f / height / sc->zoom;
@@ -1260,7 +1261,7 @@ static void draw_tracking_tracks(SpaceClip *sc, Scene *scene, ARegion *ar, Movie
/* ** find window pixel coordinates of origin ** */
/* UI_view2d_view_to_region_no_clip return integer values, this could
- * lead to 1px flickering when view is locked to selection during playbeck.
+ * lead to 1px flickering when view is locked to selection during playback.
* to avoid this flickering, calculate base point in the same way as it happens
* in UI_view2d_view_to_region_no_clip, but do it in floats here */
@@ -1787,7 +1788,7 @@ void clip_draw_grease_pencil(bContext *C, int onlyv2d)
int framenr = ED_space_clip_get_clip_frame_number(sc);
MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
- glTranslatef(marker->pos[0], marker->pos[1], 0.0f);
+ glTranslate2fv(marker->pos);
}
}
diff --git a/source/blender/editors/space_clip/clip_ops.c b/source/blender/editors/space_clip/clip_ops.c
index 55805e0b907..af3d460fe0f 100644
--- a/source/blender/editors/space_clip/clip_ops.c
+++ b/source/blender/editors/space_clip/clip_ops.c
@@ -213,7 +213,7 @@ static int open_exec(bContext *C, wmOperator *op)
errno = 0;
- clip = BKE_movieclip_file_add(bmain, str);
+ clip = BKE_movieclip_file_add_exists(bmain, str);
if (!clip) {
if (op->customdata)
diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c
index dac9124a4cb..2d9ecbdf415 100644
--- a/source/blender/editors/space_file/file_draw.c
+++ b/source/blender/editors/space_file/file_draw.c
@@ -232,9 +232,17 @@ void file_draw_buttons(const bContext *C, ARegion *ar)
/* Execute / cancel buttons. */
if (loadbutton) {
const struct FileDirEntry *file = sfile->files ? filelist_file(sfile->files, params->active_file) : NULL;
- const char *str_exec = (file && (file->typeflag & FILE_TYPE_FOLDER)) ?
- /* params->title is already translated! */
- IFACE_("Open Directory") : params->title;
+ char const *str_exec;
+
+ if (file && FILENAME_IS_PARENT(file->relpath)) {
+ str_exec = IFACE_("Parent Directory");
+ }
+ else if (file && file->typeflag & FILE_TYPE_DIR) {
+ str_exec = IFACE_("Open Directory");
+ }
+ else {
+ str_exec = params->title; /* params->title is already translated! */
+ }
uiDefButO(block, UI_BTYPE_BUT, "FILE_OT_execute", WM_OP_EXEC_REGION_WIN, str_exec,
max_x - loadbutton, line1_y, loadbutton, btn_h, "");
diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c
index 7f5e6b93cfb..36572d6469d 100644
--- a/source/blender/editors/space_file/file_ops.c
+++ b/source/blender/editors/space_file/file_ops.c
@@ -237,6 +237,49 @@ static bool file_is_any_selected(struct FileList *files)
return false;
}
+/**
+ * If \a file is outside viewbounds, this adjusts view to make sure it's inside
+ */
+static void file_ensure_inside_viewbounds(ARegion *ar, SpaceFile *sfile, const int file)
+{
+ FileLayout *layout = ED_fileselect_get_layout(sfile, ar);
+ rctf *cur = &ar->v2d.cur;
+ rcti rect;
+ bool changed = true;
+
+ file_tile_boundbox(ar, layout, file, &rect);
+
+ /* down - also use if tile is higher than viewbounds so view is aligned to file name */
+ if (cur->ymin > rect.ymin || layout->tile_h > ar->winy) {
+ cur->ymin = rect.ymin - (2 * layout->tile_border_y);
+ cur->ymax = cur->ymin + ar->winy;
+ }
+ /* up */
+ else if (cur->ymax < rect.ymax) {
+ cur->ymax = rect.ymax + layout->tile_border_y;
+ cur->ymin = cur->ymax - ar->winy;
+ }
+ /* left - also use if tile is wider than viewbounds so view is aligned to file name */
+ else if (cur->xmin > rect.xmin || layout->tile_w > ar->winx) {
+ cur->xmin = rect.xmin - layout->tile_border_x;
+ cur->xmax = cur->xmin + ar->winx;
+ }
+ /* right */
+ else if (cur->xmax < rect.xmax) {
+ cur->xmax = rect.xmax + (2 * layout->tile_border_x);
+ cur->xmin = cur->xmax - ar->winx;
+ }
+ else {
+ BLI_assert(cur->xmin <= rect.xmin && cur->xmax >= rect.xmax &&
+ cur->ymin <= rect.ymin && cur->ymax >= rect.ymax);
+ changed = false;
+ }
+
+ if (changed) {
+ UI_view2d_curRect_validate(&ar->v2d);
+ }
+}
+
static FileSelect file_select(bContext *C, const rcti *rect, FileSelType select, bool fill, bool do_diropen)
{
@@ -262,6 +305,20 @@ static FileSelect file_select(bContext *C, const rcti *rect, FileSelType select,
if (select != FILE_SEL_ADD && !file_is_any_selected(sfile->files)) {
sfile->params->active_file = -1;
}
+ else {
+ ARegion *ar = CTX_wm_region(C);
+ const FileLayout *layout = ED_fileselect_get_layout(sfile, ar);
+
+ /* Adjust view to display selection. Doing iterations for first and last
+ * selected item makes view showing as much of the selection possible.
+ * Not really useful if tiles are (almost) bigger than viewbounds though. */
+ if (((layout->flag & FILE_LAYOUT_HOR) && ar->winx > (1.2f * layout->tile_w)) ||
+ ((layout->flag & FILE_LAYOUT_VER) && ar->winy > (2.0f * layout->tile_h)))
+ {
+ file_ensure_inside_viewbounds(ar, sfile, sel.last);
+ file_ensure_inside_viewbounds(ar, sfile, sel.first);
+ }
+ }
/* update operator for name change event */
file_draw_check(C);
@@ -276,6 +333,9 @@ static int file_border_select_find_last_selected(
FileLayout *layout = ED_fileselect_get_layout(sfile, ar);
rcti bounds_first, bounds_last;
int dist_first, dist_last;
+ float mouseco_view[2];
+
+ UI_view2d_region_to_view(&ar->v2d, UNPACK2(mouse_xy), &mouseco_view[0], &mouseco_view[1]);
file_tile_boundbox(ar, layout, sel->first, &bounds_first);
file_tile_boundbox(ar, layout, sel->last, &bounds_last);
@@ -285,18 +345,18 @@ static int file_border_select_find_last_selected(
(layout->flag & FILE_LAYOUT_VER && bounds_first.ymin != bounds_last.ymin))
{
/* use vertical distance */
- const int my_loc = mouse_xy[1] - ar->winrct.ymin;
+ const int my_loc = (int)mouseco_view[1];
dist_first = BLI_rcti_length_y(&bounds_first, my_loc);
dist_last = BLI_rcti_length_y(&bounds_last, my_loc);
}
else {
/* use horizontal distance */
- const int mx_loc = mouse_xy[0] - ar->winrct.xmin;
+ const int mx_loc = (int)mouseco_view[0];
dist_first = BLI_rcti_length_x(&bounds_first, mx_loc);
dist_last = BLI_rcti_length_x(&bounds_last, mx_loc);
}
- return dist_first < dist_last ? sel->first : sel->last;
+ return (dist_first < dist_last) ? sel->first : sel->last;
}
static int file_border_select_modal(bContext *C, wmOperator *op, const wmEvent *event)
@@ -339,7 +399,7 @@ static int file_border_select_modal(bContext *C, wmOperator *op, const wmEvent *
}
}
params->sel_first = sel.first; params->sel_last = sel.last;
- params->active_file = file_border_select_find_last_selected(sfile, ar, &sel, &event->x);
+ params->active_file = file_border_select_find_last_selected(sfile, ar, &sel, event->mval);
}
else {
params->highlight_file = -1;
@@ -571,6 +631,9 @@ static bool file_walk_select_selection_set(
BLI_assert(IN_RANGE(active, -1, numfiles));
fileselect_file_set(sfile, params->active_file);
+ /* ensure newly selected file is inside viewbounds */
+ file_ensure_inside_viewbounds(CTX_wm_region(C), sfile, params->active_file);
+
/* selection changed */
return true;
}
@@ -1831,12 +1894,13 @@ void file_filename_enter_handle(bContext *C, void *UNUSED(arg_unused), void *arg
matched_file[0] = '\0';
filepath[0] = '\0';
- BLI_filename_make_safe(sfile->params->file);
-
file_expand_directory(C);
matches = file_select_match(sfile, sfile->params->file, matched_file);
+ /* *After* file_select_match! */
+ BLI_filename_make_safe(sfile->params->file);
+
if (matches) {
/* int i, numfiles = filelist_numfiles(sfile->files); */ /* XXX UNUSED */
sfile->params->file[0] = '\0';
@@ -1969,6 +2033,37 @@ void FILE_OT_bookmark_toggle(struct wmOperatorType *ot)
}
+/**
+ * Looks for a string of digits within name (using BLI_stringdec) and adjusts it by add.
+ */
+static void filenum_newname(char *name, size_t name_size, int add)
+{
+ char head[FILE_MAXFILE], tail[FILE_MAXFILE];
+ char name_temp[FILE_MAXFILE];
+ int pic;
+ unsigned short digits;
+
+ pic = BLI_stringdec(name, head, tail, &digits);
+
+ /* are we going from 100 -> 99 or from 10 -> 9 */
+ if (add < 0 && digits > 0) {
+ int i, exp;
+ exp = 1;
+ for (i = digits; i > 1; i--) {
+ exp *= 10;
+ }
+ if (pic >= exp && (pic + add) < exp) {
+ digits--;
+ }
+ }
+
+ pic += add;
+ if (pic < 0)
+ pic = 0;
+ BLI_stringenc(name_temp, head, tail, digits, pic);
+ BLI_strncpy(name, name_temp, name_size);
+}
+
static int file_filenum_exec(bContext *C, wmOperator *op)
{
SpaceFile *sfile = CTX_wm_space_file(C);
@@ -1976,7 +2071,7 @@ static int file_filenum_exec(bContext *C, wmOperator *op)
int inc = RNA_int_get(op->ptr, "increment");
if (sfile->params && (inc != 0)) {
- BLI_newname(sfile->params->file, inc);
+ filenum_newname(sfile->params->file, sizeof(sfile->params->file), inc);
ED_area_tag_redraw(sa);
file_draw_check(C);
// WM_event_add_notifier(C, NC_WINDOW, NULL);
diff --git a/source/blender/editors/space_file/file_utils.c b/source/blender/editors/space_file/file_utils.c
index 8a80e4a69ee..3c007f25da3 100644
--- a/source/blender/editors/space_file/file_utils.c
+++ b/source/blender/editors/space_file/file_utils.c
@@ -41,6 +41,7 @@ void file_tile_boundbox(const ARegion *ar, FileLayout *layout, const int file, r
int xmin, ymax;
ED_fileselect_layout_tilepos(layout, file, &xmin, &ymax);
+ ymax = (int)ar->v2d.tot.ymax - ymax; /* real, view space ymax */
BLI_rcti_init(r_bounds, xmin, xmin + layout->tile_w + layout->tile_border_x,
- ar->winy - ymax - layout->tile_h - layout->tile_border_y, ar->winy - ymax);
+ ymax - layout->tile_h - layout->tile_border_y, ymax);
}
diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c
index 0a9bb40a7cd..56c48b7f650 100644
--- a/source/blender/editors/space_file/filelist.c
+++ b/source/blender/editors/space_file/filelist.c
@@ -233,6 +233,9 @@ typedef struct FileListEntryCache {
int flags;
+ /* This one gathers all entries from both block and misc caches. Used for easy bulk-freing. */
+ ListBase cached_entries;
+
/* Block cache: all entries between start and end index. used for part of the list on diplay. */
FileDirEntry **block_entries;
int block_start_index, block_end_index, block_center_index, block_cursor;
@@ -247,6 +250,7 @@ typedef struct FileListEntryCache {
GHash *uuids;
/* Previews handling. */
+ TaskScheduler *previews_scheduler;
TaskPool *previews_pool;
ThreadQueue *previews_todo;
ThreadQueue *previews_done;
@@ -528,6 +532,7 @@ void filelist_sort(struct FileList *filelist)
case FILE_SORT_NONE: /* Should never reach this point! */
default:
BLI_assert(0);
+ break;
}
filelist_filter_clear(filelist);
@@ -1016,6 +1021,7 @@ static void filelist_entry_free(FileDirEntry *entry)
static void filelist_direntryarr_free(FileDirEntryArr *array)
{
+#if 0
FileDirEntry *entry, *entry_next;
for (entry = array->entries.first; entry; entry = entry_next) {
@@ -1023,6 +1029,9 @@ static void filelist_direntryarr_free(FileDirEntryArr *array)
filelist_entry_free(entry);
}
BLI_listbase_clear(&array->entries);
+#else
+ BLI_assert(BLI_listbase_is_empty(&array->entries));
+#endif
array->nbr_entries = 0;
array->nbr_entries_filtered = -1;
array->entry_idx_start = -1;
@@ -1093,10 +1102,11 @@ static void filelist_cache_previewf(TaskPool *pool, void *taskdata, int UNUSED(t
static void filelist_cache_preview_ensure_running(FileListEntryCache *cache)
{
if (!cache->previews_pool) {
- TaskScheduler *scheduler = BLI_task_scheduler_get();
+ TaskScheduler *scheduler;
TaskPool *pool;
- int num_tasks = max_ii(2, BLI_system_thread_count() / 2);
+ int num_tasks = max_ii(1, (BLI_system_thread_count() / 2) + 1);
+ scheduler = cache->previews_scheduler = BLI_task_scheduler_create(num_tasks + 1);
pool = cache->previews_pool = BLI_task_pool_create(scheduler, NULL);
cache->previews_todo = BLI_thread_queue_init();
cache->previews_done = BLI_thread_queue_init();
@@ -1143,6 +1153,8 @@ static void filelist_cache_previews_free(FileListEntryCache *cache, const bool s
BLI_thread_queue_free(cache->previews_done);
BLI_thread_queue_free(cache->previews_todo);
BLI_task_pool_free(cache->previews_pool);
+ BLI_task_scheduler_free(cache->previews_scheduler);
+ cache->previews_scheduler = NULL;
cache->previews_pool = NULL;
cache->previews_todo = NULL;
cache->previews_done = NULL;
@@ -1182,6 +1194,8 @@ static void filelist_cache_previews_push(FileList *filelist, FileDirEntry *entry
static void filelist_cache_init(FileListEntryCache *cache, size_t cache_size)
{
+ BLI_listbase_clear(&cache->cached_entries);
+
cache->block_cursor = cache->block_start_index = cache->block_center_index = cache->block_end_index = 0;
cache->block_entries = MEM_mallocN(sizeof(*cache->block_entries) * cache_size, __func__);
@@ -1200,30 +1214,38 @@ static void filelist_cache_init(FileListEntryCache *cache, size_t cache_size)
static void filelist_cache_free(FileListEntryCache *cache)
{
+ FileDirEntry *entry, *entry_next;
+
if (!(cache->flags & FLC_IS_INIT)) {
return;
}
filelist_cache_previews_free(cache, true);
- /* Note we nearly have nothing to do here, entries are just 'borrowed', not owned by cache... */
MEM_freeN(cache->block_entries);
BLI_ghash_free(cache->misc_entries, NULL, NULL);
MEM_freeN(cache->misc_entries_indices);
BLI_ghash_free(cache->uuids, NULL, NULL);
+
+ for (entry = cache->cached_entries.first; entry; entry = entry_next) {
+ entry_next = entry->next;
+ filelist_entry_free(entry);
+ }
+ BLI_listbase_clear(&cache->cached_entries);
}
static void filelist_cache_clear(FileListEntryCache *cache, size_t new_size)
{
+ FileDirEntry *entry, *entry_next;
+
if (!(cache->flags & FLC_IS_INIT)) {
return;
}
filelist_cache_previews_clear(cache);
- /* Note we nearly have nothing to do here, entries are just 'borrowed', not owned by cache... */
cache->block_cursor = cache->block_start_index = cache->block_center_index = cache->block_end_index = 0;
if (new_size != cache->size) {
cache->block_entries = MEM_reallocN(cache->block_entries, sizeof(*cache->block_entries) * new_size);
@@ -1239,6 +1261,12 @@ static void filelist_cache_clear(FileListEntryCache *cache, size_t new_size)
BLI_ghash_clear_ex(cache->uuids, NULL, NULL, new_size * 2);
cache->size = new_size;
+
+ for (entry = cache->cached_entries.first; entry; entry = entry_next) {
+ entry_next = entry->next;
+ filelist_entry_free(entry);
+ }
+ BLI_listbase_clear(&cache->cached_entries);
}
FileList *filelist_new(short type)
@@ -1417,6 +1445,7 @@ int filelist_files_ensure(FileList *filelist)
static FileDirEntry *filelist_file_create_entry(FileList *filelist, const int index)
{
FileListInternEntry *entry = filelist->filelist_intern.filtered[index];
+ FileListEntryCache *cache = &filelist->filelist_cache;
FileDirEntry *ret;
FileDirEntryRevision *rev;
@@ -1435,13 +1464,13 @@ static FileDirEntry *filelist_file_create_entry(FileList *filelist, const int in
ret->blentype = entry->blentype;
ret->typeflag = entry->typeflag;
- BLI_addtail(&filelist->filelist.entries, ret);
+ BLI_addtail(&cache->cached_entries, ret);
return ret;
}
static void filelist_file_release_entry(FileList *filelist, FileDirEntry *entry)
{
- BLI_remlink(&filelist->filelist.entries, entry);
+ BLI_remlink(&filelist->filelist_cache.cached_entries, entry);
filelist_entry_free(entry);
}
@@ -1507,7 +1536,7 @@ int filelist_file_findpath(struct FileList *filelist, const char *filename)
}
/* XXX TODO Cache could probably use a ghash on paths too? Not really urgent though.
- * This is only used to find again renamed entry, annoying but looks hairy to get rid of it currently. */
+ * This is only used to find again renamed entry, annoying but looks hairy to get rid of it currently. */
for (fidx = 0; fidx < filelist->filelist.nbr_entries_filtered; fidx++) {
FileListInternEntry *entry = filelist->filelist_intern.filtered[fidx];
@@ -2138,11 +2167,10 @@ static unsigned int groupname_to_filter_id(const char *group)
return BKE_idcode_to_idfilter(id_code);
}
-/*
- * From here, we are in 'Job Context', i.e. have to be careful about sharing stuff between bacground working thread
+/**
+ * From here, we are in 'Job Context', i.e. have to be careful about sharing stuff between background working thread
* and main one (used by UI among other things).
*/
-
typedef struct TodoDir {
int level;
char *dir;
@@ -2167,14 +2195,14 @@ static int filelist_readjob_list_dir(
entry = MEM_callocN(sizeof(*entry), __func__);
entry->relpath = MEM_dupallocN(files[i].relname);
- if (S_ISDIR(files[i].s.st_mode)) {
- entry->typeflag |= FILE_TYPE_DIR;
- }
entry->st = files[i].s;
/* Set file type. */
- /* If we are considering .blend files as libs, promote them to directory status! */
- if (do_lib && BLO_has_bfile_extension(entry->relpath)) {
+ if (S_ISDIR(files[i].s.st_mode)) {
+ entry->typeflag = FILE_TYPE_DIR;
+ }
+ else if (do_lib && BLO_has_bfile_extension(entry->relpath)) {
+ /* If we are considering .blend files as libs, promote them to directory status. */
char name[FILE_MAX];
entry->typeflag = FILE_TYPE_BLENDER;
@@ -2188,11 +2216,9 @@ static int filelist_readjob_list_dir(
}
/* Otherwise, do not check extensions for directories! */
else if (!(entry->typeflag & FILE_TYPE_DIR)) {
+ entry->typeflag = file_extension_type(root, entry->relpath);
if (filter_glob[0] && BLI_testextensie_glob(entry->relpath, filter_glob)) {
- entry->typeflag = FILE_TYPE_OPERATOR;
- }
- else {
- entry->typeflag = file_extension_type(root, entry->relpath);
+ entry->typeflag |= FILE_TYPE_OPERATOR;
}
}
@@ -2472,7 +2498,7 @@ static void filelist_readjob_do(
* things would crash way before we overflow that counter!
* Using an atomic operation to avoid having to lock thread...
* Note that we do not really need this here currently, since there is a single listing thread, but better
- * remain consistent about threading! */
+ * remain consistent about threading! */
*((uint32_t *)entry->uuid) = atomic_add_uint32((uint32_t *)filelist->filelist_intern.curr_uuid, 1);
BLI_path_rel(dir, root);
diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c
index da24f1ce95d..a83cae6eb17 100644
--- a/source/blender/editors/space_file/filesel.c
+++ b/source/blender/editors/space_file/filesel.c
@@ -260,6 +260,7 @@ short ED_fileselect_set_params(SpaceFile *sfile)
params->flag |= FILE_HIDE_DOT;
params->flag &= ~FILE_DIRSEL_ONLY;
params->display = FILE_SHORTDISPLAY;
+ params->sort = FILE_SORT_ALPHA;
params->filter = 0;
params->filter_glob[0] = '\0';
}
diff --git a/source/blender/editors/space_file/fsmenu.c b/source/blender/editors/space_file/fsmenu.c
index fdf7b458865..33e6990b179 100644
--- a/source/blender/editors/space_file/fsmenu.c
+++ b/source/blender/editors/space_file/fsmenu.c
@@ -292,6 +292,30 @@ void fsmenu_insert_entry(struct FSMenu *fsmenu, FSMenuCategory category, const c
fsm_iter = MEM_mallocN(sizeof(*fsm_iter), "fsme");
fsm_iter->path = BLI_strdup(path);
fsm_iter->save = (flag & FS_INSERT_SAVE) != 0;
+
+ if ((category == FS_CATEGORY_RECENT) && (!name || !name[0])) {
+ /* Special handling when adding new recent entry - check if dir exists in some other categories,
+ * and try to use name from there if so. */
+ FSMenuCategory cats[] = {FS_CATEGORY_SYSTEM, FS_CATEGORY_SYSTEM_BOOKMARKS, FS_CATEGORY_BOOKMARKS};
+ int i = ARRAY_SIZE(cats);
+
+ while (i--) {
+ FSMenuEntry *tfsm = ED_fsmenu_get_category(fsmenu, cats[i]);
+
+ for (; tfsm; tfsm = tfsm->next) {
+ if (STREQ(tfsm->path, fsm_iter->path)) {
+ if (tfsm->name[0]) {
+ name = tfsm->name;
+ }
+ break;
+ }
+ }
+ if (tfsm) {
+ break;
+ }
+ }
+ }
+
if (name && name[0]) {
BLI_strncpy(fsm_iter->name, name, sizeof(fsm_iter->name));
}
@@ -439,19 +463,36 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks)
{
wchar_t wline[FILE_MAXDIR];
__int64 tmp;
- char tmps[4];
+ char tmps[4], *name;
int i;
-
+
tmp = GetLogicalDrives();
-
+
for (i = 0; i < 26; i++) {
if ((tmp >> i) & 1) {
tmps[0] = 'A' + i;
tmps[1] = ':';
tmps[2] = '\\';
- tmps[3] = 0;
-
- fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, tmps, NULL, FS_INSERT_SORTED);
+ tmps[3] = '\0';
+ name = NULL;
+
+ /* Flee from horrible win querying hover floppy drives! */
+ if (i > 1) {
+ /* Try to get volume label as well... */
+ BLI_strncpy_wchar_from_utf8(wline, tmps, 4);
+ if (GetVolumeInformationW(wline, wline + 4, FILE_MAXDIR - 4, NULL, NULL, NULL, NULL, 0)) {
+ size_t label_len;
+
+ BLI_strncpy_wchar_as_utf8(line, wline + 4, FILE_MAXDIR - 4);
+
+ label_len = MIN2(strlen(line), FILE_MAXDIR - 6);
+ BLI_snprintf(line + label_len, 6, " (%.2s)", tmps);
+
+ name = line;
+ }
+ }
+
+ fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, tmps, name, FS_INSERT_SORTED);
}
}
diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c
index 191a709af4f..1ee9a67a7a1 100644
--- a/source/blender/editors/space_image/image_buttons.c
+++ b/source/blender/editors/space_image/image_buttons.c
@@ -411,7 +411,7 @@ static void ui_imageuser_pass_menu(bContext *UNUSED(C), uiLayout *layout, void *
uiDefMenuTitleBut(block, IFACE_("Pass"));
- nr = (rl ? BLI_listbase_count(&rl->passes) : 0) - 1;
+ nr = 0;
fake_name = ui_imageuser_pass_fake_name(rl);
if (fake_name) {
@@ -420,7 +420,8 @@ static void ui_imageuser_pass_menu(bContext *UNUSED(C), uiLayout *layout, void *
}
/* rendered results don't have a Combined pass */
- for (rpass = rl ? rl->passes.last : NULL; rpass; rpass = rpass->prev, nr--) {
+ /* multiview: the ordering must be ascending, so the left-most pass is always the one picked */
+ for (rpass = rl ? rl->passes.first : NULL; rpass; rpass = rpass->next, nr++) {
/* just show one pass of each kind */
if (passflag & rpass->passtype)
@@ -429,18 +430,17 @@ static void ui_imageuser_pass_menu(bContext *UNUSED(C), uiLayout *layout, void *
passflag |= rpass->passtype;
final:
- uiDefButI(block, UI_BTYPE_BUT_MENU, B_NOP, IFACE_(rpass->internal_name), 0, 0,
- UI_UNIT_X * 5, UI_UNIT_X, &iuser->passtype, (float) rpass->passtype, 0.0, 0, -1, "");
+ uiDefButS(block, UI_BTYPE_BUT_MENU, B_NOP, IFACE_(rpass->internal_name), 0, 0,
+ UI_UNIT_X * 5, UI_UNIT_X, &iuser->pass, (float) nr, 0.0, 0, -1, "");
}
if (fake_name) {
fake_name = NULL;
rpass = &rpass_fake;
+ nr = 0;
goto final;
}
- BLI_assert(nr == -1);
-
BKE_image_release_renderresult(scene, image);
}
@@ -537,7 +537,6 @@ static void image_multi_incpass_cb(bContext *C, void *rr_v, void *iuser_v)
ImageUser *iuser = iuser_v;
RenderLayer *rl;
RenderPass *rp;
- RenderPass *next = NULL;
int layer = iuser->layer;
if (RE_HasFakeLayer(rr))
@@ -546,20 +545,20 @@ static void image_multi_incpass_cb(bContext *C, void *rr_v, void *iuser_v)
rl = BLI_findlink(&rr->layers, layer);
if (rl) {
- for (rp = rl->passes.first; rp; rp = rp->next) {
- if (rp->passtype == iuser->passtype) {
- next = rp->next;
- if (next != NULL && next->passtype == rp->passtype)
- next = next->next;
+ RenderPass *rpass = BLI_findlink(&rl->passes, iuser->pass);
+ int rp_index = iuser->pass + 1;
+
+ if (rpass == NULL)
+ return;
+
+ for (rp = rpass->next; rp; rp = rp->next, rp_index++) {
+ if (rp->passtype != rpass->passtype) {
+ iuser->pass = rp_index;
+ BKE_image_multilayer_index(rr, iuser);
+ WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL);
break;
}
}
-
- if (next != NULL && iuser->passtype != next->passtype) {
- iuser->passtype = next->passtype;
- BKE_image_multilayer_index(rr, iuser);
- WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL);
- }
}
}
static void image_multi_decpass_cb(bContext *C, void *rr_v, void *iuser_v)
@@ -568,29 +567,31 @@ static void image_multi_decpass_cb(bContext *C, void *rr_v, void *iuser_v)
ImageUser *iuser = iuser_v;
RenderLayer *rl;
RenderPass *rp;
- RenderPass *prev = NULL;
int layer = iuser->layer;
+ if (iuser->pass == 0)
+ return;
+
if (RE_HasFakeLayer(rr))
layer -= 1;
rl = BLI_findlink(&rr->layers, layer);
if (rl) {
- for (rp = rl->passes.last; rp; rp = rp->prev) {
- if (rp->passtype == iuser->passtype) {
- prev = rp->prev;
- if (prev != NULL && prev->passtype == rp->passtype)
- prev = prev->prev;
+ RenderPass *rpass = BLI_findlink(&rl->passes, iuser->pass);
+ int rp_index = 0;
+
+ if (rpass == NULL)
+ return;
+
+ for (rp = rl->passes.first; rp; rp = rp->next, rp_index++) {
+ if (rp->passtype == rpass->passtype) {
+ iuser->pass = rp_index - 1;
+ BKE_image_multilayer_index(rr, iuser);
+ WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL);
break;
}
}
-
- if (prev != NULL && iuser->passtype != prev->passtype) {
- iuser->passtype = prev->passtype;
- BKE_image_multilayer_index(rr, iuser);
- WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL);
- }
}
}
@@ -630,7 +631,7 @@ static void uiblock_layer_pass_buttons(uiLayout *layout, Image *image, RenderRes
int wmenu1, wmenu2, wmenu3, wmenu4;
const char *fake_name;
const char *display_name = "";
- const bool show_stereo = (iuser->flag & IMA_SHOW_STEREO);
+ const bool show_stereo = (iuser->flag & IMA_SHOW_STEREO) != 0;
uiLayoutRow(layout, true);
@@ -679,7 +680,7 @@ static void uiblock_layer_pass_buttons(uiLayout *layout, Image *image, RenderRes
/* pass */
fake_name = ui_imageuser_pass_fake_name(rl);
- rpass = (rl ? RE_pass_find_by_type(rl, iuser->passtype, ((RenderView *)rr->views.first)->name) : NULL);
+ rpass = (rl ? BLI_findlink(&rl->passes, iuser->pass - (fake_name ? 1 : 0)) : NULL);
display_name = rpass ? rpass->internal_name : (fake_name ? fake_name : "");
but = uiDefMenuBut(block, ui_imageuser_pass_menu, rnd_pt, IFACE_(display_name),
@@ -688,7 +689,9 @@ static void uiblock_layer_pass_buttons(uiLayout *layout, Image *image, RenderRes
UI_but_type_set_menu_from_pulldown(but);
/* view */
- if (BLI_listbase_count_ex(&rr->views, 2) > 1 && !show_stereo) {
+ if (BLI_listbase_count_ex(&rr->views, 2) > 1 &&
+ ((!show_stereo) || (!RE_RenderResult_is_stereo(rr))))
+ {
rview = BLI_findlink(&rr->views, iuser->view);
display_name = rview ? rview->name : "";
@@ -699,8 +702,8 @@ static void uiblock_layer_pass_buttons(uiLayout *layout, Image *image, RenderRes
}
/* stereo image */
- else if (((image->flag & IMA_IS_STEREO) && (!show_stereo)) ||
- ((image->flag & IMA_IS_MULTIVIEW) && ((image->flag & IMA_IS_STEREO) == 0)))
+ else if ((BKE_image_is_stereo(image) && (!show_stereo)) ||
+ (BKE_image_is_multiview(image) && !BKE_image_is_stereo(image)))
{
ImageView *iv;
int nr = 0;
diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c
index b157d1c7627..4f5fa6c2063 100644
--- a/source/blender/editors/space_image/image_draw.c
+++ b/source/blender/editors/space_image/image_draw.c
@@ -813,7 +813,7 @@ void draw_image_main(const bContext *C, ARegion *ar)
show_viewer = (ima && ima->source == IMA_SRC_VIEWER) != 0;
show_render = (show_viewer && ima->type == IMA_TYPE_R_RESULT) != 0;
show_paint = (ima && (sima->mode == SI_MODE_PAINT) && (show_viewer == false) && (show_render == false));
- show_stereo3d = (ima && (ima->flag & IMA_IS_STEREO) && (sima->iuser.flag & IMA_SHOW_STEREO));
+ show_stereo3d = (ima && BKE_image_is_stereo(ima) && (sima->iuser.flag & IMA_SHOW_STEREO));
show_multilayer = ima && BKE_image_is_multilayer(ima);
if (show_viewer) {
@@ -855,7 +855,7 @@ void draw_image_main(const bContext *C, ARegion *ar)
BLI_rctf_init(&frame, 0.0f, ibuf->x, 0.0f, ibuf->y);
UI_view2d_view_to_region(&ar->v2d, 0.0f, 0.0f, &x, &y);
- ED_region_image_metadata_draw(x, y, ibuf, frame, zoomx, zoomy);
+ ED_region_image_metadata_draw(x, y, ibuf, &frame, zoomx, zoomy);
}
}
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index 3c5aff4d698..faba61c7d28 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -1153,8 +1153,6 @@ static int image_open_exec(bContext *C, wmOperator *op)
}
else {
ima->flag &= ~IMA_USE_VIEWS;
- ima->flag &= ~IMA_IS_STEREO;
- ima->flag &= ~IMA_IS_MULTIVIEW;
BKE_image_free_views(ima);
}
@@ -1703,7 +1701,7 @@ static bool save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI
/* we need renderresult for exr and rendered multiview */
scene = CTX_data_scene(C);
rr = BKE_image_acquire_renderresult(scene, ima);
- is_mono = rr ? BLI_listbase_count_ex(&rr->views, 2) < 2 : (ima->flag & IMA_IS_MULTIVIEW) == 0;
+ is_mono = rr ? BLI_listbase_count_ex(&rr->views, 2) < 2 : BLI_listbase_count_ex(&ima->views, 2) < 2;
/* error handling */
if (!rr) {
@@ -1714,7 +1712,7 @@ static bool save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI
}
else {
if (imf->views_format == R_IMF_VIEWS_STEREO_3D) {
- if ((ima->flag & IMA_IS_STEREO) == 0) {
+ if (!BKE_image_is_stereo(ima)) {
BKE_reportf(op->reports, RPT_ERROR, "Did not write, the image doesn't have a \"%s\" and \"%s\" views",
STEREO_LEFT_NAME, STEREO_RIGHT_NAME);
goto cleanup;
@@ -1959,9 +1957,9 @@ static int image_save_as_invoke(bContext *C, wmOperator *op, const wmEvent *UNUS
/* show multiview save options only if image has multiviews */
prop = RNA_struct_find_property(op->ptr, "show_multiview");
- RNA_property_boolean_set(op->ptr, prop, (ima->flag & IMA_IS_MULTIVIEW) != 0);
+ RNA_property_boolean_set(op->ptr, prop, BKE_image_is_multiview(ima));
prop = RNA_struct_find_property(op->ptr, "use_multiview");
- RNA_property_boolean_set(op->ptr, prop, (ima->flag & IMA_IS_MULTIVIEW) != 0);
+ RNA_property_boolean_set(op->ptr, prop, BKE_image_is_multiview(ima));
image_filesel(C, op, simopts.filepath);
diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c
index 928e064b730..97e3390f142 100644
--- a/source/blender/editors/space_image/space_image.c
+++ b/source/blender/editors/space_image/space_image.c
@@ -157,7 +157,6 @@ static SpaceLink *image_new(const bContext *UNUSED(C))
simage->iuser.fie_ima = 2;
simage->iuser.frames = 100;
simage->iuser.flag = IMA_SHOW_STEREO;
- simage->iuser.passtype = SCE_PASS_COMBINED;
scopes_new(&simage->scopes);
simage->sample_line_hist.height = 100;
@@ -920,7 +919,8 @@ static void image_tools_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa),
ED_region_tag_redraw(ar);
break;
case NC_BRUSH:
- if (wmn->action == NA_EDITED)
+ /* NA_SELECTED is used on brush changes */
+ if (ELEM(wmn->action, NA_EDITED, NA_SELECTED))
ED_region_tag_redraw(ar);
break;
case NC_SCENE:
diff --git a/source/blender/editors/space_logic/logic_window.c b/source/blender/editors/space_logic/logic_window.c
index ccf8460e9a3..a8536496059 100644
--- a/source/blender/editors/space_logic/logic_window.c
+++ b/source/blender/editors/space_logic/logic_window.c
@@ -1696,7 +1696,7 @@ static void draw_actuator_filter_2d(uiLayout *layout, PointerRNA *ptr)
static void draw_actuator_game(uiLayout *layout, PointerRNA *ptr)
{
uiItemR(layout, ptr, "mode", 0, NULL, ICON_NONE);
- if (RNA_enum_get(ptr, "mode") == ACT_GAME_LOAD)
+ if (ELEM(RNA_enum_get(ptr, "mode"), ACT_GAME_LOAD, ACT_GAME_SCREENSHOT))
uiItemR(layout, ptr, "filename", 0, NULL, ICON_NONE);
}
diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c
index 745774577be..b0adabe4d1d 100644
--- a/source/blender/editors/space_nla/nla_draw.c
+++ b/source/blender/editors/space_nla/nla_draw.c
@@ -422,13 +422,14 @@ static void nla_draw_strip(SpaceNla *snla, AnimData *adt, NlaTrack *nlt, NlaStri
}
/* add the relevant text to the cache of text-strings to draw in pixelspace */
-static void nla_draw_strip_text(AnimData *adt, NlaTrack *nlt, NlaStrip *strip, int index, View2D *v2d, float yminc, float ymaxc)
+static void nla_draw_strip_text(
+ AnimData *adt, NlaTrack *nlt, NlaStrip *strip, int index, View2D *v2d,
+ float xminc, float xmaxc, float yminc, float ymaxc)
{
const bool non_solo = ((adt && (adt->flag & ADT_NLA_SOLO_TRACK)) && (nlt->flag & NLATRACK_SOLO) == 0);
char str[256];
size_t str_len;
char col[4];
- float xofs;
rctf rect;
/* just print the name and the range */
@@ -452,20 +453,14 @@ static void nla_draw_strip_text(AnimData *adt, NlaTrack *nlt, NlaStrip *strip, i
col[3] = 255;
else
col[3] = 128;
-
- /* determine the amount of padding required - cannot be constant otherwise looks weird in some cases */
- if ((strip->end - strip->start) <= 5.0f)
- xofs = 0.5f;
- else
- xofs = 1.0f;
-
+
/* set bounding-box for text
* - padding of 2 'units' on either side
*/
// TODO: make this centered?
- rect.xmin = strip->start + xofs;
+ rect.xmin = xminc;
rect.ymin = yminc;
- rect.xmax = strip->end - xofs;
+ rect.xmax = xmaxc;
rect.ymax = ymaxc;
/* add this string to the cache of texts to draw */
@@ -510,6 +505,8 @@ void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *ar)
float y = 0.0f;
size_t items;
int height;
+ const float pixelx = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask);
+ const float text_margin_x = (8 * UI_DPI_FAC) * pixelx;
/* build list of channels to draw */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
@@ -550,11 +547,16 @@ void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *ar)
/* draw each strip in the track (if visible) */
for (strip = nlt->strips.first, index = 1; strip; strip = strip->next, index++) {
if (BKE_nlastrip_within_bounds(strip, v2d->cur.xmin, v2d->cur.xmax)) {
+ const float xminc = strip->start + text_margin_x;
+ const float xmaxc = strip->end + text_margin_x;
+
/* draw the visualization of the strip */
nla_draw_strip(snla, adt, nlt, strip, v2d, yminc, ymaxc);
/* add the text for this strip to the cache */
- nla_draw_strip_text(adt, nlt, strip, index, v2d, yminc, ymaxc);
+ if (xminc < xmaxc) {
+ nla_draw_strip_text(adt, nlt, strip, index, v2d, xminc, xmaxc, yminc, ymaxc);
+ }
/* if transforming strips (only real reason for temp-metas currently),
* add to the cache the frame numbers of the strip's extents
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index 7ba75f99211..a25b55b7108 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -391,6 +391,7 @@ static void node_draw_frame_label(bNodeTree *ntree, bNode *node, const float asp
float x, y;
const int font_size = data->label_size / aspect;
const float margin = (float)(NODE_DY / 4);
+ int label_height;
nodeLabel(ntree, node, label, sizeof(label));
@@ -403,10 +404,11 @@ static void node_draw_frame_label(bNodeTree *ntree, bNode *node, const float asp
width = BLF_width(fontid, label, sizeof(label));
ascender = BLF_ascender(fontid);
+ label_height = ((margin / aspect) + (ascender * aspect));
/* 'x' doesn't need aspect correction */
x = BLI_rctf_cent_x(rct) - (0.5f * width);
- y = rct->ymax - ((margin / aspect) + (ascender * aspect));
+ y = rct->ymax - label_height;
BLF_position(fontid, x, y, 0);
BLF_draw(fontid, label, BLF_DRAW_STR_DUMMY_MAX);
@@ -415,31 +417,39 @@ static void node_draw_frame_label(bNodeTree *ntree, bNode *node, const float asp
if (node->id) {
Text *text = (Text *)node->id;
TextLine *line;
- const float line_spacing = (BLF_height_max(fontid) * aspect) * 0.7f;
+ const int line_height_max = BLF_height_max(fontid);
+ const float line_spacing = (line_height_max * aspect);
+ const float line_width = (BLI_rctf_size_x(rct) - margin) / aspect;
+ int y_min;
/* 'x' doesn't need aspect correction */
x = rct->xmin + margin;
- y = rct->ymax - ((margin / aspect) + (ascender * aspect));
- y -= line_spacing;
+ y = rct->ymax - (label_height + line_spacing);
+ /* early exit */
+ y_min = y + ((margin * 2) - (y - rct->ymin));
- BLF_enable(fontid, BLF_CLIPPING);
+ BLF_enable(fontid, BLF_CLIPPING | BLF_WORD_WRAP);
BLF_clipping(
fontid,
rct->xmin,
- rct->ymin,
- rct->xmin + ((rct->xmax - rct->xmin) / aspect) - margin,
+ /* round to avoid clipping half-way through a line */
+ y - (floorf(((y - rct->ymin) - (margin * 2)) / line_spacing) * line_spacing),
+ rct->xmin + line_width,
rct->ymax);
+ BLF_wordwrap(fontid, line_width);
+
for (line = text->lines.first; line; line = line->next) {
+ struct ResultBLF info;
BLF_position(fontid, x, y, 0);
- BLF_draw(fontid, line->line, line->len);
- y -= line_spacing;
- if (y < rct->ymin) {
+ BLF_draw_ex(fontid, line->line, line->len, &info);
+ y -= line_spacing * info.lines;
+ if (y < y_min) {
break;
}
}
- BLF_disable(fontid, BLF_CLIPPING);
+ BLF_disable(fontid, BLF_CLIPPING | BLF_WORD_WRAP);
}
BLF_disable(fontid, BLF_ASPECT);
@@ -847,6 +857,7 @@ static void node_shader_buts_tex_environment(uiLayout *layout, bContext *C, Poin
node_buts_image_user(layout, C, &iuserptr, &imaptr, &iuserptr);
uiItemR(layout, ptr, "color_space", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "interpolation", 0, "", ICON_NONE);
uiItemR(layout, ptr, "projection", 0, "", ICON_NONE);
}
@@ -888,6 +899,7 @@ static void node_shader_buts_tex_environment_ex(uiLayout *layout, bContext *C, P
}
uiItemR(layout, ptr, "color_space", 0, IFACE_("Color Space"), ICON_NONE);
+ uiItemR(layout, ptr, "interpolation", 0, IFACE_("Interpolation"), ICON_NONE);
uiItemR(layout, ptr, "projection", 0, IFACE_("Projection"), ICON_NONE);
}
diff --git a/source/blender/editors/space_node/node_relationships.c b/source/blender/editors/space_node/node_relationships.c
index d31d1687e5e..4097db29e5a 100644
--- a/source/blender/editors/space_node/node_relationships.c
+++ b/source/blender/editors/space_node/node_relationships.c
@@ -1436,7 +1436,7 @@ static void node_parent_offset_apply(NodeInsertOfsData *data, bNode *parent, con
#define NODE_INSOFS_ANIM_DURATION 0.25f
/**
- * Callback that applies NodeInsertOfsData.offset_x to a node or its parent, similiar
+ * Callback that applies NodeInsertOfsData.offset_x to a node or its parent, similar
* to node_link_insert_offset_output_chain_cb below, but with slightly different logic
*/
static bool node_link_insert_offset_frame_chain_cb(
@@ -1600,7 +1600,7 @@ static void node_link_insert_offset_ntree(
node_offset_apply(offs_node, addval);
}
else if (!insert->parent && offs_node->parent) {
- node_offset_apply(offs_node->parent, addval);
+ node_offset_apply(nodeFindRootParent(offs_node), addval);
}
margin = addval;
}
@@ -1634,12 +1634,36 @@ static int node_insert_offset_modal(bContext *C, wmOperator *UNUSED(op), const w
NodeInsertOfsData *iofsd = snode->iofsd;
bNode *node;
float duration;
+ bool redraw = false;
if (!snode || event->type != TIMER || iofsd->anim_timer != event->customdata)
return OPERATOR_PASS_THROUGH;
- /* end timer + free insert offset data */
duration = (float)iofsd->anim_timer->duration;
+
+ /* handle animation - do this before possibly aborting due to duration, since
+ * main thread might be so busy that node hasn't reached final position yet */
+ for (node = snode->edittree->nodes.first; node; node = node->next) {
+ if (UNLIKELY(node->anim_ofsx)) {
+ const float endval = node->anim_init_locx + node->anim_ofsx;
+ if (IS_EQF(node->locx, endval) == false) {
+ node->locx = BLI_easing_cubic_ease_in_out(duration, node->anim_init_locx, node->anim_ofsx,
+ NODE_INSOFS_ANIM_DURATION);
+ if (node->anim_ofsx < 0) {
+ CLAMP_MIN(node->locx, endval);
+ }
+ else {
+ CLAMP_MAX(node->locx, endval);
+ }
+ redraw = true;
+ }
+ }
+ }
+ if (redraw) {
+ ED_region_tag_redraw(CTX_wm_region(C));
+ }
+
+ /* end timer + free insert offset data */
if (duration > NODE_INSOFS_ANIM_DURATION) {
WM_event_remove_timer(CTX_wm_manager(C), NULL, iofsd->anim_timer);
@@ -1653,15 +1677,6 @@ static int node_insert_offset_modal(bContext *C, wmOperator *UNUSED(op), const w
return (OPERATOR_FINISHED | OPERATOR_PASS_THROUGH);
}
- /* handle animation */
- for (node = snode->edittree->nodes.first; node; node = node->next) {
- if (node->anim_ofsx) {
- node->locx = BLI_easing_cubic_ease_in_out(duration, node->anim_init_locx, node->anim_ofsx,
- NODE_INSOFS_ANIM_DURATION);
- }
- }
- ED_region_tag_redraw(CTX_wm_region(C));
-
return OPERATOR_RUNNING_MODAL;
}
diff --git a/source/blender/editors/space_node/node_templates.c b/source/blender/editors/space_node/node_templates.c
index 85288aa0011..ec6ef3c4697 100644
--- a/source/blender/editors/space_node/node_templates.c
+++ b/source/blender/editors/space_node/node_templates.c
@@ -524,7 +524,7 @@ static void ui_template_node_link_menu(bContext *C, uiLayout *layout, void *but_
bNodeSocket *sock = arg->sock;
bNodeTreeType *ntreetype = arg->ntree->typeinfo;
- UI_block_flag_enable(block, UI_BLOCK_NO_FLIP);
+ UI_block_flag_enable(block, UI_BLOCK_NO_FLIP | UI_BLOCK_IS_FLIP);
UI_block_layout_set_current(block, layout);
split = uiLayoutSplit(layout, 0.0f, false);
@@ -622,7 +622,7 @@ static void ui_node_draw_input(uiLayout *layout, bContext *C, bNodeTree *ntree,
uiLayout *split, *row, *col;
bNode *lnode;
char label[UI_MAX_NAME_STR];
- int indent = (depth > 1) ? 2 * (depth - 1) : 0;
+ int i, indent = (depth > 1) ? 2 * (depth - 1) : 0;
int dependency_loop;
if (input->flag & SOCK_UNAVAIL)
@@ -641,7 +641,8 @@ static void ui_node_draw_input(uiLayout *layout, bContext *C, bNodeTree *ntree,
RNA_pointer_create(&ntree->id, &RNA_Node, node, &nodeptr);
/* indented label */
- memset(label, ' ', indent);
+ for (i = 0; i < indent; i++)
+ label[i] = ' ';
label[indent] = '\0';
BLI_snprintf(label, UI_MAX_NAME_STR, "%s%s:", label, IFACE_(input->name));
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index ac9e2e36ded..665ae88d833 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -1318,7 +1318,16 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto
case ID_GR:
tselem_draw_icon_uibut(&arg, ICON_GROUP); break;
case ID_LI:
- tselem_draw_icon_uibut(&arg, ICON_LIBRARY_DATA_DIRECT); break;
+ if (tselem->id->flag & LIB_MISSING) {
+ tselem_draw_icon_uibut(&arg, ICON_LIBRARY_DATA_BROKEN);
+ }
+ else if (((Library *)tselem->id)->parent) {
+ tselem_draw_icon_uibut(&arg, ICON_LIBRARY_DATA_INDIRECT);
+ }
+ else {
+ tselem_draw_icon_uibut(&arg, ICON_LIBRARY_DATA_DIRECT);
+ }
+ break;
case ID_LS:
tselem_draw_icon_uibut(&arg, ICON_LINE_DATA); break;
case ID_GD:
@@ -1553,10 +1562,15 @@ static void outliner_draw_tree_element(
if (tselem->type == 0 && tselem->id->lib) {
glPixelTransferf(GL_ALPHA_SCALE, 0.5f);
- if (tselem->id->flag & LIB_INDIRECT)
+ if (tselem->id->flag & LIB_MISSING) {
+ UI_icon_draw((float)startx + offsx, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_BROKEN);
+ }
+ else if (tselem->id->flag & LIB_INDIRECT) {
UI_icon_draw((float)startx + offsx, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_INDIRECT);
- else
+ }
+ else {
UI_icon_draw((float)startx + offsx, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_DIRECT);
+ }
glPixelTransferf(GL_ALPHA_SCALE, 1.0f);
offsx += UI_UNIT_X;
}
diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c
index 1ddd25f9219..6d420674f3e 100644
--- a/source/blender/editors/space_outliner/outliner_edit.c
+++ b/source/blender/editors/space_outliner/outliner_edit.c
@@ -220,7 +220,7 @@ static void do_item_rename(ARegion *ar, TreeElement *te, TreeStoreElem *tselem,
else if (tselem->id->lib) {
BKE_report(reports, RPT_WARNING, "Cannot edit external libdata");
}
- else if (te->idcode == ID_LI && te->parent) {
+ else if (te->idcode == ID_LI && ((Library *)tselem->id)->parent) {
BKE_report(reports, RPT_WARNING, "Cannot edit the path of an indirectly linked library");
}
else {
diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h
index 7d151282bd2..c89a1bb1b9f 100644
--- a/source/blender/editors/space_outliner/outliner_intern.h
+++ b/source/blender/editors/space_outliner/outliner_intern.h
@@ -58,9 +58,9 @@ typedef struct TreeElement {
} TreeElement;
#define TREESTORE_ID_TYPE(_id) \
- (ELEM(GS((_id)->name), ID_SCE, ID_LI, ID_OB, ID_ME, ID_CU, ID_MB, ID_MA, ID_TE, ID_IM, ID_LT, ID_LA, ID_CA) || \
+ (ELEM(GS((_id)->name), ID_SCE, ID_LI, ID_OB, ID_ME, ID_CU, ID_MB, ID_NT, ID_MA, ID_TE, ID_IM, ID_LT, ID_LA, ID_CA) || \
ELEM(GS((_id)->name), ID_KE, ID_WO, ID_SPK, ID_GR, ID_AR, ID_AC, ID_BR, ID_PA, ID_GD, ID_LS) || \
- ELEM(GS((_id)->name), ID_SCR, ID_WM, ID_TXT)) /* Only in 'blendfile' mode ... :/ */
+ ELEM(GS((_id)->name), ID_SCR, ID_WM, ID_TXT, ID_VF)) /* Only in 'blendfile' mode ... :/ */
/* TreeElement->flag */
#define TE_ACTIVE 1
@@ -68,47 +68,6 @@ typedef struct TreeElement {
#define TE_LAZY_CLOSED 4
#define TE_FREE_NAME 8
-/* TreeStoreElem types */
-#define TSE_NLA 1
-#define TSE_NLA_ACTION 2
-#define TSE_DEFGROUP_BASE 3
-#define TSE_DEFGROUP 4
-#define TSE_BONE 5
-#define TSE_EBONE 6
-#define TSE_CONSTRAINT_BASE 7
-#define TSE_CONSTRAINT 8
-#define TSE_MODIFIER_BASE 9
-#define TSE_MODIFIER 10
-#define TSE_LINKED_OB 11
-// #define TSE_SCRIPT_BASE 12 // UNUSED
-#define TSE_POSE_BASE 13
-#define TSE_POSE_CHANNEL 14
-#define TSE_ANIM_DATA 15
-#define TSE_DRIVER_BASE 16
-#define TSE_DRIVER 17
-
-#define TSE_PROXY 18
-#define TSE_R_LAYER_BASE 19
-#define TSE_R_LAYER 20
-#define TSE_R_PASS 21
-#define TSE_LINKED_MAT 22
-/* NOTE, is used for light group */
-#define TSE_LINKED_LAMP 23
-#define TSE_POSEGRP_BASE 24
-#define TSE_POSEGRP 25
-#define TSE_SEQUENCE 26
-#define TSE_SEQ_STRIP 27
-#define TSE_SEQUENCE_DUP 28
-#define TSE_LINKED_PSYS 29
-#define TSE_RNA_STRUCT 30
-#define TSE_RNA_PROPERTY 31
-#define TSE_RNA_ARRAY_ELEM 32
-#define TSE_NLA_TRACK 33
-#define TSE_KEYMAP 34
-#define TSE_KEYMAP_ITEM 35
-#define TSE_ID_BASE 36
-#define TSE_GP_LAYER 37
-
/* button events */
#define OL_NAMEBUTTON 1
diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c
index ba07572a8b0..17d2208d4f8 100644
--- a/source/blender/editors/space_sequencer/sequencer_draw.c
+++ b/source/blender/editors/space_sequencer/sequencer_draw.c
@@ -198,7 +198,7 @@ static void drawseqwave(const bContext *C, SpaceSeq *sseq, Scene *scene, Sequenc
float yscale = (y2 - y1) / 2;
float samplestep;
float startsample, endsample;
- float value;
+ float value1, value2;
bSound *sound = seq->sound;
SoundWaveform *waveform;
@@ -238,35 +238,37 @@ static void drawseqwave(const bContext *C, SpaceSeq *sseq, Scene *scene, Sequenc
if (length > floor((waveform->length - startsample) / samplestep))
length = floor((waveform->length - startsample) / samplestep);
- glBegin(GL_LINE_STRIP);
+ glColor4f(1.0f, 1.0f, 1.0f, 0.5);
+ glEnable(GL_BLEND);
+ glBegin(GL_TRIANGLE_STRIP);
for (i = 0; i < length; i++) {
- pos = startsample + i * samplestep;
-
- value = waveform->data[pos * 3];
-
- for (j = pos + 1; (j < waveform->length) && (j < pos + samplestep); j++) {
- if (value > waveform->data[j * 3])
- value = waveform->data[j * 3];
- }
-
- glVertex2f(x1 + i * stepsize, ymid + value * yscale);
- }
- glEnd();
+ float sampleoffset = startsample + i * samplestep;
+ pos = sampleoffset;
- glBegin(GL_LINE_STRIP);
- for (i = 0; i < length; i++) {
- pos = startsample + i * samplestep;
+ value1 = waveform->data[pos * 3];
+ value2 = waveform->data[pos * 3 + 1];
- value = waveform->data[pos * 3 + 1];
+ if (samplestep > 1.0f) {
+ for (j = pos + 1; (j < waveform->length) && (j < pos + samplestep); j++) {
+ if (value1 > waveform->data[j * 3])
+ value1 = waveform->data[j * 3];
- for (j = pos + 1; (j < waveform->length) && (j < pos + samplestep); j++) {
- if (value < waveform->data[j * 3 + 1])
- value = waveform->data[j * 3 + 1];
+ if (value2 < waveform->data[j * 3 + 1])
+ value2 = waveform->data[j * 3 + 1];
+ }
+ }
+ else {
+ /* use simple linear interpolation */
+ float f = sampleoffset - pos;
+ value1 = (1.0f - f) * value1 + f * waveform->data[pos * 3 + 3];
+ value2 = (1.0f - f) * value2 + f * waveform->data[pos * 3 + 4];
}
- glVertex2f(x1 + i * stepsize, ymid + value * yscale);
+ glVertex2f(x1 + i * stepsize, ymid + value1 * yscale);
+ glVertex2f(x1 + i * stepsize, ymid + value2 * yscale);
}
glEnd();
+ glDisable(GL_BLEND);
}
}
@@ -1347,7 +1349,7 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
IMB_freeImBuf(ibuf);
if (draw_metadata) {
- ED_region_image_metadata_draw(0.0, 0.0, ibuf, v2d->tot, 1.0, 1.0);
+ ED_region_image_metadata_draw(0.0, 0.0, ibuf, &v2d->tot, 1.0, 1.0);
}
if (draw_overdrop) {
diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c
index 3cc0276104e..8025994d16c 100644
--- a/source/blender/editors/space_sequencer/sequencer_edit.c
+++ b/source/blender/editors/space_sequencer/sequencer_edit.c
@@ -3859,7 +3859,9 @@ static int sequencer_export_subtitles_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
Sequence *seq = BKE_sequencer_active_get(scene);
+ Sequence *seq_next;
Editing *ed = BKE_sequencer_editing_get(scene, false);
+ ListBase text_seq = {0};
int iter = 0;
FILE *file;
char filepath[FILE_MAX];
@@ -3885,35 +3887,40 @@ static int sequencer_export_subtitles_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- /* time to open and write! */
- file = BLI_fopen(filepath, "w");
-
SEQ_BEGIN(ed, seq)
{
if (seq->type == SEQ_TYPE_TEXT) {
- TextVars *data = seq->effectdata;
- char timecode_str[32];
- double sec;
- int frac;
- int len;
- fprintf(file, "%d\n", iter++);
- sec = FRA2TIME(seq->startdisp);
- frac = 1000 * (sec - floor(sec));
- sec = floor(sec);
- BLI_timecode_string_from_time(timecode_str, sizeof(timecode_str), 1, sec, FPS, USER_TIMECODE_SMPTE_FULL);
- len = strlen(timecode_str);
- timecode_str[len - 3] = 0;
- fprintf(file, "%s,%d", timecode_str, frac);
- sec = FRA2TIME(seq->enddisp);
- BLI_timecode_string_from_time(timecode_str, sizeof(timecode_str), 1, sec, FPS, USER_TIMECODE_SMPTE_FULL);
- len = strlen(timecode_str);
- timecode_str[len - 3] = 0;
- fprintf(file, " --> %s,%d\n", timecode_str, frac);
- fprintf(file, "%s\n\n", data->text);
+ BLI_addtail(&text_seq, MEM_dupallocN(seq));
}
}
SEQ_END
+ if (BLI_listbase_is_empty(&text_seq)) {
+ BKE_report(op->reports, RPT_ERROR, "No subtitles (text strips) to export");
+ return OPERATOR_CANCELLED;
+ }
+
+ BLI_listbase_sort(&text_seq, BKE_sequencer_cmp_time_startdisp);
+
+ /* time to open and write! */
+ file = BLI_fopen(filepath, "w");
+
+ for (seq = text_seq.first; seq; seq = seq_next) {
+ TextVars *data = seq->effectdata;
+ char timecode_str_start[32];
+ char timecode_str_end[32];
+
+ BLI_timecode_string_from_time(timecode_str_start, sizeof(timecode_str_start),
+ -2, FRA2TIME(seq->startdisp), FPS, USER_TIMECODE_SUBRIP);
+ BLI_timecode_string_from_time(timecode_str_end, sizeof(timecode_str_end),
+ -2, FRA2TIME(seq->enddisp), FPS, USER_TIMECODE_SUBRIP);
+
+ fprintf(file, "%d\n%s --> %s\n%s\n\n", iter++, timecode_str_start, timecode_str_end, data->text);
+
+ seq_next = seq->next;
+ MEM_freeN(seq);
+ }
+
fclose(file);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c
index a2fae2d5667..948293d150b 100644
--- a/source/blender/editors/space_text/text_ops.c
+++ b/source/blender/editors/space_text/text_ops.c
@@ -1054,108 +1054,102 @@ static int text_convert_whitespace_exec(bContext *C, wmOperator *op)
Text *text = CTX_data_edit_text(C);
TextLine *tmp;
FlattenString fs;
- size_t a, j;
- char *new_line;
- int extra, number; //unknown for now
+ size_t a, j, max_len = 0;
int type = RNA_enum_get(op->ptr, "type");
/* first convert to all space, this make it a lot easier to convert to tabs
* because there is no mixtures of ' ' && '\t' */
for (tmp = text->lines.first; tmp; tmp = tmp->next) {
- const char *text_check_line = tmp->line;
- const int text_check_line_len = tmp->len;
- number = flatten_string(st, &fs, text_check_line) + 1;
+ char *new_line;
+
+ BLI_assert(tmp->line);
+
+ flatten_string(st, &fs, tmp->line);
+ new_line = BLI_strdup(fs.buf);
flatten_string_free(&fs);
- new_line = MEM_callocN(number, "Converted_Line");
- j = 0;
- for (a = 0; a < text_check_line_len; a++) { //foreach char in line
- if (text_check_line[a] == '\t') { //checking for tabs
- //get the number of spaces this tabs is showing
- //i don't like doing it this way but will look into it later
- new_line[j] = '\0';
- number = flatten_string(st, &fs, new_line);
- flatten_string_free(&fs);
- new_line[j] = '\t';
- new_line[j + 1] = '\0';
- number = flatten_string(st, &fs, new_line) - number;
- flatten_string_free(&fs);
- for (extra = 0; extra < number; extra++) {
- new_line[j] = ' ';
- j++;
- }
- }
- else {
- new_line[j] = text_check_line[a];
- j++;
- }
- }
- new_line[j] = '\0';
- // put new_line in the tmp->line spot still need to try and set the curc correctly
- if (tmp->line) MEM_freeN(tmp->line);
- if (tmp->format) MEM_freeN(tmp->format);
+ MEM_freeN(tmp->line);
+ if (tmp->format)
+ MEM_freeN(tmp->format);
+ /* Put new_line in the tmp->line spot still need to try and set the curc correctly. */
tmp->line = new_line;
tmp->len = strlen(new_line);
tmp->format = NULL;
+ if (tmp->len > max_len) {
+ max_len = tmp->len;
+ }
}
- if (type == TO_TABS) { // Converting to tabs
- //start over from the beginning
-
+ if (type == TO_TABS) {
+ char *tmp_line = MEM_mallocN(sizeof(*tmp_line) * (max_len + 1), __func__);
+
for (tmp = text->lines.first; tmp; tmp = tmp->next) {
const char *text_check_line = tmp->line;
const int text_check_line_len = tmp->len;
- extra = 0;
- for (a = 0; a < text_check_line_len; a++) {
- number = 0;
- for (j = 0; j < (size_t)st->tabnumber; j++) {
- if ((a + j) <= text_check_line_len) { //check to make sure we are not pass the end of the line
- if (text_check_line[a + j] != ' ') {
- number = 1;
+ char *tmp_line_cur = tmp_line;
+ const size_t tab_len = st->tabnumber;
+
+ BLI_assert(text_check_line);
+
+ for (a = 0; a < text_check_line_len;) {
+ /* A tab can only start at a position multiple of tab_len... */
+ if (!(a % tab_len) && (text_check_line[a] == ' ')) {
+ /* a + 0 we already know to be ' ' char... */
+ for (j = 1; (j < tab_len) && (a + j < text_check_line_len) && (text_check_line[a + j] == ' '); j++);
+
+ if (j == tab_len) {
+ /* We found a set of spaces that can be replaced by a tab... */
+ if ((tmp_line_cur == tmp_line) && a != 0) {
+ /* Copy all 'valid' string already 'parsed'... */
+ memcpy(tmp_line_cur, text_check_line, a);
+ tmp_line_cur += a;
}
+ *tmp_line_cur = '\t';
+ tmp_line_cur++;
+ a += j;
}
- }
- if (!number) { //found all number of space to equal a tab
- a = a + (st->tabnumber - 1);
- extra = extra + 1;
- }
- }
-
- if (extra > 0) { //got tabs make malloc and do what you have to do
- new_line = MEM_callocN(text_check_line_len - (((st->tabnumber * extra) - extra) - 1), "Converted_Line");
- extra = 0; //reuse vars
- for (a = 0; a < text_check_line_len; a++) {
- number = 0;
- for (j = 0; j < (size_t)st->tabnumber; j++) {
- if ((a + j) <= text_check_line_len) { //check to make sure we are not pass the end of the line
- if (text_check_line[a + j] != ' ') {
- number = 1;
- }
+ else {
+ if (tmp_line_cur != tmp_line) {
+ memcpy(tmp_line_cur, &text_check_line[a], j);
+ tmp_line_cur += j;
}
+ a += j;
}
-
- if (!number) { //found all number of space to equal a tab
- new_line[extra] = '\t';
- a = a + (st->tabnumber - 1);
- extra++;
-
- }
- else { //not adding a tab
- new_line[extra] = text_check_line[a];
- extra++;
+ }
+ else {
+ size_t len = BLI_str_utf8_size_safe(&text_check_line[a]);
+ if (tmp_line_cur != tmp_line) {
+ memcpy(tmp_line_cur, &text_check_line[a], len);
+ tmp_line_cur += len;
}
+ a += len;
}
- new_line[extra] = '\0';
- // put new_line in the tmp->line spot still need to try and set the curc correctly
- if (tmp->line) MEM_freeN(tmp->line);
- if (tmp->format) MEM_freeN(tmp->format);
-
- tmp->line = new_line;
- tmp->len = strlen(new_line);
+ }
+
+ if (tmp_line_cur != tmp_line) {
+ *tmp_line_cur = '\0';
+
+#ifndef NDEBUG
+ BLI_assert(tmp_line_cur - tmp_line <= max_len);
+
+ flatten_string(st, &fs, tmp_line);
+ BLI_assert(STREQ(fs.buf, tmp->line));
+ flatten_string_free(&fs);
+#endif
+
+ MEM_freeN(tmp->line);
+ if (tmp->format)
+ MEM_freeN(tmp->format);
+
+ /* Put new_line in the tmp->line spot still need to try and set the curc correctly. */
+ tmp->line = BLI_strdup(tmp_line);
+ tmp->len = strlen(tmp_line);
tmp->format = NULL;
}
}
+
+ MEM_freeN(tmp_line);
}
text_update_edited(text);
@@ -2375,21 +2369,23 @@ static int flatten_column_to_offset(SpaceText *st, const char *str, int index)
return j;
}
-static TextLine *get_first_visible_line(SpaceText *st, ARegion *ar, int *y)
+static TextLine *get_line_pos_wrapped(SpaceText *st, ARegion *ar, int *y)
{
TextLine *linep = st->text->lines.first;
- int i;
- for (i = st->top; i > 0 && linep; ) {
- int lines = text_get_visible_lines(st, ar, linep->line);
-
- if (i - lines < 0) {
- *y += i;
+ int i, lines;
+
+ if (*y < -st->top) {
+ return NULL; /* We are beyond the first line... */
+ }
+
+ for (i = -st->top; i <= *y && linep; linep = linep->next, i += lines) {
+ lines = text_get_visible_lines(st, ar, linep->line);
+
+ if (i + lines > *y) {
+ /* We found the line matching given vertical 'coordinate', now set y relative to this line's start. */
+ *y -= i;
break;
}
- else {
- linep = linep->next;
- i -= lines;
- }
}
return linep;
}
@@ -2399,23 +2395,22 @@ static void text_cursor_set_to_pos_wrapped(SpaceText *st, ARegion *ar, int x, in
Text *text = st->text;
int max = wrap_width(st, ar); /* column */
int charp = -1; /* mem */
- int loop = 1, found = 0; /* flags */
- char ch;
+ bool found = false; /* flags */
- /* Point to first visible line */
- TextLine *linep = get_first_visible_line(st, ar, &y);
-
- while (loop && linep) {
+ /* Point to line matching given y position, if any. */
+ TextLine *linep = get_line_pos_wrapped(st, ar, &y);
+
+ if (linep) {
int i = 0, start = 0, end = max; /* column */
- int j = 0, curs = 0, endj = 0; /* mem */
- int chop = 1; /* flags */
-
- for (; loop; j += BLI_str_utf8_size_safe(linep->line + j)) {
+ int j, curs = 0, endj = 0; /* mem */
+ bool chop = true; /* flags */
+ char ch;
+
+ for (j = 0 ; !found && ((ch = linep->line[j]) != '\0'); j += BLI_str_utf8_size_safe(linep->line + j)) {
int chars;
int columns = BLI_str_utf8_char_width_safe(linep->line + j); /* = 1 for tab */
/* Mimic replacement of tabs */
- ch = linep->line[j];
if (ch == '\t') {
chars = st->tabnumber - i % st->tabnumber;
ch = ' ';
@@ -2428,7 +2423,8 @@ static void text_cursor_set_to_pos_wrapped(SpaceText *st, ARegion *ar, int x, in
/* Gone too far, go back to last wrap point */
if (y < 0) {
charp = endj;
- loop = 0;
+ y = 0;
+ found = true;
break;
/* Exactly at the cursor */
}
@@ -2436,7 +2432,7 @@ static void text_cursor_set_to_pos_wrapped(SpaceText *st, ARegion *ar, int x, in
/* current position could be wrapped to next line */
/* this should be checked when end of current line would be reached */
charp = curs = j;
- found = 1;
+ found = true;
/* Prepare curs for next wrap */
}
else if (i - end <= x && i + columns - end > x) {
@@ -2446,68 +2442,70 @@ static void text_cursor_set_to_pos_wrapped(SpaceText *st, ARegion *ar, int x, in
end = MIN2(end, i);
if (found) {
- /* exact cursor position was found, check if it's */
- /* still on needed line (hasn't been wrapped) */
- if (charp > endj && !chop && ch != '\0') charp = endj;
- loop = 0;
+ /* exact cursor position was found, check if it's still on needed line (hasn't been wrapped) */
+ if (charp > endj && !chop && ch != '\0')
+ charp = endj;
break;
}
- if (chop) endj = j;
+ if (chop)
+ endj = j;
start = end;
end += max;
if (j < linep->len)
y--;
- chop = 1;
+ chop = true;
if (y == 0 && i + columns - start > x) {
charp = curs;
- loop = 0;
+ found = true;
break;
}
}
else if (ch == ' ' || ch == '-' || ch == '\0') {
if (found) {
- loop = 0;
break;
}
if (y == 0 && i + columns - start > x) {
charp = curs;
- loop = 0;
+ found = true;
break;
}
end = i + 1;
endj = j;
- chop = 0;
+ chop = false;
}
i += columns;
}
-
- if (ch == '\0') break;
- }
-
- if (!loop || found) break;
-
- if (!linep->next) {
- charp = linep->len;
- break;
}
+
+ BLI_assert(y == 0);
- /* On correct line but didn't meet cursor, must be at end */
- if (y == 0) {
+ if (!found) {
+ /* On correct line but didn't meet cursor, must be at end */
charp = linep->len;
- break;
}
- linep = linep->next;
-
- y--;
+ }
+ else if (y < 0) { /* Before start of text. */
+ linep = st->text->lines.first;
+ charp = 0;
+ }
+ else { /* Beyond end of text */
+ linep = st->text->lines.last;
+ charp = linep->len;
}
- if (linep && charp != -1) {
- if (sel) { text->sell = linep; text->selc = charp; }
- else { text->curl = linep; text->curc = charp; }
+ BLI_assert(linep && charp != -1);
+
+ if (sel) {
+ text->sell = linep;
+ text->selc = charp;
+ }
+ else {
+ text->curl = linep;
+ text->curc = charp;
}
}
diff --git a/source/blender/editors/space_view3d/CMakeLists.txt b/source/blender/editors/space_view3d/CMakeLists.txt
index 181a0adfd28..059b384a9e2 100644
--- a/source/blender/editors/space_view3d/CMakeLists.txt
+++ b/source/blender/editors/space_view3d/CMakeLists.txt
@@ -90,4 +90,8 @@ if(WITH_FREESTYLE)
add_definitions(-DWITH_FREESTYLE)
endif()
+if(WITH_LEGACY_DEPSGRAPH)
+ add_definitions(-DWITH_LEGACY_DEPSGRAPH)
+endif()
+
blender_add_lib(bf_editor_space_view3d "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/editors/space_view3d/SConscript b/source/blender/editors/space_view3d/SConscript
index 6e4e47e22a4..7fdccce1c0e 100644
--- a/source/blender/editors/space_view3d/SConscript
+++ b/source/blender/editors/space_view3d/SConscript
@@ -68,4 +68,7 @@ if env['WITH_BF_INTERNATIONAL']:
if env['WITH_BF_FREESTYLE']:
defs.append('WITH_FREESTYLE')
+if env['WITH_BF_LEGACY_DEPSGRAPH']:
+ defs.append('WITH_LEGACY_DEPSGRAPH')
+
env.BlenderLib ( 'bf_editors_space_view3d', sources, incs, defines = defs, libtype=['core'], priority=[40] )
diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c
index fc7c5c897d8..02a53521a46 100644
--- a/source/blender/editors/space_view3d/drawarmature.c
+++ b/source/blender/editors/space_view3d/drawarmature.c
@@ -1547,7 +1547,7 @@ static void draw_pose_dofs(Object *ob)
glPushMatrix();
copy_v3_v3(posetrans, pchan->pose_mat[3]);
- glTranslatef(posetrans[0], posetrans[1], posetrans[2]);
+ glTranslate3fv(posetrans);
if (pchan->parent) {
copy_m4_m4(mat, pchan->parent->pose_mat);
@@ -1780,7 +1780,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
}
draw_custom_bone(scene, v3d, rv3d, pchan->custom,
- OB_SOLID, arm->flag, flag, index, bone->length);
+ OB_SOLID, arm->flag, flag, index, PCHAN_CUSTOM_DRAW_SIZE(pchan));
}
}
else {
@@ -1871,7 +1871,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
flag |= BONE_DRAW_ACTIVE;
draw_custom_bone(scene, v3d, rv3d, pchan->custom,
- OB_WIRE, arm->flag, flag, index, bone->length);
+ OB_WIRE, arm->flag, flag, index, PCHAN_CUSTOM_DRAW_SIZE(pchan));
glPopMatrix();
}
diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c
index d806dfa015a..68e536662d6 100644
--- a/source/blender/editors/space_view3d/drawmesh.c
+++ b/source/blender/editors/space_view3d/drawmesh.c
@@ -664,7 +664,7 @@ static void update_tface_color_layer(DerivedMesh *dm, bool use_mcol)
else if (ma && (ma->shade_flag & MA_OBCOLOR)) {
int loop_index = mp->loopstart;
for (j = 0; j < mp->totloop; j++, loop_index++) {
- copy_v3_v3_char(&finalCol[loop_index].r, (char *)Gtexdraw.obcol);
+ copy_v3_v3_uchar(&finalCol[loop_index].r, Gtexdraw.obcol);
}
copy_mode = COPY_PREV;
}
@@ -1114,8 +1114,7 @@ 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) ||
- ((ob->mode & OB_MODE_TEXTURE_PAINT) && ELEM(v3d->drawtype, OB_TEXTURE, OB_SOLID)))
+ (BKE_scene_use_new_shading_nodes(scene) == false))
{
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 0747ade18bd..62204eee518 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -830,7 +830,7 @@ void view3d_cached_text_draw_add(const float co[3],
BLI_LINKS_PREPEND(g_v3d_strings[g_v3d_string_level], vos);
copy_v3_v3(vos->vec, co);
- copy_v4_v4_char((char *)vos->col.ub, (const char *)col);
+ copy_v4_v4_uchar(vos->col.ub, col);
vos->xoffs = xoffs;
vos->flag = flag;
vos->str_len = str_len;
@@ -977,7 +977,7 @@ static void drawcube_size(const float size[3])
{
glPushMatrix();
- glScalef(size[0], size[1], size[2]);
+ glScale3fv(size);
glBegin(GL_LINE_STRIP);
@@ -1199,7 +1199,7 @@ static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base,
Object *ob = base->object;
const float pixsize = ED_view3d_pixel_size(rv3d, ob->obmat[3]);
Lamp *la = ob->data;
- float vec[3], lvec[3], vvec[3], circrad, x, y, z;
+ float vec[3], lvec[3], vvec[3], circrad;
float lampsize;
float imat[4][4];
@@ -1316,7 +1316,7 @@ static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base,
mul_v3_v3fl(v2, imat[0], circrad * 2.5f);
/* center */
- glTranslatef(vec[0], vec[1], vec[2]);
+ glTranslate3fv(vec);
setlinestyle(3);
@@ -1346,7 +1346,7 @@ static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base,
/* skip drawing extra info */
}
else if ((la->type == LA_SPOT) || (la->type == LA_YF_PHOTON)) {
-
+ float x, y, z, z_abs;
copy_v3_fl3(lvec, 0.0f, 0.0f, 1.0f);
copy_v3_fl3(vvec, rv3d->persmat[0][2], rv3d->persmat[1][2], rv3d->persmat[2][2]);
mul_transposed_mat3_m4_v3(ob->obmat, vvec);
@@ -1359,46 +1359,75 @@ static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base,
mul_v3_fl(lvec, x);
mul_v3_fl(vvec, x);
- /* draw the angled sides of the cone */
- glBegin(GL_LINE_STRIP);
- glVertex3fv(vvec);
- glVertex3fv(vec);
- glVertex3fv(lvec);
- glEnd();
-
x *= y;
- /* draw the circle/square at the end of the cone */
- glTranslatef(0.0, 0.0, x);
+ z_abs = fabsf(z);
+
if (la->mode & LA_SQUARE) {
- float tvec[3];
- float z_abs = fabsf(z);
-
- tvec[0] = tvec[1] = z_abs;
- tvec[2] = 0.0;
-
- glBegin(GL_LINE_LOOP);
- glVertex3fv(tvec);
- tvec[1] = -z_abs; /* neg */
- glVertex3fv(tvec);
- tvec[0] = -z_abs; /* neg */
- glVertex3fv(tvec);
- tvec[1] = z_abs; /* pos */
- glVertex3fv(tvec);
- glEnd();
+ /* draw pyramid */
+ const float vertices[5][3] = {
+ /* 5 of vertex coords of pyramid */
+ {0.0f, 0.0f, 0.0f},
+ {z_abs, z_abs, x},
+ {-z_abs, -z_abs, x},
+ {z_abs, -z_abs, x},
+ {-z_abs, z_abs, x},
+ };
+ const unsigned char indices[] = {
+ 0, 1, 3,
+ 0, 3, 2,
+ 0, 2, 4,
+ 0, 1, 4,
+ };
+
+ /* Draw call:
+ * activate and specify pointer to vertex array */
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glVertexPointer(3, GL_FLOAT, 0, vertices);
+ /* draw the pyramid */
+ glDrawElements(GL_LINE_STRIP, 12, GL_UNSIGNED_BYTE, indices);
+
+ /* deactivate vertex arrays after drawing */
+ glDisableClientState(GL_VERTEX_ARRAY);
+
+ glTranslatef(0.0f, 0.0f, x);
+
+ /* draw the square representing spotbl */
+ if (la->type == LA_SPOT) {
+ float blend = z_abs * (1.0f - pow2f(la->spotblend));
+
+ /* hide line if it is zero size or overlaps with outer border,
+ * previously it adjusted to always to show it but that seems
+ * confusing because it doesn't show the actual blend size */
+ if (blend != 0.0f && blend != z_abs) {
+ fdrawbox(blend, -blend, -blend, blend);
+ }
+ }
}
else {
- circ(0.0, 0.0, fabsf(z));
- }
- /* draw the circle/square representing spotbl */
- if (la->type == LA_SPOT) {
- float spotblcirc = fabsf(z) * (1.0f - pow2f(la->spotblend));
- /* hide line if it is zero size or overlaps with outer border,
- * previously it adjusted to always to show it but that seems
- * confusing because it doesn't show the actual blend size */
- if (spotblcirc != 0 && spotblcirc != fabsf(z))
- circ(0.0, 0.0, spotblcirc);
+ /* draw the angled sides of the cone */
+ glBegin(GL_LINE_STRIP);
+ glVertex3fv(vvec);
+ glVertex3fv(vec);
+ glVertex3fv(lvec);
+ glEnd();
+
+ /* draw the circle at the end of the cone */
+ glTranslatef(0.0f, 0.0f, x);
+ circ(0.0f, 0.0f, z_abs);
+
+ /* draw the circle representing spotbl */
+ if (la->type == LA_SPOT) {
+ float blend = z_abs * (1.0f - pow2f(la->spotblend));
+
+ /* hide line if it is zero size or overlaps with outer border,
+ * previously it adjusted to always to show it but that seems
+ * confusing because it doesn't show the actual blend size */
+ if (blend != 0.0f && blend != z_abs) {
+ circ(0.0f, 0.0f, blend);
+ }
+ }
}
if (drawcone)
@@ -1660,7 +1689,7 @@ static void draw_viewport_object_reconstruction(Scene *scene, Base *base, View3D
GPU_select_load_id(base->selcol + (tracknr << 16));
glPushMatrix();
- glTranslatef(track->bundle_pos[0], track->bundle_pos[1], track->bundle_pos[2]);
+ glTranslate3fv(track->bundle_pos);
glScalef(v3d->bundle_size / 0.05f / camera_size[0],
v3d->bundle_size / 0.05f / camera_size[1],
v3d->bundle_size / 0.05f / camera_size[2]);
@@ -7185,7 +7214,7 @@ static void draw_bb_quadric(BoundBox *bb, char type, bool around_origin)
glPushMatrix();
if (type == OB_BOUND_SPHERE) {
float scale = MAX3(size[0], size[1], size[2]);
- glTranslatef(cent[0], cent[1], cent[2]);
+ glTranslate3fv(cent);
glScalef(scale, scale, scale);
gluSphere(qobj, 1.0, 8, 5);
}
@@ -7654,7 +7683,10 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
}
}
- if ((md = modifiers_findByType(ob, eModifierType_Smoke)) && (modifier_isEnabled(scene, md, eModifierMode_Realtime))) {
+ if (((base->flag & OB_FROMDUPLI) == 0) &&
+ (md = modifiers_findByType(ob, eModifierType_Smoke)) &&
+ (modifier_isEnabled(scene, md, eModifierMode_Realtime)))
+ {
smd = (SmokeModifierData *)md;
if (smd->domain) {
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index 22090e6cb30..7f038a13fd0 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -1096,6 +1096,7 @@ static void view3d_main_area_listener(bScreen *sc, ScrArea *sa, ARegion *ar, wmN
case ND_SHADING:
case ND_NODES:
{
+#ifdef WITH_LEGACY_DEPSGRAPH
Object *ob = OBACT;
if ((v3d->drawtype == OB_MATERIAL) ||
(ob && (ob->mode == OB_MODE_TEXTURE_PAINT)) ||
@@ -1103,6 +1104,7 @@ static void view3d_main_area_listener(bScreen *sc, ScrArea *sa, ARegion *ar, wmN
(scene->gm.matmode == GAME_MAT_GLSL ||
BKE_scene_use_new_shading_nodes(scene))) ||
!DEG_depsgraph_use_legacy())
+#endif
{
ED_region_tag_redraw(ar);
}
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index e6a73048273..25fa3085596 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -1381,7 +1381,7 @@ static void backdrawview3d(Scene *scene, ARegion *ar, View3D *v3d)
}
if (!rv3d->gpuoffscreen) {
- rv3d->gpuoffscreen = GPU_offscreen_create(w, h, error);
+ rv3d->gpuoffscreen = GPU_offscreen_create(w, h, 0, error);
if (!rv3d->gpuoffscreen)
fprintf(stderr, "Failed to create offscreen selection buffer for multisample: %s\n", error);
@@ -1618,7 +1618,7 @@ exit:
static void view3d_stereo_bgpic_setup(Scene *scene, View3D *v3d, Image *ima, ImageUser *iuser)
{
- if ((ima->flag & IMA_IS_STEREO)) {
+ if (BKE_image_is_stereo(ima)) {
iuser->flag |= IMA_SHOW_STEREO;
if ((scene->r.scemode & R_MULTIVIEW) == 0) {
@@ -1961,15 +1961,13 @@ void ED_view3d_after_add(ListBase *lb, Base *base, const short dflag)
/* disables write in zbuffer and draws it over */
static void view3d_draw_transp(Scene *scene, ARegion *ar, View3D *v3d)
{
- View3DAfter *v3da, *next;
+ View3DAfter *v3da;
glDepthMask(GL_FALSE);
v3d->transp = true;
- for (v3da = v3d->afterdraw_transp.first; v3da; v3da = next) {
- next = v3da->next;
+ while ((v3da = BLI_pophead(&v3d->afterdraw_transp))) {
draw_object(scene, ar, v3d, v3da->base, v3da->dflag);
- BLI_remlink(&v3d->afterdraw_transp, v3da);
MEM_freeN(v3da);
}
v3d->transp = false;
@@ -1981,7 +1979,7 @@ static void view3d_draw_transp(Scene *scene, ARegion *ar, View3D *v3d)
/* clears zbuffer and draws it over */
static void view3d_draw_xray(Scene *scene, ARegion *ar, View3D *v3d, bool *clear)
{
- View3DAfter *v3da, *next;
+ View3DAfter *v3da;
if (*clear && v3d->zbuf) {
glClear(GL_DEPTH_BUFFER_BIT);
@@ -1989,10 +1987,8 @@ static void view3d_draw_xray(Scene *scene, ARegion *ar, View3D *v3d, bool *clear
}
v3d->xray = true;
- for (v3da = v3d->afterdraw_xray.first; v3da; v3da = next) {
- next = v3da->next;
+ while ((v3da = BLI_pophead(&v3d->afterdraw_xray))) {
draw_object(scene, ar, v3d, v3da->base, v3da->dflag);
- BLI_remlink(&v3d->afterdraw_xray, v3da);
MEM_freeN(v3da);
}
v3d->xray = false;
@@ -2002,7 +1998,7 @@ static void view3d_draw_xray(Scene *scene, ARegion *ar, View3D *v3d, bool *clear
/* clears zbuffer and draws it over */
static void view3d_draw_xraytransp(Scene *scene, ARegion *ar, View3D *v3d, const bool clear)
{
- View3DAfter *v3da, *next;
+ View3DAfter *v3da;
if (clear && v3d->zbuf)
glClear(GL_DEPTH_BUFFER_BIT);
@@ -2012,10 +2008,8 @@ static void view3d_draw_xraytransp(Scene *scene, ARegion *ar, View3D *v3d, const
glDepthMask(GL_FALSE);
- for (v3da = v3d->afterdraw_xraytransp.first; v3da; v3da = next) {
- next = v3da->next;
+ while ((v3da = BLI_pophead(&v3d->afterdraw_xraytransp))) {
draw_object(scene, ar, v3d, v3da->base, v3da->dflag);
- BLI_remlink(&v3d->afterdraw_xraytransp, v3da);
MEM_freeN(v3da);
}
@@ -2431,7 +2425,7 @@ void ED_view3d_draw_depth(Scene *scene, ARegion *ar, View3D *v3d, bool alphaover
v3d->afterdraw_xray.first ||
v3d->afterdraw_xraytransp.first)
{
- View3DAfter *v3da, *next;
+ View3DAfter *v3da;
int mask_orig;
v3d->xray = true;
@@ -2442,8 +2436,7 @@ void ED_view3d_draw_depth(Scene *scene, ARegion *ar, View3D *v3d, bool alphaover
if (v3d->afterdraw_xray.first || v3d->afterdraw_xraytransp.first) {
glDepthFunc(GL_ALWAYS); /* always write into the depth bufer, overwriting front z values */
- for (v3da = v3d->afterdraw_xray.first; v3da; v3da = next) {
- next = v3da->next;
+ for (v3da = v3d->afterdraw_xray.first; v3da; v3da = v3da->next) {
draw_object(scene, ar, v3d, v3da->base, dflag_depth);
}
glDepthFunc(GL_LEQUAL); /* Now write the depth buffer normally */
@@ -2452,28 +2445,22 @@ void ED_view3d_draw_depth(Scene *scene, ARegion *ar, View3D *v3d, bool alphaover
/* draw 3 passes, transp/xray/xraytransp */
v3d->xray = false;
v3d->transp = true;
- for (v3da = v3d->afterdraw_transp.first; v3da; v3da = next) {
- next = v3da->next;
+ while ((v3da = BLI_pophead(&v3d->afterdraw_transp))) {
draw_object(scene, ar, v3d, v3da->base, dflag_depth);
- BLI_remlink(&v3d->afterdraw_transp, v3da);
MEM_freeN(v3da);
}
v3d->xray = true;
v3d->transp = false;
- for (v3da = v3d->afterdraw_xray.first; v3da; v3da = next) {
- next = v3da->next;
+ while ((v3da = BLI_pophead(&v3d->afterdraw_xray))) {
draw_object(scene, ar, v3d, v3da->base, dflag_depth);
- BLI_remlink(&v3d->afterdraw_xray, v3da);
MEM_freeN(v3da);
}
v3d->xray = true;
v3d->transp = true;
- for (v3da = v3d->afterdraw_xraytransp.first; v3da; v3da = next) {
- next = v3da->next;
+ while ((v3da = BLI_pophead(&v3d->afterdraw_xraytransp))) {
draw_object(scene, ar, v3d, v3da->base, dflag_depth);
- BLI_remlink(&v3d->afterdraw_xraytransp, v3da);
MEM_freeN(v3da);
}
@@ -3153,10 +3140,9 @@ static void view3d_main_area_clear(Scene *scene, View3D *v3d, ARegion *ar)
void ED_view3d_draw_offscreen(
Scene *scene, View3D *v3d, ARegion *ar, int winx, int winy,
float viewmat[4][4], float winmat[4][4],
- bool do_bgpic, bool do_sky, bool is_persp,
- GPUOffScreen *ofs,
+ bool do_bgpic, bool do_sky, bool is_persp, const char *viewname,
GPUFX *fx, GPUFXSettings *fx_settings,
- const char *viewname)
+ GPUOffScreen *ofs)
{
struct bThemeState theme_state;
int bwinx, bwiny;
@@ -3256,26 +3242,37 @@ void ED_view3d_draw_offscreen(
G.f &= ~G_RENDER_OGL;
}
-/* utility func for ED_view3d_draw_offscreen */
-ImBuf *ED_view3d_draw_offscreen_imbuf(Scene *scene, View3D *v3d, ARegion *ar, int sizex, int sizey, unsigned int flag,
- bool draw_background, int alpha_mode, const char *viewname, char err_out[256])
+/**
+ * Utility func for ED_view3d_draw_offscreen
+ *
+ * \param ofs: Optional off-screen buffer, can be NULL.
+ * (avoids re-creating when doing multiple GL renders).
+ */
+ImBuf *ED_view3d_draw_offscreen_imbuf(
+ Scene *scene, View3D *v3d, ARegion *ar, int sizex, int sizey,
+ unsigned int flag, bool draw_background,
+ int alpha_mode, int samples, const char *viewname,
+ /* output vars */
+ GPUOffScreen *ofs, char err_out[256])
{
RegionView3D *rv3d = ar->regiondata;
ImBuf *ibuf;
- GPUOffScreen *ofs;
- bool draw_sky = (alpha_mode == R_ADDSKY) && v3d && (v3d->flag3 & V3D_SHOW_WORLD);
+ const bool draw_sky = (alpha_mode == R_ADDSKY) && v3d && (v3d->flag3 & V3D_SHOW_WORLD);
+ const bool own_ofs = (ofs == NULL);
if (UNLIKELY(v3d == NULL))
return NULL;
- /* state changes make normal drawing go weird otherwise */
- glPushAttrib(GL_LIGHTING_BIT);
+ if (own_ofs) {
+ /* state changes make normal drawing go weird otherwise */
+ glPushAttrib(GL_LIGHTING_BIT);
- /* bind */
- ofs = GPU_offscreen_create(sizex, sizey, err_out);
- if (ofs == NULL) {
- glPopAttrib();
- return NULL;
+ /* bind */
+ ofs = GPU_offscreen_create(sizex, sizey, samples, err_out);
+ if (ofs == NULL) {
+ glPopAttrib();
+ return NULL;
+ }
}
ED_view3d_draw_offscreen_init(scene, v3d);
@@ -3301,14 +3298,15 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Scene *scene, View3D *v3d, ARegion *ar, in
ED_view3d_draw_offscreen(
scene, v3d, ar, sizex, sizey, NULL, params.winmat,
- draw_background, draw_sky, !params.is_ortho,
- ofs, NULL, &fx_settings, viewname);
+ draw_background, draw_sky, !params.is_ortho, viewname,
+ NULL, &fx_settings,
+ ofs);
}
else {
ED_view3d_draw_offscreen(
scene, v3d, ar, sizex, sizey, NULL, NULL,
- draw_background, draw_sky, true,
- ofs, NULL, NULL, viewname);
+ draw_background, draw_sky, true, viewname,
+ NULL, NULL, ofs);
}
/* read in pixels & stamp */
@@ -3321,9 +3319,12 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Scene *scene, View3D *v3d, ARegion *ar, in
/* unbind */
GPU_offscreen_unbind(ofs, true);
- GPU_offscreen_free(ofs);
- glPopAttrib();
+ if (own_ofs) {
+ GPU_offscreen_free(ofs);
+
+ glPopAttrib();
+ }
if (ibuf->rect_float && ibuf->rect)
IMB_rect_from_float(ibuf);
@@ -3331,10 +3332,19 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Scene *scene, View3D *v3d, ARegion *ar, in
return ibuf;
}
-/* creates own 3d views, used by the sequencer */
-ImBuf *ED_view3d_draw_offscreen_imbuf_simple(Scene *scene, Object *camera, int width, int height, unsigned int flag, int drawtype,
- bool use_solid_tex, bool use_gpencil, bool draw_background, int alpha_mode,
- const char *viewname, char err_out[256])
+/**
+ * Creates own fake 3d views (wrapping #ED_view3d_draw_offscreen_imbuf)
+ *
+ * \param ofs: Optional off-screen buffer can be NULL.
+ * (avoids re-creating when doing multiple GL renders).
+ *
+ * \note used by the sequencer
+ */
+ImBuf *ED_view3d_draw_offscreen_imbuf_simple(
+ Scene *scene, Object *camera, int width, int height,
+ unsigned int flag, int drawtype, bool use_solid_tex, bool use_gpencil, bool draw_background,
+ int alpha_mode, int samples, const char *viewname,
+ GPUOffScreen *ofs, char err_out[256])
{
View3D v3d = {NULL};
ARegion ar = {NULL};
@@ -3381,8 +3391,10 @@ ImBuf *ED_view3d_draw_offscreen_imbuf_simple(Scene *scene, Object *camera, int w
mul_m4_m4m4(rv3d.persmat, rv3d.winmat, rv3d.viewmat);
invert_m4_m4(rv3d.persinv, rv3d.viewinv);
- return ED_view3d_draw_offscreen_imbuf(scene, &v3d, &ar, width, height, flag,
- draw_background, alpha_mode, viewname, err_out);
+ return ED_view3d_draw_offscreen_imbuf(
+ scene, &v3d, &ar, width, height, flag,
+ draw_background, alpha_mode, samples, viewname,
+ ofs, err_out);
// seq_view3d_cb(scene, cfra, render_size, seqrectx, seqrecty);
}
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index 9a4cd3f248e..b774b2e192d 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -44,6 +44,7 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
+#include "BKE_armature.h"
#include "BKE_camera.h"
#include "BKE_context.h"
#include "BKE_font.h"
@@ -557,7 +558,7 @@ typedef struct ViewOpsData {
} ViewOpsData;
-#define TRACKBALLSIZE (1.1)
+#define TRACKBALLSIZE (1.1f)
static void calctrackballvec(const rcti *rect, int mx, int my, float vec[3])
{
@@ -1027,31 +1028,25 @@ static void viewrotate_apply(ViewOpsData *vod, int x, int y)
rv3d->view = RV3D_VIEW_USER; /* need to reset every time because of view snapping */
if (U.flag & USER_TRACKBALL) {
- float phi, si, q1[4], dvec[3], newvec[3];
+ float axis[3], q1[4], dvec[3], newvec[3];
+ float angle;
calctrackballvec(&vod->ar->winrct, x, y, newvec);
sub_v3_v3v3(dvec, newvec, vod->trackvec);
- si = len_v3(dvec);
- si /= (float)(2.0 * TRACKBALLSIZE);
-
- cross_v3_v3v3(q1 + 1, vod->trackvec, newvec);
- normalize_v3(q1 + 1);
+ angle = (len_v3(dvec) / (2.0f * TRACKBALLSIZE)) * (float)M_PI;
/* Allow for rotation beyond the interval [-pi, pi] */
- while (si > 1.0f)
- si -= 2.0f;
-
- /* This relation is used instead of
- * - phi = asin(si) so that the angle
- * - of rotation is linearly proportional
- * - to the distance that the mouse is
- * - dragged. */
- phi = si * (float)M_PI_2;
-
- q1[0] = cosf(phi);
- mul_v3_fl(q1 + 1, sinf(phi));
+ angle = angle_wrap_rad(angle);
+
+ /* This relation is used instead of the actual angle between vectors
+ * so that the angle of rotation is linearly proportional to
+ * the distance that the mouse is dragged. */
+
+ cross_v3_v3v3(axis, vod->trackvec, newvec);
+ axis_angle_to_quat(q1, axis, angle);
+
mul_qt_qtqt(vod->viewquat, q1, vod->oldquat);
viewrotate_apply_dyn_ofs(vod, vod->viewquat);
@@ -1475,8 +1470,7 @@ static void view3d_ndof_orbit(const struct wmNDOFMotionData *ndof, ScrArea *sa,
/* Perform the up/down rotation */
angle = ndof->dt * rot[0];
- quat[0] = cosf(angle);
- mul_v3_v3fl(quat + 1, xvec, sinf(angle));
+ axis_angle_to_quat(quat, xvec, angle * 2);
mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, quat);
/* Perform the orbital rotation */
@@ -3042,24 +3036,7 @@ static int viewselected_exec(bContext *C, wmOperator *op)
ok = ED_view3d_minmax_verts(obedit, min, max); /* only selected */
}
else if (ob && (ob->mode & OB_MODE_POSE)) {
- if (ob->pose) {
- bArmature *arm = ob->data;
- bPoseChannel *pchan;
- float vec[3];
-
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- if (pchan->bone->flag & BONE_SELECTED) {
- if (pchan->bone->layer & arm->layer) {
- bPoseChannel *pchan_tx = pchan->custom_tx ? pchan->custom_tx : pchan;
- ok = 1;
- mul_v3_m4v3(vec, ob->obmat, pchan_tx->pose_head);
- minmax_v3v3_v3(min, max, vec);
- mul_v3_m4v3(vec, ob->obmat, pchan_tx->pose_tail);
- minmax_v3v3_v3(min, max, vec);
- }
- }
- }
- }
+ ok = BKE_pose_minmax(ob, min, max, true, true);
}
else if (BKE_paint_select_face_test(ob)) {
ok = paintface_minmax(ob, min, max);
@@ -3785,7 +3762,7 @@ static void axis_set_view(bContext *C, View3D *v3d, ARegion *ar,
float twmat[3][3];
/* same as transform manipulator when normal is set */
- ED_getTransformOrientationMatrix(C, twmat, true);
+ ED_getTransformOrientationMatrix(C, twmat, V3D_ACTIVE);
mat3_to_quat(obact_quat, twmat);
invert_qt(obact_quat);
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index 5a35e9fcad1..69e354d87c7 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -1193,7 +1193,10 @@ 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], bool *p_do_nearest, bool enumerate)
+static short mixed_bones_object_selectbuffer(
+ ViewContext *vc, unsigned int *buffer, const int mval[2],
+ bool use_cycle, bool enumerate,
+ bool *r_do_nearest)
{
rcti rect;
int offs;
@@ -1204,16 +1207,24 @@ static short mixed_bones_object_selectbuffer(ViewContext *vc, unsigned int *buff
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;
+ if (use_cycle) {
+ 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);
+ }
+ else {
+ if (v3d->drawtype > OB_WIRE) {
+ do_nearest = true;
}
}
- copy_v2_v2_int(last_mval, mval);
- if (p_do_nearest)
- *p_do_nearest = do_nearest;
+ if (r_do_nearest) {
+ *r_do_nearest = do_nearest;
+ }
do_nearest = do_nearest && !enumerate;
@@ -1353,7 +1364,7 @@ Base *ED_view3d_give_base_under_cursor(bContext *C, const int mval[2])
view3d_operator_needs_opengl(C);
view3d_set_viewcontext(C, &vc);
- hits = mixed_bones_object_selectbuffer(&vc, buffer, mval, &do_nearest, false);
+ hits = mixed_bones_object_selectbuffer(&vc, buffer, mval, false, false, &do_nearest);
if (hits > 0) {
const bool has_bones = selectbuffer_has_bones(buffer, hits);
@@ -1448,7 +1459,7 @@ static bool mouse_select(bContext *C, const int mval[2],
/* if objects have posemode set, the bones are in the same selection buffer */
- hits = mixed_bones_object_selectbuffer(&vc, buffer, mval, &do_nearest, enumerate);
+ hits = mixed_bones_object_selectbuffer(&vc, buffer, mval, true, enumerate, &do_nearest);
if (hits > 0) {
/* note: bundles are handling in the same way as bones */
diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c
index 49ac3881fab..0f05f4e52dd 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -1785,7 +1785,7 @@ float ED_view3d_radius_to_dist(
lens = params.lens;
sensor_size = BKE_camera_sensor_size(params.sensor_fit, params.sensor_x, params.sensor_y);
- /* ignore 'rv3d->camzoom' because we wan't to fit to the cameras frame */
+ /* ignore 'rv3d->camzoom' because we want to fit to the cameras frame */
zoom = CAMERA_PARAM_ZOOM_INIT_CAMOB;
}
else {
diff --git a/source/blender/editors/space_view3d/view3d_walk.c b/source/blender/editors/space_view3d/view3d_walk.c
index e2fbbf58a5c..0bda6e37fd1 100644
--- a/source/blender/editors/space_view3d/view3d_walk.c
+++ b/source/blender/editors/space_view3d/view3d_walk.c
@@ -62,6 +62,9 @@
#define USE_TABLET_SUPPORT
+/* ensure the target position is one we can reach, see: T45771 */
+#define USE_PIXELSIZE_NATIVE_SUPPORT
+
/* prototypes */
static float getVelocityZeroTime(const float gravity, const float velocity);
@@ -578,6 +581,16 @@ static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op)
walk->center_mval[0] = walk->ar->winx * 0.5f;
walk->center_mval[1] = walk->ar->winy * 0.5f;
+#ifdef USE_PIXELSIZE_NATIVE_SUPPORT
+ walk->center_mval[0] += walk->ar->winrct.xmin;
+ walk->center_mval[1] += walk->ar->winrct.ymin;
+
+ WM_cursor_compatible_xy(win, &walk->center_mval[0], &walk->center_mval[1]);
+
+ walk->center_mval[0] -= walk->ar->winrct.xmin;
+ walk->center_mval[1] -= walk->ar->winrct.ymin;
+#endif
+
copy_v2_v2_int(walk->prev_mval, walk->center_mval);
WM_cursor_warp(win,
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index 3f9077421b1..d6ce32f9974 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -168,11 +168,12 @@ static void applyBoneEnvelope(TransInfo *t, const int mval[2]);
static void initBoneRoll(TransInfo *t);
static void applyBoneRoll(TransInfo *t, const int mval[2]);
-static void initEdgeSlide_ex(TransInfo *t, bool use_double_side);
+static void initEdgeSlide_ex(TransInfo *t, bool use_double_side, bool use_even, bool flipped, bool use_clamp);
static void initEdgeSlide(TransInfo *t);
static eRedrawFlag handleEventEdgeSlide(TransInfo *t, const struct wmEvent *event);
static void applyEdgeSlide(TransInfo *t, const int mval[2]);
+static void initVertSlide_ex(TransInfo *t, bool use_even, bool flipped, bool use_clamp);
static void initVertSlide(TransInfo *t);
static eRedrawFlag handleEventVertSlide(TransInfo *t, const struct wmEvent *event);
static void applyVertSlide(TransInfo *t, const int mval[2]);
@@ -1037,6 +1038,7 @@ int transformEvent(TransInfo *t, const wmEvent *event)
}
/* vert slide can fail on unconnected vertices (rare but possible) */
if (t->state == TRANS_CANCEL) {
+ t->mode = TFM_TRANSLATION;
t->state = TRANS_STARTING;
restoreTransObjects(t);
resetTransRestrictions(t);
@@ -1063,15 +1065,14 @@ int transformEvent(TransInfo *t, const wmEvent *event)
/* only switch when... */
if (!(t->options & CTX_TEXTURE) && !(t->options & (CTX_MOVIECLIP | CTX_MASK))) {
if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_TRANSLATION, TFM_EDGE_SLIDE, TFM_VERT_SLIDE)) {
+ restoreTransObjects(t);
resetTransModal(t);
resetTransRestrictions(t);
if (t->mode == TFM_ROTATION) {
- restoreTransObjects(t);
initTrackball(t);
}
else {
- restoreTransObjects(t);
initRotation(t);
}
initSnapping(t, NULL); // need to reinit after mode change
@@ -1363,15 +1364,14 @@ int transformEvent(TransInfo *t, const wmEvent *event)
/* only switch when... */
if (!(t->options & CTX_TEXTURE)) {
if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_TRANSLATION)) {
+ restoreTransObjects(t);
resetTransModal(t);
resetTransRestrictions(t);
if (t->mode == TFM_ROTATION) {
- restoreTransObjects(t);
initTrackball(t);
}
else {
- restoreTransObjects(t);
initRotation(t);
}
initSnapping(t, NULL); // need to reinit after mode change
@@ -1721,7 +1721,7 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata)
glVertex2fv(cent);
glEnd();
- glTranslatef(mval[0], mval[1], 0);
+ glTranslate2iv(mval);
glRotatef(-RAD2DEGF(atan2f(cent[0] - t->mval[0], cent[1] - t->mval[1])), 0, 0, 1);
setlinestyle(0);
@@ -1733,7 +1733,7 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata)
case HLP_HARROW:
UI_ThemeColor(TH_VIEW_OVERLAY);
- glTranslatef(mval[0], mval[1], 0);
+ glTranslate2iv(mval);
glLineWidth(3.0);
drawArrow(RIGHT, 5, 10, 5);
@@ -1743,7 +1743,7 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata)
case HLP_VARROW:
UI_ThemeColor(TH_VIEW_OVERLAY);
- glTranslatef(mval[0], mval[1], 0);
+ glTranslate2iv(mval);
glLineWidth(3.0);
drawArrow(UP, 5, 10, 5);
@@ -1794,7 +1794,7 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata)
unsigned char col[3], col2[3];
UI_GetThemeColor3ubv(TH_GRID, col);
- glTranslatef(mval[0], mval[1], 0);
+ glTranslate2iv(mval);
glLineWidth(3.0);
@@ -2077,47 +2077,41 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
t->launch_event = LEFTMOUSE;
}
+ unit_m3(t->spacemtx);
+
initTransInfo(C, t, op, event);
+ initTransformOrientation(C, t);
if (t->spacetype == SPACE_VIEW3D) {
- initTransformOrientation(C, t);
-
t->draw_handle_apply = ED_region_draw_cb_activate(t->ar->type, drawTransformApply, t, REGION_DRAW_PRE_VIEW);
t->draw_handle_view = ED_region_draw_cb_activate(t->ar->type, drawTransformView, t, REGION_DRAW_POST_VIEW);
t->draw_handle_pixel = ED_region_draw_cb_activate(t->ar->type, drawTransformPixel, t, REGION_DRAW_POST_PIXEL);
t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C), helpline_poll, drawHelpline, t);
}
else if (t->spacetype == SPACE_IMAGE) {
- unit_m3(t->spacemtx);
t->draw_handle_view = ED_region_draw_cb_activate(t->ar->type, drawTransformView, t, REGION_DRAW_POST_VIEW);
//t->draw_handle_pixel = ED_region_draw_cb_activate(t->ar->type, drawTransformPixel, t, REGION_DRAW_POST_PIXEL);
t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C), helpline_poll, drawHelpline, t);
}
else if (t->spacetype == SPACE_CLIP) {
- unit_m3(t->spacemtx);
t->draw_handle_view = ED_region_draw_cb_activate(t->ar->type, drawTransformView, t, REGION_DRAW_POST_VIEW);
t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C), helpline_poll, drawHelpline, t);
}
else if (t->spacetype == SPACE_NODE) {
- unit_m3(t->spacemtx);
/*t->draw_handle_apply = ED_region_draw_cb_activate(t->ar->type, drawTransformApply, t, REGION_DRAW_PRE_VIEW);*/
t->draw_handle_view = ED_region_draw_cb_activate(t->ar->type, drawTransformView, t, REGION_DRAW_POST_VIEW);
t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C), helpline_poll, drawHelpline, t);
}
else if (t->spacetype == SPACE_IPO) {
- unit_m3(t->spacemtx);
t->draw_handle_view = ED_region_draw_cb_activate(t->ar->type, drawTransformView, t, REGION_DRAW_POST_VIEW);
//t->draw_handle_pixel = ED_region_draw_cb_activate(t->ar->type, drawTransformPixel, t, REGION_DRAW_POST_PIXEL);
t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C), helpline_poll, drawHelpline, t);
}
else if (t->spacetype == SPACE_ACTION) {
- unit_m3(t->spacemtx);
t->draw_handle_view = ED_region_draw_cb_activate(t->ar->type, drawTransformView, t, REGION_DRAW_POST_VIEW);
//t->draw_handle_pixel = ED_region_draw_cb_activate(t->ar->type, drawTransformPixel, t, REGION_DRAW_POST_PIXEL);
t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C), helpline_poll, drawHelpline, t);
}
- else
- unit_m3(t->spacemtx);
createTransData(C, t); // make TransData structs from selection
@@ -2234,14 +2228,20 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
t->mode = TFM_BONE_ENVELOPE_DIST;
break;
case TFM_EDGE_SLIDE:
+ case TFM_VERT_SLIDE:
{
- const bool use_double_side = (op ? !RNA_boolean_get(op->ptr, "single_side") : true);
- initEdgeSlide_ex(t, use_double_side);
+ const bool use_even = (op ? RNA_boolean_get(op->ptr, "use_even") : false);
+ const bool flipped = (op ? RNA_boolean_get(op->ptr, "flipped") : false);
+ const bool use_clamp = (op ? RNA_boolean_get(op->ptr, "use_clamp") : true);
+ if (mode == TFM_EDGE_SLIDE) {
+ const bool use_double_side = (op ? !RNA_boolean_get(op->ptr, "single_side") : true);
+ initEdgeSlide_ex(t, use_double_side, use_even, flipped, use_clamp);
+ }
+ else {
+ initVertSlide_ex(t, use_even, flipped, use_clamp);
+ }
break;
}
- case TFM_VERT_SLIDE:
- initVertSlide(t);
- break;
case TFM_BONE_ROLL:
initBoneRoll(t);
break;
@@ -3092,6 +3092,7 @@ static void applyShear(TransInfo *t, const int UNUSED(mval[2]))
float value;
int i;
char str[MAX_INFO_LEN];
+ const bool is_local_center = transdata_check_local_center(t, t->around);
copy_m3_m4(persmat, t->viewmat);
invert_m3_m3(persinv, persmat);
@@ -3127,8 +3128,10 @@ static void applyShear(TransInfo *t, const int UNUSED(mval[2]))
mul_m3_m3m3(tmat, smat, persmat);
mul_m3_m3m3(totmat, persinv, tmat);
-
+
for (i = 0; i < t->total; i++, td++) {
+ const float *center, *co;
+
if (td->flag & TD_NOACTION)
break;
@@ -3143,12 +3146,22 @@ static void applyShear(TransInfo *t, const int UNUSED(mval[2]))
else {
copy_m3_m3(tmat, totmat);
}
- sub_v3_v3v3(vec, td->center, t->center);
+
+ if (is_local_center) {
+ center = td->center;
+ co = td->loc;
+ }
+ else {
+ center = t->center;
+ co = td->center;
+ }
+
+ sub_v3_v3v3(vec, co, center);
mul_m3_v3(tmat, vec);
- add_v3_v3(vec, t->center);
- sub_v3_v3(vec, td->center);
+ add_v3_v3(vec, center);
+ sub_v3_v3(vec, co);
mul_v3_fl(vec, td->factor);
@@ -5967,7 +5980,7 @@ static void calcEdgeSlide_mval_range(
}
}
-static void calcEdgeSlide_non_proportional(
+static void calcEdgeSlide_even(
TransInfo *t, EdgeSlideData *sld, const float mval[2])
{
TransDataEdgeSlideVert *sv = sld->sv;
@@ -6013,7 +6026,7 @@ static void calcEdgeSlide_non_proportional(
}
}
-static bool createEdgeSlideVerts_double_side(TransInfo *t)
+static bool createEdgeSlideVerts_double_side(TransInfo *t, bool use_even, bool flipped, bool use_clamp)
{
BMEditMesh *em = BKE_editmesh_from_object(t->obedit);
BMesh *bm = em->bm;
@@ -6032,9 +6045,11 @@ static bool createEdgeSlideVerts_double_side(TransInfo *t)
slide_origdata_init_flag(t, &sld->orig_data);
- sld->is_proportional = true;
+ sld->use_even = use_even;
sld->curr_sv_index = 0;
- sld->flipped_vtx = false;
+ sld->flipped = flipped;
+ if (!use_clamp)
+ t->flag |= T_ALT_TRANSFORM;
/*ensure valid selection*/
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
@@ -6340,7 +6355,7 @@ static bool createEdgeSlideVerts_double_side(TransInfo *t)
slide_origdata_create_data(t, &sld->orig_data, (TransDataGenericSlideVert *)sld->sv, sizeof(*sld->sv), sld->totsv);
if (rv3d) {
- calcEdgeSlide_non_proportional(t, sld, mval);
+ calcEdgeSlide_even(t, sld, mval);
}
sld->em = em;
@@ -6358,7 +6373,7 @@ static bool createEdgeSlideVerts_double_side(TransInfo *t)
* A simple version of #createEdgeSlideVerts_double_side
* Which assumes the longest unselected.
*/
-static bool createEdgeSlideVerts_single_side(TransInfo *t)
+static bool createEdgeSlideVerts_single_side(TransInfo *t, bool use_even, bool flipped, bool use_clamp)
{
BMEditMesh *em = BKE_editmesh_from_object(t->obedit);
BMesh *bm = em->bm;
@@ -6383,10 +6398,12 @@ static bool createEdgeSlideVerts_single_side(TransInfo *t)
slide_origdata_init_flag(t, &sld->orig_data);
- sld->is_proportional = true;
+ sld->use_even = use_even;
sld->curr_sv_index = 0;
- /* heppans to be best for single-sided */
- sld->flipped_vtx = true;
+ /* happens to be best for single-sided */
+ sld->flipped = !flipped;
+ if (!use_clamp)
+ t->flag |= T_ALT_TRANSFORM;
/* ensure valid selection */
j = 0;
@@ -6532,7 +6549,7 @@ static bool createEdgeSlideVerts_single_side(TransInfo *t)
slide_origdata_create_data(t, &sld->orig_data, (TransDataGenericSlideVert *)sld->sv, sizeof(*sld->sv), sld->totsv);
if (rv3d) {
- calcEdgeSlide_non_proportional(t, sld, mval);
+ calcEdgeSlide_even(t, sld, mval);
}
sld->em = em;
@@ -6580,7 +6597,7 @@ void freeEdgeSlideVerts(TransInfo *t)
t->customData = NULL;
}
-static void initEdgeSlide_ex(TransInfo *t, bool use_double_side)
+static void initEdgeSlide_ex(TransInfo *t, bool use_double_side, bool use_even, bool flipped, bool use_clamp)
{
EdgeSlideData *sld;
bool ok;
@@ -6590,10 +6607,10 @@ static void initEdgeSlide_ex(TransInfo *t, bool use_double_side)
t->handleEvent = handleEventEdgeSlide;
if (use_double_side) {
- ok = createEdgeSlideVerts_double_side(t);
+ ok = createEdgeSlideVerts_double_side(t, use_even, flipped, use_clamp);
}
else {
- ok = createEdgeSlideVerts_single_side(t);
+ ok = createEdgeSlideVerts_single_side(t, use_even, flipped, use_clamp);
}
if (!ok) {
@@ -6627,7 +6644,7 @@ static void initEdgeSlide_ex(TransInfo *t, bool use_double_side)
static void initEdgeSlide(TransInfo *t)
{
- initEdgeSlide_ex(t, true);
+ initEdgeSlide_ex(t, true, false, false, true);
}
static eRedrawFlag handleEventEdgeSlide(struct TransInfo *t, const struct wmEvent *event)
@@ -6639,16 +6656,14 @@ static eRedrawFlag handleEventEdgeSlide(struct TransInfo *t, const struct wmEven
switch (event->type) {
case EKEY:
if (event->val == KM_PRESS) {
- sld->is_proportional = !sld->is_proportional;
+ sld->use_even = !sld->use_even;
calcEdgeSlideCustomPoints(t);
return TREDRAW_HARD;
}
break;
case FKEY:
if (event->val == KM_PRESS) {
- if (sld->is_proportional == false) {
- sld->flipped_vtx = !sld->flipped_vtx;
- }
+ sld->flipped = !sld->flipped;
calcEdgeSlideCustomPoints(t);
return TREDRAW_HARD;
}
@@ -6688,8 +6703,8 @@ static void drawEdgeSlide(TransInfo *t)
EdgeSlideData *sld = t->customData;
const bool is_clamp = !(t->flag & T_ALT_TRANSFORM);
- /* Non-Prop mode */
- if ((sld->is_proportional == false) || (is_clamp == false)) {
+ /* Even mode */
+ if ((sld->use_even == true) || (is_clamp == false)) {
View3D *v3d = t->view;
const float line_size = UI_GetThemeValuef(TH_OUTLINE_WIDTH) + 0.5f;
@@ -6704,7 +6719,7 @@ static void drawEdgeSlide(TransInfo *t)
glMultMatrixf(t->obedit->obmat);
- if (sld->is_proportional == false) {
+ if (sld->use_even == true) {
float co_a[3], co_b[3], co_mark[3];
TransDataEdgeSlideVert *curr_sv = &sld->sv[sld->curr_sv_index];
const float fac = (sld->perc + 1.0f) / 2.0f;
@@ -6731,7 +6746,7 @@ static void drawEdgeSlide(TransInfo *t)
UI_ThemeColorShadeAlpha(TH_SELECT, -30, alpha_shade);
glPointSize(ctrl_size);
bglBegin(GL_POINTS);
- if (sld->flipped_vtx) {
+ if (sld->flipped) {
if (curr_sv->v_side[1]) bglVertex3fv(curr_sv->v_side[1]->co);
}
else {
@@ -6807,7 +6822,7 @@ static void doEdgeSlide(TransInfo *t, float perc)
sld->perc = perc;
sv = svlist;
- if (sld->is_proportional == true) {
+ if (sld->use_even == false) {
const bool is_clamp = !(t->flag & T_ALT_TRANSFORM);
if (is_clamp) {
const int side_index = (perc < 0.0f);
@@ -6837,7 +6852,7 @@ static void doEdgeSlide(TransInfo *t, float perc)
}
else {
/**
- * Implementation note, non proportional mode ignores the starting positions and uses only the
+ * Implementation note, even mode ignores the starting positions and uses only the
* a/b verts, this could be changed/improved so the distance is still met but the verts are moved along
* their original path (which may not be straight), however how it works now is OK and matches 2.4x - Campbell
*
@@ -6845,7 +6860,7 @@ static void doEdgeSlide(TransInfo *t, float perc)
* is the same as the distance between the original vert locations, same goes for the lines below.
*/
TransDataEdgeSlideVert *curr_sv = &sld->sv[sld->curr_sv_index];
- const float curr_length_perc = curr_sv->edge_len * (((sld->flipped_vtx ? perc : -perc) + 1.0f) / 2.0f);
+ const float curr_length_perc = curr_sv->edge_len * (((sld->flipped ? perc : -perc) + 1.0f) / 2.0f);
float co_a[3];
float co_b[3];
@@ -6857,7 +6872,7 @@ static void doEdgeSlide(TransInfo *t, float perc)
add_v3_v3v3(co_a, sv->v_co_orig, sv->dir_side[0]);
add_v3_v3v3(co_b, sv->v_co_orig, sv->dir_side[1]);
- if (sld->flipped_vtx) {
+ if (sld->flipped) {
interp_line_v3_v3v3v3(sv->v->co, co_b, sv->v_co_orig, co_a, fac);
}
else {
@@ -6874,8 +6889,8 @@ static void applyEdgeSlide(TransInfo *t, const int UNUSED(mval[2]))
size_t ofs = 0;
float final;
EdgeSlideData *sld = t->customData;
- bool flipped = sld->flipped_vtx;
- bool is_proportional = sld->is_proportional;
+ bool flipped = sld->flipped;
+ bool use_even = sld->use_even;
const bool is_clamp = !(t->flag & T_ALT_TRANSFORM);
const bool is_constrained = !(is_clamp == false || hasNumInput(&t->num));
@@ -6902,8 +6917,8 @@ static void applyEdgeSlide(TransInfo *t, const int UNUSED(mval[2]))
else {
ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, "%.4f ", final);
}
- ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("(E)ven: %s, "), WM_bool_as_string(!is_proportional));
- if (!is_proportional) {
+ ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("(E)ven: %s, "), WM_bool_as_string(use_even));
+ if (use_even) {
ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("(F)lipped: %s, "), WM_bool_as_string(flipped));
}
ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("Alt or (C)lamp: %s"), WM_bool_as_string(is_clamp));
@@ -6944,7 +6959,7 @@ static void calcVertSlideCustomPoints(struct TransInfo *t)
ARRAY_SET_ITEMS(mval_start, co_orig_2d[0] + mval_ofs[0], co_orig_2d[1] + mval_ofs[1]);
ARRAY_SET_ITEMS(mval_end, co_curr_2d[0] + mval_ofs[0], co_curr_2d[1] + mval_ofs[1]);
- if (sld->flipped_vtx && sld->is_proportional == false) {
+ if (sld->flipped && sld->use_even) {
setCustomPoints(t, &t->mouse, mval_start, mval_end);
}
else {
@@ -7035,7 +7050,7 @@ static void calcVertSlideMouseActiveEdges(struct TransInfo *t, const int mval[2]
}
}
-static bool createVertSlideVerts(TransInfo *t)
+static bool createVertSlideVerts(TransInfo *t, bool use_even, bool flipped, bool use_clamp)
{
BMEditMesh *em = BKE_editmesh_from_object(t->obedit);
BMesh *bm = em->bm;
@@ -7049,9 +7064,11 @@ static bool createVertSlideVerts(TransInfo *t)
slide_origdata_init_flag(t, &sld->orig_data);
- sld->is_proportional = true;
+ sld->use_even = use_even;
sld->curr_sv_index = 0;
- sld->flipped_vtx = false;
+ sld->flipped = flipped;
+ if (!use_clamp)
+ t->flag |= T_ALT_TRANSFORM;
j = 0;
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
@@ -7185,7 +7202,7 @@ void freeVertSlideVerts(TransInfo *t)
t->customData = NULL;
}
-static void initVertSlide(TransInfo *t)
+static void initVertSlide_ex(TransInfo *t, bool use_even, bool flipped, bool use_clamp)
{
VertSlideData *sld;
@@ -7193,7 +7210,7 @@ static void initVertSlide(TransInfo *t)
t->transform = applyVertSlide;
t->handleEvent = handleEventVertSlide;
- if (!createVertSlideVerts(t)) {
+ if (!createVertSlideVerts(t, use_even, flipped, use_clamp)) {
t->state = TRANS_CANCEL;
return;
}
@@ -7222,6 +7239,11 @@ static void initVertSlide(TransInfo *t)
t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT;
}
+static void initVertSlide(TransInfo *t)
+{
+ initVertSlide_ex(t, false, false, true);
+}
+
static eRedrawFlag handleEventVertSlide(struct TransInfo *t, const struct wmEvent *event)
{
if (t->mode == TFM_VERT_SLIDE) {
@@ -7231,8 +7253,8 @@ static eRedrawFlag handleEventVertSlide(struct TransInfo *t, const struct wmEven
switch (event->type) {
case EKEY:
if (event->val == KM_PRESS) {
- sld->is_proportional = !sld->is_proportional;
- if (sld->flipped_vtx) {
+ sld->use_even = !sld->use_even;
+ if (sld->flipped) {
calcVertSlideCustomPoints(t);
}
return TREDRAW_HARD;
@@ -7240,7 +7262,7 @@ static eRedrawFlag handleEventVertSlide(struct TransInfo *t, const struct wmEven
break;
case FKEY:
if (event->val == KM_PRESS) {
- sld->flipped_vtx = !sld->flipped_vtx;
+ sld->flipped = !sld->flipped;
calcVertSlideCustomPoints(t);
return TREDRAW_HARD;
}
@@ -7339,7 +7361,7 @@ static void drawVertSlide(TransInfo *t)
glPointSize(ctrl_size);
bglBegin(GL_POINTS);
- bglVertex3fv((sld->flipped_vtx && sld->is_proportional == false) ?
+ bglVertex3fv((sld->flipped && sld->use_even) ?
curr_sv->co_link_orig_3d[curr_sv->co_link_curr] :
curr_sv->co_orig_3d);
bglEnd();
@@ -7397,7 +7419,7 @@ static void doVertSlide(TransInfo *t, float perc)
sld->perc = perc;
sv = svlist;
- if (sld->is_proportional == true) {
+ if (sld->use_even == false) {
for (i = 0; i < sld->totsv; i++, sv++) {
interp_v3_v3v3(sv->v->co, sv->co_orig_3d, sv->co_link_orig_3d[sv->co_link_curr], perc);
}
@@ -7415,7 +7437,7 @@ static void doVertSlide(TransInfo *t, float perc)
edge_len = normalize_v3(dir);
if (edge_len > FLT_EPSILON) {
- if (sld->flipped_vtx) {
+ if (sld->flipped) {
madd_v3_v3v3fl(sv->v->co, sv->co_link_orig_3d[sv->co_link_curr], dir, -tperc);
}
else {
@@ -7435,8 +7457,8 @@ static void applyVertSlide(TransInfo *t, const int UNUSED(mval[2]))
size_t ofs = 0;
float final;
VertSlideData *sld = t->customData;
- const bool flipped = sld->flipped_vtx;
- const bool is_proportional = sld->is_proportional;
+ const bool flipped = sld->flipped;
+ const bool use_even = sld->use_even;
const bool is_clamp = !(t->flag & T_ALT_TRANSFORM);
const bool is_constrained = !(is_clamp == false || hasNumInput(&t->num));
@@ -7463,8 +7485,8 @@ static void applyVertSlide(TransInfo *t, const int UNUSED(mval[2]))
else {
ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, "%.4f ", final);
}
- ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("(E)ven: %s, "), WM_bool_as_string(!is_proportional));
- if (!is_proportional) {
+ ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("(E)ven: %s, "), WM_bool_as_string(use_even));
+ if (use_even) {
ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("(F)lipped: %s, "), WM_bool_as_string(flipped));
}
ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("Alt or (C)lamp: %s"), WM_bool_as_string(is_clamp));
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index 79bb0fe0b76..a735801ff47 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -252,8 +252,8 @@ typedef struct EdgeSlideData {
float perc;
- bool is_proportional;
- bool flipped_vtx;
+ bool use_even;
+ bool flipped;
int curr_sv_index;
@@ -284,8 +284,8 @@ typedef struct VertSlideData {
float perc;
- bool is_proportional;
- bool flipped_vtx;
+ bool use_even;
+ bool flipped;
int curr_sv_index;
@@ -729,7 +729,7 @@ bool createSpaceNormalTangent(float mat[3][3], const float normal[3], const floa
struct TransformOrientation *addMatrixSpace(struct bContext *C, float mat[3][3],
const char *name, const bool overwrite);
-bool applyTransformOrientation(const struct bContext *C, float mat[3][3], char r_name[64]);
+bool applyTransformOrientation(const struct bContext *C, float mat[3][3], char r_name[64], int index);
#define ORIENTATION_NONE 0
#define ORIENTATION_NORMAL 1
@@ -737,7 +737,8 @@ bool applyTransformOrientation(const struct bContext *C, float mat[3][3], char r
#define ORIENTATION_EDGE 3
#define ORIENTATION_FACE 4
-int getTransformOrientation(const struct bContext *C, float normal[3], float plane[3], const bool activeOnly);
+int getTransformOrientation_ex(const struct bContext *C, float normal[3], float plane[3], const short around);
+int getTransformOrientation(const struct bContext *C, float normal[3], float plane[3]);
void freeEdgeSlideTempFaces(EdgeSlideData *sld);
void freeEdgeSlideVerts(TransInfo *t);
diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c
index 9f4d53f1f22..895c8a81044 100644
--- a/source/blender/editors/transform/transform_constraints.c
+++ b/source/blender/editors/transform/transform_constraints.c
@@ -855,21 +855,15 @@ void getConstraintMatrix(TransInfo *t)
unit_m3(t->con.pmtx);
if (!(t->con.mode & CON_AXIS0)) {
- t->con.pmtx[0][0] =
- t->con.pmtx[0][1] =
- t->con.pmtx[0][2] = 0.0f;
+ zero_v3(t->con.pmtx[0]);
}
if (!(t->con.mode & CON_AXIS1)) {
- t->con.pmtx[1][0] =
- t->con.pmtx[1][1] =
- t->con.pmtx[1][2] = 0.0f;
+ zero_v3(t->con.pmtx[1]);
}
if (!(t->con.mode & CON_AXIS2)) {
- t->con.pmtx[2][0] =
- t->con.pmtx[2][1] =
- t->con.pmtx[2][2] = 0.0f;
+ zero_v3(t->con.pmtx[2]);
}
mul_m3_m3m3(mat, t->con.pmtx, t->con.imtx);
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index 687cf2f69e4..5e13afdc152 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -1252,7 +1252,18 @@ static void createTransArmatureVerts(TransInfo *t)
else {
if (ebo->flag & BONE_TIPSEL) {
copy_v3_v3(td->iloc, ebo->tail);
- copy_v3_v3(td->center, (t->around == V3D_LOCAL) ? ebo->head : td->iloc);
+
+ /* Don't allow single selected tips to have a modified center,
+ * causes problem with snapping (see T45974).
+ * However, in rotation mode, we want to keep that 'rotate bone around root with
+ * only its tip selected' behavior (see T46325). */
+ if ((t->around == V3D_LOCAL) && ((t->mode == TFM_ROTATION) || (ebo->flag & BONE_ROOTSEL))) {
+ copy_v3_v3(td->center, ebo->head);
+ }
+ else {
+ copy_v3_v3(td->center, td->iloc);
+ }
+
td->loc = ebo->tail;
td->flag = TD_SELECTED;
if (ebo->flag & BONE_EDITMODE_LOCKED)
@@ -1655,7 +1666,7 @@ static void createTransCurveVerts(TransInfo *t)
/* TODO - in the case of tilt and radius we can also avoid allocating the initTransDataCurveHandles
* but for now just don't change handle types */
- if (ELEM(t->mode, TFM_CURVE_SHRINKFATTEN, TFM_TILT) == 0) {
+ if (ELEM(t->mode, TFM_CURVE_SHRINKFATTEN, TFM_TILT, TFM_DUMMY) == 0) {
/* sets the handles based on their selection, do this after the data is copied to the TransData */
BKE_nurb_handles_test(nu, !hide_handles);
}
@@ -5548,7 +5559,7 @@ void autokeyframe_ob_cb_func(bContext *C, Scene *scene, View3D *v3d, Object *ob,
if (IS_AUTOKEY_FLAG(scene, ONLYKEYINGSET) && (active_ks)) {
/* only insert into active keyingset
- * NOTE: we assume here that the active Keying Set does not need to have its iterator overridden spe
+ * NOTE: we assume here that the active Keying Set does not need to have its iterator overridden
*/
ANIM_apply_keyingset(C, &dsources, NULL, active_ks, MODIFYKEY_MODE_INSERT, cfra);
}
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index 83e43bd08af..f3009ba0068 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -1213,18 +1213,7 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
t->around = V3D_CURSOR;
}
- if (op && ((prop = RNA_struct_find_property(op->ptr, "constraint_orientation")) &&
- RNA_property_is_set(op->ptr, prop)))
- {
- t->current_orientation = RNA_property_enum_get(op->ptr, prop);
-
- if (t->current_orientation >= V3D_MANIP_CUSTOM + BIF_countTransformOrientation(C)) {
- t->current_orientation = V3D_MANIP_GLOBAL;
- }
- }
- else {
- t->current_orientation = v3d->twmode;
- }
+ t->current_orientation = v3d->twmode;
/* exceptional case */
if (t->around == V3D_LOCAL) {
@@ -1311,6 +1300,16 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
}
t->around = V3D_CENTER;
}
+
+ if (op && ((prop = RNA_struct_find_property(op->ptr, "constraint_orientation")) &&
+ RNA_property_is_set(op->ptr, prop)))
+ {
+ t->current_orientation = RNA_property_enum_get(op->ptr, prop);
+
+ if (t->current_orientation >= V3D_MANIP_CUSTOM + BIF_countTransformOrientation(C)) {
+ t->current_orientation = V3D_MANIP_GLOBAL;
+ }
+ }
if (op && ((prop = RNA_struct_find_property(op->ptr, "release_confirm")) &&
RNA_property_is_set(op->ptr, prop)))
@@ -1838,7 +1837,7 @@ void calculateCenter(TransInfo *t)
/* zfac is only used convertViewVec only in cases operator was invoked in RGN_TYPE_WINDOW
* and never used in other cases.
*
- * We need special case here as well, since ED_view3d_calc_zfac will crahs when called
+ * We need special case here as well, since ED_view3d_calc_zfac will crash when called
* for a region different from RGN_TYPE_WINDOW.
*/
if (t->ar->regiontype == RGN_TYPE_WINDOW) {
diff --git a/source/blender/editors/transform/transform_manipulator.c b/source/blender/editors/transform/transform_manipulator.c
index a4ea37bc175..522cf15eb10 100644
--- a/source/blender/editors/transform/transform_manipulator.c
+++ b/source/blender/editors/transform/transform_manipulator.c
@@ -889,6 +889,7 @@ static int calc_manipulator_stats(const bContext *C)
/* fall-through */
case V3D_MANIP_NORMAL:
if (obedit || ob->mode & OB_MODE_POSE) {
+ float mat[3][3];
ED_getTransformOrientationMatrix(C, mat, (v3d->around == V3D_ACTIVE));
copy_m4_m3(rv3d->twmat, mat);
break;
@@ -901,6 +902,7 @@ static int calc_manipulator_stats(const bContext *C)
* use the active pones axis for display [#33575], this works as expected on a single bone
* and users who select many bones will understand whats going on and what local means
* when they start transforming */
+ float mat[3][3];
ED_getTransformOrientationMatrix(C, mat, (v3d->around == V3D_ACTIVE));
copy_m4_m3(rv3d->twmat, mat);
break;
@@ -914,10 +916,13 @@ static int calc_manipulator_stats(const bContext *C)
copy_m4_m3(rv3d->twmat, mat);
break;
default: /* V3D_MANIP_CUSTOM */
- if (applyTransformOrientation(C, mat, NULL)) {
+ {
+ float mat[3][3];
+ if (applyTransformOrientation(C, mat, NULL, v3d->twmode - V3D_MANIP_CUSTOM)) {
copy_m4_m3(rv3d->twmat, mat);
}
break;
+ }
}
}
diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c
index d7cb5362cd6..a95fa627ef2 100644
--- a/source/blender/editors/transform/transform_ops.c
+++ b/source/blender/editors/transform/transform_ops.c
@@ -644,8 +644,6 @@ static void TRANSFORM_OT_skin_resize(struct wmOperatorType *ot)
static void TRANSFORM_OT_trackball(struct wmOperatorType *ot)
{
- PropertyRNA *prop;
-
/* identifiers */
ot->name = "Trackball";
ot->description = "Trackball style rotation of selected items";
@@ -660,16 +658,13 @@ static void TRANSFORM_OT_trackball(struct wmOperatorType *ot)
ot->poll = ED_operator_screenactive;
/* Maybe we could use float_vector_xyz here too? */
- prop = RNA_def_float_vector(ot->srna, "value", 2, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -FLT_MAX, FLT_MAX);
- RNA_def_property_subtype(prop, PROP_ANGLE);
+ RNA_def_float_rotation(ot->srna, "value", 2, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -FLT_MAX, FLT_MAX);
Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP | P_GPENCIL_EDIT);
}
static void TRANSFORM_OT_rotate(struct wmOperatorType *ot)
{
- PropertyRNA *prop;
-
/* identifiers */
ot->name = "Rotate";
ot->description = "Rotate selected items";
@@ -683,8 +678,7 @@ static void TRANSFORM_OT_rotate(struct wmOperatorType *ot)
ot->cancel = transform_cancel;
ot->poll = ED_operator_screenactive;
- prop = RNA_def_float(ot->srna, "value", 0.0f, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI * 2, M_PI * 2);
- RNA_def_property_subtype(prop, PROP_ANGLE);
+ RNA_def_float_rotation(ot->srna, "value", 0, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI * 2, M_PI * 2);
Transform_Properties(ot, P_AXIS | P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_GEO_SNAP | P_GPENCIL_EDIT);
}
@@ -858,6 +852,12 @@ static void TRANSFORM_OT_edge_slide(struct wmOperatorType *ot)
prop = RNA_def_boolean(ot->srna, "single_side", false, "Single Side", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ RNA_def_boolean(ot->srna, "use_even", false, "Even",
+ "Make the edge loop match the shape of the adjacent edge loop");
+ RNA_def_boolean(ot->srna, "flipped", false, "Flipped",
+ "When Even mode is active, flips between the two adjacent edge loops");
+ RNA_def_boolean(ot->srna, "use_clamp", true, "Clamp",
+ "Clamp within the edge extents");
Transform_Properties(ot, P_MIRROR | P_SNAP | P_CORRECT_UV);
}
@@ -878,6 +878,12 @@ static void TRANSFORM_OT_vert_slide(struct wmOperatorType *ot)
ot->poll = ED_operator_editmesh_region_view3d;
RNA_def_float_factor(ot->srna, "value", 0, -10.0f, 10.0f, "Factor", "", -1.0f, 1.0f);
+ RNA_def_boolean(ot->srna, "use_even", false, "Even",
+ "Make the edge loop match the shape of the adjacent edge loop");
+ RNA_def_boolean(ot->srna, "flipped", false, "Flipped",
+ "When Even mode is active, flips between the two adjacent edge loops");
+ RNA_def_boolean(ot->srna, "use_clamp", true, "Clamp",
+ "Clamp within the edge extents");
Transform_Properties(ot, P_MIRROR | P_SNAP | P_CORRECT_UV);
}
diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c
index cea19e928bc..d6fbc46715e 100644
--- a/source/blender/editors/transform/transform_orientations.c
+++ b/source/blender/editors/transform/transform_orientations.c
@@ -36,6 +36,7 @@
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
#include "DNA_view3d_types.h"
#include "BLI_math.h"
@@ -144,7 +145,7 @@ static TransformOrientation *createBoneSpace(bContext *C, ReportList *reports,
float mat[3][3];
float normal[3], plane[3];
- getTransformOrientation(C, normal, plane, 0);
+ getTransformOrientation(C, normal, plane);
if (createSpaceNormalTangent(mat, normal, plane) == 0) {
BKE_reports_prepend(reports, "Cannot use zero-length bone");
@@ -164,7 +165,7 @@ static TransformOrientation *createCurveSpace(bContext *C, ReportList *reports,
float mat[3][3];
float normal[3], plane[3];
- getTransformOrientation(C, normal, plane, 0);
+ getTransformOrientation(C, normal, plane);
if (createSpaceNormalTangent(mat, normal, plane) == 0) {
BKE_reports_prepend(reports, "Cannot use zero-length curve");
@@ -186,7 +187,7 @@ static TransformOrientation *createMeshSpace(bContext *C, ReportList *reports,
float normal[3], plane[3];
int type;
- type = getTransformOrientation(C, normal, plane, 0);
+ type = getTransformOrientation(C, normal, plane);
switch (type) {
case ORIENTATION_VERT:
@@ -390,15 +391,12 @@ int BIF_countTransformOrientation(const bContext *C)
return BLI_listbase_count(transform_spaces);
}
-bool applyTransformOrientation(const bContext *C, float mat[3][3], char *r_name)
+bool applyTransformOrientation(const bContext *C, float mat[3][3], char *r_name, int index)
{
- View3D *v3d = CTX_wm_view3d(C);
- int selected_index = (v3d->twmode - V3D_MANIP_CUSTOM);
-
ListBase *transform_spaces = &CTX_data_scene(C)->transform_spaces;
- TransformOrientation *ts = BLI_findlink(transform_spaces, selected_index);
+ TransformOrientation *ts = BLI_findlink(transform_spaces, index);
- BLI_assert(selected_index >= 0);
+ BLI_assert(index >= 0);
if (ts) {
if (r_name) {
@@ -442,7 +440,6 @@ static int count_bone_select(bArmature *arm, ListBase *lb, const bool do_it)
void initTransformOrientation(bContext *C, TransInfo *t)
{
- View3D *v3d = CTX_wm_view3d(C);
Object *ob = CTX_data_active_object(C);
Object *obedit = CTX_data_active_object(C);
@@ -462,7 +459,7 @@ void initTransformOrientation(bContext *C, TransInfo *t)
case V3D_MANIP_NORMAL:
if (obedit || (ob && ob->mode & OB_MODE_POSE)) {
BLI_strncpy(t->spacename, IFACE_("normal"), sizeof(t->spacename));
- ED_getTransformOrientationMatrix(C, t->spacemtx, (v3d->around == V3D_ACTIVE));
+ ED_getTransformOrientationMatrix(C, t->spacemtx, t->around);
break;
}
/* fall-through */ /* we define 'normal' as 'local' in Object mode */
@@ -480,7 +477,9 @@ void initTransformOrientation(bContext *C, TransInfo *t)
break;
case V3D_MANIP_VIEW:
- if (t->ar->regiontype == RGN_TYPE_WINDOW) {
+ if ((t->spacetype == SPACE_VIEW3D) &&
+ (t->ar->regiontype == RGN_TYPE_WINDOW))
+ {
RegionView3D *rv3d = t->ar->regiondata;
float mat[3][3];
@@ -494,7 +493,7 @@ void initTransformOrientation(bContext *C, TransInfo *t)
}
break;
default: /* V3D_MANIP_CUSTOM */
- if (applyTransformOrientation(C, t->spacemtx, t->spacename)) {
+ if (applyTransformOrientation(C, t->spacemtx, t->spacename, t->current_orientation - V3D_MANIP_CUSTOM)) {
/* pass */
}
else {
@@ -585,14 +584,14 @@ static unsigned int bm_mesh_faces_select_get_n(BMesh *bm, BMVert **elems, const
}
#endif
-int getTransformOrientation(const bContext *C, float normal[3], float plane[3], const bool activeOnly)
+int getTransformOrientation_ex(const bContext *C, float normal[3], float plane[3], const short around)
{
Scene *scene = CTX_data_scene(C);
- View3D *v3d = CTX_wm_view3d(C);
Object *obedit = CTX_data_edit_object(C);
Base *base;
Object *ob = OBACT;
int result = ORIENTATION_NONE;
+ const bool activeOnly = (around == V3D_ACTIVE);
zero_v3(normal);
zero_v3(plane);
@@ -855,7 +854,7 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3],
/* exception */
if (flag) {
float tvec[3];
- if ((v3d->around == V3D_LOCAL) ||
+ if ((around == V3D_LOCAL) ||
ELEM(flag, SEL_F2, SEL_F1 | SEL_F3, SEL_F1 | SEL_F2 | SEL_F3))
{
BKE_nurb_bezt_calc_normal(nu, bezt, tvec);
@@ -1017,6 +1016,7 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3],
}
else {
/* we need the one selected object, if its not active */
+ View3D *v3d = CTX_wm_view3d(C);
ob = OBACT;
if (ob && (ob->flag & SELECT)) {
/* pass */
@@ -1042,14 +1042,22 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3],
return result;
}
-void ED_getTransformOrientationMatrix(const bContext *C, float orientation_mat[3][3], const bool activeOnly)
+int getTransformOrientation(const bContext *C, float normal[3], float plane[3])
+{
+ /* dummy value, not V3D_ACTIVE and not V3D_LOCAL */
+ short around = V3D_CENTER;
+
+ return getTransformOrientation_ex(C, normal, plane, around);
+}
+
+void ED_getTransformOrientationMatrix(const bContext *C, float orientation_mat[3][3], const short around)
{
float normal[3] = {0.0, 0.0, 0.0};
float plane[3] = {0.0, 0.0, 0.0};
int type;
- type = getTransformOrientation(C, normal, plane, activeOnly);
+ type = getTransformOrientation_ex(C, normal, plane, around);
switch (type) {
case ORIENTATION_NORMAL:
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
index dfa5032d303..0e954d40c18 100644
--- a/source/blender/editors/transform/transform_snap.c
+++ b/source/blender/editors/transform/transform_snap.c
@@ -85,6 +85,8 @@
#define TRANSFORM_DIST_MAX_PX 1000.0f
#define TRANSFORM_SNAP_MAX_PX 100.0f
+#define TRANSFORM_DIST_INVALID NAN_FLT
+
/* use half of flt-max so we can scale up without an exception */
/********************* PROTOTYPES ***********************/
@@ -220,7 +222,7 @@ void drawSnapping(const struct bContext *C, TransInfo *t)
h = (((float)hi) / IMG_SIZE_FALLBACK) * G.sima->zoom * yuser_asp;
cpack(0xFFFFFF);
- glTranslatef(t->tsnap.snapPoint[0], t->tsnap.snapPoint[1], 0.0f);
+ glTranslate2fv(t->tsnap.snapPoint);
//glRectf(0, 0, 1, 1);
@@ -897,7 +899,10 @@ static float ResizeBetween(TransInfo *t, const float p1[3], const float p2[3])
len_d1 = len_v3(d1);
- return len_d1 != 0.0f ? len_v3(d2) / len_d1 : 1;
+ /* Use 'invalid' dist when `center == p1` (after projecting),
+ * in this case scale will _never_ move the point in relation to the center,
+ * so it makes no sense to take it into account when scaling. see: T46503 */
+ return len_d1 != 0.0f ? len_v3(d2) / len_d1 : TRANSFORM_DIST_INVALID;
}
/********************** CALC **************************/
@@ -981,7 +986,7 @@ static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec))
break;
}
- new_dist = len_v3v3(last_p, vec);
+ new_dist = len_squared_v3v3(last_p, vec);
if (new_dist < max_dist) {
copy_v3_v3(p, vec);
@@ -1002,6 +1007,7 @@ static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec))
BLI_freelistN(&depth_peels);
}
else {
+ zero_v3(no); /* objects won't set this */
found = snapObjectsTransform(t, mval, &dist_px, loc, no, t->tsnap.modeSelect);
}
@@ -1176,8 +1182,10 @@ static void TargetSnapClosest(TransInfo *t)
mul_m4_v3(td->ext->obmat, loc);
dist = t->tsnap.distance(t, loc, t->tsnap.snapPoint);
-
- if (closest == NULL || fabsf(dist) < fabsf(t->tsnap.dist)) {
+
+ if ((dist != TRANSFORM_DIST_INVALID) &&
+ (closest == NULL || fabsf(dist) < fabsf(t->tsnap.dist)))
+ {
copy_v3_v3(t->tsnap.snapTarget, loc);
closest = td;
t->tsnap.dist = dist;
@@ -1192,8 +1200,10 @@ static void TargetSnapClosest(TransInfo *t)
copy_v3_v3(loc, td->center);
dist = t->tsnap.distance(t, loc, t->tsnap.snapPoint);
-
- if (closest == NULL || fabsf(dist) < fabsf(t->tsnap.dist)) {
+
+ if ((dist != TRANSFORM_DIST_INVALID) &&
+ (closest == NULL || fabsf(dist) < fabsf(t->tsnap.dist)))
+ {
copy_v3_v3(t->tsnap.snapTarget, loc);
closest = td;
t->tsnap.dist = dist;
@@ -1216,7 +1226,9 @@ static void TargetSnapClosest(TransInfo *t)
dist = t->tsnap.distance(t, loc, t->tsnap.snapPoint);
- if (closest == NULL || fabsf(dist) < fabsf(t->tsnap.dist)) {
+ if ((dist != TRANSFORM_DIST_INVALID) &&
+ (closest == NULL || fabsf(dist) < fabsf(t->tsnap.dist)))
+ {
copy_v3_v3(t->tsnap.snapTarget, loc);
closest = td;
t->tsnap.dist = dist;
@@ -1526,8 +1538,17 @@ static bool snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMes
if (do_bb) {
BoundBox *bb = BKE_object_boundbox_get(ob);
- if (!BKE_boundbox_ray_hit_check(bb, ray_start_local, ray_normal_local, &len_diff)) {
- return retval;
+
+ if (bb) {
+ BoundBox bb_temp;
+
+ /* We cannot aford a bbox with some null dimension, which may happen in some cases...
+ * Threshold is rather high, but seems to be needed to get good behavior, see T46099. */
+ bb = BKE_boundbox_ensure_minimum_dimensions(bb, &bb_temp, 1e-1f);
+
+ if (!BKE_boundbox_ray_hit_check(bb, ray_start_local, ray_normal_local, &len_diff)) {
+ return retval;
+ }
}
}
else if (do_ray_start_correction) {
@@ -1539,6 +1560,7 @@ static bool snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMes
len_diff = 0.0f; /* In case BVHTree would fail for some reason... */
treeData.em_evil = em;
+ treeData.em_evil_all = false;
bvhtree_from_mesh_looptri(&treeData, dm, 0.0f, 2, 6);
if (treeData.tree != NULL) {
nearest.index = -1;
@@ -1581,6 +1603,7 @@ static bool snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMes
}
treeData.em_evil = em;
+ treeData.em_evil_all = false;
bvhtree_from_mesh_looptri(&treeData, dm, 0.0f, 4, 6);
hit.index = -1;
@@ -1853,8 +1876,16 @@ static bool snapObject(Scene *scene, short snap_mode, ARegion *ar, Object *ob, f
do_bb = false;
}
else {
+ /* in this case we want the mesh from the editmesh, avoids stale data. see: T45978.
+ * still set the 'em' to NULL, since we only want the 'dm'. */
+ em = BKE_editmesh_from_object(ob);
+ if (em) {
+ editbmesh_get_derived_cage_and_final(scene, ob, em, CD_MASK_BAREMESH, &dm);
+ }
+ else {
+ dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
+ }
em = NULL;
- dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
}
retval = snapDerivedMesh(snap_mode, ar, ob, dm, em, obmat, ray_start, ray_normal, ray_origin, mval, r_loc, r_no, r_dist_px, r_depth, do_bb);
@@ -1974,8 +2005,20 @@ static bool snapObjects(Scene *scene, short snap_mode, Base *base_act, View3D *v
bool snapObjectsTransform(TransInfo *t, const float mval[2], float *r_dist_px, float r_loc[3], float r_no[3], SnapMode mode)
{
float ray_dist = TRANSFORM_DIST_MAX_RAY;
- return snapObjects(t->scene, t->scene->toolsettings->snap_mode, t->scene->basact, t->view, t->ar, t->obedit,
- mval, r_dist_px, r_loc, r_no, &ray_dist, mode);
+ Object *obedit = NULL;
+ Base *base_act = NULL;
+
+ if (t->flag & T_EDIT) {
+ obedit = t->obedit;
+ }
+
+ if ((t->options & CTX_GPENCIL_STROKES) == 0) {
+ base_act = t->scene->basact;
+ }
+
+ return snapObjects(
+ t->scene, t->scene->toolsettings->snap_mode, base_act, t->view, t->ar, obedit,
+ mval, r_dist_px, r_loc, r_no, &ray_dist, mode);
}
bool snapObjectsContext(bContext *C, const float mval[2], float *r_dist_px, float r_loc[3], float r_no[3], SnapMode mode)
@@ -2130,20 +2173,30 @@ static bool peelDerivedMesh(
* test against boundbox first
* */
if (looptri_num > 16) {
- struct BoundBox *bb = BKE_object_boundbox_get(ob);
- test = BKE_boundbox_ray_hit_check(bb, ray_start_local, ray_normal_local, NULL);
+ BoundBox *bb = BKE_object_boundbox_get(ob);
+
+ if (bb) {
+ BoundBox bb_temp;
+
+ /* We cannot aford a bbox with some null dimension, which may happen in some cases...
+ * Threshold is rather high, but seems to be needed to get good behavior, see T46099. */
+ bb = BKE_boundbox_ensure_minimum_dimensions(bb, &bb_temp, 1e-1f);
+
+ test = BKE_boundbox_ray_hit_check(bb, ray_start_local, ray_normal_local, NULL);
+ }
}
if (test == true) {
struct PeelRayCast_Data data;
data.bvhdata.em_evil = em;
+ data.bvhdata.em_evil_all = false;
bvhtree_from_mesh_looptri(&data.bvhdata, dm, 0.0f, 4, 6);
if (data.bvhdata.tree != NULL) {
data.ob = ob;
- data.obmat = obmat;
- data.timat = timat;
+ data.obmat = (const float (*)[4])obmat;
+ data.timat = (const float (*)[3])timat;
data.ray_start = ray_start;
data.looptri = looptri;
data.polynors = dm->getPolyDataArray(dm, CD_NORMAL); /* can be NULL */
diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c
index 802c4e796dd..f727f48e993 100644
--- a/source/blender/editors/util/ed_util.c
+++ b/source/blender/editors/util/ed_util.c
@@ -111,7 +111,7 @@ void ED_editors_init(bContext *C)
/* image editor paint mode */
if (sce) {
- ED_space_image_paint_update(wm, sce->toolsettings);
+ ED_space_image_paint_update(wm, sce);
}
SWAP(int, reports->flag, reports_flag_prev);
diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c
index 9431d754b5f..f4eed3e1fda 100644
--- a/source/blender/editors/uvedit/uvedit_draw.c
+++ b/source/blender/editors/uvedit/uvedit_draw.c
@@ -81,7 +81,7 @@ void ED_image_draw_cursor(ARegion *ar, const float cursor[2])
y_fac = zoom[1];
cpack(0xFFFFFF);
- glTranslatef(cursor[0], cursor[1], 0.0);
+ glTranslate2fv(cursor);
fdrawline(-0.05f * x_fac, 0, 0, 0.05f * y_fac);
fdrawline(0, 0.05f * y_fac, 0.05f * x_fac, 0.0f);
fdrawline(0.05f * x_fac, 0.0f, 0.0f, -0.05f * y_fac);
@@ -187,8 +187,8 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
const int efa_len = efa->len;
- float (*tf_uv)[2] = (float (*)[2])BLI_buffer_resize_data(&tf_uv_buf, vec2f, efa_len);
- float (*tf_uvorig)[2] = (float (*)[2])BLI_buffer_resize_data(&tf_uvorig_buf, vec2f, efa_len);
+ float (*tf_uv)[2] = (float (*)[2])BLI_buffer_reinit_data(&tf_uv_buf, vec2f, efa_len);
+ float (*tf_uvorig)[2] = (float (*)[2])BLI_buffer_reinit_data(&tf_uvorig_buf, vec2f, efa_len);
tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
@@ -230,8 +230,8 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
if (BM_elem_flag_test(efa, BM_ELEM_TAG)) {
const int efa_len = efa->len;
- float (*tf_uv)[2] = (float (*)[2])BLI_buffer_resize_data(&tf_uv_buf, vec2f, efa_len);
- float (*tf_uvorig)[2] = (float (*)[2])BLI_buffer_resize_data(&tf_uvorig_buf, vec2f, efa_len);
+ float (*tf_uv)[2] = (float (*)[2])BLI_buffer_reinit_data(&tf_uv_buf, vec2f, efa_len);
+ float (*tf_uvorig)[2] = (float (*)[2])BLI_buffer_reinit_data(&tf_uvorig_buf, vec2f, efa_len);
area = BM_face_calc_area(efa) / totarea;
@@ -284,12 +284,12 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe
if (uvedit_face_visible_test(scene, ima, efa, tf)) {
const int efa_len = efa->len;
- float (*tf_uv)[2] = (float (*)[2])BLI_buffer_resize_data(&tf_uv_buf, vec2f, efa_len);
- float (*tf_uvorig)[2] = (float (*)[2])BLI_buffer_resize_data(&tf_uvorig_buf, vec2f, efa_len);
- float *uvang = BLI_buffer_resize_data(&uvang_buf, float, efa_len);
- float *ang = BLI_buffer_resize_data(&ang_buf, float, efa_len);
- float (*av)[3] = (float (*)[3])BLI_buffer_resize_data(&av_buf, vec3f, efa_len);
- float (*auv)[2] = (float (*)[2])BLI_buffer_resize_data(&auv_buf, vec2f, efa_len);
+ float (*tf_uv)[2] = (float (*)[2])BLI_buffer_reinit_data(&tf_uv_buf, vec2f, efa_len);
+ float (*tf_uvorig)[2] = (float (*)[2])BLI_buffer_reinit_data(&tf_uvorig_buf, vec2f, efa_len);
+ float *uvang = BLI_buffer_reinit_data(&uvang_buf, float, efa_len);
+ float *ang = BLI_buffer_reinit_data(&ang_buf, float, efa_len);
+ float (*av)[3] = (float (*)[3])BLI_buffer_reinit_data(&av_buf, vec3f, efa_len);
+ float (*auv)[2] = (float (*)[2])BLI_buffer_reinit_data(&auv_buf, vec2f, efa_len);
int j;
BM_elem_flag_enable(efa, BM_ELEM_TAG);
diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c
index 71d557f6fc7..728e3662ce6 100644
--- a/source/blender/editors/uvedit/uvedit_ops.c
+++ b/source/blender/editors/uvedit/uvedit_ops.c
@@ -4119,7 +4119,13 @@ static int uv_seams_from_islands_exec(bContext *C, wmOperator *op)
}
}
- me->drawflag |= ME_DRAWSEAMS;
+ if (mark_seams) {
+ me->drawflag |= ME_DRAWSEAMS;
+ }
+ if (mark_sharp) {
+ me->drawflag |= ME_DRAWSHARP;
+ }
+
BM_uv_vert_map_free(vmap);
diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
index f915a4b2e51..3ff3e29f79d 100644
--- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c
+++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
@@ -344,7 +344,8 @@ static ParamHandle *construct_param_handle_subsurfed(Scene *scene, Object *ob, B
{
ParamHandle *handle;
/* index pointers */
- MFace *face;
+ MPoly *mpoly;
+ MLoop *mloop;
MEdge *edge;
int i;
@@ -356,11 +357,12 @@ static ParamHandle *construct_param_handle_subsurfed(Scene *scene, Object *ob, B
/* Used to hold subsurfed Mesh */
DerivedMesh *derivedMesh, *initialDerived;
/* holds original indices for subsurfed mesh */
- const int *origVertIndices, *origEdgeIndices, *origFaceIndices, *origPolyIndices;
+ const int *origVertIndices, *origEdgeIndices, *origPolyIndices;
/* Holds vertices of subsurfed mesh */
MVert *subsurfedVerts;
MEdge *subsurfedEdges;
- MFace *subsurfedFaces;
+ MPoly *subsurfedPolys;
+ MLoop *subsurfedLoops;
/* number of vertices and faces for subsurfed mesh*/
int numOfEdges, numOfFaces;
@@ -398,15 +400,15 @@ static ParamHandle *construct_param_handle_subsurfed(Scene *scene, Object *ob, B
/* get the derived data */
subsurfedVerts = derivedMesh->getVertArray(derivedMesh);
subsurfedEdges = derivedMesh->getEdgeArray(derivedMesh);
- subsurfedFaces = derivedMesh->getTessFaceArray(derivedMesh);
+ subsurfedPolys = derivedMesh->getPolyArray(derivedMesh);
+ subsurfedLoops = derivedMesh->getLoopArray(derivedMesh);
origVertIndices = derivedMesh->getVertDataArray(derivedMesh, CD_ORIGINDEX);
origEdgeIndices = derivedMesh->getEdgeDataArray(derivedMesh, CD_ORIGINDEX);
- origFaceIndices = derivedMesh->getTessFaceDataArray(derivedMesh, CD_ORIGINDEX);
origPolyIndices = derivedMesh->getPolyDataArray(derivedMesh, CD_ORIGINDEX);
numOfEdges = derivedMesh->getNumEdges(derivedMesh);
- numOfFaces = derivedMesh->getNumTessFaces(derivedMesh);
+ numOfFaces = derivedMesh->getNumPolys(derivedMesh);
faceMap = MEM_mallocN(numOfFaces * sizeof(BMFace *), "unwrap_edit_face_map");
@@ -415,7 +417,7 @@ static ParamHandle *construct_param_handle_subsurfed(Scene *scene, Object *ob, B
/* map subsurfed faces to original editFaces */
for (i = 0; i < numOfFaces; i++)
- faceMap[i] = BM_face_at_index(em->bm, DM_origindex_mface_mpoly(origFaceIndices, origPolyIndices, i));
+ faceMap[i] = BM_face_at_index(em->bm, origPolyIndices[i]);
edgeMap = MEM_mallocN(numOfEdges * sizeof(BMEdge *), "unwrap_edit_edge_map");
@@ -427,15 +429,13 @@ static ParamHandle *construct_param_handle_subsurfed(Scene *scene, Object *ob, B
}
/* Prepare and feed faces to the solver */
- for (i = 0; i < numOfFaces; i++) {
+ for (i = 0, mpoly = subsurfedPolys; i < numOfFaces; i++, mpoly++) {
ParamKey key, vkeys[4];
ParamBool pin[4], select[4];
float *co[4];
float *uv[4];
BMFace *origFace = faceMap[i];
- face = subsurfedFaces + i;
-
if (scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
if (BM_elem_flag_test(origFace, BM_ELEM_HIDDEN))
continue;
@@ -445,24 +445,27 @@ static ParamHandle *construct_param_handle_subsurfed(Scene *scene, Object *ob, B
continue;
}
+ mloop = &subsurfedLoops[mpoly->loopstart];
+
/* We will not check for v4 here. Subsurfed mfaces always have 4 vertices. */
- key = (ParamKey)face;
- vkeys[0] = (ParamKey)face->v1;
- vkeys[1] = (ParamKey)face->v2;
- vkeys[2] = (ParamKey)face->v3;
- vkeys[3] = (ParamKey)face->v4;
-
- co[0] = subsurfedVerts[face->v1].co;
- co[1] = subsurfedVerts[face->v2].co;
- co[2] = subsurfedVerts[face->v3].co;
- co[3] = subsurfedVerts[face->v4].co;
+ BLI_assert(mpoly->totloop == 4);
+ key = (ParamKey)mpoly;
+ vkeys[0] = (ParamKey)mloop[0].v;
+ vkeys[1] = (ParamKey)mloop[1].v;
+ vkeys[2] = (ParamKey)mloop[2].v;
+ vkeys[3] = (ParamKey)mloop[3].v;
+
+ co[0] = subsurfedVerts[mloop[0].v].co;
+ co[1] = subsurfedVerts[mloop[1].v].co;
+ co[2] = subsurfedVerts[mloop[2].v].co;
+ co[3] = subsurfedVerts[mloop[3].v].co;
/* This is where all the magic is done. If the vertex exists in the, we pass the original uv pointer to the solver, thus
* flushing the solution to the edit mesh. */
- texface_from_original_index(origFace, origVertIndices[face->v1], &uv[0], &pin[0], &select[0], scene, cd_loop_uv_offset);
- texface_from_original_index(origFace, origVertIndices[face->v2], &uv[1], &pin[1], &select[1], scene, cd_loop_uv_offset);
- texface_from_original_index(origFace, origVertIndices[face->v3], &uv[2], &pin[2], &select[2], scene, cd_loop_uv_offset);
- texface_from_original_index(origFace, origVertIndices[face->v4], &uv[3], &pin[3], &select[3], scene, cd_loop_uv_offset);
+ texface_from_original_index(origFace, origVertIndices[mloop[0].v], &uv[0], &pin[0], &select[0], scene, cd_loop_uv_offset);
+ texface_from_original_index(origFace, origVertIndices[mloop[1].v], &uv[1], &pin[1], &select[1], scene, cd_loop_uv_offset);
+ texface_from_original_index(origFace, origVertIndices[mloop[2].v], &uv[2], &pin[2], &select[2], scene, cd_loop_uv_offset);
+ texface_from_original_index(origFace, origVertIndices[mloop[3].v], &uv[3], &pin[3], &select[3], scene, cd_loop_uv_offset);
param_face_add(handle, key, 4, vkeys, co, uv, pin, select, NULL);
}
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
index 64ef49d74a3..7c10591591c 100644
--- a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
+++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
@@ -55,6 +55,8 @@ extern "C" {
#include "BLI_ghash.h"
#include "BLI_listbase.h"
+#include "BLI_math_color.h"
+#include "BLI_math_vector.h"
#include "BLI_utildefines.h"
#include "RE_pipeline.h"
@@ -113,7 +115,6 @@ BlenderStrokeRenderer::BlenderStrokeRenderer(Render *re, int render_count) : Str
BLI_strncpy(freestyle_scene->r.engine, old_scene->r.engine, sizeof(freestyle_scene->r.engine));
freestyle_scene->r.im_format.planes = R_IMF_PLANES_RGBA;
freestyle_scene->r.im_format.imtype = R_IMF_IMTYPE_PNG;
- BKE_scene_disable_color_management(freestyle_scene);
if (G.debug & G_DEBUG_FREESTYLE) {
printf("%s: %d thread(s)\n", __func__, BKE_render_num_threads(&freestyle_scene->r));
@@ -871,38 +872,24 @@ void BlenderStrokeRenderer::GenerateStrokeMesh(StrokeGroup *group, bool hasTex)
}
}
- // colors and alpha transparency
+ // colors and alpha transparency. vertex colors are in sRGB
+ // space by convention, so convert from linear
+ float rgba[3][4];
+
+ for (int i = 0; i < 3; i++) {
+ copy_v3fl_v3db(rgba[i], &svRep[i]->color()[0]);
+ rgba[i][3] = svRep[i]->alpha();
+ }
+
if (is_odd) {
- colors[0].r = (short)(255.0f * svRep[2]->color()[0]);
- colors[0].g = (short)(255.0f * svRep[2]->color()[1]);
- colors[0].b = (short)(255.0f * svRep[2]->color()[2]);
- colors[0].a = (short)(255.0f * svRep[2]->alpha());
-
- colors[1].r = (short)(255.0f * svRep[0]->color()[0]);
- colors[1].g = (short)(255.0f * svRep[0]->color()[1]);
- colors[1].b = (short)(255.0f * svRep[0]->color()[2]);
- colors[1].a = (short)(255.0f * svRep[0]->alpha());
-
- colors[2].r = (short)(255.0f * svRep[1]->color()[0]);
- colors[2].g = (short)(255.0f * svRep[1]->color()[1]);
- colors[2].b = (short)(255.0f * svRep[1]->color()[2]);
- colors[2].a = (short)(255.0f * svRep[1]->alpha());
+ linearrgb_to_srgb_uchar4(&colors[0].r, rgba[2]);
+ linearrgb_to_srgb_uchar4(&colors[1].r, rgba[0]);
+ linearrgb_to_srgb_uchar4(&colors[2].r, rgba[1]);
}
else {
- colors[0].r = (short)(255.0f * svRep[2]->color()[0]);
- colors[0].g = (short)(255.0f * svRep[2]->color()[1]);
- colors[0].b = (short)(255.0f * svRep[2]->color()[2]);
- colors[0].a = (short)(255.0f * svRep[2]->alpha());
-
- colors[1].r = (short)(255.0f * svRep[1]->color()[0]);
- colors[1].g = (short)(255.0f * svRep[1]->color()[1]);
- colors[1].b = (short)(255.0f * svRep[1]->color()[2]);
- colors[1].a = (short)(255.0f * svRep[1]->alpha());
-
- colors[2].r = (short)(255.0f * svRep[0]->color()[0]);
- colors[2].g = (short)(255.0f * svRep[0]->color()[1]);
- colors[2].b = (short)(255.0f * svRep[0]->color()[2]);
- colors[2].a = (short)(255.0f * svRep[0]->alpha());
+ linearrgb_to_srgb_uchar4(&colors[0].r, rgba[2]);
+ linearrgb_to_srgb_uchar4(&colors[1].r, rgba[1]);
+ linearrgb_to_srgb_uchar4(&colors[2].r, rgba[0]);
}
transp[0].r = transp[0].g = transp[0].b = colors[0].a;
transp[1].r = transp[1].g = transp[1].b = colors[1].a;
diff --git a/source/blender/freestyle/intern/geometry/GeomUtils.h b/source/blender/freestyle/intern/geometry/GeomUtils.h
index 64aa6379e80..5a5d0809083 100644
--- a/source/blender/freestyle/intern/geometry/GeomUtils.h
+++ b/source/blender/freestyle/intern/geometry/GeomUtils.h
@@ -200,7 +200,7 @@ void fromWorldToCamera(const Vec3r& p, Vec3r& q, const real model_view_matrix[4]
void fromCameraToRetina(const Vec3r& p, Vec3r& q, const real projection_matrix[4][4]);
/*! From retina to image.
- * Returns the coordinates expressed in Image coorinates system.
+ * Returns the coordinates expressed in Image coordinates system.
* p
* point's coordinates expressed in retina system
* q
diff --git a/source/blender/freestyle/intern/geometry/Noise.cpp b/source/blender/freestyle/intern/geometry/Noise.cpp
index 8ec56e84f95..dd5f2f6ea4c 100644
--- a/source/blender/freestyle/intern/geometry/Noise.cpp
+++ b/source/blender/freestyle/intern/geometry/Noise.cpp
@@ -147,7 +147,7 @@ float Noise::smoothNoise2(Vec2f& vec)
{
int bx0, bx1, by0, by1, b00, b10, b01, b11;
float rx0, rx1, ry0, ry1, *q, sx, sy, a, b, t, u, v;
- register int i, j;
+ int i, j;
SETUP(vec.x(), bx0, bx1, rx0, rx1);
SETUP(vec.y(), by0, by1, ry0, ry1);
@@ -186,7 +186,7 @@ float Noise::smoothNoise3(Vec3f& vec)
{
int bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11;
float rx0, rx1, ry0, ry1, rz0, rz1, *q, sy, sz, a, b, c, d, t, u, v;
- register int i, j;
+ int i, j;
SETUP(vec.x(), bx0, bx1, rx0, rx1);
SETUP(vec.y(), by0, by1, ry0, ry1);
diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp b/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp
index 9f0660baa9b..446587c2388 100644
--- a/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp
+++ b/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp
@@ -220,8 +220,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 *)"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/Stroke.cpp b/source/blender/freestyle/intern/stroke/Stroke.cpp
index b4a3646edef..053015f459d 100644
--- a/source/blender/freestyle/intern/stroke/Stroke.cpp
+++ b/source/blender/freestyle/intern/stroke/Stroke.cpp
@@ -419,12 +419,7 @@ Stroke::Stroke(const Stroke& iBrother)
_textureId = iBrother._textureId;
_textureStep = iBrother._textureStep;
for (int a = 0; a < MAX_MTEX; a++) {
- if (iBrother._mtex) {
- _mtex[a] = iBrother._mtex[a];
- }
- else {
- _mtex[a] = NULL;
- }
+ _mtex[a] = iBrother._mtex[a];
}
_nodeTree = iBrother._nodeTree;
_tips = iBrother._tips;
diff --git a/source/blender/freestyle/intern/winged_edge/WEdge.h b/source/blender/freestyle/intern/winged_edge/WEdge.h
index f610f6965aa..8001342775b 100644
--- a/source/blender/freestyle/intern/winged_edge/WEdge.h
+++ b/source/blender/freestyle/intern/winged_edge/WEdge.h
@@ -989,7 +989,7 @@ public:
}
/*! For triangles, returns the edge opposite to the vertex in e.
- * returns flase if the face is not a triangle or if the vertex is not found
+ * returns false if the face is not a triangle or if the vertex is not found
*/
bool getOppositeEdge (const WVertex *v, WOEdge *&e);
diff --git a/source/blender/gpu/GPU_extensions.h b/source/blender/gpu/GPU_extensions.h
index f3927ba960b..685ae59c47b 100644
--- a/source/blender/gpu/GPU_extensions.h
+++ b/source/blender/gpu/GPU_extensions.h
@@ -130,6 +130,8 @@ GPUTexture *GPU_texture_create_depth(int w, int h, char err_out[256]);
GPUTexture *GPU_texture_create_vsm_shadow_map(int size, char err_out[256]);
GPUTexture *GPU_texture_create_2D_procedural(int w, int h, const float *pixels, bool repeat, char err_out[256]);
GPUTexture *GPU_texture_create_1D_procedural(int w, const float *pixels, char err_out[256]);
+GPUTexture *GPU_texture_create_2D_multisample(int w, int h, const float *pixels, GPUHDRType hdr, int samples, char err_out[256]);
+GPUTexture *GPU_texture_create_depth_multisample(int w, int h, int samples, char err_out[256]);
GPUTexture *GPU_texture_from_blender(struct Image *ima,
struct ImageUser *iuser, bool is_data, double time, int mipmap);
GPUTexture *GPU_texture_from_preview(struct PreviewImage *prv, int mipmap);
@@ -179,13 +181,14 @@ void GPU_framebuffer_blur(GPUFrameBuffer *fb, GPUTexture *tex, GPUFrameBuffer *b
* - wrapper around framebuffer and texture for simple offscreen drawing
* - changes size if graphics card can't support it */
-GPUOffScreen *GPU_offscreen_create(int width, int height, char err_out[256]);
+GPUOffScreen *GPU_offscreen_create(int width, int height, int samples, char err_out[256]);
void GPU_offscreen_free(GPUOffScreen *ofs);
void GPU_offscreen_bind(GPUOffScreen *ofs, bool save);
void GPU_offscreen_unbind(GPUOffScreen *ofs, bool restore);
void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels);
int GPU_offscreen_width(const GPUOffScreen *ofs);
int GPU_offscreen_height(const GPUOffScreen *ofs);
+int GPU_offscreen_color_texture(const GPUOffScreen *ofs);
/* Builtin/Non-generated shaders */
typedef enum GPUProgramType {
@@ -204,6 +207,19 @@ void GPU_program_unbind(GPUProgram *);
* - must call texture bind before setting a texture as uniform! */
GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, const char *geocode, const char *libcode, const char *defines, int input, int output, int number);
+enum {
+ GPU_SHADER_FLAGS_NONE = 0,
+ GPU_SHADER_FLAGS_SPECIAL_OPENSUBDIV = (1 << 0),
+};
+GPUShader *GPU_shader_create_ex(const char *vertexcode,
+ const char *fragcode,
+ const char *geocode,
+ const char *libcode,
+ const char *defines,
+ int input,
+ int output,
+ int number,
+ const int flags);
void GPU_shader_free(GPUShader *shader);
void GPU_shader_bind(GPUShader *shader);
diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h
index dd08ed83e5a..25a4f33b526 100644
--- a/source/blender/gpu/GPU_material.h
+++ b/source/blender/gpu/GPU_material.h
@@ -160,6 +160,7 @@ typedef enum GPUDynamicType {
GPU_DYNAMIC_LAMP_ATT2 = 9 | GPU_DYNAMIC_GROUP_LAMP,
GPU_DYNAMIC_LAMP_SPOTSIZE = 10 | GPU_DYNAMIC_GROUP_LAMP,
GPU_DYNAMIC_LAMP_SPOTBLEND = 11 | GPU_DYNAMIC_GROUP_LAMP,
+ GPU_DYNAMIC_LAMP_SPOTSCALE = 12 | GPU_DYNAMIC_GROUP_LAMP,
GPU_DYNAMIC_SAMPLER_2DBUFFER = 1 | GPU_DYNAMIC_GROUP_SAMPLER,
GPU_DYNAMIC_SAMPLER_2DIMAGE = 2 | GPU_DYNAMIC_GROUP_SAMPLER,
@@ -314,13 +315,13 @@ void GPU_mist_update_values(int type, float start, float dist, float inten, floa
void GPU_horizon_update_color(float color[3]);
void GPU_ambient_update_color(float color[3]);
-typedef struct GPUParticleInfo
+struct GPUParticleInfo
{
float scalprops[4];
float location[3];
float velocity[3];
float angular_velocity[3];
-} GPUParticleInfo;
+};
#ifdef WITH_OPENSUBDIV
struct DerivedMesh;
diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c
index f03632883bb..2c434fb405e 100644
--- a/source/blender/gpu/intern/gpu_buffers.c
+++ b/source/blender/gpu/intern/gpu_buffers.c
@@ -95,8 +95,6 @@ const GPUBufferTypeSettings gpu_buffer_type_settings[] = {
{GL_ELEMENT_ARRAY_BUFFER_ARB, 4},
/* triangles, 1 point since we are allocating from tottriangle points, which account for all points */
{GL_ELEMENT_ARRAY_BUFFER_ARB, 1},
- /* fast triangles */
- {GL_ELEMENT_ARRAY_BUFFER_ARB, 1},
};
#define MAX_GPU_ATTRIB_DATA 32
diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c
index 12292f4897c..496302bb44e 100644
--- a/source/blender/gpu/intern/gpu_codegen.c
+++ b/source/blender/gpu/intern/gpu_codegen.c
@@ -718,7 +718,7 @@ static char *code_generate_vertex(ListBase *nodes, const GPUMatType type)
GPUNode *node;
GPUInput *input;
char *code;
- char *vertcode;
+ char *vertcode = NULL;
for (node = nodes->first; node; node = node->next) {
for (input = node->inputs.first; input; input = input->next) {
@@ -1615,7 +1615,16 @@ GPUPass *GPU_generate_pass(ListBase *nodes, GPUNodeLink *outlink,
fragmentcode = code_generate_fragment(nodes, outlink->output);
vertexcode = code_generate_vertex(nodes, type);
geometrycode = code_generate_geometry(nodes, use_opensubdiv);
- shader = GPU_shader_create(vertexcode, fragmentcode, geometrycode, glsl_material_library, NULL, 0, 0, 0);
+ shader = GPU_shader_create_ex(vertexcode,
+ fragmentcode,
+ geometrycode,
+ glsl_material_library,
+ NULL,
+ 0,
+ 0,
+ 0,
+ use_opensubdiv ? GPU_SHADER_FLAGS_SPECIAL_OPENSUBDIV
+ : GPU_SHADER_FLAGS_NONE);
/* failed? */
if (!shader) {
diff --git a/source/blender/gpu/intern/gpu_compositing.c b/source/blender/gpu/intern/gpu_compositing.c
index 2bafee0fb52..da5db73d382 100644
--- a/source/blender/gpu/intern/gpu_compositing.c
+++ b/source/blender/gpu/intern/gpu_compositing.c
@@ -306,6 +306,9 @@ bool GPU_fx_compositor_initialize_passes(
fx->effects = 0;
+ if (!GPU_non_power_of_two_support() || !GLEW_EXT_framebuffer_object || !GLEW_ARB_fragment_shader)
+ return false;
+
if (!fx_settings) {
cleanup_fx_gl_data(fx, true);
return false;
@@ -340,16 +343,18 @@ bool GPU_fx_compositor_initialize_passes(
if (fx_flag & GPU_FX_FLAG_SSAO)
num_passes++;
- if (!fx->gbuffer)
+ if (!fx->gbuffer) {
fx->gbuffer = GPU_framebuffer_create();
+ if (!fx->gbuffer) {
+ return false;
+ }
+ }
+
/* try creating the jitter texture */
if (!fx->jitter_buffer)
fx->jitter_buffer = create_jitter_texture();
- if (!fx->gbuffer)
- return false;
-
/* check if color buffers need recreation */
if (!fx->color_buffer || !fx->depth_buffer || w != fx->gbuffer_dim[0] || h != fx->gbuffer_dim[1]) {
cleanup_fx_gl_data(fx, false);
diff --git a/source/blender/gpu/intern/gpu_debug.c b/source/blender/gpu/intern/gpu_debug.c
index 1c194f517aa..29b7ff11586 100644
--- a/source/blender/gpu/intern/gpu_debug.c
+++ b/source/blender/gpu/intern/gpu_debug.c
@@ -43,7 +43,7 @@
#define CASE_CODE_RETURN_STR(code) case code: return #code;
-static const char* gpu_gl_error_symbol(GLenum err)
+static const char *gpu_gl_error_symbol(GLenum err)
{
switch (err) {
CASE_CODE_RETURN_STR(GL_NO_ERROR)
@@ -81,8 +81,8 @@ static bool gpu_report_gl_errors(const char *file, int line, const char *str)
}
else {
/* glGetError should have cleared the error flag, so if we get the
- same flag twice that means glGetError itself probably triggered
- the error. This happens on Windows if the GL context is invalid.
+ * same flag twice that means glGetError itself probably triggered
+ * the error. This happens on Windows if the GL context is invalid.
*/
{
GLenum new_error = glGetError();
@@ -92,22 +92,18 @@ static bool gpu_report_gl_errors(const char *file, int line, const char *str)
}
}
- fprintf(
- stderr,
- "%s(%d): ``%s'' -> GL Error (0x%04X - %s): %s\n",
- file,
- line,
- str,
- gl_error,
- gpu_gl_error_symbol(gl_error),
- gpuErrorString(gl_error));
+ fprintf(stderr,
+ "%s:%d: ``%s'' -> GL Error (0x%04X - %s): %s\n",
+ file, line, str, gl_error,
+ gpu_gl_error_symbol(gl_error),
+ gpuErrorString(gl_error));
return false;
}
}
-const char* gpuErrorString(GLenum err)
+const char *gpuErrorString(GLenum err)
{
switch (err) {
case GL_NO_ERROR:
@@ -208,9 +204,9 @@ void gpu_debug_init(void)
if (GLEW_KHR_debug) {
#ifndef GLEW_ES_ONLY
- glDebugMessageCallback(gpu_debug_proc, mxGetCurrentContext());
- glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE);
- GPU_string_marker(sizeof(success), success);
+ glDebugMessageCallback(gpu_debug_proc, mxGetCurrentContext());
+ glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE);
+ GPU_string_marker(sizeof(success), success);
#endif
return;
}
@@ -324,7 +320,7 @@ void GPU_print_error_debug(const char *str)
}
-void GPU_assert_no_gl_errors(const char* file, int line, const char* str)
+void GPU_assert_no_gl_errors(const char *file, int line, const char *str)
{
if (G.debug) {
GLboolean gl_ok = gpu_report_gl_errors(file, line, str);
diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c
index 74488e5928e..e1dff03d500 100644
--- a/source/blender/gpu/intern/gpu_extensions.c
+++ b/source/blender/gpu/intern/gpu_extensions.c
@@ -110,6 +110,7 @@ static struct GPUGlobal {
int glslsupport;
int extdisabled;
int colordepth;
+ int samples_color_texture_max;
int npotdisabled; /* ATI 3xx-5xx (and more) chipsets support NPoT partially (== not enough) */
int dlistsdisabled; /* Legacy ATI driver does not support display lists well */
GPUDeviceType device;
@@ -180,6 +181,10 @@ void gpu_extensions_init(void)
glGetIntegerv(GL_BLUE_BITS, &b);
GG.colordepth = r + g + b; /* assumes same depth for RGB */
+ if (GLEW_ARB_texture_multisample) {
+ glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES , &GG.samples_color_texture_max);
+ }
+
vendor = (const char *)glGetString(GL_VENDOR);
renderer = (const char *)glGetString(GL_RENDERER);
version = (const char *)glGetString(GL_VERSION);
@@ -380,15 +385,18 @@ static void GPU_print_framebuffer_error(GLenum status, char err_out[256])
struct GPUTexture {
int w, h; /* width/height */
+ int w_orig, h_orig; /* width/height (before power of 2 is applied) */
int number; /* number for multitexture binding */
int refcount; /* reference count */
GLenum target; /* GL_TEXTURE_* */
+ GLenum target_base; /* same as target, (but no multisample) */
GLuint bindcode; /* opengl identifier for texture */
int fromblender; /* we got the texture from Blender */
GPUFrameBuffer *fb; /* GPUFramebuffer this texture is attached to */
int fb_attachment; /* slot the texture is attached to */
int depth; /* is a depth texture? if 3D how deep? */
+ int depth_orig; /* depth (before power of 2 is applied) */
};
static unsigned char *GPU_texture_convert_pixels(int length, const float *fpixels)
@@ -419,7 +427,8 @@ static void GPU_glTexSubImageEmpty(GLenum target, GLenum format, int x, int y, i
}
static GPUTexture *GPU_texture_create_nD(
- int w, int h, int n, const float *fpixels, int depth, GPUHDRType hdr_type, int components,
+ int w, int h, int n, const float *fpixels, int depth,
+ GPUHDRType hdr_type, int components, int samples,
char err_out[256])
{
GPUTexture *tex;
@@ -429,13 +438,18 @@ static GPUTexture *GPU_texture_create_nD(
if (depth && !GLEW_ARB_depth_texture)
return NULL;
+ if (samples) {
+ CLAMP_MAX(samples, GG.samples_color_texture_max);
+ }
+
tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
- tex->w = w;
- tex->h = h;
+ tex->w = tex->w_orig = w;
+ tex->h = tex->h_orig = h;
tex->number = -1;
tex->refcount = 1;
- tex->target = (n == 1)? GL_TEXTURE_1D: GL_TEXTURE_2D;
- tex->depth = depth;
+ tex->target = (n == 1) ? GL_TEXTURE_1D : (samples ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D);
+ tex->target_base = (n == 1) ? GL_TEXTURE_1D : GL_TEXTURE_2D;
+ tex->depth = tex->depth_orig = depth;
tex->fb_attachment = -1;
glGenTextures(1, &tex->bindcode);
@@ -521,8 +535,13 @@ static GPUTexture *GPU_texture_create_nD(
}
}
else {
- glTexImage2D(tex->target, 0, internalformat, tex->w, tex->h, 0,
- format, type, NULL);
+ if (samples) {
+ glTexImage2DMultisample(tex->target, samples, internalformat, tex->w, tex->h, true);
+ }
+ else {
+ glTexImage2D(tex->target, 0, internalformat, tex->w, tex->h, 0,
+ format, type, NULL);
+ }
if (fpixels) {
glTexSubImage2D(tex->target, 0, 0, 0, w, h,
@@ -539,23 +558,23 @@ static GPUTexture *GPU_texture_create_nD(
MEM_freeN(pixels);
if (depth) {
- glTexParameteri(tex->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(tex->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(tex->target, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE);
- glTexParameteri(tex->target, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
- glTexParameteri(tex->target, GL_DEPTH_TEXTURE_MODE_ARB, GL_INTENSITY);
+ glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE);
+ glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
+ glTexParameteri(tex->target_base, GL_DEPTH_TEXTURE_MODE_ARB, GL_INTENSITY);
}
else {
- glTexParameteri(tex->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(tex->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
- if (tex->target != GL_TEXTURE_1D) {
- glTexParameteri(tex->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(tex->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ if (tex->target_base != GL_TEXTURE_1D) {
+ glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
else
- glTexParameteri(tex->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
return tex;
}
@@ -573,12 +592,13 @@ GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, const f
return NULL;
tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
- tex->w = w;
- tex->h = h;
- tex->depth = depth;
+ tex->w = tex->w_orig = w;
+ tex->h = tex->h_orig = h;
+ tex->depth = tex->depth_orig = depth;
tex->number = -1;
tex->refcount = 1;
tex->target = GL_TEXTURE_3D;
+ tex->target_base = GL_TEXTURE_3D;
glGenTextures(1, &tex->bindcode);
@@ -725,6 +745,7 @@ GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, bool is_data,
tex->number = -1;
tex->refcount = 1;
tex->target = GL_TEXTURE_2D;
+ tex->target_base = GL_TEXTURE_2D;
tex->fromblender = 1;
ima->gputexture= tex;
@@ -738,8 +759,8 @@ GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, bool is_data,
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_BORDER, &border);
- tex->w = w - border;
- tex->h = h - border;
+ tex->w = tex->w_orig = w - border;
+ tex->h = tex->h_orig = h - border;
}
glBindTexture(GL_TEXTURE_2D, lastbindcode);
@@ -773,6 +794,7 @@ GPUTexture *GPU_texture_from_preview(PreviewImage *prv, int mipmap)
tex->number = -1;
tex->refcount = 1;
tex->target = GL_TEXTURE_2D;
+ tex->target_base = GL_TEXTURE_2D;
prv->gputexture[0] = tex;
@@ -784,8 +806,8 @@ GPUTexture *GPU_texture_from_preview(PreviewImage *prv, int mipmap)
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h);
- tex->w = w;
- tex->h = h;
+ tex->w = tex->w_orig = w;
+ tex->h = tex->h_orig = h;
}
glBindTexture(GL_TEXTURE_2D, lastbindcode);
@@ -796,7 +818,7 @@ GPUTexture *GPU_texture_from_preview(PreviewImage *prv, int mipmap)
GPUTexture *GPU_texture_create_1D(int w, const float *fpixels, char err_out[256])
{
- GPUTexture *tex = GPU_texture_create_nD(w, 1, 1, fpixels, 0, GPU_HDR_NONE, 4, err_out);
+ GPUTexture *tex = GPU_texture_create_nD(w, 1, 1, fpixels, 0, GPU_HDR_NONE, 4, 0, err_out);
if (tex)
GPU_texture_unbind(tex);
@@ -806,30 +828,48 @@ GPUTexture *GPU_texture_create_1D(int w, const float *fpixels, char err_out[256]
GPUTexture *GPU_texture_create_2D(int w, int h, const float *fpixels, GPUHDRType hdr, char err_out[256])
{
- GPUTexture *tex = GPU_texture_create_nD(w, h, 2, fpixels, 0, hdr, 4, err_out);
+ GPUTexture *tex = GPU_texture_create_nD(w, h, 2, fpixels, 0, hdr, 4, 0, err_out);
if (tex)
GPU_texture_unbind(tex);
return tex;
}
+GPUTexture *GPU_texture_create_2D_multisample(int w, int h, const float *fpixels, GPUHDRType hdr, int samples, char err_out[256])
+{
+ GPUTexture *tex = GPU_texture_create_nD(w, h, 2, fpixels, 0, hdr, 4, samples, err_out);
+
+ if (tex)
+ GPU_texture_unbind(tex);
+
+ return tex;
+}
GPUTexture *GPU_texture_create_depth(int w, int h, char err_out[256])
{
- GPUTexture *tex = GPU_texture_create_nD(w, h, 2, NULL, 1, GPU_HDR_NONE, 1, err_out);
+ GPUTexture *tex = GPU_texture_create_nD(w, h, 2, NULL, 1, GPU_HDR_NONE, 1, 0, err_out);
if (tex)
GPU_texture_unbind(tex);
return tex;
}
+GPUTexture *GPU_texture_create_depth_multisample(int w, int h, int samples, char err_out[256])
+{
+ GPUTexture *tex = GPU_texture_create_nD(w, h, 2, NULL, 1, GPU_HDR_NONE, 1, samples, err_out);
+
+ if (tex)
+ GPU_texture_unbind(tex);
+
+ return tex;
+}
/**
* A shadow map for VSM needs two components (depth and depth^2)
*/
GPUTexture *GPU_texture_create_vsm_shadow_map(int size, char err_out[256])
{
- GPUTexture *tex = GPU_texture_create_nD(size, size, 2, NULL, 0, GPU_HDR_FULL_FLOAT, 2, err_out);
+ GPUTexture *tex = GPU_texture_create_nD(size, size, 2, NULL, 0, GPU_HDR_FULL_FLOAT, 2, 0, err_out);
if (tex) {
/* Now we tweak some of the settings */
@@ -844,7 +884,7 @@ GPUTexture *GPU_texture_create_vsm_shadow_map(int size, char err_out[256])
GPUTexture *GPU_texture_create_2D_procedural(int w, int h, const float *pixels, bool repeat, char err_out[256])
{
- GPUTexture *tex = GPU_texture_create_nD(w, h, 2, pixels, 0, GPU_HDR_HALF_FLOAT, 2, err_out);
+ GPUTexture *tex = GPU_texture_create_nD(w, h, 2, pixels, 0, GPU_HDR_HALF_FLOAT, 2, 0, err_out);
if (tex) {
/* Now we tweak some of the settings */
@@ -863,7 +903,7 @@ GPUTexture *GPU_texture_create_2D_procedural(int w, int h, const float *pixels,
GPUTexture *GPU_texture_create_1D_procedural(int w, const float *pixels, char err_out[256])
{
- GPUTexture *tex = GPU_texture_create_nD(w, 0, 1, pixels, 0, GPU_HDR_HALF_FLOAT, 2, err_out);
+ GPUTexture *tex = GPU_texture_create_nD(w, 0, 1, pixels, 0, GPU_HDR_HALF_FLOAT, 2, 0, err_out);
if (tex) {
/* Now we tweak some of the settings */
@@ -963,7 +1003,7 @@ void GPU_texture_unbind(GPUTexture *tex)
arbnumber = (GLenum)((GLuint)GL_TEXTURE0_ARB + tex->number);
if (tex->number != 0) glActiveTextureARB(arbnumber);
glBindTexture(tex->target, 0);
- glDisable(tex->target);
+ glDisable(tex->target_base);
if (tex->number != 0) glActiveTextureARB(GL_TEXTURE0_ARB);
tex->number = -1;
@@ -1187,8 +1227,12 @@ void GPU_texture_bind_as_framebuffer(GPUTexture *tex)
glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + tex->fb_attachment);
}
+ if (tex->target == GL_TEXTURE_2D_MULTISAMPLE) {
+ glEnable(GL_MULTISAMPLE_ARB);
+ }
+
/* push matrices and set default viewport and matrix */
- glViewport(0, 0, tex->w, tex->h);
+ glViewport(0, 0, tex->w_orig, tex->h_orig);
GG.currentfb = tex->fb->object;
glMatrixMode(GL_PROJECTION);
@@ -1226,7 +1270,7 @@ void GPU_framebuffer_slots_bind(GPUFrameBuffer *fb, int slot)
glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + slot);
/* push matrices and set default viewport and matrix */
- glViewport(0, 0, fb->colortex[slot]->w, fb->colortex[slot]->h);
+ glViewport(0, 0, fb->colortex[slot]->w_orig, fb->colortex[slot]->h_orig);
GG.currentfb = fb->object;
glMatrixMode(GL_PROJECTION);
@@ -1256,7 +1300,7 @@ void GPU_framebuffer_bind_no_save(GPUFrameBuffer *fb, int slot)
glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + slot);
/* push matrices and set default viewport and matrix */
- glViewport(0, 0, fb->colortex[slot]->w, fb->colortex[slot]->h);
+ glViewport(0, 0, fb->colortex[slot]->w_orig, fb->colortex[slot]->h_orig);
GG.currentfb = fb->object;
GG.currentfb = fb->object;
}
@@ -1316,8 +1360,8 @@ void GPU_framebuffer_restore(void)
void GPU_framebuffer_blur(GPUFrameBuffer *fb, GPUTexture *tex, GPUFrameBuffer *blurfb, GPUTexture *blurtex)
{
- const float scaleh[2] = {1.0f / GPU_texture_opengl_width(blurtex), 0.0f};
- const float scalev[2] = {0.0f, 1.0f / GPU_texture_opengl_height(tex)};
+ const float scaleh[2] = {1.0f / blurtex->w_orig, 0.0f};
+ const float scalev[2] = {0.0f, 1.0f / tex->h_orig};
GPUShader *blur_shader = GPU_shader_get_builtin_shader(GPU_SHADER_SEP_GAUSSIAN_BLUR);
int scale_uniform, texture_source_uniform;
@@ -1341,7 +1385,7 @@ void GPU_framebuffer_blur(GPUFrameBuffer *fb, GPUTexture *tex, GPUFrameBuffer *b
GPU_shader_bind(blur_shader);
GPU_shader_uniform_vector(blur_shader, scale_uniform, 2, 1, scaleh);
GPU_shader_uniform_texture(blur_shader, texture_source_uniform, tex);
- glViewport(0, 0, GPU_texture_opengl_width(blurtex), GPU_texture_opengl_height(blurtex));
+ glViewport(0, 0, blurtex->w_orig, blurtex->h_orig);
/* Peparing to draw quad */
glMatrixMode(GL_MODELVIEW);
@@ -1370,7 +1414,7 @@ void GPU_framebuffer_blur(GPUFrameBuffer *fb, GPUTexture *tex, GPUFrameBuffer *b
GG.currentfb = fb->object;
- glViewport(0, 0, GPU_texture_opengl_width(tex), GPU_texture_opengl_height(tex));
+ glViewport(0, 0, tex->w_orig, tex->h_orig);
GPU_shader_uniform_vector(blur_shader, scale_uniform, 2, 1, scalev);
GPU_shader_uniform_texture(blur_shader, texture_source_uniform, blurtex);
GPU_texture_bind(blurtex, 0);
@@ -1393,7 +1437,7 @@ struct GPUOffScreen {
GPUTexture *depth;
};
-GPUOffScreen *GPU_offscreen_create(int width, int height, char err_out[256])
+GPUOffScreen *GPU_offscreen_create(int width, int height, int samples, char err_out[256])
{
GPUOffScreen *ofs;
@@ -1405,7 +1449,22 @@ GPUOffScreen *GPU_offscreen_create(int width, int height, char err_out[256])
return NULL;
}
- ofs->depth = GPU_texture_create_depth(width, height, err_out);
+ if (samples) {
+ if (!GLEW_EXT_framebuffer_multisample ||
+ !GLEW_ARB_texture_multisample ||
+ /* Only needed for GPU_offscreen_read_pixels.
+ * We could add an arg if we intend to use multi-samle
+ * offscreen buffers w/o reading their pixels */
+ !GLEW_EXT_framebuffer_blit ||
+ /* This is required when blitting from a multi-sampled buffers,
+ * even though we're not scaling. */
+ !GLEW_EXT_framebuffer_multisample_blit_scaled)
+ {
+ samples = 0;
+ }
+ }
+
+ ofs->depth = GPU_texture_create_depth_multisample(width, height, samples, err_out);
if (!ofs->depth) {
GPU_offscreen_free(ofs);
return NULL;
@@ -1416,7 +1475,7 @@ GPUOffScreen *GPU_offscreen_create(int width, int height, char err_out[256])
return NULL;
}
- ofs->color = GPU_texture_create_2D(width, height, NULL, GPU_HDR_NONE, err_out);
+ ofs->color = GPU_texture_create_2D_multisample(width, height, NULL, GPU_HDR_NONE, samples, err_out);
if (!ofs->color) {
GPU_offscreen_free(ofs);
return NULL;
@@ -1470,17 +1529,96 @@ void GPU_offscreen_unbind(GPUOffScreen *ofs, bool restore)
void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels)
{
- glReadPixels(0, 0, ofs->color->w, ofs->color->h, GL_RGBA, type, pixels);
+ const int w = ofs->color->w_orig;
+ const int h = ofs->color->h_orig;
+
+ if (ofs->color->target == GL_TEXTURE_2D_MULTISAMPLE) {
+ /* For a multi-sample texture,
+ * we need to create an intermediate buffer to blit to,
+ * before its copied using 'glReadPixels' */
+
+ /* not needed since 'ofs' needs to be bound to the framebuffer already */
+// #define USE_FBO_CTX_SWITCH
+
+ GLuint fbo_blit = 0;
+ GLuint tex_blit = 0;
+ GLenum status;
+
+ /* create texture for new 'fbo_blit' */
+ glGenTextures(1, &tex_blit);
+ if (!tex_blit) {
+ goto finally;
+ }
+
+ glBindTexture(GL_TEXTURE_2D, tex_blit);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, type, 0);
+
+#ifdef USE_FBO_CTX_SWITCH
+ /* read from multi-sample buffer */
+ glBindFramebufferEXT(GL_READ_FRAMEBUFFER, ofs->color->fb->object);
+ glFramebufferTexture2DEXT(
+ GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + ofs->color->fb_attachment,
+ GL_TEXTURE_2D_MULTISAMPLE, ofs->color->bindcode, 0);
+ status = glCheckFramebufferStatus(GL_READ_FRAMEBUFFER);
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
+ goto finally;
+ }
+#endif
+
+ /* write into new single-sample buffer */
+ glGenFramebuffersEXT(1, &fbo_blit);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_blit);
+ glFramebufferTexture2DEXT(
+ GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_2D, tex_blit, 0);
+ status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
+ goto finally;
+ }
+
+ /* perform the copy */
+ glBlitFramebufferEXT(0, 0, w, h, 0, 0, w, h, GL_COLOR_BUFFER_BIT, GL_NEAREST);
+
+ /* read the results */
+ glBindFramebufferEXT(GL_READ_FRAMEBUFFER, fbo_blit);
+ glReadPixels(0, 0, w, h, GL_RGBA, type, pixels);
+
+#ifdef USE_FBO_CTX_SWITCH
+ /* restore the original frame-bufer */
+ glBindFramebufferEXT(GL_FRAMEBUFFER, ofs->color->fb->object);
+#undef USE_FBO_CTX_SWITCH
+#endif
+
+
+finally:
+ /* cleanup */
+ if (tex_blit) {
+ glDeleteTextures(1, &tex_blit);
+ }
+ if (fbo_blit) {
+ glDeleteFramebuffersEXT(1, &fbo_blit);
+ }
+
+ GPU_ASSERT_NO_GL_ERRORS("Read Multi-Sample Pixels");
+ }
+ else {
+ glReadPixels(0, 0, w, h, GL_RGBA, type, pixels);
+ }
}
int GPU_offscreen_width(const GPUOffScreen *ofs)
{
- return ofs->color->w;
+ return ofs->color->w_orig;
}
int GPU_offscreen_height(const GPUOffScreen *ofs)
{
- return ofs->color->h;
+ return ofs->color->h_orig;
+}
+
+int GPU_offscreen_color_texture(const GPUOffScreen *ofs)
+{
+ return ofs->color->bindcode;
}
/* GPUShader */
@@ -1679,16 +1817,42 @@ void GPU_program_parameter_4f(GPUProgram *program, unsigned int location, float
glProgramLocalParameter4fARB(program->type, location, x, y, z, w);
}
-
-
-GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, const char *geocode, const char *libcode, const char *defines, int input, int output, int number)
+GPUShader *GPU_shader_create(const char *vertexcode,
+ const char *fragcode,
+ const char *geocode,
+ const char *libcode,
+ const char *defines,
+ int input,
+ int output,
+ int number)
+{
+ return GPU_shader_create_ex(vertexcode,
+ fragcode,
+ geocode,
+ libcode,
+ defines,
+ input,
+ output,
+ number,
+ GPU_SHADER_FLAGS_NONE);
+}
+
+GPUShader *GPU_shader_create_ex(const char *vertexcode,
+ const char *fragcode,
+ const char *geocode,
+ const char *libcode,
+ const char *defines,
+ int input,
+ int output,
+ int number,
+ const int flags)
{
#ifdef WITH_OPENSUBDIV
/* TODO(sergey): used to add #version 150 to the geometry shader.
- * Could safely be renamed to "use_geometry_code" since it's evry much
- * liely any of geometry code will want to use GLSL 1.5.
+ * Could safely be renamed to "use_geometry_code" since it's very
+ * likely any of geometry code will want to use GLSL 1.5.
*/
- bool use_opensubdiv = geocode != NULL;
+ bool use_opensubdiv = (flags & GPU_SHADER_FLAGS_SPECIAL_OPENSUBDIV) != 0;
#else
bool use_opensubdiv = false;
#endif
@@ -1699,6 +1863,10 @@ GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, const
char standard_defines[MAX_DEFINE_LENGTH] = "";
char standard_extensions[MAX_EXT_DEFINE_LENGTH] = "";
+#ifndef WITH_OPENSUBDIV
+ UNUSED_VARS(flags);
+#endif
+
if (!GLEW_ARB_vertex_shader || !GLEW_ARB_fragment_shader || (geocode && !GPU_geometry_shader_support()))
return NULL;
diff --git a/source/blender/gpu/intern/gpu_init_exit.c b/source/blender/gpu/intern/gpu_init_exit.c
index 3a8a6fca23b..da4dd65d2e1 100644
--- a/source/blender/gpu/intern/gpu_init_exit.c
+++ b/source/blender/gpu/intern/gpu_init_exit.c
@@ -49,7 +49,7 @@ static bool initialized = false;
void GPU_init(void)
{
- /* can't avoid calling this multiple times, see wm_window_add_ghostwindow */
+ /* can't avoid calling this multiple times, see wm_window_ghostwindow_add */
if (initialized)
return;
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index 5b647232934..82902f8d69c 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -141,6 +141,7 @@ struct GPULamp {
float dynimat[4][4];
float spotsi, spotbl, k;
+ float spotvec[2];
float dyndist, dynatt1, dynatt2;
float dist, att1, att2;
float shadow_color[3];
@@ -536,12 +537,15 @@ static GPUNodeLink *lamp_get_visibility(GPUMaterial *mat, GPULamp *lamp, GPUNode
if (lamp->type == LA_SPOT) {
if (lamp->mode & LA_SQUARE) {
- mat->dynproperty |= DYN_LAMP_VEC|DYN_LAMP_IMAT;
- GPU_link(mat, "lamp_visibility_spot_square", GPU_dynamic_uniform(lamp->dynvec, GPU_DYNAMIC_LAMP_DYNVEC, lamp->ob), GPU_dynamic_uniform((float*)lamp->dynimat, GPU_DYNAMIC_LAMP_DYNIMAT, lamp->ob), *lv, &inpr);
+ mat->dynproperty |= DYN_LAMP_VEC | DYN_LAMP_IMAT;
+ GPU_link(mat, "lamp_visibility_spot_square", GPU_dynamic_uniform(lamp->dynvec, GPU_DYNAMIC_LAMP_DYNVEC, lamp->ob), GPU_dynamic_uniform((float*)lamp->dynimat, GPU_DYNAMIC_LAMP_DYNIMAT, lamp->ob),
+ GPU_dynamic_uniform((float *)lamp->spotvec, GPU_DYNAMIC_LAMP_SPOTSCALE, lamp->ob), *lv, &inpr);
}
else {
- mat->dynproperty |= DYN_LAMP_VEC;
- GPU_link(mat, "lamp_visibility_spot_circle", GPU_dynamic_uniform(lamp->dynvec, GPU_DYNAMIC_LAMP_DYNVEC, lamp->ob), *lv, &inpr);
+ mat->dynproperty |= DYN_LAMP_VEC | DYN_LAMP_IMAT;
+ GPU_link(mat, "lamp_visibility_spot_circle", GPU_dynamic_uniform(lamp->dynvec, GPU_DYNAMIC_LAMP_DYNVEC, lamp->ob),
+ GPU_dynamic_uniform((float *)lamp->dynimat, GPU_DYNAMIC_LAMP_DYNIMAT, lamp->ob),
+ GPU_dynamic_uniform((float *)lamp->spotvec, GPU_DYNAMIC_LAMP_SPOTSCALE, lamp->ob), *lv, &inpr);
}
GPU_link(mat, "lamp_visibility_spot", GPU_dynamic_uniform(&lamp->spotsi, GPU_DYNAMIC_LAMP_SPOTSIZE, lamp->ob), GPU_dynamic_uniform(&lamp->spotbl, GPU_DYNAMIC_LAMP_SPOTSIZE, lamp->ob), inpr, visifac, &visifac);
@@ -1854,24 +1858,41 @@ static void gpu_lamp_calc_winmat(GPULamp *lamp)
temp = 0.5f * lamp->size * cosf(angle) / sinf(angle);
pixsize = lamp->d / temp;
wsize = pixsize * 0.5f * lamp->size;
- perspective_m4(lamp->winmat, -wsize, wsize, -wsize, wsize, lamp->d, lamp->clipend);
+ if (lamp->type & LA_SPOT) {
+ /* compute shadows according to X and Y scaling factors */
+ perspective_m4(
+ lamp->winmat,
+ -wsize * lamp->spotvec[0], wsize * lamp->spotvec[0],
+ -wsize * lamp->spotvec[1], wsize * lamp->spotvec[1],
+ lamp->d, lamp->clipend);
+ }
+ else {
+ perspective_m4(lamp->winmat, -wsize, wsize, -wsize, wsize, lamp->d, lamp->clipend);
+ }
}
}
void GPU_lamp_update(GPULamp *lamp, int lay, int hide, float obmat[4][4])
{
float mat[4][4];
+ float obmat_scale[3];
lamp->lay = lay;
lamp->hide = hide;
- copy_m4_m4(mat, obmat);
- normalize_m4(mat);
+ normalize_m4_m4_ex(mat, obmat, obmat_scale);
copy_v3_v3(lamp->vec, mat[2]);
copy_v3_v3(lamp->co, mat[3]);
copy_m4_m4(lamp->obmat, mat);
invert_m4_m4(lamp->imat, mat);
+
+ /* update spotlamp scale on X and Y axis */
+ lamp->spotvec[0] = obmat_scale[0] / obmat_scale[2];
+ lamp->spotvec[1] = obmat_scale[1] / obmat_scale[2];
+
+ /* makeshadowbuf */
+ gpu_lamp_calc_winmat(lamp);
}
void GPU_lamp_update_colors(GPULamp *lamp, float r, float g, float b, float energy)
@@ -1895,8 +1916,6 @@ void GPU_lamp_update_spot(GPULamp *lamp, float spotsize, float spotblend)
{
lamp->spotsi = cosf(spotsize * 0.5f);
lamp->spotbl = (1.0f - lamp->spotsi) * spotblend;
-
- gpu_lamp_calc_winmat(lamp);
}
static void gpu_lamp_from_blender(Scene *scene, Object *ob, Object *par, Lamp *la, GPULamp *lamp)
@@ -1941,9 +1960,6 @@ static void gpu_lamp_from_blender(Scene *scene, Object *ob, Object *par, Lamp *l
/* arbitrary correction for the fact we do no soft transition */
lamp->bias *= 0.25f;
-
- /* makeshadowbuf */
- gpu_lamp_calc_winmat(lamp);
}
static void gpu_lamp_shadow_free(GPULamp *lamp)
diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl
index 311fcb8ead2..5b62739b0eb 100644
--- a/source/blender/gpu/shaders/gpu_shader_material.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_material.glsl
@@ -1584,11 +1584,13 @@ void lamp_visibility_sphere(float lampdist, float dist, float visifac, out float
outvisifac= visifac*max(t, 0.0)/lampdist;
}
-void lamp_visibility_spot_square(vec3 lampvec, mat4 lampimat, vec3 lv, out float inpr)
+void lamp_visibility_spot_square(vec3 lampvec, mat4 lampimat, vec2 scale, vec3 lv, out float inpr)
{
if(dot(lv, lampvec) > 0.0) {
vec3 lvrot = (lampimat*vec4(lv, 0.0)).xyz;
- float x = max(abs(lvrot.x/lvrot.z), abs(lvrot.y/lvrot.z));
+ /* without clever non-uniform scale, we could do: */
+ // float x = max(abs(lvrot.x / lvrot.z), abs(lvrot.y / lvrot.z));
+ float x = max(abs((lvrot.x / scale.x) / lvrot.z), abs((lvrot.y / scale.y) / lvrot.z));
inpr = 1.0/sqrt(1.0 + x*x);
}
@@ -1596,9 +1598,21 @@ void lamp_visibility_spot_square(vec3 lampvec, mat4 lampimat, vec3 lv, out float
inpr = 0.0;
}
-void lamp_visibility_spot_circle(vec3 lampvec, vec3 lv, out float inpr)
+void lamp_visibility_spot_circle(vec3 lampvec, mat4 lampimat, vec2 scale, vec3 lv, out float inpr)
{
- inpr = dot(lv, lampvec);
+ /* without clever non-uniform scale, we could do: */
+ // inpr = dot(lv, lampvec);
+ if (dot(lv, lampvec) > 0.0) {
+ vec3 lvrot = (lampimat * vec4(lv, 0.0)).xyz;
+ float x = abs(lvrot.x / lvrot.z);
+ float y = abs(lvrot.y / lvrot.z);
+
+ float ellipse = abs((x * x) / (scale.x * scale.x) + (y * y) / (scale.y * scale.y));
+
+ inpr = 1.0 / sqrt(1.0 + ellipse);
+ }
+ else
+ inpr = 0.0;
}
void lamp_visibility_spot(float spotsi, float spotbl, float inpr, float visifac, out float outvisifac)
diff --git a/source/blender/imbuf/CMakeLists.txt b/source/blender/imbuf/CMakeLists.txt
index bdd8230a6ff..295a48dc245 100644
--- a/source/blender/imbuf/CMakeLists.txt
+++ b/source/blender/imbuf/CMakeLists.txt
@@ -120,7 +120,7 @@ if(WITH_IMAGE_OPENJPEG)
intern/jp2.c
)
- add_definitions(-DWITH_OPENJPEG)
+ add_definitions(-DWITH_OPENJPEG ${OPENJPEG_DEFINES})
endif()
if(WITH_IMAGE_REDCODE)
diff --git a/source/blender/imbuf/IMB_imbuf_types.h b/source/blender/imbuf/IMB_imbuf_types.h
index 08ce9c0469b..e9dcf2da723 100644
--- a/source/blender/imbuf/IMB_imbuf_types.h
+++ b/source/blender/imbuf/IMB_imbuf_types.h
@@ -67,32 +67,34 @@ typedef struct DDSData {
*/
/* ibuf->ftype flag, main image types */
+/* Warning: Keep explicit value assignements here, this file is included in areas where not all format defines
+ * are set (e.g. intern/dds only get WITH_DDS, even if TIFF, HDR etc are also defined). See T46524. */
enum eImbTypes {
- IMB_FTYPE_PNG = 1,
- IMB_FTYPE_TGA,
- IMB_FTYPE_JPG,
- IMB_FTYPE_BMP,
- IMB_FTYPE_OPENEXR,
- IMB_FTYPE_IMAGIC,
+ IMB_FTYPE_PNG = 1,
+ IMB_FTYPE_TGA = 2,
+ IMB_FTYPE_JPG = 3,
+ IMB_FTYPE_BMP = 4,
+ IMB_FTYPE_OPENEXR = 5,
+ IMB_FTYPE_IMAGIC = 6,
#ifdef WITH_OPENIMAGEIO
- IMB_FTYPE_PSD,
+ IMB_FTYPE_PSD = 7,
#endif
#ifdef WITH_OPENJPEG
- IMB_FTYPE_JP2,
+ IMB_FTYPE_JP2 = 8,
#endif
#ifdef WITH_HDR
- IMB_FTYPE_RADHDR,
+ IMB_FTYPE_RADHDR = 9,
#endif
#ifdef WITH_TIFF
- IMB_FTYPE_TIF,
+ IMB_FTYPE_TIF = 10,
#endif
#ifdef WITH_CINEON
- IMB_FTYPE_CINEON,
- IMB_FTYPE_DPX,
+ IMB_FTYPE_CINEON = 11,
+ IMB_FTYPE_DPX = 12,
#endif
#ifdef WITH_DDS
- IMB_FTYPE_DDS,
+ IMB_FTYPE_DDS = 13,
#endif
};
@@ -124,12 +126,6 @@ enum eImbTypes {
#define RAWTGA 1
-#define JPG_STD 0
-#define JPG_VID 1
-#define JPG_JST 2
-#define JPG_MAX 3
-#define JPG_MSK 0x03
-
#ifdef WITH_TIFF
#define TIF_16BIT (1 << 8 )
#endif
diff --git a/source/blender/imbuf/IMB_thumbs.h b/source/blender/imbuf/IMB_thumbs.h
index aaa5eea04ad..6ca4b919c1d 100644
--- a/source/blender/imbuf/IMB_thumbs.h
+++ b/source/blender/imbuf/IMB_thumbs.h
@@ -63,7 +63,7 @@ typedef enum ThumbSource {
#define PREVIEW_RENDER_DEFAULT_HEIGHT 128
-/* Note this can also be used as versionning system,
+/* Note this can also be used as versioning system,
* to force refreshing all thumbnails if e.g. we change some thumb generating code or so.
* Only used by fonts so far. */
#define THUMB_DEFAULT_HASH "00000000000000000000000000000000"
diff --git a/source/blender/imbuf/intern/IMB_allocimbuf.h b/source/blender/imbuf/intern/IMB_allocimbuf.h
index f4d6d869f1b..a754a4919eb 100644
--- a/source/blender/imbuf/intern/IMB_allocimbuf.h
+++ b/source/blender/imbuf/intern/IMB_allocimbuf.h
@@ -38,6 +38,18 @@ struct ImBuf;
void imb_refcounter_lock_init(void);
void imb_refcounter_lock_exit(void);
+#ifdef WIN32
+void imb_mmap_lock_init(void);
+void imb_mmap_lock_exit(void);
+void imb_mmap_lock(void);
+void imb_mmap_unlock(void);
+#else
+# define imb_mmap_lock_init()
+# define imb_mmap_lock_exit()
+# define imb_mmap_lock()
+# define imb_mmap_unlock()
+#endif
+
bool imb_addencodedbufferImBuf(struct ImBuf *ibuf);
bool imb_enlargeencodedbufferImBuf(struct ImBuf *ibuf);
diff --git a/source/blender/imbuf/intern/allocimbuf.c b/source/blender/imbuf/intern/allocimbuf.c
index 9042c4bd09c..19b68b17e70 100644
--- a/source/blender/imbuf/intern/allocimbuf.c
+++ b/source/blender/imbuf/intern/allocimbuf.c
@@ -62,6 +62,30 @@ void imb_refcounter_lock_exit(void)
BLI_spin_end(&refcounter_spin);
}
+#ifdef WIN32
+static SpinLock mmap_spin;
+
+void imb_mmap_lock_init(void)
+{
+ BLI_spin_init(&mmap_spin);
+}
+
+void imb_mmap_lock_exit(void)
+{
+ BLI_spin_end(&mmap_spin);
+}
+
+void imb_mmap_lock(void)
+{
+ BLI_spin_lock(&mmap_spin);
+}
+
+void imb_mmap_unlock(void)
+{
+ BLI_spin_unlock(&mmap_spin);
+}
+#endif
+
void imb_freemipmapImBuf(ImBuf *ibuf)
{
int a;
@@ -128,6 +152,13 @@ void imb_freetilesImBuf(ImBuf *ibuf)
ibuf->mall &= ~IB_tiles;
}
+static void imb_free_bitmap_font(ImBuf *ibuf)
+{
+ if (ibuf->userdata && (ibuf->userflags & IB_BITMAPFONT)) {
+ MEM_freeN(ibuf->userdata);
+ }
+}
+
static void freeencodedbufferImBuf(ImBuf *ibuf)
{
if (ibuf == NULL) return;
@@ -181,6 +212,7 @@ void IMB_freeImBuf(ImBuf *ibuf)
imb_freerectImBuf(ibuf);
imb_freerectfloatImBuf(ibuf);
imb_freetilesImBuf(ibuf);
+ imb_free_bitmap_font(ibuf);
IMB_freezbufImBuf(ibuf);
IMB_freezbuffloatImBuf(ibuf);
freeencodedbufferImBuf(ibuf);
@@ -206,7 +238,18 @@ ImBuf *IMB_makeSingleUser(ImBuf *ibuf)
{
ImBuf *rval;
- if (!ibuf || ibuf->refcounter == 0) { return ibuf; }
+ if (ibuf) {
+ bool is_single;
+ BLI_spin_lock(&refcounter_spin);
+ is_single = (ibuf->refcounter == 0);
+ BLI_spin_unlock(&refcounter_spin);
+ if (is_single) {
+ return ibuf;
+ }
+ }
+ else {
+ return NULL;
+ }
rval = IMB_dupImBuf(ibuf);
diff --git a/source/blender/imbuf/intern/dds/ColorBlock.cpp b/source/blender/imbuf/intern/dds/ColorBlock.cpp
index 28f31fcad8b..dd4ae3e518e 100644
--- a/source/blender/imbuf/intern/dds/ColorBlock.cpp
+++ b/source/blender/imbuf/intern/dds/ColorBlock.cpp
@@ -38,6 +38,7 @@
#include <Image.h>
#include <Common.h>
+#if 0
// Get approximate luminance.
inline static uint colorLuminance(Color32 c)
{
@@ -49,6 +50,7 @@
{
return (c0.r - c1.r) * (c0.r - c1.r) + (c0.g - c1.g) * (c0.g - c1.g) + (c0.b - c1.b) * (c0.b - c1.b);
}
+#endif
/// Default constructor.
@@ -86,8 +88,8 @@ void ColorBlock::init(const Image *img, uint x, uint y)
void ColorBlock::init(uint w, uint h, const uint *data, uint x, uint y)
{
- const uint bw = min(w - x, 4U);
- const uint bh = min(h - y, 4U);
+ const uint bw = MIN(w - x, 4U);
+ const uint bh = MIN(h - y, 4U);
// Blocks that are smaller than 4x4 are handled by repeating the pixels.
// @@ Thats only correct when block size is 1, 2 or 4, but not with 3. :(
@@ -107,8 +109,8 @@ void ColorBlock::init(uint w, uint h, const uint *data, uint x, uint y)
void ColorBlock::init(uint w, uint h, const float *data, uint x, uint y)
{
- const uint bw = min(w - x, 4U);
- const uint bh = min(h - y, 4U);
+ const uint bw = MIN(w - x, 4U);
+ const uint bh = MIN(h - y, 4U);
// Blocks that are smaller than 4x4 are handled by repeating the pixels.
// @@ Thats only correct when block size is 1, 2 or 4, but not with 3. :(
@@ -124,10 +126,10 @@ void ColorBlock::init(uint w, uint h, const float *data, uint x, uint y)
const uint idx = ((y + by) * w + x + bx);
Color32 & c = color(e, i);
- c.r = uint8(255 * clamp(data[idx + 0 * srcPlane], 0.0f, 1.0f)); // @@ Is this the right way to quantize floats to bytes?
- c.g = uint8(255 * clamp(data[idx + 1 * srcPlane], 0.0f, 1.0f));
- c.b = uint8(255 * clamp(data[idx + 2 * srcPlane], 0.0f, 1.0f));
- c.a = uint8(255 * clamp(data[idx + 3 * srcPlane], 0.0f, 1.0f));
+ c.r = uint8(255 * CLAMP(data[idx + 0 * srcPlane], 0.0f, 1.0f)); // @@ Is this the right way to quantize floats to bytes?
+ c.g = uint8(255 * CLAMP(data[idx + 1 * srcPlane], 0.0f, 1.0f));
+ c.b = uint8(255 * CLAMP(data[idx + 2 * srcPlane], 0.0f, 1.0f));
+ c.a = uint8(255 * CLAMP(data[idx + 3 * srcPlane], 0.0f, 1.0f));
}
}
}
diff --git a/source/blender/imbuf/intern/dds/Common.h b/source/blender/imbuf/intern/dds/Common.h
index ab929b82264..b1beb3f3a1b 100644
--- a/source/blender/imbuf/intern/dds/Common.h
+++ b/source/blender/imbuf/intern/dds/Common.h
@@ -28,14 +28,14 @@
#ifndef __COMMON_H__
#define __COMMON_H__
-#ifndef min
-#define min(a,b) ((a) <= (b) ? (a) : (b))
+#ifndef MIN
+#define MIN(a,b) ((a) <= (b) ? (a) : (b))
#endif
-#ifndef max
-#define max(a,b) ((a) >= (b) ? (a) : (b))
+#ifndef MAX
+#define MAX(a,b) ((a) >= (b) ? (a) : (b))
#endif
-#ifndef clamp
-#define clamp(x,a,b) min(max((x), (a)), (b))
+#ifndef CLAMP
+#define CLAMP(x,a,b) MIN(MAX((x), (a)), (b))
#endif
template<typename T>
diff --git a/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp b/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp
index 6bf82776afe..a4281514e39 100644
--- a/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp
+++ b/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp
@@ -83,7 +83,7 @@ static const uint FOURCC_RXGB = DDS_MAKEFOURCC('R', 'X', 'G', 'B');
static const uint FOURCC_ATI1 = DDS_MAKEFOURCC('A', 'T', 'I', '1');
static const uint FOURCC_ATI2 = DDS_MAKEFOURCC('A', 'T', 'I', '2');
-static const uint FOURCC_A2XY = DDS_MAKEFOURCC('A', '2', 'X', 'Y');
+//static const uint FOURCC_A2XY = DDS_MAKEFOURCC('A', '2', 'X', 'Y');
static const uint FOURCC_DX10 = DDS_MAKEFOURCC('D', 'X', '1', '0');
@@ -107,25 +107,25 @@ static const uint D3DFMT_X8B8G8R8 = 33;
static const uint D3DFMT_G16R16 = 34;
static const uint D3DFMT_A2R10G10B10 = 35;
-static const uint D3DFMT_A16B16G16R16 = 36;
+//static const uint D3DFMT_A16B16G16R16 = 36;
// Palette formats.
-static const uint D3DFMT_A8P8 = 40;
-static const uint D3DFMT_P8 = 41;
+//static const uint D3DFMT_A8P8 = 40;
+//static const uint D3DFMT_P8 = 41;
// Luminance formats.
static const uint D3DFMT_L8 = 50;
-static const uint D3DFMT_A8L8 = 51;
-static const uint D3DFMT_A4L4 = 52;
+//static const uint D3DFMT_A8L8 = 51;
+//static const uint D3DFMT_A4L4 = 52;
static const uint D3DFMT_L16 = 81;
// Floating point formats
-static const uint D3DFMT_R16F = 111;
-static const uint D3DFMT_G16R16F = 112;
-static const uint D3DFMT_A16B16G16R16F = 113;
-static const uint D3DFMT_R32F = 114;
-static const uint D3DFMT_G32R32F = 115;
-static const uint D3DFMT_A32B32G32R32F = 116;
+//static const uint D3DFMT_R16F = 111;
+//static const uint D3DFMT_G16R16F = 112;
+//static const uint D3DFMT_A16B16G16R16F = 113;
+//static const uint D3DFMT_R32F = 114;
+//static const uint D3DFMT_G32R32F = 115;
+//static const uint D3DFMT_A32B32G32R32F = 116;
static const uint DDSD_CAPS = 0x00000001U;
static const uint DDSD_PIXELFORMAT = 0x00001000U;
@@ -1102,8 +1102,8 @@ void DirectDrawSurface::mipmap(Image *img, uint face, uint mipmap)
// Compute width and height.
for (uint m = 0; m < mipmap; m++)
{
- w = max(1U, w / 2);
- h = max(1U, h / 2);
+ w = MAX(1U, w / 2);
+ h = MAX(1U, h / 2);
}
img->allocate(w, h);
@@ -1223,9 +1223,9 @@ void DirectDrawSurface::readBlockImage(Image *img)
readBlock(&block);
// Write color block.
- for (uint y = 0; y < min(4U, h-4*by); y++)
+ for (uint y = 0; y < MIN(4U, h-4*by); y++)
{
- for (uint x = 0; x < min(4U, w-4*bx); x++)
+ for (uint x = 0; x < MIN(4U, w-4*bx); x++)
{
img->pixel(4*bx+x, 4*by+y) = block.color(x, y);
}
@@ -1240,7 +1240,7 @@ static Color32 buildNormal(uint8 x, uint8 y)
float ny = 2 * (y / 255.0f) - 1;
float nz = 0.0f;
if (1 - nx*nx - ny*ny > 0) nz = sqrt(1 - nx*nx - ny*ny);
- uint8 z = clamp(int(255.0f * (nz + 1) / 2.0f), 0, 255);
+ uint8 z = CLAMP(int(255.0f * (nz + 1) / 2.0f), 0, 255);
return Color32(x, y, z);
}
@@ -1379,9 +1379,9 @@ uint DirectDrawSurface::mipmapSize(uint mipmap) const
for (uint m = 0; m < mipmap; m++)
{
- w = max(1U, w / 2);
- h = max(1U, h / 2);
- d = max(1U, d / 2);
+ w = MAX(1U, w / 2);
+ h = MAX(1U, h / 2);
+ d = MAX(1U, d / 2);
}
if (header.pf.flags & DDPF_FOURCC)
diff --git a/source/blender/imbuf/intern/dds/FlipDXT.cpp b/source/blender/imbuf/intern/dds/FlipDXT.cpp
index 4f63d17dc90..604796d1705 100644
--- a/source/blender/imbuf/intern/dds/FlipDXT.cpp
+++ b/source/blender/imbuf/intern/dds/FlipDXT.cpp
@@ -246,8 +246,8 @@ int FlipDXTCImage(unsigned int width, unsigned int height, unsigned int levels,
// mip levels are contiguous.
data += block_bytes * blocks;
- mip_width = max(1U, mip_width >> 1);
- mip_height = max(1U, mip_height >> 1);
+ mip_width = MAX(1U, mip_width >> 1);
+ mip_height = MAX(1U, mip_height >> 1);
}
return 1;
diff --git a/source/blender/imbuf/intern/jpeg.c b/source/blender/imbuf/intern/jpeg.c
index ff2a9767386..35c7b6363a1 100644
--- a/source/blender/imbuf/intern/jpeg.c
+++ b/source/blender/imbuf/intern/jpeg.c
@@ -54,12 +54,6 @@
#include "IMB_colormanagement.h"
#include "IMB_colormanagement_intern.h"
-// #define IS_jpg(x) (x->ftype & JPG) // UNUSED
-#define IS_stdjpg(x) ((x->foptions.flag & JPG_MSK) == JPG_STD)
-// #define IS_vidjpg(x) ((x->foptions & JPG_MSK) == JPG_VID) // UNUSED
-#define IS_jstjpg(x) ((x->foptions.flag & JPG_MSK) == JPG_JST)
-#define IS_maxjpg(x) ((x->foptions.flag & JPG_MSK) == JPG_MAX)
-
/* the types are from the jpeg lib */
static void jpeg_error(j_common_ptr cinfo) ATTR_NORETURN;
static void init_source(j_decompress_ptr cinfo);
@@ -70,22 +64,8 @@ static void memory_source(j_decompress_ptr cinfo, const unsigned char *buffer, s
static boolean handle_app1(j_decompress_ptr cinfo);
static ImBuf *ibJpegImageFromCinfo(struct jpeg_decompress_struct *cinfo, int flags);
-
-/*
- * In principle there are 4 jpeg formats.
- *
- * 1. jpeg - standard printing, u & v at quarter of resolution
- * 2. jvid - standard video, u & v half resolution, frame not interlaced
- *
- * type 3 is unsupported as of jul 05 2000 Frank.
- *
- * 3. jstr - as 2, but written in 2 separate fields
- *
- * 4. jmax - no scaling in the components
- */
-
-static int jpeg_default_quality;
-static int ibuf_foptions;
+static const uchar jpeg_default_quality = 75;
+static uchar ibuf_quality;
int imb_is_a_jpeg(const unsigned char *mem)
{
@@ -254,6 +234,13 @@ static void memory_source(j_decompress_ptr cinfo, const unsigned char *buffer, s
bytes_in_buffer--; \
V += GETJOCTET(*next_input_byte++); )
+struct NeoGeo_Word {
+ uchar pad1;
+ uchar pad2;
+ uchar pad3;
+ uchar quality;
+} ;
+BLI_STATIC_ASSERT(sizeof(struct NeoGeo_Word) == 4, "Must be 4 bytes");
static boolean handle_app1(j_decompress_ptr cinfo)
{
@@ -267,13 +254,19 @@ static boolean handle_app1(j_decompress_ptr cinfo)
length -= 2;
if (length < 16) {
- for (i = 0; i < length; i++) INPUT_BYTE(cinfo, neogeo[i], return false);
+ for (i = 0; i < length; i++) {
+ INPUT_BYTE(cinfo, neogeo[i], return false);
+ }
length = 0;
- if (STREQLEN(neogeo, "NeoGeo", 6)) memcpy(&ibuf_foptions, neogeo + 6, 4);
- ibuf_foptions = BIG_LONG(ibuf_foptions);
+ if (STREQLEN(neogeo, "NeoGeo", 6)) {
+ struct NeoGeo_Word *neogeo_word = (struct NeoGeo_Word *)(neogeo + 6);
+ ibuf_quality = neogeo_word->quality;
+ }
}
INPUT_SYNC(cinfo); /* do before skip_input_data */
- if (length > 0) (*cinfo->src->skip_input_data)(cinfo, length);
+ if (length > 0) {
+ (*cinfo->src->skip_input_data)(cinfo, length);
+ }
return true;
}
@@ -290,7 +283,7 @@ static ImBuf *ibJpegImageFromCinfo(struct jpeg_decompress_struct *cinfo, int fla
char *str, *key, *value;
/* install own app1 handler */
- ibuf_foptions = 0;
+ ibuf_quality = jpeg_default_quality;
jpeg_set_marker_processor(cinfo, 0xe1, handle_app1);
cinfo->dct_method = JDCT_FLOAT;
jpeg_save_markers(cinfo, JPEG_COM, 0xffff);
@@ -304,14 +297,6 @@ static ImBuf *ibJpegImageFromCinfo(struct jpeg_decompress_struct *cinfo, int fla
jpeg_start_decompress(cinfo);
- if (ibuf_foptions == 0) {
- ibuf_foptions = JPG_STD;
- if (cinfo->max_v_samp_factor == 1) {
- if (cinfo->max_h_samp_factor == 1) ibuf_foptions = JPG_MAX;
- else ibuf_foptions = JPG_VID;
- }
- }
-
if (flags & IB_test) {
jpeg_abort_decompress(cinfo);
ibuf = IMB_allocImBuf(x, y, 8 * depth, 0);
@@ -436,7 +421,7 @@ next_stamp_marker:
jpeg_destroy((j_common_ptr) cinfo);
if (ibuf) {
ibuf->ftype = IMB_FTYPE_JPG;
- ibuf->foptions.flag = ibuf_foptions;
+ ibuf->foptions.quality = MIN2(ibuf_quality, 100);
}
}
@@ -481,16 +466,16 @@ static void write_jpeg(struct jpeg_compress_struct *cinfo, struct ImBuf *ibuf)
uchar *rect;
int x, y;
char neogeo[128];
+ struct NeoGeo_Word *neogeo_word;
char *text;
jpeg_start_compress(cinfo, true);
strcpy(neogeo, "NeoGeo");
- ibuf_foptions = BIG_LONG((((int)ibuf->foptions.flag) << 8) | (int)ibuf->foptions.quality);
-
- memcpy(neogeo + 6, &ibuf_foptions, 4);
+ neogeo_word = (struct NeoGeo_Word *)(neogeo + 6);
+ memset(neogeo_word, 0, sizeof(*neogeo_word));
+ neogeo_word->quality = ibuf->foptions.quality;
jpeg_write_marker(cinfo, 0xe1, (JOCTET *) neogeo, 10);
-
if (ibuf->metadata) {
IDProperty *prop;
/* key + max value + "Blender" */
@@ -613,113 +598,8 @@ static int save_stdjpeg(const char *name, struct ImBuf *ibuf)
struct jpeg_compress_struct _cinfo, *cinfo = &_cinfo;
struct my_error_mgr jerr;
- if ((outfile = BLI_fopen(name, "wb")) == NULL) return 0;
- jpeg_default_quality = 75;
-
- cinfo->err = jpeg_std_error(&jerr.pub);
- jerr.pub.error_exit = jpeg_error;
-
- /* Establish the setjmp return context for jpeg_error to use. */
- if (setjmp(jerr.setjmp_buffer)) {
- /* If we get here, the JPEG code has signaled an error.
- * We need to clean up the JPEG object, close the input file, and return.
- */
- jpeg_destroy_compress(cinfo);
- fclose(outfile);
- remove(name);
+ if ((outfile = BLI_fopen(name, "wb")) == NULL)
return 0;
- }
-
- init_jpeg(outfile, cinfo, ibuf);
-
- write_jpeg(cinfo, ibuf);
-
- fclose(outfile);
- jpeg_destroy_compress(cinfo);
-
- return 1;
-}
-
-
-static int save_vidjpeg(const char *name, struct ImBuf *ibuf)
-{
- FILE *outfile;
- struct jpeg_compress_struct _cinfo, *cinfo = &_cinfo;
- struct my_error_mgr jerr;
-
- if ((outfile = BLI_fopen(name, "wb")) == NULL) return 0;
- jpeg_default_quality = 90;
-
- cinfo->err = jpeg_std_error(&jerr.pub);
- jerr.pub.error_exit = jpeg_error;
-
- /* Establish the setjmp return context for jpeg_error to use. */
- if (setjmp(jerr.setjmp_buffer)) {
- /* If we get here, the JPEG code has signaled an error.
- * We need to clean up the JPEG object, close the input file, and return.
- */
- jpeg_destroy_compress(cinfo);
- fclose(outfile);
- remove(name);
- return 0;
- }
-
- init_jpeg(outfile, cinfo, ibuf);
-
- /* adjust scaling factors */
- if (cinfo->in_color_space == JCS_RGB) {
- cinfo->comp_info[0].h_samp_factor = 2;
- cinfo->comp_info[0].v_samp_factor = 1;
- }
-
- write_jpeg(cinfo, ibuf);
-
- fclose(outfile);
- jpeg_destroy_compress(cinfo);
-
- return 1;
-}
-
-static int save_jstjpeg(const char *name, struct ImBuf *ibuf)
-{
- char fieldname[1024];
- struct ImBuf *tbuf;
- int oldy, returnval;
-
- tbuf = IMB_allocImBuf(ibuf->x, ibuf->y / 2, 24, IB_rect);
- tbuf->ftype = ibuf->ftype;
- tbuf->foptions = ibuf->foptions;
- tbuf->flags = ibuf->flags;
-
- oldy = ibuf->y;
- ibuf->x *= 2;
- ibuf->y /= 2;
-
- IMB_rectcpy(tbuf, ibuf, 0, 0, 0, 0, ibuf->x, ibuf->y);
- sprintf(fieldname, "%s.jf0", name);
-
- returnval = save_vidjpeg(fieldname, tbuf);
- if (returnval == 1) {
- IMB_rectcpy(tbuf, ibuf, 0, 0, tbuf->x, 0, ibuf->x, ibuf->y);
- sprintf(fieldname, "%s.jf1", name);
- returnval = save_vidjpeg(fieldname, tbuf);
- }
-
- ibuf->y = oldy;
- ibuf->x /= 2;
- IMB_freeImBuf(tbuf);
-
- return returnval;
-}
-
-static int save_maxjpeg(const char *name, struct ImBuf *ibuf)
-{
- FILE *outfile;
- struct jpeg_compress_struct _cinfo, *cinfo = &_cinfo;
- struct my_error_mgr jerr;
-
- if ((outfile = BLI_fopen(name, "wb")) == NULL) return 0;
- jpeg_default_quality = 100;
cinfo->err = jpeg_std_error(&jerr.pub);
jerr.pub.error_exit = jpeg_error;
@@ -737,12 +617,6 @@ static int save_maxjpeg(const char *name, struct ImBuf *ibuf)
init_jpeg(outfile, cinfo, ibuf);
- /* adjust scaling factors */
- if (cinfo->in_color_space == JCS_RGB) {
- cinfo->comp_info[0].h_samp_factor = 1;
- cinfo->comp_info[0].v_samp_factor = 1;
- }
-
write_jpeg(cinfo, ibuf);
fclose(outfile);
@@ -755,9 +629,5 @@ int imb_savejpeg(struct ImBuf *ibuf, const char *name, int flags)
{
ibuf->flags = flags;
- if (IS_stdjpg(ibuf)) return save_stdjpeg(name, ibuf);
- if (IS_jstjpg(ibuf)) return save_jstjpeg(name, ibuf);
- if (IS_maxjpg(ibuf)) return save_maxjpeg(name, ibuf);
- return save_vidjpeg(name, ibuf);
+ return save_stdjpeg(name, ibuf);
}
-
diff --git a/source/blender/imbuf/intern/module.c b/source/blender/imbuf/intern/module.c
index 4097deb00ed..777fe77f032 100644
--- a/source/blender/imbuf/intern/module.c
+++ b/source/blender/imbuf/intern/module.c
@@ -37,6 +37,7 @@
void IMB_init(void)
{
imb_refcounter_lock_init();
+ imb_mmap_lock_init();
imb_filetypes_init();
imb_tile_cache_init();
colormanagement_init();
@@ -47,6 +48,7 @@ void IMB_exit(void)
imb_tile_cache_exit();
imb_filetypes_exit();
colormanagement_exit();
+ imb_mmap_lock_exit();
imb_refcounter_lock_exit();
}
diff --git a/source/blender/imbuf/intern/radiance_hdr.c b/source/blender/imbuf/intern/radiance_hdr.c
index f97860cc66c..71e74928e20 100644
--- a/source/blender/imbuf/intern/radiance_hdr.c
+++ b/source/blender/imbuf/intern/radiance_hdr.c
@@ -37,13 +37,10 @@
* ----------------------------------------------------------------------
*/
-#ifdef WIN32
-# include "BLI_utildefines.h"
-#endif
-
#include "MEM_guardedalloc.h"
#include "BLI_fileops.h"
+#include "BLI_utildefines.h"
#include "imbuf.h"
@@ -76,7 +73,7 @@ static const unsigned char *oldreadcolrs(RGBE *scan, const unsigned char *mem, i
{
int i, rshift = 0, len = xmax;
while (len > 0) {
- if (mem_eof - mem < 4) {
+ if (UNLIKELY(mem_eof - mem < 4)) {
return NULL;
}
scan[0][RED] = *mem++;
@@ -104,11 +101,11 @@ static const unsigned char *freadcolrs(RGBE *scan, const unsigned char *mem, int
{
int i, j, code, val;
- if (mem_eof - mem < 4) {
+ if (UNLIKELY(mem_eof - mem < 4)) {
return NULL;
}
- if ((xmax < MINELEN) | (xmax > MAXELEN)) {
+ if (UNLIKELY((xmax < MINELEN) | (xmax > MAXELEN))) {
return oldreadcolrs(scan, mem, xmax, mem_eof);
}
@@ -128,25 +125,31 @@ static const unsigned char *freadcolrs(RGBE *scan, const unsigned char *mem, int
return oldreadcolrs(scan + 1, mem, xmax - 1, mem_eof);
}
- if (((scan[0][BLU] << 8) | i) != xmax) {
+ if (UNLIKELY(((scan[0][BLU] << 8) | i) != xmax)) {
return NULL;
}
for (i = 0; i < 4; i++) {
- if (mem_eof - mem < 2) {
+ if (UNLIKELY(mem_eof - mem < 2)) {
return NULL;
}
for (j = 0; j < xmax; ) {
code = *mem++;
if (code > 128) {
code &= 127;
+ if (UNLIKELY(code + j > xmax)) {
+ return NULL;
+ }
val = *mem++;
while (code--) {
scan[j++][i] = (unsigned char)val;
}
}
else {
- if (mem_eof - mem < code) {
+ if (UNLIKELY(mem_eof - mem < code)) {
+ return NULL;
+ }
+ if (UNLIKELY(code + j > xmax)) {
return NULL;
}
while (code--) {
@@ -240,13 +243,17 @@ struct ImBuf *imb_loadhdr(const unsigned char *mem, size_t size, int flags, char
if (flags & IB_test) ibuf = IMB_allocImBuf(width, height, 32, 0);
else ibuf = IMB_allocImBuf(width, height, 32, (flags & IB_rect) | IB_rectfloat);
- if (ibuf == NULL) return NULL;
+ if (UNLIKELY(ibuf == NULL)) {
+ return NULL;
+ }
ibuf->ftype = IMB_FTYPE_RADHDR;
if (flags & IB_alphamode_detect)
ibuf->flags |= IB_alphamode_premul;
- if (flags & IB_test) return ibuf;
+ if (flags & IB_test) {
+ return ibuf;
+ }
/* read in and decode the actual data */
sline = (RGBE *)MEM_mallocN(sizeof(*sline) * width, __func__);
@@ -290,7 +297,9 @@ static int fwritecolrs(FILE *file, int width, int channels, unsigned char *ibufs
fCOLOR fcol;
RGBE rgbe, *rgbe_scan;
- if ((ibufscan == NULL) && (fpscan == NULL)) return 0;
+ if (UNLIKELY((ibufscan == NULL) && (fpscan == NULL))) {
+ return 0;
+ }
rgbe_scan = (RGBE *)MEM_mallocN(sizeof(RGBE) * width, "radhdr_write_tmpscan");
@@ -381,7 +390,9 @@ int imb_savehdr(struct ImBuf *ibuf, const char *name, int flags)
(void)flags; /* unused */
- if (file == NULL) return 0;
+ if (file == NULL) {
+ return 0;
+ }
writeHeader(file, width, height);
diff --git a/source/blender/imbuf/intern/readimage.c b/source/blender/imbuf/intern/readimage.c
index 1c83b33e296..afa3ffb31f3 100644
--- a/source/blender/imbuf/intern/readimage.c
+++ b/source/blender/imbuf/intern/readimage.c
@@ -46,6 +46,7 @@
#include "BLI_fileops.h"
#include "imbuf.h"
+#include "IMB_allocimbuf.h"
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
#include "IMB_filetype.h"
@@ -174,7 +175,10 @@ ImBuf *IMB_loadifffile(int file, const char *filepath, int flags, char colorspac
size = BLI_file_descriptor_size(file);
+ imb_mmap_lock();
mem = mmap(NULL, size, PROT_READ, MAP_SHARED, file, 0);
+ imb_mmap_unlock();
+
if (mem == (unsigned char *) -1) {
fprintf(stderr, "%s: couldn't get mapping %s\n", __func__, descr);
return NULL;
@@ -182,8 +186,10 @@ ImBuf *IMB_loadifffile(int file, const char *filepath, int flags, char colorspac
ibuf = IMB_ibImageFromMemory(mem, size, flags, colorspace, descr);
+ imb_mmap_lock();
if (munmap(mem, size))
fprintf(stderr, "%s: couldn't unmap file %s\n", __func__, descr);
+ imb_mmap_unlock();
return ibuf;
}
@@ -269,7 +275,10 @@ static void imb_loadtilefile(ImBuf *ibuf, int file, int tx, int ty, unsigned int
size = BLI_file_descriptor_size(file);
+ imb_mmap_lock();
mem = mmap(NULL, size, PROT_READ, MAP_SHARED, file, 0);
+ imb_mmap_unlock();
+
if (mem == (unsigned char *) -1) {
fprintf(stderr, "Couldn't get memory mapping for %s\n", ibuf->cachename);
return;
@@ -279,8 +288,10 @@ static void imb_loadtilefile(ImBuf *ibuf, int file, int tx, int ty, unsigned int
if (type->load_tile && type->ftype(type, ibuf))
type->load_tile(ibuf, mem, size, tx, ty, rect);
+ imb_mmap_lock();
if (munmap(mem, size))
fprintf(stderr, "Couldn't unmap memory for %s.\n", ibuf->cachename);
+ imb_mmap_unlock();
}
void imb_loadtile(ImBuf *ibuf, int tx, int ty, unsigned int *rect)
diff --git a/source/blender/imbuf/intern/scaling.c b/source/blender/imbuf/intern/scaling.c
index 2601fe62c2f..605adffb813 100644
--- a/source/blender/imbuf/intern/scaling.c
+++ b/source/blender/imbuf/intern/scaling.c
@@ -1555,7 +1555,7 @@ struct ImBuf *IMB_scalefastImBuf(struct ImBuf *ibuf, unsigned int newx, unsigned
struct imbufRGBA *rectf, *_newrectf, *newrectf;
int x, y;
bool do_float = false, do_rect = false;
- int ofsx, ofsy, stepx, stepy;
+ size_t ofsx, ofsy, stepx, stepy;
rect = NULL; _newrect = NULL; newrect = NULL;
rectf = NULL; _newrectf = NULL; newrectf = NULL;
diff --git a/source/blender/imbuf/intern/stereoimbuf.c b/source/blender/imbuf/intern/stereoimbuf.c
index 3b9da639a86..13a15f101e7 100644
--- a/source/blender/imbuf/intern/stereoimbuf.c
+++ b/source/blender/imbuf/intern/stereoimbuf.c
@@ -343,7 +343,7 @@ static void imb_stereo3d_write_interlace(Stereo3DData *s3d, enum eStereo3dInterl
};
char i = (char) swap;
for (x = 0; x < width; x++, from[0] += 3, from[1] += 3, to += 3) {
- copy_v3_v3_char((char *)to, (char *)from[i]);
+ copy_v3_v3_uchar(to, from[i]);
i = !i;
}
}
@@ -357,7 +357,7 @@ static void imb_stereo3d_write_interlace(Stereo3DData *s3d, enum eStereo3dInterl
};
char i = (char) swap;
for (x = 0; x < width; x++, from[0] += 4, from[1] += 4, to += 4) {
- copy_v4_v4_char((char *)to, (char *)from[i]);
+ copy_v4_v4_uchar(to, from[i]);
i = !i;
}
}
@@ -392,7 +392,7 @@ static void imb_stereo3d_write_interlace(Stereo3DData *s3d, enum eStereo3dInterl
};
char j = i;
for (x = 0; x < width; x++, from[0] += 3, from[1] += 3, to += 3) {
- copy_v3_v3_char((char *)to, (char *)from[j]);
+ copy_v3_v3_uchar(to, from[j]);
j = !j;
}
i = !i;
@@ -408,7 +408,7 @@ static void imb_stereo3d_write_interlace(Stereo3DData *s3d, enum eStereo3dInterl
};
char j = i;
for (x = 0; x < width; x++, from[0] += 4, from[1] += 4, to += 4) {
- copy_v4_v4_char((char *)to, (char *)from[j]);
+ copy_v4_v4_uchar(to, from[j]);
j = !j;
}
i = !i;
@@ -1035,7 +1035,7 @@ static void imb_stereo3d_read_interlace(Stereo3DData *s3d, enum eStereo3dInterla
};
char i = (char) swap;
for (x = 0; x < width; x++, from += 3, to[0] += 3, to[1] += 3) {
- copy_v3_v3_char((char *)to[i], (char *)from);
+ copy_v3_v3_uchar(to[i], from);
i = !i;
}
}
@@ -1049,7 +1049,7 @@ static void imb_stereo3d_read_interlace(Stereo3DData *s3d, enum eStereo3dInterla
};
char i = (char) swap;
for (x = 0; x < width; x++, from += 4, to[0] += 4, to[1] += 4) {
- copy_v4_v4_char((char *)to[i], (char *)from);
+ copy_v4_v4_uchar(to[i], from);
i = !i;
}
}
@@ -1084,7 +1084,7 @@ static void imb_stereo3d_read_interlace(Stereo3DData *s3d, enum eStereo3dInterla
};
char j = i;
for (x = 0; x < width; x++, from += 3, to[0] += 3, to[1] += 3) {
- copy_v3_v3_char((char *)to[j], (char *)from);
+ copy_v3_v3_uchar(to[j], from);
j = !j;
}
i = !i;
@@ -1100,7 +1100,7 @@ static void imb_stereo3d_read_interlace(Stereo3DData *s3d, enum eStereo3dInterla
};
char j = i;
for (x = 0; x < width; x++, from += 4, to[0] += 4, to[1] += 4) {
- copy_v4_v4_char((char *)to[j], (char *)from);
+ copy_v4_v4_uchar(to[j], from);
j = !j;
}
i = !i;
diff --git a/source/blender/imbuf/intern/thumbs.c b/source/blender/imbuf/intern/thumbs.c
index e7bec7e643c..95d061bcb75 100644
--- a/source/blender/imbuf/intern/thumbs.c
+++ b/source/blender/imbuf/intern/thumbs.c
@@ -217,7 +217,7 @@ static bool thumbhash_from_path(const char *UNUSED(path), ThumbSource source, ch
}
}
-static int uri_from_filename(const char *path, char *uri)
+static bool uri_from_filename(const char *path, char *uri)
{
char orig_uri[URI_MAX];
const char *dirstart = path;
@@ -243,16 +243,9 @@ static int uri_from_filename(const char *path, char *uri)
#else
BLI_snprintf(orig_uri, URI_MAX, "file://%s", dirstart);
#endif
-
-#ifdef WITH_ICONV
- {
- char uri_utf8[URI_MAX];
- escape_uri_string(orig_uri, uri_utf8, URI_MAX, UNSAFE_PATH);
- BLI_string_to_utf8(uri_utf8, uri, NULL);
- }
-#else
+
escape_uri_string(orig_uri, uri, URI_MAX, UNSAFE_PATH);
-#endif
+
return 1;
}
@@ -489,7 +482,9 @@ ImBuf *IMB_thumb_create(const char *path, ThumbSize size, ThumbSource source, Im
char uri[URI_MAX] = "";
char thumb_name[40];
- uri_from_filename(path, uri);
+ if (!uri_from_filename(path, uri)) {
+ return NULL;
+ }
thumbname_from_uri(uri, thumb_name, sizeof(thumb_name));
return thumb_create_ex(path, uri, thumb_name, false, THUMB_DEFAULT_HASH, NULL, NULL, size, source, img);
diff --git a/source/blender/imbuf/intern/thumbs_blend.c b/source/blender/imbuf/intern/thumbs_blend.c
index 17d9f3d0735..b5c6deb6b01 100644
--- a/source/blender/imbuf/intern/thumbs_blend.c
+++ b/source/blender/imbuf/intern/thumbs_blend.c
@@ -28,8 +28,6 @@
#include <stdlib.h>
#include <string.h>
-#include "zlib.h"
-
#include "BLI_utildefines.h"
#include "BLI_endian_switch.h"
#include "BLI_fileops.h"
@@ -41,6 +39,8 @@
#include "BKE_global.h"
#include "BKE_idcode.h"
#include "BKE_icons.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
#include "DNA_ID.h" /* For preview images... */
@@ -48,97 +48,20 @@
#include "IMB_imbuf.h"
#include "IMB_thumbs.h"
-/* extracts the thumbnail from between the 'REND' and the 'GLOB'
- * chunks of the header, don't use typical blend loader because its too slow */
-
-static ImBuf *loadblend_thumb(gzFile gzfile)
-{
- char buf[12];
- int bhead[24 / sizeof(int)]; /* max size on 64bit */
- char endian, pointer_size;
- char endian_switch;
- int sizeof_bhead;
-
- /* read the blend file header */
- if (gzread(gzfile, buf, 12) != 12)
- return NULL;
- if (!STREQLEN(buf, "BLENDER", 7))
- return NULL;
-
- if (buf[7] == '-')
- pointer_size = 8;
- else if (buf[7] == '_')
- pointer_size = 4;
- else
- return NULL;
-
- sizeof_bhead = 16 + pointer_size;
-
- if (buf[8] == 'V')
- endian = B_ENDIAN; /* big: PPC */
- else if (buf[8] == 'v')
- endian = L_ENDIAN; /* little: x86 */
- else
- return NULL;
-
- endian_switch = ((ENDIAN_ORDER != endian)) ? 1 : 0;
-
- while (gzread(gzfile, bhead, sizeof_bhead) == sizeof_bhead) {
- if (endian_switch)
- BLI_endian_switch_int32(&bhead[1]); /* length */
-
- if (bhead[0] == REND) {
- gzseek(gzfile, bhead[1], SEEK_CUR); /* skip to the next */
- }
- else {
- break;
- }
- }
-
- /* using 'TEST' since new names segfault when loading in old blenders */
- if (bhead[0] == TEST) {
- ImBuf *img = NULL;
- int size[2];
-
- if (gzread(gzfile, size, sizeof(size)) != sizeof(size))
- return NULL;
-
- if (endian_switch) {
- BLI_endian_switch_int32(&size[0]);
- BLI_endian_switch_int32(&size[1]);
- }
- /* length */
- bhead[1] -= sizeof(int) * 2;
-
- /* inconsistent image size, quit early */
- if (bhead[1] != size[0] * size[1] * sizeof(int))
- return NULL;
-
- /* finally malloc and read the data */
- img = IMB_allocImBuf(size[0], size[1], 32, IB_rect | IB_metadata);
-
- if (gzread(gzfile, img->rect, bhead[1]) != bhead[1]) {
- IMB_freeImBuf(img);
- img = NULL;
- }
-
- return img;
- }
-
- return NULL;
-}
+#include "MEM_guardedalloc.h"
ImBuf *IMB_thumb_load_blend(const char *blen_path, const char *blen_group, const char *blen_id)
{
+ ImBuf *ima = NULL;
+
if (blen_group && blen_id) {
LinkNode *ln, *names, *lp, *previews = NULL;
struct BlendHandle *libfiledata = BLO_blendhandle_from_file(blen_path, NULL);
- ImBuf *ima = NULL;
int idcode = BKE_idcode_from_name(blen_group);
int i, nprevs, nnames;
if (libfiledata == NULL) {
- return NULL;
+ return ima;
}
/* Note: we should handle all previews for a same group at once, would avoid reopening .blend file
@@ -180,25 +103,19 @@ ImBuf *IMB_thumb_load_blend(const char *blen_path, const char *blen_group, const
BLI_linklist_free(previews, BKE_previewimg_freefunc);
BLI_linklist_free(names, free);
- return ima;
}
else {
- gzFile gzfile;
- /* not necessarily a gzip */
- gzfile = BLI_gzopen(blen_path, "rb");
+ BlendThumbnail *data;
- if (NULL == gzfile) {
- return NULL;
- }
- else {
- ImBuf *img = loadblend_thumb(gzfile);
-
- /* read ok! */
- gzclose(gzfile);
+ data = BLO_thumbnail_from_file(blen_path);
+ ima = BKE_main_thumbnail_to_imbuf(NULL, data);
- return img;
+ if (data) {
+ MEM_freeN(data);
}
}
+
+ return ima;
}
/* add a fake passepartout overlay to a byte buffer, use for blend file thumbnails */
diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h
index 342245fa393..c2901b8b9a5 100644
--- a/source/blender/makesdna/DNA_ID.h
+++ b/source/blender/makesdna/DNA_ID.h
@@ -261,6 +261,8 @@ typedef struct PreviewImage {
#define ID_BLEND_PATH(_bmain, _id) ((_id)->lib ? (_id)->lib->filepath : (_bmain)->name)
+#define ID_MISSING(_id) (((_id)->flag & LIB_MISSING) != 0)
+
#ifdef GS
# undef GS
#endif
@@ -280,6 +282,8 @@ enum {
LIB_TESTIND = (LIB_NEED_EXPAND | LIB_INDIRECT),
LIB_READ = 1 << 4,
LIB_NEED_LINK = 1 << 5,
+ /* tag datablock as a place-holder (because the real one could not be linked from its library e.g.). */
+ LIB_MISSING = 1 << 6,
LIB_NEW = 1 << 8,
LIB_FAKEUSER = 1 << 9,
diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h
index b8688e5e12a..d574694c70d 100644
--- a/source/blender/makesdna/DNA_action_types.h
+++ b/source/blender/makesdna/DNA_action_types.h
@@ -198,7 +198,8 @@ typedef struct bPoseChannel {
short agrp_index; /* index of action-group this bone belongs to (0 = default/no group) */
char constflag; /* for quick detecting which constraints affect this channel */
char selectflag; /* copy of bone flag, so you can work with library armatures, not for runtime use */
- char pad0[6];
+ char drawflag;
+ char pad0[5];
struct Bone *bone; /* set on read file or rebuild pose */
struct bPoseChannel *parent; /* set on read file or rebuild pose */
@@ -212,6 +213,9 @@ typedef struct bPoseChannel {
struct bPoseChannel *custom_tx; /* odd feature, display with another bones transform.
* needed in rare cases for advanced rigs,
* since the alternative is highly complicated - campbell */
+ float custom_scale;
+
+ char pad1[4];
/* transforms - written in by actions or transform */
float loc[3];
@@ -306,6 +310,14 @@ typedef enum ePchan_IkFlag {
BONE_IK_NO_ZDOF_TEMP = (1 << 12)
} ePchan_IkFlag;
+/* PoseChannel->drawflag */
+typedef enum ePchan_DrawFlag {
+ PCHAN_DRAW_NO_CUSTOM_BONE_SIZE = (1 << 0),
+} ePchan_DrawFlag;
+
+#define PCHAN_CUSTOM_DRAW_SIZE(pchan) \
+ (pchan)->custom_scale * (((pchan)->drawflag & PCHAN_DRAW_NO_CUSTOM_BONE_SIZE) ? 1.0f : (pchan)->bone->length)
+
/* PoseChannel->rotmode and Object->rotmode */
typedef enum eRotationModes {
/* quaternion rotations (default, and for older Blender versions) */
diff --git a/source/blender/makesdna/DNA_actuator_types.h b/source/blender/makesdna/DNA_actuator_types.h
index 9af0c1dac10..59a058925a6 100644
--- a/source/blender/makesdna/DNA_actuator_types.h
+++ b/source/blender/makesdna/DNA_actuator_types.h
@@ -512,6 +512,7 @@ typedef struct bActuator {
#define ACT_GAME_QUIT 3
#define ACT_GAME_SAVECFG 4
#define ACT_GAME_LOADCFG 5
+#define ACT_GAME_SCREENSHOT 6
/* visibilityact->flag */
/* Set means the object will become invisible */
diff --git a/source/blender/makesdna/DNA_image_types.h b/source/blender/makesdna/DNA_image_types.h
index 6088dccd4e9..d112790eb47 100644
--- a/source/blender/makesdna/DNA_image_types.h
+++ b/source/blender/makesdna/DNA_image_types.h
@@ -55,7 +55,8 @@ typedef struct ImageUser {
char ok;
char multiview_eye; /* multiview current eye - for internal use of drawing routines */
- int passtype;
+ short pass;
+ short pad;
short multi_index, view, layer; /* listbase indices, for menu browsing or retrieve buffer */
short flag;
@@ -171,8 +172,8 @@ enum {
IMA_IGNORE_ALPHA = (1 << 12),
IMA_DEINTERLACE = (1 << 13),
IMA_USE_VIEWS = (1 << 14),
- IMA_IS_STEREO = (1 << 15),
- IMA_IS_MULTIVIEW = (1 << 16), /* similar to stereo, but a more general case */
+ // IMA_IS_STEREO = (1 << 15), /* deprecated */
+ // IMA_IS_MULTIVIEW = (1 << 16), /* deprecated */
};
/* Image.tpageflag */
diff --git a/source/blender/makesdna/DNA_meshdata_types.h b/source/blender/makesdna/DNA_meshdata_types.h
index b78cd65e913..621807d111c 100644
--- a/source/blender/makesdna/DNA_meshdata_types.h
+++ b/source/blender/makesdna/DNA_meshdata_types.h
@@ -71,7 +71,7 @@ typedef struct MVert {
* at the moment alpha is abused for vertex painting and not used for transparency, note that red and blue are swapped
*/
typedef struct MCol {
- char a, r, g, b;
+ unsigned char a, r, g, b;
} MCol;
/* new face structure, replaces MFace, which is now only used for storing tessellations.*/
@@ -224,7 +224,7 @@ enum {
* \note red and blue are _not_ swapped, as they are with #MCol
*/
typedef struct MLoopCol {
- char r, g, b, a;
+ unsigned char r, g, b, a;
} MLoopCol;
#define MESH_MLOOPCOL_FROM_MCOL(_mloopcol, _mcol) \
@@ -446,6 +446,16 @@ enum {
/* number of tri's that make up this polygon once tessellated */
#define ME_POLY_TRI_TOT(mp) ((mp)->totloop - 2)
+/**
+ * Check out-of-bounds material, note that this is nearly always prevented,
+ * yet its still possible in rare cases.
+ * So usage such as array lookup needs to check.
+ */
+#define ME_MAT_NR_TEST(mat_nr, totmat) \
+ (CHECK_TYPE_ANY(mat_nr, short, const short), \
+ CHECK_TYPE_ANY(totmat, short, const short), \
+ (LIKELY(mat_nr < totmat) ? mat_nr : 0))
+
/* mselect->type */
enum {
ME_VSEL = 0,
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index 32f766ecae5..1176ce1c9e6 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -748,6 +748,8 @@ typedef struct NodeTexEnvironment {
ImageUser iuser;
int color_space;
int projection;
+ int interpolation;
+ int pad;
} NodeTexEnvironment;
typedef struct NodeTexGradient {
diff --git a/source/blender/makesdna/DNA_object_fluidsim.h b/source/blender/makesdna/DNA_object_fluidsim.h
index aaebdf579f8..a714195dd5d 100644
--- a/source/blender/makesdna/DNA_object_fluidsim.h
+++ b/source/blender/makesdna/DNA_object_fluidsim.h
@@ -88,11 +88,6 @@ typedef struct FluidsimSettings {
/* gravity strength */
float iniVelx, iniVely, iniVelz;
- /* store pointer to original mesh (for replacing the current one) */
- struct Mesh *orgMesh;
- /* a mesh to display the bounding box used for simulation */
- struct Mesh *meshBB;
-
/* store output path, and file prefix for baked fluid surface */
/* strlens; 256= FILE_MAXFILE, 768= FILE_MAXDIR */
char surfdataPath[1024];
diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h
index 3d3adec7aae..5ae82b9980e 100644
--- a/source/blender/makesdna/DNA_object_types.h
+++ b/source/blender/makesdna/DNA_object_types.h
@@ -200,7 +200,7 @@ typedef struct Object {
/* did last modifier stack generation need mapping support? */
char lastNeedMapping; /* bool */
- char pad[5];
+ char pad;
/* dupli-frame settings */
int dupon, dupoff, dupsta, dupend;
@@ -233,6 +233,8 @@ typedef struct Object {
float step_height;
float jump_speed;
float fall_speed;
+ unsigned char max_jumps;
+ char pad2[3];
/** Collision mask settings */
unsigned short col_group, col_mask;
@@ -258,7 +260,7 @@ typedef struct Object {
short index; /* custom index, for renderpasses */
unsigned short actdef; /* current deformation group, note: index starts at 1 */
unsigned short actfmap; /* current face map, note: index starts at 1 */
- unsigned short pad2[3];
+ unsigned short pad3[3];
float col[4]; /* object color */
int gameflag;
diff --git a/source/blender/makesdna/DNA_outliner_types.h b/source/blender/makesdna/DNA_outliner_types.h
index 53061b55e2d..984e3334414 100644
--- a/source/blender/makesdna/DNA_outliner_types.h
+++ b/source/blender/makesdna/DNA_outliner_types.h
@@ -56,7 +56,55 @@ typedef struct TreeStore {
#define TSE_CHILDSEARCH 8
#define TSE_SEARCHMATCH 16
-/* TreeStoreElem types in BIF_outliner.h */
+/* TreeStoreElem->types */
+#define TSE_NLA 1 /* NO ID */
+#define TSE_NLA_ACTION 2
+#define TSE_DEFGROUP_BASE 3
+#define TSE_DEFGROUP 4
+#define TSE_BONE 5
+#define TSE_EBONE 6
+#define TSE_CONSTRAINT_BASE 7
+#define TSE_CONSTRAINT 8
+#define TSE_MODIFIER_BASE 9
+#define TSE_MODIFIER 10
+#define TSE_LINKED_OB 11
+/* #define TSE_SCRIPT_BASE 12 */ /* UNUSED */
+#define TSE_POSE_BASE 13
+#define TSE_POSE_CHANNEL 14
+#define TSE_ANIM_DATA 15
+#define TSE_DRIVER_BASE 16 /* NO ID */
+/* #define TSE_DRIVER 17 */ /* UNUSED */
+
+#define TSE_PROXY 18
+#define TSE_R_LAYER_BASE 19
+#define TSE_R_LAYER 20
+#define TSE_R_PASS 21
+#define TSE_LINKED_MAT 22
+/* NOTE, is used for light group */
+#define TSE_LINKED_LAMP 23
+#define TSE_POSEGRP_BASE 24
+#define TSE_POSEGRP 25
+#define TSE_SEQUENCE 26 /* NO ID */
+#define TSE_SEQ_STRIP 27 /* NO ID */
+#define TSE_SEQUENCE_DUP 28 /* NO ID */
+#define TSE_LINKED_PSYS 29
+#define TSE_RNA_STRUCT 30 /* NO ID */
+#define TSE_RNA_PROPERTY 31 /* NO ID */
+#define TSE_RNA_ARRAY_ELEM 32 /* NO ID */
+#define TSE_NLA_TRACK 33 /* NO ID */
+#define TSE_KEYMAP 34 /* NO ID */
+#define TSE_KEYMAP_ITEM 35 /* NO ID */
+#define TSE_ID_BASE 36 /* NO ID */
+#define TSE_GP_LAYER 37 /* NO ID */
+
+
+/* Check whether given TreeStoreElem should have a real ID in its ->id member. */
+#define TSE_IS_REAL_ID(_tse) \
+ (!ELEM((_tse)->type, TSE_NLA, TSE_NLA_TRACK, TSE_DRIVER_BASE, \
+ TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP, \
+ TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM, \
+ TSE_KEYMAP, TSE_KEYMAP_ITEM, TSE_ID_BASE, TSE_GP_LAYER))
+
#endif
diff --git a/source/blender/makesdna/DNA_sequence_types.h b/source/blender/makesdna/DNA_sequence_types.h
index 3f3bfdfe1b1..69e7fb43fb6 100644
--- a/source/blender/makesdna/DNA_sequence_types.h
+++ b/source/blender/makesdna/DNA_sequence_types.h
@@ -275,9 +275,10 @@ typedef struct TextVars {
char text[512];
int text_size;
float loc[2];
- short flag;
- char align;
- char pad;
+ float wrap_width;
+ char flag;
+ char align, align_y;
+ char pad[5];
} TextVars;
/* TextVars.flag */
@@ -287,9 +288,16 @@ enum {
/* TextVars.align */
enum {
- SEQ_TEXT_ALIGN_LEFT = 0,
- SEQ_TEXT_ALIGN_CENTER = 1,
- SEQ_TEXT_ALIGN_RIGHT = 2,
+ SEQ_TEXT_ALIGN_X_LEFT = 0,
+ SEQ_TEXT_ALIGN_X_CENTER = 1,
+ SEQ_TEXT_ALIGN_X_RIGHT = 2,
+};
+
+/* TextVars.align_y */
+enum {
+ SEQ_TEXT_ALIGN_Y_TOP = 0,
+ SEQ_TEXT_ALIGN_Y_CENTER = 1,
+ SEQ_TEXT_ALIGN_Y_BOTTOM = 2,
};
/* ***************** Sequence modifiers ****************** */
diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h
index f10d4131162..e2c7478f5d3 100644
--- a/source/blender/makesdna/DNA_userdef_types.h
+++ b/source/blender/makesdna/DNA_userdef_types.h
@@ -74,7 +74,8 @@ typedef struct uiFontStyle {
short uifont_id; /* saved in file, 0 is default */
short points; /* actual size depends on 'global' dpi */
short kerning; /* unfitted or default kerning value. */
- char pad[6];
+ char word_wrap; /* enable word-wrap when drawing */
+ char pad[5];
short italic, bold; /* style hint */
short shadow; /* value is amount of pixels blur */
short shadx, shady; /* shadow offset in pixels */
@@ -818,19 +819,23 @@ typedef enum eTimecodeStyles {
* with '+' to denote the frames
* i.e. HH:MM:SS+FF, MM:SS+FF, SS+FF, or MM:SS
*/
- USER_TIMECODE_MINIMAL = 0,
-
+ USER_TIMECODE_MINIMAL = 0,
+
/* reduced SMPTE - (HH:)MM:SS:FF */
- USER_TIMECODE_SMPTE_MSF = 1,
-
+ USER_TIMECODE_SMPTE_MSF = 1,
+
/* full SMPTE - HH:MM:SS:FF */
- USER_TIMECODE_SMPTE_FULL = 2,
-
+ USER_TIMECODE_SMPTE_FULL = 2,
+
/* milliseconds for sub-frames - HH:MM:SS.sss */
- USER_TIMECODE_MILLISECONDS = 3,
-
+ USER_TIMECODE_MILLISECONDS = 3,
+
/* seconds only */
- USER_TIMECODE_SECONDS_ONLY = 4,
+ USER_TIMECODE_SECONDS_ONLY = 4,
+
+ /* Private (not exposed as generic choices) options. */
+ /* milliseconds for sub-frames , SubRip format- HH:MM:SS,sss */
+ USER_TIMECODE_SUBRIP = 100,
} eTimecodeStyles;
/* theme drawtypes */
diff --git a/source/blender/makesdna/intern/CMakeLists.txt b/source/blender/makesdna/intern/CMakeLists.txt
index be097c0e51e..52487edfd2b 100644
--- a/source/blender/makesdna/intern/CMakeLists.txt
+++ b/source/blender/makesdna/intern/CMakeLists.txt
@@ -57,7 +57,7 @@ add_executable(makesdna ${SRC} ${SRC_DNA_INC})
# Output dna.c
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/dna.c
- COMMAND ${CMAKE_BINARY_DIR}/bin/${CMAKE_CFG_INTDIR}/makesdna ${CMAKE_CURRENT_BINARY_DIR}/dna.c ${CMAKE_SOURCE_DIR}/source/blender/makesdna/
+ COMMAND "$<TARGET_FILE:makesdna>" ${CMAKE_CURRENT_BINARY_DIR}/dna.c ${CMAKE_SOURCE_DIR}/source/blender/makesdna/
DEPENDS makesdna
)
diff --git a/source/blender/makesdna/intern/dna_genfile.c b/source/blender/makesdna/intern/dna_genfile.c
index 499c430306b..16fbcbebe50 100644
--- a/source/blender/makesdna/intern/dna_genfile.c
+++ b/source/blender/makesdna/intern/dna_genfile.c
@@ -311,7 +311,21 @@ int DNA_struct_find_nr(SDNA *sdna, const char *str)
}
#ifdef WITH_DNA_GHASH
- return (intptr_t)BLI_ghash_lookup(sdna->structs_map, str) - 1;
+ {
+ void **index_p;
+ int a;
+
+ index_p = BLI_ghash_lookup_p(sdna->structs_map, str);
+
+ if (index_p) {
+ a = GET_INT_FROM_POINTER(*index_p);
+ sdna->lastfind = a;
+ }
+ else {
+ a = -1;
+ }
+ return a;
+ }
#else
{
int a;
@@ -525,7 +539,7 @@ static void init_structDNA(SDNA *sdna, bool do_endian_swap)
for (nr = 0; nr < sdna->nr_structs; nr++) {
sp = sdna->structs[nr];
- BLI_ghash_insert(sdna->structs_map, sdna->types[sp[0]], SET_INT_IN_POINTER(nr + 1));
+ BLI_ghash_insert(sdna->structs_map, sdna->types[sp[0]], SET_INT_IN_POINTER(nr));
}
#endif
}
diff --git a/source/blender/makesrna/SConscript b/source/blender/makesrna/SConscript
index 260784788db..1ed4982cf94 100644
--- a/source/blender/makesrna/SConscript
+++ b/source/blender/makesrna/SConscript
@@ -148,6 +148,9 @@ if env['WITH_BF_OPENSUBDIV']:
incs += ' #/intern/opensubdiv'
defs.append('WITH_OPENSUBDIV')
+if env['WITH_BF_AUDASPACE']:
+ defs.append('WITH_AUDASPACE')
+
if env['OURPLATFORM'] == 'linux':
cflags='-pthread'
diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt
index b34763e0ae8..987b594421f 100644
--- a/source/blender/makesrna/intern/CMakeLists.txt
+++ b/source/blender/makesrna/intern/CMakeLists.txt
@@ -350,7 +350,7 @@ target_link_libraries(makesrna bf_dna_blenlib)
# note (linux only): with crashes try add this after COMMAND: valgrind --leak-check=full --track-origins=yes
add_custom_command(
OUTPUT ${GENSRC}
- COMMAND ${CMAKE_BINARY_DIR}/bin/${CMAKE_CFG_INTDIR}/makesrna ${CMAKE_CURRENT_BINARY_DIR}/
+ COMMAND "$<TARGET_FILE:makesrna>" ${CMAKE_CURRENT_BINARY_DIR}/
DEPENDS makesrna
)
diff --git a/source/blender/makesrna/intern/SConscript b/source/blender/makesrna/intern/SConscript
index e8842ae2943..8307e4cec6f 100644
--- a/source/blender/makesrna/intern/SConscript
+++ b/source/blender/makesrna/intern/SConscript
@@ -163,6 +163,9 @@ if env['WITH_BF_OPENSUBDIV']:
defs.append('WITH_OPENSUBDIV')
incs += ' #intern/opensubdiv'
+if env['WITH_BF_AUDASPACE']:
+ defs.append('WITH_AUDASPACE')
+
if env['OURPLATFORM'] == 'linux':
cflags='-pthread'
diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c
index 0f00dd7a586..e887397f4d7 100644
--- a/source/blender/makesrna/intern/makesrna.c
+++ b/source/blender/makesrna/intern/makesrna.c
@@ -1079,11 +1079,18 @@ static char *rna_def_property_length_func(FILE *f, StructRNA *srna, PropertyRNA
fprintf(f, " return %s(ptr);\n", manualfunc);
}
else {
- rna_print_data_get(f, dp);
+ if (dp->dnaarraylength <= 1 || dp->dnalengthname)
+ rna_print_data_get(f, dp);
+
+ if (dp->dnaarraylength > 1)
+ fprintf(f, " return ");
+ else
+ fprintf(f, " return (data->%s == NULL) ? 0 : ", dp->dnaname);
+
if (dp->dnalengthname)
- fprintf(f, " return (data->%s == NULL) ? 0 : data->%s;\n", dp->dnaname, dp->dnalengthname);
+ fprintf(f, "data->%s;\n", dp->dnalengthname);
else
- fprintf(f, " return (data->%s == NULL) ? 0 : %d;\n", dp->dnaname, dp->dnalengthfixed);
+ fprintf(f, "%d;\n", dp->dnalengthfixed);
}
fprintf(f, "}\n\n");
}
diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c
index 19b5a1b8219..f0119c7d665 100644
--- a/source/blender/makesrna/intern/rna_ID.c
+++ b/source/blender/makesrna/intern/rna_ID.c
@@ -126,7 +126,7 @@ static int rna_ID_name_editable(PointerRNA *ptr)
return false;
}
- return true;
+ return PROP_EDITABLE;
}
short RNA_type_to_ID_code(StructRNA *type)
@@ -484,6 +484,7 @@ static void rna_ImagePreview_size_set(PointerRNA *ptr, const int *values, enum e
prv_img->flag[size] |= (PRV_CHANGED | PRV_USER_EDITED);
}
+
static int rna_ImagePreview_pixels_get_length(PointerRNA *ptr, int length[RNA_MAX_ARRAY_DIMENSION], enum eIconSizes size)
{
ID *id = ptr->id.data;
@@ -527,6 +528,70 @@ static void rna_ImagePreview_pixels_set(PointerRNA *ptr, const int *values, enum
prv_img->flag[size] |= PRV_USER_EDITED;
}
+
+static int rna_ImagePreview_pixels_float_get_length(
+ PointerRNA *ptr, int length[RNA_MAX_ARRAY_DIMENSION], enum eIconSizes size)
+{
+ ID *id = ptr->id.data;
+ PreviewImage *prv_img = (PreviewImage *)ptr->data;
+
+ BLI_assert(sizeof(unsigned int) == 4);
+
+ if (id != NULL) {
+ BLI_assert(prv_img == BKE_previewimg_id_ensure(id));
+ }
+
+ BKE_previewimg_ensure(prv_img, size);
+
+ length[0] = prv_img->w[size] * prv_img->h[size] * 4;
+
+ return length[0];
+}
+
+static void rna_ImagePreview_pixels_float_get(PointerRNA *ptr, float *values, enum eIconSizes size)
+{
+ ID *id = ptr->id.data;
+ PreviewImage *prv_img = (PreviewImage *)ptr->data;
+
+ unsigned char *data = (unsigned char *)prv_img->rect[size];
+ const size_t len = prv_img->w[size] * prv_img->h[size] * 4;
+ size_t i;
+
+ BLI_assert(sizeof(unsigned int) == 4);
+
+ if (id != NULL) {
+ BLI_assert(prv_img == BKE_previewimg_id_ensure(id));
+ }
+
+ BKE_previewimg_ensure(prv_img, size);
+
+ for (i = 0; i < len; i++) {
+ values[i] = data[i] * (1.0f / 255.0f);
+ }
+}
+
+static void rna_ImagePreview_pixels_float_set(PointerRNA *ptr, const float *values, enum eIconSizes size)
+{
+ ID *id = ptr->id.data;
+ PreviewImage *prv_img = (PreviewImage *)ptr->data;
+
+ unsigned char *data = (unsigned char *)prv_img->rect[size];
+ const size_t len = prv_img->w[size] * prv_img->h[size] * 4;
+ size_t i;
+
+ BLI_assert(sizeof(unsigned int) == 4);
+
+ if (id != NULL) {
+ BLI_assert(prv_img == BKE_previewimg_id_ensure(id));
+ }
+
+ for (i = 0; i < len; i++) {
+ data[i] = FTOCHAR(values[i]);
+ }
+ prv_img->flag[size] |= PRV_USER_EDITED;
+}
+
+
static void rna_ImagePreview_is_image_custom_set(PointerRNA *ptr, int value)
{
rna_ImagePreview_is_custom_set(ptr, value, ICON_SIZE_PREVIEW);
@@ -557,6 +622,22 @@ static void rna_ImagePreview_image_pixels_set(PointerRNA *ptr, const int *values
rna_ImagePreview_pixels_set(ptr, values, ICON_SIZE_PREVIEW);
}
+static int rna_ImagePreview_image_pixels_float_get_length(PointerRNA *ptr, int length[RNA_MAX_ARRAY_DIMENSION])
+{
+ return rna_ImagePreview_pixels_float_get_length(ptr, length, ICON_SIZE_PREVIEW);
+}
+
+static void rna_ImagePreview_image_pixels_float_get(PointerRNA *ptr, float *values)
+{
+ rna_ImagePreview_pixels_float_get(ptr, values, ICON_SIZE_PREVIEW);
+}
+
+static void rna_ImagePreview_image_pixels_float_set(PointerRNA *ptr, const float *values)
+{
+ rna_ImagePreview_pixels_float_set(ptr, values, ICON_SIZE_PREVIEW);
+}
+
+
static void rna_ImagePreview_is_icon_custom_set(PointerRNA *ptr, int value)
{
rna_ImagePreview_is_custom_set(ptr, value, ICON_SIZE_ICON);
@@ -587,6 +668,22 @@ static void rna_ImagePreview_icon_pixels_set(PointerRNA *ptr, const int *values)
rna_ImagePreview_pixels_set(ptr, values, ICON_SIZE_ICON);
}
+static int rna_ImagePreview_icon_pixels_float_get_length(PointerRNA *ptr, int length[RNA_MAX_ARRAY_DIMENSION])
+{
+ return rna_ImagePreview_pixels_float_get_length(ptr, length, ICON_SIZE_ICON);
+}
+
+static void rna_ImagePreview_icon_pixels_float_get(PointerRNA *ptr, float *values)
+{
+ rna_ImagePreview_pixels_float_get(ptr, values, ICON_SIZE_ICON);
+}
+
+static void rna_ImagePreview_icon_pixels_float_set(PointerRNA *ptr, const float *values)
+{
+ rna_ImagePreview_pixels_float_set(ptr, values, ICON_SIZE_ICON);
+}
+
+
static int rna_ImagePreview_icon_id_get(PointerRNA *ptr)
{
/* Using a callback here allows us to only generate icon matching that preview when icon_id is requested. */
@@ -754,6 +851,15 @@ static void rna_def_image_preview(BlenderRNA *brna)
RNA_def_property_dynamic_array_funcs(prop, "rna_ImagePreview_image_pixels_get_length");
RNA_def_property_int_funcs(prop, "rna_ImagePreview_image_pixels_get", "rna_ImagePreview_image_pixels_set", NULL);
+ prop = RNA_def_property(srna, "image_pixels_float", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_DYNAMIC);
+ RNA_def_property_multi_array(prop, 1, NULL);
+ RNA_def_property_ui_text(prop, "Float Image Pixels",
+ "Image pixels components, as floats (RGBA concatenated values)");
+ RNA_def_property_dynamic_array_funcs(prop, "rna_ImagePreview_image_pixels_float_get_length");
+ RNA_def_property_float_funcs(prop, "rna_ImagePreview_image_pixels_float_get",
+ "rna_ImagePreview_image_pixels_float_set", NULL);
+
prop = RNA_def_property(srna, "is_icon_custom", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag[ICON_SIZE_ICON]", PRV_USER_EDITED);
@@ -773,6 +879,14 @@ static void rna_def_image_preview(BlenderRNA *brna)
RNA_def_property_dynamic_array_funcs(prop, "rna_ImagePreview_icon_pixels_get_length");
RNA_def_property_int_funcs(prop, "rna_ImagePreview_icon_pixels_get", "rna_ImagePreview_icon_pixels_set", NULL);
+ prop = RNA_def_property(srna, "icon_pixels_float", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_DYNAMIC);
+ RNA_def_property_multi_array(prop, 1, NULL);
+ RNA_def_property_ui_text(prop, "Float Icon Pixels", "Icon pixels components, as floats (RGBA concatenated values)");
+ RNA_def_property_dynamic_array_funcs(prop, "rna_ImagePreview_icon_pixels_float_get_length");
+ RNA_def_property_float_funcs(prop, "rna_ImagePreview_icon_pixels_float_get",
+ "rna_ImagePreview_icon_pixels_float_set", NULL);
+
prop = RNA_def_int(srna, "icon_id", 0, INT_MIN, INT_MAX, "Icon ID",
"Unique integer identifying this preview as an icon (zero means invalid)", INT_MIN, INT_MAX);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c
index 41bb0386ce6..b41568d0aba 100644
--- a/source/blender/makesrna/intern/rna_access.c
+++ b/source/blender/makesrna/intern/rna_access.c
@@ -1570,7 +1570,9 @@ bool RNA_property_editable(PointerRNA *ptr, PropertyRNA *prop)
prop = rna_ensure_property(prop);
flag = prop->editable ? prop->editable(ptr) : prop->flag;
- return (flag & PROP_EDITABLE) && (!id || !id->lib || (prop->flag & PROP_LIB_EXCEPTION));
+ return ((flag & PROP_EDITABLE) &&
+ (flag & PROP_REGISTER) == 0 &&
+ (!id || !id->lib || (prop->flag & PROP_LIB_EXCEPTION)));
}
bool RNA_property_editable_flag(PointerRNA *ptr, PropertyRNA *prop)
@@ -4720,6 +4722,7 @@ char *RNA_path_full_struct_py(struct PointerRNA *ptr)
char *RNA_path_full_property_py(PointerRNA *ptr, PropertyRNA *prop, int index)
{
char *id_path;
+ const char *data_delim;
char *data_path;
char *ret;
@@ -4733,13 +4736,15 @@ char *RNA_path_full_property_py(PointerRNA *ptr, PropertyRNA *prop, int index)
data_path = RNA_path_from_ID_to_property(ptr, prop);
+ data_delim = (data_path && data_path[0] == '[') ? "" : ".";
+
if ((index == -1) || (RNA_property_array_check(prop) == false)) {
- ret = BLI_sprintfN("%s.%s",
- id_path, data_path);
+ ret = BLI_sprintfN("%s%s%s",
+ id_path, data_delim, data_path);
}
else {
- ret = BLI_sprintfN("%s.%s[%d]",
- id_path, data_path, index);
+ ret = BLI_sprintfN("%s%s%s[%d]",
+ id_path, data_delim, data_path, index);
}
MEM_freeN(id_path);
if (data_path) {
diff --git a/source/blender/makesrna/intern/rna_actuator.c b/source/blender/makesrna/intern/rna_actuator.c
index 5dba21dda40..b425a454d33 100644
--- a/source/blender/makesrna/intern/rna_actuator.c
+++ b/source/blender/makesrna/intern/rna_actuator.c
@@ -1706,6 +1706,7 @@ static void rna_def_game_actuator(BlenderRNA *brna)
{ACT_GAME_QUIT, "QUIT", 0, "Quit Game", ""},
{ACT_GAME_SAVECFG, "SAVECFG", 0, "Save bge.logic.globalDict", ""},
{ACT_GAME_LOADCFG, "LOADCFG", 0, "Load bge.logic.globalDict", ""},
+ {ACT_GAME_SCREENSHOT, "SCREENSHOT", 0, "Screenshot", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -1722,8 +1723,8 @@ static void rna_def_game_actuator(BlenderRNA *brna)
/* ACT_GAME_LOAD */
prop = RNA_def_property(srna, "filename", PROP_STRING, PROP_FILEPATH);
RNA_def_property_ui_text(prop, "File",
- "Load this blend file, use the \"//\" prefix for a path relative to the current "
- "blend file");
+ "The file to use, depending on the mode (e.g. the blend file to load or a destination "
+ "for saving a screenshot) - use the \"//\" prefix for a relative path");
RNA_def_property_update(prop, NC_LOGIC, NULL);
/*XXX to do: an operator that calls file_browse with relative_path on and blender filtering active */
}
diff --git a/source/blender/makesrna/intern/rna_animation.c b/source/blender/makesrna/intern/rna_animation.c
index ac30c615438..165c969ebc2 100644
--- a/source/blender/makesrna/intern/rna_animation.c
+++ b/source/blender/makesrna/intern/rna_animation.c
@@ -97,7 +97,7 @@ static int rna_AnimData_action_editable(PointerRNA *ptr)
if ((adt->flag & ADT_NLA_EDIT_ON) || (adt->actstrip) || (adt->tmpact))
return 0;
else
- return 1;
+ return PROP_EDITABLE;
}
static void rna_AnimData_action_set(PointerRNA *ptr, PointerRNA value)
@@ -381,7 +381,7 @@ static int rna_KeyingSet_active_ksPath_editable(PointerRNA *ptr)
KeyingSet *ks = (KeyingSet *)ptr->data;
/* only editable if there are some paths to change to */
- return (BLI_listbase_is_empty(&ks->paths) == false);
+ return (BLI_listbase_is_empty(&ks->paths) == false) ? PROP_EDITABLE : 0;
}
static PointerRNA rna_KeyingSet_active_ksPath_get(PointerRNA *ptr)
diff --git a/source/blender/makesrna/intern/rna_armature.c b/source/blender/makesrna/intern/rna_armature.c
index 93e5ceaa229..3e41ea4134c 100644
--- a/source/blender/makesrna/intern/rna_armature.c
+++ b/source/blender/makesrna/intern/rna_armature.c
@@ -746,7 +746,7 @@ static void rna_def_edit_bone(BlenderRNA *brna)
prop = RNA_def_property(srna, "roll", PROP_FLOAT, PROP_ANGLE);
RNA_def_property_float_sdna(prop, NULL, "roll");
- RNA_def_property_ui_range(prop, -M_PI * 2, M_PI * 2, 0.1, 2);
+ RNA_def_property_ui_range(prop, -M_PI * 2, M_PI * 2, 10, 2);
RNA_def_property_ui_text(prop, "Roll", "Bone rotation around head-tail axis");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_update(prop, 0, "rna_Armature_editbone_transform_update");
diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c
index 2c69331f50a..93cbd5fa246 100644
--- a/source/blender/makesrna/intern/rna_brush.c
+++ b/source/blender/makesrna/intern/rna_brush.c
@@ -510,7 +510,7 @@ static EnumPropertyItem *rna_Brush_direction_itemf(bContext *C, PointerRNA *ptr,
Brush *me = (Brush *)(ptr->data);
switch (mode) {
- case PAINT_SCULPT:
+ case ePaintSculpt:
switch (me->sculpt_tool) {
case SCULPT_TOOL_DRAW:
case SCULPT_TOOL_CREASE:
@@ -550,8 +550,8 @@ static EnumPropertyItem *rna_Brush_direction_itemf(bContext *C, PointerRNA *ptr,
}
break;
- case PAINT_TEXTURE_2D:
- case PAINT_TEXTURE_PROJECTIVE:
+ case ePaintTexture2D:
+ case ePaintTextureProjective:
switch (me->imagepaint_tool) {
case PAINT_TOOL_SOFTEN:
return prop_soften_sharpen_items;
@@ -581,9 +581,9 @@ static EnumPropertyItem *rna_Brush_stroke_itemf(bContext *C, PointerRNA *UNUSED(
};
switch (mode) {
- case PAINT_SCULPT:
- case PAINT_TEXTURE_2D:
- case PAINT_TEXTURE_PROJECTIVE:
+ case ePaintSculpt:
+ case ePaintTexture2D:
+ case ePaintTextureProjective:
return sculpt_stroke_method_items;
default:
diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c
index 6dac2e27f9c..860ed5e49ab 100644
--- a/source/blender/makesrna/intern/rna_constraint.c
+++ b/source/blender/makesrna/intern/rna_constraint.c
@@ -412,6 +412,7 @@ static void rna_Constraint_followTrack_camera_set(PointerRNA *ptr, PointerRNA va
if (ob) {
if (ob->type == OB_CAMERA && ob != (Object *)ptr->id.data) {
data->camera = ob;
+ id_lib_extern((ID *)ob);
}
}
else {
@@ -428,6 +429,7 @@ static void rna_Constraint_followTrack_depthObject_set(PointerRNA *ptr, PointerR
if (ob) {
if (ob->type == OB_MESH && ob != (Object *)ptr->id.data) {
data->depth_ob = ob;
+ id_lib_extern((ID *)ob);
}
}
else {
@@ -457,6 +459,7 @@ static void rna_Constraint_objectSolver_camera_set(PointerRNA *ptr, PointerRNA v
if (ob) {
if (ob->type == OB_CAMERA && ob != (Object *)ptr->id.data) {
data->camera = ob;
+ id_lib_extern((ID *)ob);
}
}
else {
diff --git a/source/blender/makesrna/intern/rna_curve.c b/source/blender/makesrna/intern/rna_curve.c
index cb577c9c97d..65175e37518 100644
--- a/source/blender/makesrna/intern/rna_curve.c
+++ b/source/blender/makesrna/intern/rna_curve.c
@@ -385,6 +385,7 @@ static void rna_Curve_bevelObject_set(PointerRNA *ptr, PointerRNA value)
/* set as bevobj, there could be infinity loop in displist calculation */
if (ob->type == OB_CURVE && ob->data != cu) {
cu->bevobj = ob;
+ id_lib_extern((ID *)ob);
}
}
else {
@@ -427,6 +428,7 @@ static void rna_Curve_taperObject_set(PointerRNA *ptr, PointerRNA value)
/* set as bevobj, there could be infinity loop in displist calculation */
if (ob->type == OB_CURVE && ob->data != cu) {
cu->taperobj = ob;
+ id_lib_extern((ID *)ob);
}
}
else {
@@ -747,11 +749,12 @@ static int rna_Curve_is_editmode_get(PointerRNA *ptr)
#else
+static const float tilt_limit = DEG2RADF(21600.0f);
+
static void rna_def_bpoint(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
- const float tilt_limit = DEG2RADF(21600.0f);
srna = RNA_def_struct(brna, "SplinePoint", NULL);
RNA_def_struct_sdna(srna, "BPoint");
@@ -785,7 +788,7 @@ static void rna_def_bpoint(BlenderRNA *brna)
prop = RNA_def_property(srna, "tilt", PROP_FLOAT, PROP_ANGLE);
RNA_def_property_float_sdna(prop, NULL, "alfa");
RNA_def_property_range(prop, -tilt_limit, tilt_limit);
- RNA_def_property_ui_range(prop, -tilt_limit, tilt_limit, 0.1, 3);
+ RNA_def_property_ui_range(prop, -tilt_limit, tilt_limit, 10, 3);
RNA_def_property_ui_text(prop, "Tilt", "Tilt in 3D View");
RNA_def_property_update(prop, 0, "rna_Curve_update_data");
@@ -872,7 +875,8 @@ static void rna_def_beztriple(BlenderRNA *brna)
/* Number values */
prop = RNA_def_property(srna, "tilt", PROP_FLOAT, PROP_ANGLE);
RNA_def_property_float_sdna(prop, NULL, "alfa");
- /*RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);*/
+ RNA_def_property_range(prop, -tilt_limit, tilt_limit);
+ RNA_def_property_ui_range(prop, -tilt_limit, tilt_limit, 10, 3);
RNA_def_property_ui_text(prop, "Tilt", "Tilt in 3D View");
RNA_def_property_update(prop, 0, "rna_Curve_update_data");
diff --git a/source/blender/makesrna/intern/rna_define.c b/source/blender/makesrna/intern/rna_define.c
index 95bd4bca8e6..3b01305110c 100644
--- a/source/blender/makesrna/intern/rna_define.c
+++ b/source/blender/makesrna/intern/rna_define.c
@@ -1314,8 +1314,10 @@ void RNA_def_property_ui_icon(PropertyRNA *prop, int icon, bool consecutive)
/**
* The values hare are a little confusing:
*
- * \param step For floats this is (step / 100), why /100? - nobody knows.
- * for int's, whole values are used.
+ * \param step: Used as the value to increase/decrease when clicking on number buttons,
+ * \as well as scaling mouse input for click-dragging number buttons.
+ * For floats this is (step * UI_PRECISION_FLOAT_SCALE), why? - nobody knows.
+ * For ints, whole values are used.
*
* \param precision The number of zeros to show
* (as a whole number - common range is 1 - 6), see PRECISION_FLOAT_MAX
@@ -2857,7 +2859,7 @@ PropertyRNA *RNA_def_float_rotation(StructOrFunctionRNA *cont_, const char *iden
ASSERT_SOFT_HARD_LIMITS;
- prop = RNA_def_property(cont, identifier, PROP_FLOAT, (len != 0) ? PROP_EULER : PROP_ANGLE);
+ prop = RNA_def_property(cont, identifier, PROP_FLOAT, (len >= 3) ? PROP_EULER : PROP_ANGLE);
if (len != 0) {
RNA_def_property_array(prop, len);
if (default_value) RNA_def_property_float_array_default(prop, default_value);
@@ -2868,7 +2870,7 @@ PropertyRNA *RNA_def_float_rotation(StructOrFunctionRNA *cont_, const char *iden
}
if (hardmin != hardmax) RNA_def_property_range(prop, hardmin, hardmax);
RNA_def_property_ui_text(prop, ui_name, ui_description);
- RNA_def_property_ui_range(prop, softmin, softmax, 1, 3);
+ RNA_def_property_ui_range(prop, softmin, softmax, 10, 3);
return prop;
}
diff --git a/source/blender/makesrna/intern/rna_fluidsim.c b/source/blender/makesrna/intern/rna_fluidsim.c
index 01feb3cb748..16e0f17eac5 100644
--- a/source/blender/makesrna/intern/rna_fluidsim.c
+++ b/source/blender/makesrna/intern/rna_fluidsim.c
@@ -343,12 +343,12 @@ static void rna_def_fluidsim_domain(BlenderRNA *brna)
prop = RNA_def_property(srna, "start_time", PROP_FLOAT, PROP_TIME);
RNA_def_property_float_sdna(prop, NULL, "animStart");
- RNA_def_property_range(prop, 0, 100);
+ RNA_def_property_range(prop, 0, FLT_MAX);
RNA_def_property_ui_text(prop, "Start Time", "Simulation time of the first blender frame (in seconds)");
prop = RNA_def_property(srna, "end_time", PROP_FLOAT, PROP_TIME);
RNA_def_property_float_sdna(prop, NULL, "animEnd");
- RNA_def_property_range(prop, 0, 100);
+ RNA_def_property_range(prop, 0, FLT_MAX);
RNA_def_property_ui_text(prop, "End Time", "Simulation time of the last blender frame (in seconds)");
prop = RNA_def_property(srna, "frame_offset", PROP_INT, PROP_NONE);
@@ -627,12 +627,12 @@ static void rna_def_fluidsim_control(BlenderRNA *brna)
prop = RNA_def_property(srna, "start_time", PROP_FLOAT, PROP_TIME);
RNA_def_property_float_sdna(prop, NULL, "cpsTimeStart");
- RNA_def_property_range(prop, 0.0, 100.0);
+ RNA_def_property_range(prop, 0.0, FLT_MAX);
RNA_def_property_ui_text(prop, "Start Time", "Time when the control particles are activated");
prop = RNA_def_property(srna, "end_time", PROP_FLOAT, PROP_TIME);
RNA_def_property_float_sdna(prop, NULL, "cpsTimeEnd");
- RNA_def_property_range(prop, 0.0, 100.0);
+ RNA_def_property_range(prop, 0.0, FLT_MAX);
RNA_def_property_ui_text(prop, "End Time", "Time when the control particles are deactivated");
prop = RNA_def_property(srna, "attraction_strength", PROP_FLOAT, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_gpencil.c b/source/blender/makesrna/intern/rna_gpencil.c
index 333220146d6..80a52a0a3d1 100644
--- a/source/blender/makesrna/intern/rna_gpencil.c
+++ b/source/blender/makesrna/intern/rna_gpencil.c
@@ -73,7 +73,7 @@ static int rna_GPencilLayer_active_frame_editable(PointerRNA *ptr)
if (gpl->flag & GP_LAYER_LOCKED)
return 0;
else
- return 1;
+ return PROP_EDITABLE;
}
static void rna_GPencilLayer_line_width_range(PointerRNA *ptr, int *min, int *max,
diff --git a/source/blender/makesrna/intern/rna_image.c b/source/blender/makesrna/intern/rna_image.c
index 0d0b440ec08..64b4d17b17d 100644
--- a/source/blender/makesrna/intern/rna_image.c
+++ b/source/blender/makesrna/intern/rna_image.c
@@ -78,6 +78,16 @@ static void rna_Image_animated_update(Main *UNUSED(bmain), Scene *UNUSED(scene),
}
}
+static int rna_Image_is_stereo_3d_get(PointerRNA *ptr)
+{
+ return BKE_image_is_stereo((Image *)ptr->data);
+}
+
+static int rna_Image_is_multiview_get(PointerRNA *ptr)
+{
+ return BKE_image_is_multiview((Image *)ptr->data);
+}
+
static int rna_Image_dirty_get(PointerRNA *ptr)
{
return BKE_image_is_dirty((Image *)ptr->data);
@@ -539,6 +549,11 @@ static void rna_def_imageuser(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* image_multi_cb */
RNA_def_property_ui_text(prop, "Layer", "Layer in multilayer image");
+ prop = RNA_def_property(srna, "multilayer_pass", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_sdna(prop, NULL, "pass");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* image_multi_cb */
+ RNA_def_property_ui_text(prop, "Pass", "Pass in multilayer image");
+
prop = RNA_def_property(srna, "multilayer_view", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_sdna(prop, NULL, "view");
RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* image_multi_cb */
@@ -561,9 +576,9 @@ static void rna_def_image_packed_files(BlenderRNA *brna)
prop = RNA_def_property(srna, "filepath", PROP_STRING, PROP_FILEPATH);
RNA_def_property_string_sdna(prop, NULL, "filepath");
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_struct_name_property(srna, prop);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+
+ RNA_api_image_packed_file(srna);
}
static void rna_def_render_slot(BlenderRNA *brna)
@@ -711,12 +726,12 @@ static void rna_def_image(BlenderRNA *brna)
RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_views_format_update");
prop = RNA_def_property(srna, "is_stereo_3d", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", IMA_IS_STEREO);
+ RNA_def_property_boolean_funcs(prop, "rna_Image_is_stereo_3d_get", NULL);
RNA_def_property_ui_text(prop, "Stereo 3D", "Image has left and right views");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop = RNA_def_property(srna, "is_multiview", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", IMA_IS_MULTIVIEW);
+ RNA_def_property_boolean_funcs(prop, "rna_Image_is_multiview_get", NULL);
RNA_def_property_ui_text(prop, "Multiple Views", "Image has more than one view");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
diff --git a/source/blender/makesrna/intern/rna_image_api.c b/source/blender/makesrna/intern/rna_image_api.c
index f187a0e1804..1efa41d1b00 100644
--- a/source/blender/makesrna/intern/rna_image_api.c
+++ b/source/blender/makesrna/intern/rna_image_api.c
@@ -63,6 +63,14 @@
#include "MEM_guardedalloc.h"
+static void rna_ImagePackedFile_save(ImagePackedFile *imapf, ReportList *reports)
+{
+ if (writePackedFile(reports, imapf->filepath, imapf->packedfile, 0) != RET_OK) {
+ BKE_reportf(reports, RPT_ERROR, "Image could not save packed file to '%s'",
+ imapf->filepath);
+ }
+}
+
static void rna_Image_save_render(Image *image, bContext *C, ReportList *reports, const char *path, Scene *scene)
{
ImBuf *ibuf;
@@ -115,17 +123,10 @@ static void rna_Image_save(Image *image, Main *bmain, bContext *C, ReportList *r
BLI_strncpy(filename, image->name, sizeof(filename));
BLI_path_abs(filename, ID_BLEND_PATH(bmain, &image->id));
- if (BKE_image_has_packedfile(image)) {
- ImagePackedFile *imapf;
+ /* note, we purposefully ignore packed files here,
+ * developers need to explicitly write them via 'packed_files' */
- for (imapf = image->packedfiles.first; imapf; imapf = imapf->next) {
- if (writePackedFile(reports, imapf->filepath, imapf->packedfile, 0) != RET_OK) {
- BKE_reportf(reports, RPT_ERROR, "Image '%s' could not save packed file to '%s'",
- image->id.name + 2, imapf->filepath);
- }
- }
- }
- else if (IMB_saveiff(ibuf, filename, ibuf->flags)) {
+ if (IMB_saveiff(ibuf, filename, ibuf->flags)) {
image->type = IMA_TYPE_IMAGE;
if (image->source == IMA_SRC_GENERATED)
@@ -295,6 +296,15 @@ static void rna_Image_buffers_free(Image *image)
#else
+void RNA_api_image_packed_file(StructRNA *srna)
+{
+ FunctionRNA *func;
+
+ func = RNA_def_function(srna, "save", "rna_ImagePackedFile_save");
+ RNA_def_function_ui_description(func, "Save the packed file to its filepath");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+}
+
void RNA_api_image(StructRNA *srna)
{
FunctionRNA *func;
diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h
index a7e6600314d..0da2f7d1ad4 100644
--- a/source/blender/makesrna/intern/rna_internal.h
+++ b/source/blender/makesrna/intern/rna_internal.h
@@ -260,6 +260,7 @@ void RNA_api_camera(StructRNA *srna);
void RNA_api_curve(StructRNA *srna);
void RNA_api_fcurves(StructRNA *srna);
void RNA_api_drivers(StructRNA *srna);
+void RNA_api_image_packed_file(struct StructRNA *srna);
void RNA_api_image(struct StructRNA *srna);
void RNA_api_lattice(struct StructRNA *srna);
void RNA_api_operator(struct StructRNA *srna);
diff --git a/source/blender/makesrna/intern/rna_key.c b/source/blender/makesrna/intern/rna_key.c
index 8a3a8a60120..90794ccc211 100644
--- a/source/blender/makesrna/intern/rna_key.c
+++ b/source/blender/makesrna/intern/rna_key.c
@@ -156,6 +156,112 @@ static void rna_ShapeKey_slider_max_set(PointerRNA *ptr, float value)
#undef SHAPEKEY_SLIDER_TOL
+/* ***** Normals accessors for shapekeys. ***** */
+/* Note: with this we may recompute several times the same data, should we want to access verts, then polys, then loops
+ * normals... However, such case looks rather unlikely - and not worth adding some kind of caching in KeyBlocks.
+ */
+
+static Mesh *rna_KeyBlock_normals_get_mesh(PointerRNA *ptr, ID *id)
+{
+ Key *key = rna_ShapeKey_find_key((id == NULL && ptr != NULL) ? ptr->id.data : id);
+ id = key ? key->from : NULL;
+
+ if (id != NULL) {
+ switch (GS(id->name)) {
+ case ID_ME:
+ return (Mesh *)id;
+ case ID_OB:
+ {
+ Object *ob = (Object *)id;
+ if (ob->type == OB_MESH) {
+ return ob->data;
+ }
+ }
+ }
+ }
+
+ return NULL;
+}
+
+static int rna_KeyBlock_normals_vert_len(PointerRNA *ptr, int length[RNA_MAX_ARRAY_DIMENSION])
+{
+ Mesh *me = rna_KeyBlock_normals_get_mesh(ptr, NULL);
+
+ length[0] = me ? me->totvert : 0;
+ length[1] = 3;
+
+ return (length[0] * length[1]);
+}
+
+static void rna_KeyBlock_normals_vert_calc(ID *id, KeyBlock *data, int *normals_len, float **normals)
+{
+ Mesh *me = rna_KeyBlock_normals_get_mesh(NULL, id);
+
+ *normals_len = (me ? me->totvert : 0) * 3;
+
+ if (ELEM(NULL, me, data) || (me->totvert == 0)) {
+ *normals = NULL;
+ return;
+ }
+
+ *normals = MEM_mallocN(sizeof(**normals) * (size_t)(*normals_len), __func__);
+
+ BKE_keyblock_mesh_calc_normals(data, me, (float (*)[3])(*normals), NULL, NULL);
+}
+
+static int rna_KeyBlock_normals_poly_len(PointerRNA *ptr, int length[RNA_MAX_ARRAY_DIMENSION])
+{
+ Mesh *me = rna_KeyBlock_normals_get_mesh(ptr, NULL);
+
+ length[0] = me ? me->totpoly : 0;
+ length[1] = 3;
+
+ return (length[0] * length[1]);
+}
+
+static void rna_KeyBlock_normals_poly_calc(ID *id, KeyBlock *data, int *normals_len, float **normals)
+{
+ Mesh *me = rna_KeyBlock_normals_get_mesh(NULL, id);
+
+ *normals_len = (me ? me->totpoly : 0) * 3;
+
+ if (ELEM(NULL, me, data) || (me->totpoly == 0)) {
+ *normals = NULL;
+ return;
+ }
+
+ *normals = MEM_mallocN(sizeof(**normals) * (size_t)(*normals_len), __func__);
+
+ BKE_keyblock_mesh_calc_normals(data, me, NULL, (float (*)[3])(*normals), NULL);
+}
+
+static int rna_KeyBlock_normals_loop_len(PointerRNA *ptr, int length[RNA_MAX_ARRAY_DIMENSION])
+{
+ Mesh *me = rna_KeyBlock_normals_get_mesh(ptr, NULL);
+
+ length[0] = me ? me->totloop : 0;
+ length[1] = 3;
+
+ return (length[0] * length[1]);
+}
+
+static void rna_KeyBlock_normals_loop_calc(ID *id, KeyBlock *data, int *normals_len, float **normals)
+{
+ Mesh *me = rna_KeyBlock_normals_get_mesh(NULL, id);
+
+ *normals_len = (me ? me->totloop : 0) * 3;
+
+ if (ELEM(NULL, me, data) || (me->totloop == 0)) {
+ *normals = NULL;
+ return;
+ }
+
+ *normals = MEM_mallocN(sizeof(**normals) * (size_t)(*normals_len), __func__);
+
+ BKE_keyblock_mesh_calc_normals(data, me, NULL, NULL, (float (*)[3])(*normals));
+}
+
+
PointerRNA rna_object_shapekey_index_get(ID *id, int value)
{
Key *key = rna_ShapeKey_find_key(id);
@@ -558,7 +664,8 @@ static void rna_def_keydata(BlenderRNA *brna)
static void rna_def_keyblock(BlenderRNA *brna)
{
StructRNA *srna;
- PropertyRNA *prop;
+ PropertyRNA *prop, *parm;
+ FunctionRNA *func;
srna = RNA_def_struct(brna, "ShapeKey", NULL);
RNA_def_struct_ui_text(srna, "Shape Key", "Shape key in a shape keys datablock");
@@ -638,6 +745,36 @@ static void rna_def_keyblock(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Data", "");
RNA_def_property_collection_funcs(prop, "rna_ShapeKey_data_begin", NULL, NULL, "rna_ShapeKey_data_get",
"rna_ShapeKey_data_length", NULL, NULL, NULL);
+
+ /* XXX multi-dim dynamic arrays are very badly supported by (py)rna currently, those are defined for the day
+ * it works better, for now user will get a 1D tuple...
+ **/
+ func = RNA_def_function(srna, "normals_vertex_get", "rna_KeyBlock_normals_vert_calc");
+ RNA_def_function_ui_description(func, "Compute local space vertices' normals for this shape key");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID);
+ parm = RNA_def_property(func, "normals", PROP_FLOAT, /* PROP_DIRECTION */ PROP_NONE);
+ RNA_def_property_flag(parm, PROP_DYNAMIC | PROP_OUTPUT);
+ RNA_def_property_multi_array(parm, 2, NULL);
+ RNA_def_property_range(parm, -1.0f, 1.0f);
+ RNA_def_property_dynamic_array_funcs(parm, "rna_KeyBlock_normals_vert_len");
+
+ func = RNA_def_function(srna, "normals_polygon_get", "rna_KeyBlock_normals_poly_calc");
+ RNA_def_function_ui_description(func, "Compute local space faces' normals for this shape key");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID);
+ parm = RNA_def_property(func, "normals", PROP_FLOAT, /* PROP_DIRECTION */ PROP_NONE);
+ RNA_def_property_flag(parm, PROP_DYNAMIC | PROP_OUTPUT);
+ RNA_def_property_multi_array(parm, 2, NULL);
+ RNA_def_property_range(parm, -1.0f, 1.0f);
+ RNA_def_property_dynamic_array_funcs(parm, "rna_KeyBlock_normals_poly_len");
+
+ func = RNA_def_function(srna, "normals_split_get", "rna_KeyBlock_normals_loop_calc");
+ RNA_def_function_ui_description(func, "Compute local space face corners' normals for this shape key");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID);
+ parm = RNA_def_property(func, "normals", PROP_FLOAT, /* PROP_DIRECTION */ PROP_NONE);
+ RNA_def_property_flag(parm, PROP_DYNAMIC | PROP_OUTPUT);
+ RNA_def_property_multi_array(parm, 2, NULL);
+ RNA_def_property_range(parm, -1.0f, 1.0f);
+ RNA_def_property_dynamic_array_funcs(parm, "rna_KeyBlock_normals_loop_len");
}
static void rna_def_key(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_lattice.c b/source/blender/makesrna/intern/rna_lattice.c
index 60e5f6d205c..035e9d15641 100644
--- a/source/blender/makesrna/intern/rna_lattice.c
+++ b/source/blender/makesrna/intern/rna_lattice.c
@@ -175,7 +175,7 @@ static int rna_Lattice_size_editable(PointerRNA *ptr)
{
Lattice *lt = (Lattice *)ptr->data;
- return lt->key == NULL;
+ return (lt->key == NULL) ? PROP_EDITABLE : 0;
}
static void rna_Lattice_points_u_set(PointerRNA *ptr, int value)
diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c
index 9ccff3eb1fa..5a0da0b7651 100644
--- a/source/blender/makesrna/intern/rna_main_api.c
+++ b/source/blender/makesrna/intern/rna_main_api.c
@@ -36,6 +36,7 @@
#include "DNA_ID.h"
#include "DNA_modifier_types.h"
#include "DNA_space_types.h"
+#include "DNA_object_types.h"
#include "BLI_utildefines.h"
#include "BLI_path_util.h"
@@ -88,7 +89,6 @@
#include "DNA_lamp_types.h"
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
-#include "DNA_object_types.h"
#include "DNA_speaker_types.h"
#include "DNA_sound_types.h"
#include "DNA_text_types.h"
@@ -352,12 +352,17 @@ static Image *rna_Main_images_new(Main *bmain, const char *name, int width, int
id_us_min(&image->id);
return image;
}
-static Image *rna_Main_images_load(Main *bmain, ReportList *reports, const char *filepath)
+static Image *rna_Main_images_load(Main *bmain, ReportList *reports, const char *filepath, int check_existing)
{
Image *ima;
errno = 0;
- ima = BKE_image_load(bmain, filepath);
+ if (check_existing) {
+ ima = BKE_image_load_exists(filepath);
+ }
+ else {
+ ima = BKE_image_load(bmain, filepath);
+ }
if (!ima) {
BKE_reportf(reports, RPT_ERROR, "Cannot read '%s': %s", filepath,
@@ -436,12 +441,17 @@ static void rna_Main_metaballs_remove(Main *bmain, ReportList *reports, PointerR
}
}
-static VFont *rna_Main_fonts_load(Main *bmain, ReportList *reports, const char *filepath)
+static VFont *rna_Main_fonts_load(Main *bmain, ReportList *reports, const char *filepath, int check_existing)
{
VFont *font;
-
errno = 0;
- font = BKE_vfont_load(bmain, filepath);
+
+ if (check_existing) {
+ font = BKE_vfont_load_exists(bmain, filepath);
+ }
+ else {
+ font = BKE_vfont_load(bmain, filepath);
+ }
if (!font)
BKE_reportf(reports, RPT_ERROR, "Cannot read '%s': %s", filepath,
@@ -483,12 +493,13 @@ static void rna_Main_textures_remove(Main *bmain, ReportList *reports, PointerRN
}
}
-static Brush *rna_Main_brushes_new(Main *bmain, const char *name)
+static Brush *rna_Main_brushes_new(Main *bmain, const char *name, int mode)
{
- Brush *brush = BKE_brush_add(bmain, name);
+ Brush *brush = BKE_brush_add(bmain, name, mode);
id_us_min(&brush->id);
return brush;
}
+
static void rna_Main_brushes_remove(Main *bmain, ReportList *reports, PointerRNA *brush_ptr)
{
Brush *brush = brush_ptr->data;
@@ -552,9 +563,17 @@ static void rna_Main_speakers_remove(Main *bmain, ReportList *reports, PointerRN
}
}
-static bSound *rna_Main_sounds_load(Main *bmain, const char *name)
+static bSound *rna_Main_sounds_load(Main *bmain, const char *name, int check_existing)
{
- bSound *sound = BKE_sound_new_file(bmain, name);
+ bSound *sound;
+
+ if (check_existing) {
+ sound = BKE_sound_new_file_exists(bmain, name);
+ }
+ else {
+ sound = BKE_sound_new_file(bmain, name);
+ }
+
id_us_min(&sound->id);
return sound;
}
@@ -674,12 +693,18 @@ static void rna_Main_palettes_remove(Main *bmain, ReportList *reports, PointerRN
}
}
-static MovieClip *rna_Main_movieclip_load(Main *bmain, ReportList *reports, const char *filepath)
+static MovieClip *rna_Main_movieclip_load(Main *bmain, ReportList *reports, const char *filepath, int check_existing)
{
MovieClip *clip;
errno = 0;
- clip = BKE_movieclip_file_add(bmain, filepath);
+
+ if (check_existing) {
+ clip = BKE_movieclip_file_add_exists(bmain, filepath);
+ }
+ else {
+ clip = BKE_movieclip_file_add(bmain, filepath);
+ }
if (!clip)
BKE_reportf(reports, RPT_ERROR, "Cannot read '%s': %s", filepath,
@@ -1206,6 +1231,7 @@ void RNA_def_main_images(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_function_ui_description(func, "Load a new image into the main database");
parm = RNA_def_string_file_path(func, "filepath", "File Path", 0, "", "path of the file to load");
RNA_def_property_flag(parm, PROP_REQUIRED);
+ RNA_def_boolean(func, "check_existing", false, "", "Using existing data-block if this file is already loaded");
/* return type */
parm = RNA_def_pointer(func, "image", "Image", "", "New image datablock");
RNA_def_function_return(func, parm);
@@ -1350,6 +1376,7 @@ void RNA_def_main_fonts(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_function_ui_description(func, "Load a new font into the main database");
parm = RNA_def_string_file_path(func, "filepath", "File Path", 0, "", "path of the font to load");
RNA_def_property_flag(parm, PROP_REQUIRED);
+ RNA_def_boolean(func, "check_existing", false, "", "Using existing data-block if this file is already loaded");
/* return type */
parm = RNA_def_pointer(func, "vfont", "VectorFont", "", "New font datablock");
RNA_def_function_return(func, parm);
@@ -1422,6 +1449,7 @@ void RNA_def_main_brushes(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_function_ui_description(func, "Add a new brush to the main database");
parm = RNA_def_string(func, "name", "Brush", 0, "", "New name for the datablock");
RNA_def_property_flag(parm, PROP_REQUIRED);
+ parm = RNA_def_enum(func, "mode", object_mode_items, OB_MODE_TEXTURE_PAINT, "", "Paint Mode for the new brush");
/* return type */
parm = RNA_def_pointer(func, "brush", "Brush", "", "New brush datablock");
RNA_def_function_return(func, parm);
@@ -1612,6 +1640,7 @@ void RNA_def_main_sounds(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_function_ui_description(func, "Add a new sound to the main database from a file");
parm = RNA_def_string_file_path(func, "filepath", "Path", FILE_MAX, "", "path for the datablock");
RNA_def_property_flag(parm, PROP_REQUIRED);
+ RNA_def_boolean(func, "check_existing", false, "", "Using existing data-block if this file is already loaded");
/* return type */
parm = RNA_def_pointer(func, "sound", "Sound", "", "New text datablock");
RNA_def_function_return(func, parm);
@@ -1835,6 +1864,7 @@ void RNA_def_main_movieclips(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_function_ui_description(func, "Add a new movie clip to the main database from a file");
parm = RNA_def_string_file_path(func, "filepath", "Path", FILE_MAX, "", "path for the datablock");
RNA_def_property_flag(parm, PROP_REQUIRED);
+ RNA_def_boolean(func, "check_existing", false, "", "Using existing data-block if this file is already loaded");
/* return type */
parm = RNA_def_pointer(func, "clip", "MovieClip", "", "New movie clip datablock");
RNA_def_function_return(func, parm);
diff --git a/source/blender/makesrna/intern/rna_material.c b/source/blender/makesrna/intern/rna_material.c
index a1fa6ab13be..d7e566ff431 100644
--- a/source/blender/makesrna/intern/rna_material.c
+++ b/source/blender/makesrna/intern/rna_material.c
@@ -237,7 +237,7 @@ static int rna_Material_active_texture_editable(PointerRNA *ptr)
{
Material *ma = (Material *)ptr->id.data;
- return has_current_material_texture(ma);
+ return has_current_material_texture(ma) ? PROP_EDITABLE : 0;
}
static PointerRNA rna_Material_active_node_material_get(PointerRNA *ptr)
diff --git a/source/blender/makesrna/intern/rna_mesh_api.c b/source/blender/makesrna/intern/rna_mesh_api.c
index 632b07c19ce..1459157112e 100644
--- a/source/blender/makesrna/intern/rna_mesh_api.c
+++ b/source/blender/makesrna/intern/rna_mesh_api.c
@@ -136,8 +136,9 @@ static void rna_Mesh_normals_split_custom_do(Mesh *mesh, float (*custom_loopnors
}
else {
polynors = MEM_mallocN(sizeof(float[3]) * mesh->totpoly, __func__);
- BKE_mesh_calc_normals_poly(mesh->mvert, mesh->totvert, mesh->mloop, mesh->mpoly, mesh->totloop, mesh->totpoly,
- polynors, false);
+ BKE_mesh_calc_normals_poly(
+ mesh->mvert, NULL, mesh->totvert,
+ mesh->mloop, mesh->mpoly, mesh->totloop, mesh->totpoly, polynors, false);
free_polynors = true;
}
diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c
index 694a438333a..6b604728387 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -549,9 +549,11 @@ RNA_MOD_OBJECT_SET(Shrinkwrap, auxTarget, OB_MESH);
static void rna_HookModifier_object_set(PointerRNA *ptr, PointerRNA value)
{
HookModifierData *hmd = ptr->data;
+ Object *ob = (Object *)value.data;
- hmd->object = (Object *)value.data;
- BKE_object_modifier_hook_reset((Object *)ptr->id.data, hmd);
+ hmd->object = ob;
+ id_lib_extern((ID *)ob);
+ BKE_object_modifier_hook_reset(ob, hmd);
}
static PointerRNA rna_UVProjector_object_get(PointerRNA *ptr)
@@ -562,8 +564,10 @@ static PointerRNA rna_UVProjector_object_get(PointerRNA *ptr)
static void rna_UVProjector_object_set(PointerRNA *ptr, PointerRNA value)
{
- Object **ob = (Object **)ptr->data;
- *ob = value.data;
+ Object **ob_p = (Object **)ptr->data;
+ Object *ob = (Object *)value.data;
+ id_lib_extern((ID *)ob);
+ *ob_p = ob;
}
#undef RNA_MOD_OBJECT_SET
@@ -1493,7 +1497,7 @@ static void rna_def_modifier_decimate(BlenderRNA *brna)
prop = RNA_def_property(srna, "angle_limit", PROP_FLOAT, PROP_ANGLE);
RNA_def_property_float_sdna(prop, NULL, "angle");
RNA_def_property_range(prop, 0, DEG2RAD(180));
- RNA_def_property_ui_range(prop, 0, DEG2RAD(180), 100, 2);
+ RNA_def_property_ui_range(prop, 0, DEG2RAD(180), 10, 2);
RNA_def_property_ui_text(prop, "Angle Limit", "Only dissolve angles below this (planar only)");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
@@ -1969,7 +1973,7 @@ static void rna_def_modifier_edgesplit(BlenderRNA *brna)
prop = RNA_def_property(srna, "split_angle", PROP_FLOAT, PROP_ANGLE);
RNA_def_property_range(prop, 0.0f, DEG2RADF(180.0f));
- RNA_def_property_ui_range(prop, 0.0f, DEG2RADF(180.0f), 100, 2);
+ RNA_def_property_ui_range(prop, 0.0f, DEG2RADF(180.0f), 10, 2);
RNA_def_property_ui_text(prop, "Split Angle", "Angle above which to split edges");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
@@ -2806,7 +2810,7 @@ static void rna_def_modifier_bevel(BlenderRNA *brna)
prop = RNA_def_property(srna, "angle_limit", PROP_FLOAT, PROP_ANGLE);
RNA_def_property_float_sdna(prop, NULL, "bevel_angle");
RNA_def_property_range(prop, 0.0f, DEG2RADF(180.0f));
- RNA_def_property_ui_range(prop, 0.0f, DEG2RADF(180.0f), 100, 2);
+ RNA_def_property_ui_range(prop, 0.0f, DEG2RADF(180.0f), 10, 2);
RNA_def_property_ui_text(prop, "Angle", "Angle above which to bevel edges");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
@@ -3056,7 +3060,7 @@ static void rna_def_modifier_simpledeform(BlenderRNA *brna)
prop = RNA_def_property(srna, "factor", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
- RNA_def_property_ui_range(prop, -10, 10, 1, 3);
+ RNA_def_property_ui_range(prop, -10.0, 10.0, 1.0, 3);
RNA_def_property_ui_text(prop, "Factor", "Amount to deform object");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
@@ -3064,7 +3068,7 @@ static void rna_def_modifier_simpledeform(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "factor");
RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
RNA_def_property_float_default(prop, DEG2RADF(45.0f));
- RNA_def_property_ui_range(prop, -M_PI, M_PI, DEG2RAD(1), 3);
+ RNA_def_property_ui_range(prop, DEG2RAD(-360.0), DEG2RAD(360.0), 10.0, 3);
RNA_def_property_ui_text(prop, "Angle", "Angle of deformation");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
@@ -3260,7 +3264,7 @@ static void rna_def_modifier_screw(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_Modifier_update");
prop = RNA_def_property(srna, "angle", PROP_FLOAT, PROP_ANGLE);
- RNA_def_property_ui_range(prop, -M_PI * 2, M_PI * 2, 2, -1);
+ RNA_def_property_ui_range(prop, -M_PI * 2, M_PI * 2, 10, -1);
RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
RNA_def_property_ui_text(prop, "Angle", "Angle of revolution");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
diff --git a/source/blender/makesrna/intern/rna_nla.c b/source/blender/makesrna/intern/rna_nla.c
index 4b66313cdd4..0e8ed5eea8d 100644
--- a/source/blender/makesrna/intern/rna_nla.c
+++ b/source/blender/makesrna/intern/rna_nla.c
@@ -290,7 +290,7 @@ static int rna_NlaStrip_action_editable(PointerRNA *ptr)
return 0;
/* should be ok, though we may still miss some cases */
- return 1;
+ return PROP_EDITABLE;
}
static void rna_NlaStrip_action_start_frame_set(PointerRNA *ptr, float value)
@@ -614,7 +614,7 @@ static void rna_def_nlastrip(BlenderRNA *brna)
* (minimum should still be > 0 though) if needed... */
RNA_def_property_range(prop, 0.1f, 1000.0f);
RNA_def_property_ui_text(prop, "Repeat", "Number of times to repeat the action range");
- RNA_def_property_update(prop, NC_ANIMATION | ND_NLA, NULL); /* this will do? */
+ RNA_def_property_update(prop, 0, "rna_NlaStrip_transform_update");
prop = RNA_def_property(srna, "scale", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "scale");
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index 51e611418aa..a51dffb8ca3 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -792,6 +792,11 @@ static bNodeLink *rna_NodeTree_link_new(bNodeTree *ntree, ReportList *reports,
ret = nodeAddLink(ntree, fromnode, fromsock, tonode, tosock);
if (ret) {
+
+ /* not an issue from the UI, clear hidden from API to keep valid state. */
+ fromsock->flag &= ~SOCK_HIDDEN;
+ tosock->flag &= ~SOCK_HIDDEN;
+
if (tonode)
nodeUpdate(ntree, tonode);
@@ -3011,10 +3016,14 @@ static int point_density_color_source_from_shader(NodeShaderTexPointDensity *sha
}
}
-/* TODO(sergey): This functio nassumes allocated array was passed,
+/* TODO(sergey): This function assumes allocated array was passed,
* works fine with Cycles via C++ RNA, but fails with call from python.
*/
-void rna_ShaderNodePointDensity_density_calc(bNode *self, Scene *scene, int *length, float **values)
+void rna_ShaderNodePointDensity_density_calc(bNode *self,
+ Scene *scene,
+ int settings,
+ int *length,
+ float **values)
{
NodeShaderTexPointDensity *shader_point_density = self->storage;
PointDensity pd;
@@ -3046,6 +3055,7 @@ void rna_ShaderNodePointDensity_density_calc(bNode *self, Scene *scene, int *len
/* Single-threaded sampling of the voxel domain. */
RE_sample_point_density(scene, &pd,
shader_point_density->resolution,
+ settings == 1,
*values);
/* We're done, time to clean up. */
@@ -3538,17 +3548,29 @@ static void def_sh_tex_sky(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
+static const EnumPropertyItem sh_tex_prop_color_space_items[] = {
+ {SHD_COLORSPACE_COLOR, "COLOR", 0, "Color",
+ "Image contains color data, and will be converted to linear color for rendering"},
+ {SHD_COLORSPACE_NONE, "NONE", 0, "Non-Color Data",
+ "Image contains non-color data, for example a displacement or normal map, "
+ "and will not be converted"},
+ {0, NULL, 0, NULL, NULL}
+};
+
+static const EnumPropertyItem sh_tex_prop_interpolation_items[] = {
+ {SHD_INTERP_LINEAR, "Linear", 0, "Linear",
+ "Linear interpolation"},
+ {SHD_INTERP_CLOSEST, "Closest", 0, "Closest",
+ "No interpolation (sample closest texel)"},
+ {SHD_INTERP_CUBIC, "Cubic", 0, "Cubic",
+ "Cubic interpolation (CPU only)"},
+ {SHD_INTERP_SMART, "Smart", 0, "Smart",
+ "Bicubic when magnifying, else bilinear (OSL only)"},
+ {0, NULL, 0, NULL, NULL}
+};
+
static void def_sh_tex_environment(StructRNA *srna)
{
- static const EnumPropertyItem prop_color_space_items[] = {
- {SHD_COLORSPACE_COLOR, "COLOR", 0, "Color",
- "Image contains color data, and will be converted to linear color for rendering"},
- {SHD_COLORSPACE_NONE, "NONE", 0, "Non-Color Data",
- "Image contains non-color data, for example a displacement or normal map, "
- "and will not be converted"},
- {0, NULL, 0, NULL, NULL}
- };
-
static const EnumPropertyItem prop_projection_items[] = {
{SHD_PROJ_EQUIRECTANGULAR, "EQUIRECTANGULAR", 0, "Equirectangular",
"Equirectangular or latitude-longitude projection"},
@@ -3570,7 +3592,7 @@ static void def_sh_tex_environment(StructRNA *srna)
def_sh_tex(srna);
prop = RNA_def_property(srna, "color_space", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_items(prop, prop_color_space_items);
+ RNA_def_property_enum_items(prop, sh_tex_prop_color_space_items);
RNA_def_property_enum_default(prop, SHD_COLORSPACE_COLOR);
RNA_def_property_ui_text(prop, "Color Space", "Image file color space");
RNA_def_property_update(prop, 0, "rna_Node_update");
@@ -3580,6 +3602,11 @@ static void def_sh_tex_environment(StructRNA *srna)
RNA_def_property_ui_text(prop, "Projection", "Projection of the input image");
RNA_def_property_update(prop, 0, "rna_Node_update");
+ prop = RNA_def_property(srna, "interpolation", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, sh_tex_prop_interpolation_items);
+ RNA_def_property_ui_text(prop, "Interpolation", "Texture interpolation");
+ RNA_def_property_update(prop, 0, "rna_Node_update");
+
prop = RNA_def_property(srna, "image_user", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_NEVER_NULL);
RNA_def_property_pointer_sdna(prop, NULL, "iuser");
@@ -3590,15 +3617,6 @@ static void def_sh_tex_environment(StructRNA *srna)
static void def_sh_tex_image(StructRNA *srna)
{
- static const EnumPropertyItem prop_color_space_items[] = {
- {SHD_COLORSPACE_COLOR, "COLOR", 0, "Color",
- "Image contains color data, and will be converted to linear color for rendering"},
- {SHD_COLORSPACE_NONE, "NONE", 0, "Non-Color Data",
- "Image contains non-color data, for example a displacement or normal map, "
- "and will not be converted"},
- {0, NULL, 0, NULL, NULL}
- };
-
static const EnumPropertyItem prop_projection_items[] = {
{SHD_PROJ_FLAT, "FLAT", 0, "Flat",
"Image is projected flat using the X and Y coordinates of the texture vector"},
@@ -3611,18 +3629,6 @@ static void def_sh_tex_image(StructRNA *srna)
{0, NULL, 0, NULL, NULL}
};
- static const EnumPropertyItem prop_interpolation_items[] = {
- {SHD_INTERP_LINEAR, "Linear", 0, "Linear",
- "Linear interpolation"},
- {SHD_INTERP_CLOSEST, "Closest", 0, "Closest",
- "No interpolation (sample closest texel)"},
- {SHD_INTERP_CUBIC, "Cubic", 0, "Cubic",
- "Cubic interpolation (CPU only)"},
- {SHD_INTERP_SMART, "Smart", 0, "Smart",
- "Bicubic when magnifying, else bilinear (OSL only)"},
- {0, NULL, 0, NULL, NULL}
- };
-
static EnumPropertyItem prop_image_extension[] = {
{SHD_IMAGE_EXTENSION_REPEAT, "REPEAT", 0, "Repeat", "Cause the image to repeat horizontally and vertically"},
{SHD_IMAGE_EXTENSION_EXTEND, "EXTEND", 0, "Extend", "Extend by repeating edge pixels of the image"},
@@ -3643,7 +3649,7 @@ static void def_sh_tex_image(StructRNA *srna)
def_sh_tex(srna);
prop = RNA_def_property(srna, "color_space", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_items(prop, prop_color_space_items);
+ RNA_def_property_enum_items(prop, sh_tex_prop_color_space_items);
RNA_def_property_enum_default(prop, SHD_COLORSPACE_COLOR);
RNA_def_property_ui_text(prop, "Color Space", "Image file color space");
RNA_def_property_update(prop, 0, "rna_Node_update");
@@ -3654,7 +3660,7 @@ static void def_sh_tex_image(StructRNA *srna)
RNA_def_property_update(prop, 0, "rna_Node_update");
prop = RNA_def_property(srna, "interpolation", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_items(prop, prop_interpolation_items);
+ RNA_def_property_enum_items(prop, sh_tex_prop_interpolation_items);
RNA_def_property_ui_text(prop, "Interpolation", "Texture interpolation");
RNA_def_property_update(prop, 0, "rna_Node_update");
@@ -3929,6 +3935,13 @@ static void def_sh_tex_pointdensity(StructRNA *srna)
{0, NULL, 0, NULL, NULL}
};
+ /* TODO(sergey): Use some mnemonic names for the hardcoded values here. */
+ static EnumPropertyItem calc_mode_items[] = {
+ {0, "VIEWPORT", 0, "Viewport", "Canculate density using viewport settings"},
+ {1, "RENDER", 0, "Render", "Canculate duplis using render settings"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "id");
RNA_def_property_struct_type(prop, "Object");
@@ -3981,6 +3994,7 @@ static void def_sh_tex_pointdensity(StructRNA *srna)
func = RNA_def_function(srna, "calc_point_density", "rna_ShaderNodePointDensity_density_calc");
RNA_def_function_ui_description(func, "Calculate point density");
RNA_def_pointer(func, "scene", "Scene", "", "");
+ RNA_def_enum(func, "settings", calc_mode_items, 1, "", "Calculate density for rendering");
/* TODO, See how array size of 0 works, this shouldnt be used. */
prop = RNA_def_float_array(func, "rgba_values", 1, NULL, 0, 0, "", "RGBA Values", 0, 0);
RNA_def_property_flag(prop, PROP_DYNAMIC);
diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c
index b09a0af63b7..d24c88a74a6 100644
--- a/source/blender/makesrna/intern/rna_object.c
+++ b/source/blender/makesrna/intern/rna_object.c
@@ -108,13 +108,13 @@ static EnumPropertyItem dupli_items[] = {
#endif
static EnumPropertyItem collision_bounds_items[] = {
- {OB_BOUND_BOX, "BOX", 0, "Box", ""},
- {OB_BOUND_SPHERE, "SPHERE", 0, "Sphere", ""},
- {OB_BOUND_CYLINDER, "CYLINDER", 0, "Cylinder", ""},
- {OB_BOUND_CONE, "CONE", 0, "Cone", ""},
- {OB_BOUND_CONVEX_HULL, "CONVEX_HULL", 0, "Convex Hull", ""},
- {OB_BOUND_TRIANGLE_MESH, "TRIANGLE_MESH", 0, "Triangle Mesh", ""},
- {OB_BOUND_CAPSULE, "CAPSULE", 0, "Capsule", ""},
+ {OB_BOUND_BOX, "BOX", ICON_MESH_CUBE, "Box", ""},
+ {OB_BOUND_SPHERE, "SPHERE", ICON_MESH_UVSPHERE, "Sphere", ""},
+ {OB_BOUND_CYLINDER, "CYLINDER", ICON_MESH_CYLINDER, "Cylinder", ""},
+ {OB_BOUND_CONE, "CONE", ICON_MESH_CONE, "Cone", ""},
+ {OB_BOUND_CONVEX_HULL, "CONVEX_HULL", ICON_MESH_ICOSPHERE, "Convex Hull", ""},
+ {OB_BOUND_TRIANGLE_MESH, "TRIANGLE_MESH", ICON_MESH_MONKEY, "Triangle Mesh", ""},
+ {OB_BOUND_CAPSULE, "CAPSULE", ICON_MESH_CAPSULE, "Capsule", ""},
/*{OB_DYN_MESH, "DYNAMIC_MESH", 0, "Dynamic Mesh", ""}, */
{0, NULL, 0, NULL, NULL}
};
@@ -536,11 +536,14 @@ static void rna_Object_dup_group_set(PointerRNA *ptr, PointerRNA value)
/* must not let this be set if the object belongs in this group already,
* thus causing a cycle/infinite-recursion leading to crashes on load [#25298]
*/
- if (BKE_group_object_exists(grp, ob) == 0)
+ if (BKE_group_object_exists(grp, ob) == 0) {
ob->dup_group = grp;
- else
+ id_lib_extern((ID *)grp);
+ }
+ else {
BKE_report(NULL, RPT_ERROR,
"Cannot set dupli-group as object belongs in group being instanced, thus causing a cycle");
+ }
}
static void rna_VertexGroup_name_set(PointerRNA *ptr, const char *value)
@@ -1954,6 +1957,14 @@ static void rna_def_object_game_settings(BlenderRNA *brna)
RNA_def_property_float_default(prop, 55.0f);
RNA_def_property_ui_text(prop, "Fall Speed Max", "Maximum speed at which the character will fall");
+ prop = RNA_def_property(srna, "jump_max", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "max_jumps");
+ RNA_def_property_range(prop, 1, CHAR_MAX);
+ RNA_def_property_ui_range(prop, 1, 10, 1, 1);
+ RNA_def_property_int_default(prop, 1);
+ RNA_def_property_ui_text(prop, "Max Jumps",
+ "The maximum number of jumps the character can make before it hits the ground");
+
/* Collision Masks */
prop = RNA_def_property(srna, "collision_group", PROP_BOOLEAN, PROP_LAYER_MEMBER);
RNA_def_property_boolean_sdna(prop, NULL, "col_group", 1);
diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c
index 75becb341b9..2766540ab69 100644
--- a/source/blender/makesrna/intern/rna_object_force.c
+++ b/source/blender/makesrna/intern/rna_object_force.c
@@ -1639,7 +1639,7 @@ static void rna_def_softbody(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Goal Default",
- "Default Goal (vertex target position) value, when no Vertex Group used");
+ "Default Goal (vertex target position) value");
RNA_def_property_update(prop, 0, "rna_softbody_update");
prop = RNA_def_property(srna, "goal_spring", PROP_FLOAT, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c
index e65023132c9..27ff0a63e75 100644
--- a/source/blender/makesrna/intern/rna_pose.c
+++ b/source/blender/makesrna/intern/rna_pose.c
@@ -1062,6 +1062,17 @@ static void rna_def_pose_channel(BlenderRNA *brna)
RNA_def_property_editable_func(prop, "rna_PoseChannel_proxy_editable");
RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update");
+ prop = RNA_def_property(srna, "custom_shape_scale", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "custom_scale");
+ RNA_def_property_range(prop, 0.0f, 1000.0f);
+ RNA_def_property_ui_text(prop, "Custom Shape Scale", "Adjust the size of the custom shape");
+ RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update");
+
+ prop = RNA_def_property(srna, "use_custom_shape_bone_size", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_negative_sdna(prop, NULL, "drawflag", PCHAN_DRAW_NO_CUSTOM_BONE_SIZE);
+ RNA_def_property_ui_text(prop, "Use Bone Size", "Scale the custom object by the bone length");
+ RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update");
+
prop = RNA_def_property(srna, "custom_shape_transform", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "custom_tx");
RNA_def_property_struct_type(prop, "PoseBone");
diff --git a/source/blender/makesrna/intern/rna_rigidbody.c b/source/blender/makesrna/intern/rna_rigidbody.c
index 58a12f62644..395cb7c443d 100644
--- a/source/blender/makesrna/intern/rna_rigidbody.c
+++ b/source/blender/makesrna/intern/rna_rigidbody.c
@@ -53,7 +53,7 @@ EnumPropertyItem rigidbody_object_type_items[] = {
EnumPropertyItem rigidbody_object_shape_items[] = {
{RB_SHAPE_BOX, "BOX", ICON_MESH_CUBE, "Box", "Box-like shapes (i.e. cubes), including planes (i.e. ground planes)"},
{RB_SHAPE_SPHERE, "SPHERE", ICON_MESH_UVSPHERE, "Sphere", ""},
- {RB_SHAPE_CAPSULE, "CAPSULE", ICON_OUTLINER_OB_META, "Capsule", ""},
+ {RB_SHAPE_CAPSULE, "CAPSULE", ICON_MESH_CAPSULE, "Capsule", ""},
{RB_SHAPE_CYLINDER, "CYLINDER", ICON_MESH_CYLINDER, "Cylinder", ""},
{RB_SHAPE_CONE, "CONE", ICON_MESH_CONE, "Cone", ""},
{RB_SHAPE_CONVEXH, "CONVEX_HULL", ICON_MESH_ICOSPHERE, "Convex Hull",
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 4d7a2c13c1c..5fb6fa19fda 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -156,7 +156,7 @@ EnumPropertyItem mesh_select_mode_items[] = {
};
EnumPropertyItem snap_element_items[] = {
- {SCE_SNAP_MODE_INCREMENT, "INCREMENT", ICON_ALIGN, "Increment", "Snap to increments of grid"},
+ {SCE_SNAP_MODE_INCREMENT, "INCREMENT", ICON_SNAP_INCREMENT, "Increment", "Snap to increments of grid"},
{SCE_SNAP_MODE_VERTEX, "VERTEX", ICON_SNAP_VERTEX, "Vertex", "Snap to vertices"},
{SCE_SNAP_MODE_EDGE, "EDGE", ICON_SNAP_EDGE, "Edge", "Snap to edges"},
{SCE_SNAP_MODE_FACE, "FACE", ICON_SNAP_FACE, "Face", "Snap to faces"},
@@ -165,7 +165,7 @@ EnumPropertyItem snap_element_items[] = {
};
EnumPropertyItem snap_node_element_items[] = {
- {SCE_SNAP_MODE_GRID, "GRID", ICON_SNAP_INCREMENT, "Grid", "Snap to grid"},
+ {SCE_SNAP_MODE_GRID, "GRID", ICON_SNAP_GRID, "Grid", "Snap to grid"},
{SCE_SNAP_MODE_NODE_X, "NODE_X", ICON_SNAP_EDGE, "Node X", "Snap to left/right node border"},
{SCE_SNAP_MODE_NODE_Y, "NODE_Y", ICON_SNAP_EDGE, "Node Y", "Snap to top/bottom node border"},
{SCE_SNAP_MODE_NODE_XY, "NODE_XY", ICON_SNAP_EDGE, "Node X / Y", "Snap to any node border"},
@@ -432,7 +432,7 @@ EnumPropertyItem stereo3d_interlace_type_items[] = {
static void rna_SpaceImageEditor_uv_sculpt_update(Main *bmain, Scene *scene, PointerRNA *UNUSED(ptr))
{
- ED_space_image_uv_sculpt_update(bmain->wm.first, scene->toolsettings);
+ ED_space_image_uv_sculpt_update(bmain->wm.first, scene);
}
static int rna_Scene_object_bases_lookup_string(PointerRNA *ptr, const char *key, PointerRNA *r_ptr)
@@ -554,6 +554,7 @@ static void rna_Scene_set_set(PointerRNA *ptr, PointerRNA value)
return;
}
+ id_lib_extern((ID *)set);
scene->set = set;
}
@@ -1950,7 +1951,7 @@ static void rna_Stereo3dFormat_update(Main *UNUSED(bmain), Scene *UNUSED(scene),
ImBuf *ibuf;
void *lock;
- if ((ima->flag & IMA_IS_STEREO) == 0)
+ if (!BKE_image_is_stereo(ima))
return;
ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
@@ -2219,7 +2220,7 @@ static void rna_def_tool_settings(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "snap_flag", SCE_SNAP_ABS_GRID);
RNA_def_property_ui_text(prop, "Absolute Grid Snap",
"Absolute grid alignment while translating (based on the pivot center)");
- RNA_def_property_ui_icon(prop, ICON_SNAP_INCREMENT, 0);
+ RNA_def_property_ui_icon(prop, ICON_SNAP_GRID, 0);
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */
prop = RNA_def_property(srna, "snap_element", PROP_ENUM, PROP_NONE);
@@ -2550,7 +2551,7 @@ static void rna_def_statvis(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "overhang_max");
RNA_def_property_float_default(prop, 0.5f);
RNA_def_property_range(prop, 0.0f, DEG2RADF(180.0f));
- RNA_def_property_ui_range(prop, 0.0f, DEG2RADF(180.0f), 0.001, 3);
+ RNA_def_property_ui_range(prop, 0.0f, DEG2RADF(180.0f), 10, 3);
RNA_def_property_ui_text(prop, "Overhang Max", "Maximum angle to display");
RNA_def_property_update(prop, 0, "rna_EditMesh_update");
@@ -2589,7 +2590,7 @@ static void rna_def_statvis(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "distort_min");
RNA_def_property_float_default(prop, 0.5f);
RNA_def_property_range(prop, 0.0f, DEG2RADF(180.0f));
- RNA_def_property_ui_range(prop, 0.0f, DEG2RADF(180.0f), 0.001, 3);
+ RNA_def_property_ui_range(prop, 0.0f, DEG2RADF(180.0f), 10, 3);
RNA_def_property_ui_text(prop, "Distort Min", "Minimum angle to display");
RNA_def_property_update(prop, 0, "rna_EditMesh_update");
@@ -2597,7 +2598,7 @@ static void rna_def_statvis(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "distort_max");
RNA_def_property_float_default(prop, 0.5f);
RNA_def_property_range(prop, 0.0f, DEG2RADF(180.0f));
- RNA_def_property_ui_range(prop, 0.0f, DEG2RADF(180.0f), 0.001, 3);
+ RNA_def_property_ui_range(prop, 0.0f, DEG2RADF(180.0f), 10, 3);
RNA_def_property_ui_text(prop, "Distort Max", "Maximum angle to display");
RNA_def_property_update(prop, 0, "rna_EditMesh_update");
@@ -2606,7 +2607,7 @@ static void rna_def_statvis(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "sharp_min");
RNA_def_property_float_default(prop, 0.5f);
RNA_def_property_range(prop, -DEG2RADF(180.0f), DEG2RADF(180.0f));
- RNA_def_property_ui_range(prop, -DEG2RADF(180.0f), DEG2RADF(180.0f), 0.001, 3);
+ RNA_def_property_ui_range(prop, -DEG2RADF(180.0f), DEG2RADF(180.0f), 10, 3);
RNA_def_property_ui_text(prop, "Distort Min", "Minimum angle to display");
RNA_def_property_update(prop, 0, "rna_EditMesh_update");
@@ -2614,7 +2615,7 @@ static void rna_def_statvis(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "sharp_max");
RNA_def_property_float_default(prop, 0.5f);
RNA_def_property_range(prop, -DEG2RADF(180.0f), DEG2RADF(180.0f));
- RNA_def_property_ui_range(prop, -DEG2RADF(180.0f), DEG2RADF(180.0f), 0.001, 3);
+ RNA_def_property_ui_range(prop, -DEG2RADF(180.0f), DEG2RADF(180.0f), 10, 3);
RNA_def_property_ui_text(prop, "Distort Max", "Maximum angle to display");
RNA_def_property_update(prop, 0, "rna_EditMesh_update");
}
@@ -3814,6 +3815,7 @@ static void rna_def_scene_game_data(BlenderRNA *brna)
prop = RNA_def_property(srna, "exit_key", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "exitkey");
RNA_def_property_enum_items(prop, event_type_items);
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_UI_EVENTS);
RNA_def_property_enum_default(prop, ESCKEY);
RNA_def_property_enum_funcs(prop, NULL, "rna_GameSettings_exit_key_set", NULL);
RNA_def_property_ui_text(prop, "Exit Key", "The key that exits the Game Engine");
diff --git a/source/blender/makesrna/intern/rna_sensor.c b/source/blender/makesrna/intern/rna_sensor.c
index baf0ae3ccf5..dec305de192 100644
--- a/source/blender/makesrna/intern/rna_sensor.c
+++ b/source/blender/makesrna/intern/rna_sensor.c
@@ -458,6 +458,7 @@ static void rna_def_keyboard_sensor(BlenderRNA *brna)
prop = RNA_def_property(srna, "key", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "key");
RNA_def_property_enum_items(prop, event_type_items);
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_UI_EVENTS);
RNA_def_property_enum_funcs(prop, NULL, "rna_Sensor_keyboard_key_set", NULL);
RNA_def_property_ui_text(prop, "Key", "");
RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_WINDOWMANAGER);
@@ -466,6 +467,7 @@ static void rna_def_keyboard_sensor(BlenderRNA *brna)
prop = RNA_def_property(srna, "modifier_key_1", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "qual");
RNA_def_property_enum_items(prop, event_type_items);
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_UI_EVENTS);
RNA_def_property_enum_funcs(prop, NULL, "rna_Sensor_keyboard_modifier_set", NULL);
RNA_def_property_ui_text(prop, "Modifier Key", "Modifier key code");
RNA_def_property_update(prop, NC_LOGIC, NULL);
@@ -473,6 +475,7 @@ static void rna_def_keyboard_sensor(BlenderRNA *brna)
prop = RNA_def_property(srna, "modifier_key_2", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "qual2");
RNA_def_property_enum_items(prop, event_type_items);
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_UI_EVENTS);
RNA_def_property_enum_funcs(prop, NULL, "rna_Sensor_keyboard_modifier2_set", NULL);
RNA_def_property_ui_text(prop, "Second Modifier Key", "Modifier key code");
RNA_def_property_update(prop, NC_LOGIC, NULL);
@@ -813,7 +816,7 @@ static void rna_def_joystick_sensor(BlenderRNA *brna)
StructRNA *srna;
PropertyRNA *prop;
- static EnumPropertyItem event_type_items[] = {
+ static EnumPropertyItem event_type_joystick_items[] = {
{SENS_JOY_BUTTON, "BUTTON", 0, "Button", ""},
{SENS_JOY_AXIS, "AXIS", 0, "Axis", ""},
{SENS_JOY_HAT, "HAT", 0, "Hat", ""},
@@ -854,7 +857,8 @@ static void rna_def_joystick_sensor(BlenderRNA *brna)
prop = RNA_def_property(srna, "event_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "type");
- RNA_def_property_enum_items(prop, event_type_items);
+ RNA_def_property_enum_items(prop, event_type_joystick_items);
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_UI_EVENTS);
RNA_def_property_ui_text(prop, "Event Type", "The type of event this joystick sensor is triggered on");
RNA_def_property_update(prop, NC_LOGIC, NULL);
diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c
index bfb62395435..2192eae9fe6 100644
--- a/source/blender/makesrna/intern/rna_sequencer.c
+++ b/source/blender/makesrna/intern/rna_sequencer.c
@@ -2307,10 +2307,16 @@ static void rna_def_gaussian_blur(StructRNA *srna)
static void rna_def_text(StructRNA *srna)
{
- static EnumPropertyItem text_align_items[] = {
- {SEQ_TEXT_ALIGN_LEFT, "LEFT", 0, "Left", ""},
- {SEQ_TEXT_ALIGN_CENTER, "CENTER", 0, "Center", ""},
- {SEQ_TEXT_ALIGN_RIGHT, "RIGHT", 0, "Right", ""},
+ static EnumPropertyItem text_align_x_items[] = {
+ {SEQ_TEXT_ALIGN_X_LEFT, "LEFT", 0, "Left", ""},
+ {SEQ_TEXT_ALIGN_X_CENTER, "CENTER", 0, "Center", ""},
+ {SEQ_TEXT_ALIGN_X_RIGHT, "RIGHT", 0, "Right", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+ static EnumPropertyItem text_align_y_items[] = {
+ {SEQ_TEXT_ALIGN_Y_TOP, "TOP", 0, "Top", ""},
+ {SEQ_TEXT_ALIGN_Y_CENTER, "CENTER", 0, "Center", ""},
+ {SEQ_TEXT_ALIGN_Y_BOTTOM, "BOTTOM", 0, "Bottom", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -2324,17 +2330,30 @@ static void rna_def_text(StructRNA *srna)
RNA_def_property_ui_range(prop, 0.0f, 1000, 1, -1);
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
- prop = RNA_def_property(srna, "location", PROP_FLOAT, PROP_NONE);
+ prop = RNA_def_property(srna, "location", PROP_FLOAT, PROP_XYZ);
RNA_def_property_float_sdna(prop, NULL, "loc");
RNA_def_property_ui_text(prop, "Location", "Location of the text");
RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
RNA_def_property_ui_range(prop, 0.0, 1.0, 1, -1);
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
- prop = RNA_def_property(srna, "align", PROP_ENUM, PROP_NONE);
+ prop = RNA_def_property(srna, "wrap_width", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "wrap_width");
+ RNA_def_property_ui_text(prop, "Wrap Width", "Word wrap width as factor, zero disables");
+ RNA_def_property_range(prop, 0, FLT_MAX);
+ RNA_def_property_ui_range(prop, 0.0, 1.0, 1, -1);
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+
+ prop = RNA_def_property(srna, "align_x", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "align");
- RNA_def_property_enum_items(prop, text_align_items);
- RNA_def_property_ui_text(prop, "Align", "");
+ RNA_def_property_enum_items(prop, text_align_x_items);
+ RNA_def_property_ui_text(prop, "Align X", "");
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+
+ prop = RNA_def_property(srna, "align_y", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "align_y");
+ RNA_def_property_enum_items(prop, text_align_y_items);
+ RNA_def_property_ui_text(prop, "Align Y", "");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
prop = RNA_def_property(srna, "text", PROP_STRING, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index 4836d93876e..8a7ef7cfac1 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -740,7 +740,7 @@ static PointerRNA rna_SpaceImageEditor_uvedit_get(PointerRNA *ptr)
static void rna_SpaceImageEditor_mode_update(Main *bmain, Scene *scene, PointerRNA *UNUSED(ptr))
{
- ED_space_image_paint_update(bmain->wm.first, scene->toolsettings);
+ ED_space_image_paint_update(bmain->wm.first, scene);
}
@@ -1627,7 +1627,7 @@ static int rna_FileBrowser_FSMenuEntry_name_get_editable(PointerRNA *ptr)
{
FSMenuEntry *fsm = ptr->data;
- return fsm->save;
+ return fsm->save ? PROP_EDITABLE : 0;
}
static void rna_FileBrowser_FSMenu_next(CollectionPropertyIterator *iter)
@@ -3774,13 +3774,13 @@ static void rna_def_fileselect_params(BlenderRNA *brna)
PropertyRNA *prop;
static EnumPropertyItem file_display_items[] = {
- {FILE_SHORTDISPLAY, "FILE_SHORTDISPLAY", ICON_SHORTDISPLAY, "Short List", "Display files as short list"},
- {FILE_LONGDISPLAY, "FILE_LONGDISPLAY", ICON_LONGDISPLAY, "Long List", "Display files as a detailed list"},
- {FILE_IMGDISPLAY, "FILE_IMGDISPLAY", ICON_IMGDISPLAY, "Thumbnails", "Display files as thumbnails"},
+ {FILE_SHORTDISPLAY, "LIST_SHORT", ICON_SHORTDISPLAY, "Short List", "Display files as short list"},
+ {FILE_LONGDISPLAY, "LIST_LONG", ICON_LONGDISPLAY, "Long List", "Display files as a detailed list"},
+ {FILE_IMGDISPLAY, "THUMBNAIL", ICON_IMGDISPLAY, "Thumbnails", "Display files as thumbnails"},
{0, NULL, 0, NULL, NULL}
};
- static EnumPropertyItem thumbnail_size_items[] = {
+ static EnumPropertyItem display_size_items[] = {
{32, "TINY", 0, "Tiny", ""},
{64, "SMALL", 0, "Small", ""},
{128, "NORMAL", 0, "Normal", ""},
@@ -3979,10 +3979,11 @@ static void rna_def_fileselect_params(BlenderRNA *brna)
RNA_def_property_flag(prop, PROP_TEXTEDIT_UPDATE);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
- prop = RNA_def_property(srna, "thumbnail_size", PROP_ENUM, PROP_NONE);
+ prop = RNA_def_property(srna, "display_size", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "thumbnail_size");
- RNA_def_property_enum_items(prop, thumbnail_size_items);
- RNA_def_property_ui_text(prop, "Thumbnails Size", "Change the size of the thumbnails");
+ RNA_def_property_enum_items(prop, display_size_items);
+ RNA_def_property_ui_text(prop, "Display Size",
+ "Change the size of the display (width of columns or thumbnails size)");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
}
diff --git a/source/blender/makesrna/intern/rna_vfont.c b/source/blender/makesrna/intern/rna_vfont.c
index 0879f4d355d..e9ba0c78439 100644
--- a/source/blender/makesrna/intern/rna_vfont.c
+++ b/source/blender/makesrna/intern/rna_vfont.c
@@ -48,9 +48,9 @@ static int rna_VectorFont_filepath_editable(PointerRNA *ptr)
{
VFont *vfont = ptr->id.data;
if (BKE_vfont_is_builtin(vfont)) {
- return false;
+ return 0;
}
- return true;
+ return PROP_EDITABLE;
}
static void rna_VectorFont_reload_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c
index c982c139a53..37550b1eaed 100644
--- a/source/blender/makesrna/intern/rna_wm.c
+++ b/source/blender/makesrna/intern/rna_wm.c
@@ -1948,6 +1948,7 @@ static void rna_def_event(BlenderRNA *brna)
prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "type");
RNA_def_property_enum_items(prop, event_type_items);
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_UI_EVENTS);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Type", "");
@@ -2394,6 +2395,7 @@ static void rna_def_keyconfig(BlenderRNA *brna)
prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "type");
RNA_def_property_enum_items(prop, event_type_items);
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_UI_EVENTS);
RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_KeyMapItem_type_itemf");
RNA_def_property_ui_text(prop, "Type", "Type of event");
RNA_def_property_update(prop, 0, "rna_KeyMapItem_update");
@@ -2451,6 +2453,7 @@ static void rna_def_keyconfig(BlenderRNA *brna)
prop = RNA_def_property(srna, "key_modifier", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "keymodifier");
RNA_def_property_enum_items(prop, event_type_items);
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_UI_EVENTS);
RNA_def_property_enum_funcs(prop, NULL, "rna_wmKeyMapItem_keymodifier_set", NULL);
RNA_def_property_ui_text(prop, "Key Modifier", "Regular key pressed as a modifier");
RNA_def_property_update(prop, 0, "rna_KeyMapItem_update");
diff --git a/source/blender/modifiers/intern/MOD_armature.c b/source/blender/modifiers/intern/MOD_armature.c
index 9ce31cebb66..d9ace45453c 100644
--- a/source/blender/modifiers/intern/MOD_armature.c
+++ b/source/blender/modifiers/intern/MOD_armature.c
@@ -45,6 +45,7 @@
#include "BKE_cdderivedmesh.h"
#include "BKE_lattice.h"
+#include "BKE_library_query.h"
#include "BKE_modifier.h"
#include "MEM_guardedalloc.h"
@@ -91,12 +92,11 @@ static bool isDisabled(ModifierData *md, int UNUSED(useRenderParams))
static void foreachObjectLink(
ModifierData *md, Object *ob,
- void (*walk)(void *userData, Object *ob, Object **obpoin),
- void *userData)
+ ObjectWalkFunc walk, void *userData)
{
ArmatureModifierData *amd = (ArmatureModifierData *) md;
- walk(userData, ob, &amd->object);
+ walk(userData, ob, &amd->object, IDWALK_NOP);
}
static void updateDepgraph(ModifierData *md, DagForest *forest,
diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c
index efb77f73ec9..15a7e51e865 100644
--- a/source/blender/modifiers/intern/MOD_array.c
+++ b/source/blender/modifiers/intern/MOD_array.c
@@ -48,6 +48,7 @@
#include "BKE_cdderivedmesh.h"
#include "BKE_displist.h"
#include "BKE_curve.h"
+#include "BKE_library_query.h"
#include "BKE_modifier.h"
#include "MOD_util.h"
@@ -90,15 +91,14 @@ static void copyData(ModifierData *md, ModifierData *target)
static void foreachObjectLink(
ModifierData *md, Object *ob,
- void (*walk)(void *userData, Object *ob, Object **obpoin),
- void *userData)
+ ObjectWalkFunc walk, void *userData)
{
ArrayModifierData *amd = (ArrayModifierData *) md;
- walk(userData, ob, &amd->start_cap);
- walk(userData, ob, &amd->end_cap);
- walk(userData, ob, &amd->curve_ob);
- walk(userData, ob, &amd->offset_ob);
+ walk(userData, ob, &amd->start_cap, IDWALK_NOP);
+ walk(userData, ob, &amd->end_cap, IDWALK_NOP);
+ walk(userData, ob, &amd->curve_ob, IDWALK_NOP);
+ walk(userData, ob, &amd->offset_ob, IDWALK_NOP);
}
static void updateDepgraph(ModifierData *md, DagForest *forest,
diff --git a/source/blender/modifiers/intern/MOD_boolean.c b/source/blender/modifiers/intern/MOD_boolean.c
index eb54a3c4e9c..3fd2c8a3502 100644
--- a/source/blender/modifiers/intern/MOD_boolean.c
+++ b/source/blender/modifiers/intern/MOD_boolean.c
@@ -40,6 +40,7 @@
#include "BLI_utildefines.h"
#include "BKE_cdderivedmesh.h"
+#include "BKE_library_query.h"
#include "BKE_modifier.h"
#include "depsgraph_private.h"
@@ -65,12 +66,11 @@ static bool isDisabled(ModifierData *md, int UNUSED(useRenderParams))
static void foreachObjectLink(
ModifierData *md, Object *ob,
- void (*walk)(void *userData, Object *ob, Object **obpoin),
- void *userData)
+ ObjectWalkFunc walk, void *userData)
{
BooleanModifierData *bmd = (BooleanModifierData *) md;
- walk(userData, ob, &bmd->object);
+ walk(userData, ob, &bmd->object, IDWALK_NOP);
}
static void updateDepgraph(ModifierData *md, DagForest *forest,
diff --git a/source/blender/modifiers/intern/MOD_cast.c b/source/blender/modifiers/intern/MOD_cast.c
index 7c3d65a5c9a..32c3d41c4b6 100644
--- a/source/blender/modifiers/intern/MOD_cast.c
+++ b/source/blender/modifiers/intern/MOD_cast.c
@@ -42,6 +42,7 @@
#include "BKE_deform.h"
#include "BKE_DerivedMesh.h"
+#include "BKE_library_query.h"
#include "BKE_modifier.h"
@@ -97,12 +98,11 @@ static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
static void foreachObjectLink(
ModifierData *md, Object *ob,
- void (*walk)(void *userData, Object *ob, Object **obpoin),
- void *userData)
+ ObjectWalkFunc walk, void *userData)
{
CastModifierData *cmd = (CastModifierData *) md;
- walk(userData, ob, &cmd->object);
+ walk(userData, ob, &cmd->object, IDWALK_NOP);
}
static void updateDepgraph(ModifierData *md, DagForest *forest,
diff --git a/source/blender/modifiers/intern/MOD_cloth.c b/source/blender/modifiers/intern/MOD_cloth.c
index dac0e516e0d..6cc2f097be8 100644
--- a/source/blender/modifiers/intern/MOD_cloth.c
+++ b/source/blender/modifiers/intern/MOD_cloth.c
@@ -49,6 +49,7 @@
#include "BKE_effect.h"
#include "BKE_global.h"
#include "BKE_key.h"
+#include "BKE_library_query.h"
#include "BKE_modifier.h"
#include "BKE_pointcache.h"
@@ -241,11 +242,11 @@ static void foreachIDLink(ModifierData *md, Object *ob,
ClothModifierData *clmd = (ClothModifierData *) md;
if (clmd->coll_parms) {
- walk(userData, ob, (ID **)&clmd->coll_parms->group);
+ walk(userData, ob, (ID **)&clmd->coll_parms->group, IDWALK_NOP);
}
if (clmd->sim_parms && clmd->sim_parms->effector_weights) {
- walk(userData, ob, (ID **)&clmd->sim_parms->effector_weights->group);
+ walk(userData, ob, (ID **)&clmd->sim_parms->effector_weights->group, IDWALK_NOP);
}
}
diff --git a/source/blender/modifiers/intern/MOD_curve.c b/source/blender/modifiers/intern/MOD_curve.c
index 1488296caf9..6e2d746c858 100644
--- a/source/blender/modifiers/intern/MOD_curve.c
+++ b/source/blender/modifiers/intern/MOD_curve.c
@@ -42,6 +42,7 @@
#include "BKE_cdderivedmesh.h"
#include "BKE_lattice.h"
+#include "BKE_library_query.h"
#include "BKE_modifier.h"
#include "depsgraph_private.h"
@@ -84,12 +85,11 @@ static bool isDisabled(ModifierData *md, int UNUSED(userRenderParams))
static void foreachObjectLink(
ModifierData *md, Object *ob,
- void (*walk)(void *userData, Object *ob, Object **obpoin),
- void *userData)
+ ObjectWalkFunc walk, void *userData)
{
CurveModifierData *cmd = (CurveModifierData *) md;
- walk(userData, ob, &cmd->object);
+ walk(userData, ob, &cmd->object, IDWALK_NOP);
}
static void updateDepgraph(ModifierData *md, DagForest *forest,
@@ -112,7 +112,7 @@ static void updateDepgraph(ModifierData *md, DagForest *forest,
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
struct Scene *scene,
- Object *UNUSED(ob),
+ Object *object,
struct DepsNodeHandle *node)
{
CurveModifierData *cmd = (CurveModifierData *)md;
@@ -126,6 +126,8 @@ static void updateDepsgraph(ModifierData *md,
DEG_add_object_relation(node, cmd->object, DEG_OB_COMP_GEOMETRY, "Curve Modifier");
DEG_add_special_eval_flag(scene->depsgraph, &cmd->object->id, DAG_EVAL_NEED_CURVE_PATH);
}
+
+ DEG_add_object_relation(node, object, DEG_OB_COMP_TRANSFORM, "Curve Modifier");
}
static void deformVerts(ModifierData *md, Object *ob,
diff --git a/source/blender/modifiers/intern/MOD_datatransfer.c b/source/blender/modifiers/intern/MOD_datatransfer.c
index 85e9b4ee185..f5ab28d3d88 100644
--- a/source/blender/modifiers/intern/MOD_datatransfer.c
+++ b/source/blender/modifiers/intern/MOD_datatransfer.c
@@ -41,6 +41,7 @@
#include "BKE_data_transfer.h"
#include "BKE_DerivedMesh.h"
#include "BKE_library.h"
+#include "BKE_library_query.h"
#include "BKE_mesh_mapping.h"
#include "BKE_mesh_remap.h"
#include "BKE_modifier.h"
@@ -118,17 +119,12 @@ static bool dependsOnNormals(ModifierData *md)
return false;
}
-static void foreachObjectLink(ModifierData *md, Object *ob,
- void (*walk)(void *userData, Object *ob, Object **obpoin),
- void *userData)
+static void foreachObjectLink(
+ ModifierData *md, Object *ob,
+ ObjectWalkFunc walk, void *userData)
{
DataTransferModifierData *dtmd = (DataTransferModifierData *) md;
- walk(userData, ob, &dtmd->ob_source);
-}
-
-static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
-{
- foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData);
+ walk(userData, ob, &dtmd->ob_source, IDWALK_NOP);
}
static void updateDepgraph(ModifierData *md, DagForest *forest,
@@ -260,6 +256,6 @@ ModifierTypeInfo modifierType_DataTransfer = {
/* dependsOnTime */ NULL,
/* dependsOnNormals */ dependsOnNormals,
/* foreachObjectLink */ foreachObjectLink,
- /* foreachIDLink */ foreachIDLink,
+ /* foreachIDLink */ NULL,
/* foreachTexLink */ NULL,
};
diff --git a/source/blender/modifiers/intern/MOD_displace.c b/source/blender/modifiers/intern/MOD_displace.c
index 7523c7c7525..9ba2d214d50 100644
--- a/source/blender/modifiers/intern/MOD_displace.c
+++ b/source/blender/modifiers/intern/MOD_displace.c
@@ -41,6 +41,7 @@
#include "BKE_cdderivedmesh.h"
#include "BKE_library.h"
+#include "BKE_library_query.h"
#include "BKE_mesh.h"
#include "BKE_modifier.h"
#include "BKE_texture.h"
@@ -129,7 +130,7 @@ static void foreachObjectLink(ModifierData *md, Object *ob,
{
DisplaceModifierData *dmd = (DisplaceModifierData *) md;
- walk(userData, ob, &dmd->map_object);
+ walk(userData, ob, &dmd->map_object, IDWALK_NOP);
}
static void foreachIDLink(ModifierData *md, Object *ob,
@@ -137,7 +138,7 @@ static void foreachIDLink(ModifierData *md, Object *ob,
{
DisplaceModifierData *dmd = (DisplaceModifierData *) md;
- walk(userData, ob, (ID **)&dmd->texture);
+ walk(userData, ob, (ID **)&dmd->texture, IDWALK_USER);
foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData);
}
@@ -235,7 +236,8 @@ static void displaceModifier_do(
clnors = CustomData_get_layer(ldata, CD_NORMAL);
vert_clnors = MEM_mallocN(sizeof(*vert_clnors) * (size_t)numVerts, __func__);
- BKE_mesh_normals_loop_to_vertex(numVerts, dm->getLoopArray(dm), dm->getNumLoops(dm), clnors, vert_clnors);
+ BKE_mesh_normals_loop_to_vertex(numVerts, dm->getLoopArray(dm), dm->getNumLoops(dm),
+ (const float (*)[3])clnors, vert_clnors);
}
else {
direction = MOD_DISP_DIR_NOR;
diff --git a/source/blender/modifiers/intern/MOD_dynamicpaint.c b/source/blender/modifiers/intern/MOD_dynamicpaint.c
index f1b6ceb070c..91af9659d79 100644
--- a/source/blender/modifiers/intern/MOD_dynamicpaint.c
+++ b/source/blender/modifiers/intern/MOD_dynamicpaint.c
@@ -35,6 +35,7 @@
#include "BKE_cdderivedmesh.h"
#include "BKE_dynamicpaint.h"
+#include "BKE_library_query.h"
#include "BKE_modifier.h"
#include "depsgraph_private.h"
@@ -170,12 +171,12 @@ static void foreachIDLink(ModifierData *md, Object *ob,
DynamicPaintSurface *surface = pmd->canvas->surfaces.first;
for (; surface; surface = surface->next) {
- walk(userData, ob, (ID **)&surface->brush_group);
- walk(userData, ob, (ID **)&surface->init_texture);
+ walk(userData, ob, (ID **)&surface->brush_group, IDWALK_NOP);
+ walk(userData, ob, (ID **)&surface->init_texture, IDWALK_USER);
}
}
if (pmd->brush) {
- walk(userData, ob, (ID **)&pmd->brush->mat);
+ walk(userData, ob, (ID **)&pmd->brush->mat, IDWALK_USER);
}
}
diff --git a/source/blender/modifiers/intern/MOD_explode.c b/source/blender/modifiers/intern/MOD_explode.c
index 82600421736..d57ace8d7fe 100644
--- a/source/blender/modifiers/intern/MOD_explode.c
+++ b/source/blender/modifiers/intern/MOD_explode.c
@@ -861,7 +861,7 @@ static DerivedMesh *explodeMesh(ExplodeModifierData *emd,
BLI_edgehashIterator_free(ehi);
/* the final duplicated vertices */
- explode = CDDM_from_template(dm, totdup, 0, totface - delface, 0, 0);
+ explode = CDDM_from_template_ex(dm, totdup, 0, totface - delface, 0, 0, CD_MASK_DERIVEDMESH | CD_MASK_FACECORNERS);
mtface = CustomData_get_layer_named(&explode->faceData, CD_MTFACE, emd->uvname);
/*dupvert = CDDM_get_verts(explode);*/
diff --git a/source/blender/modifiers/intern/MOD_hook.c b/source/blender/modifiers/intern/MOD_hook.c
index 3a10fabbb8e..1a27202fb34 100644
--- a/source/blender/modifiers/intern/MOD_hook.c
+++ b/source/blender/modifiers/intern/MOD_hook.c
@@ -41,6 +41,7 @@
#include "BKE_action.h"
#include "BKE_cdderivedmesh.h"
+#include "BKE_library_query.h"
#include "BKE_modifier.h"
#include "BKE_deform.h"
#include "BKE_colortools.h"
@@ -103,12 +104,11 @@ static bool isDisabled(ModifierData *md, int UNUSED(useRenderParams))
static void foreachObjectLink(
ModifierData *md, Object *ob,
- void (*walk)(void *userData, Object *ob, Object **obpoin),
- void *userData)
+ ObjectWalkFunc walk, void *userData)
{
HookModifierData *hmd = (HookModifierData *) md;
- walk(userData, ob, &hmd->object);
+ walk(userData, ob, &hmd->object, IDWALK_NOP);
}
static void updateDepgraph(ModifierData *md, DagForest *forest,
diff --git a/source/blender/modifiers/intern/MOD_lattice.c b/source/blender/modifiers/intern/MOD_lattice.c
index 52a4f441b63..0f49ce6cfbf 100644
--- a/source/blender/modifiers/intern/MOD_lattice.c
+++ b/source/blender/modifiers/intern/MOD_lattice.c
@@ -41,6 +41,7 @@
#include "BKE_cdderivedmesh.h"
#include "BKE_lattice.h"
+#include "BKE_library_query.h"
#include "BKE_modifier.h"
#include "depsgraph_private.h"
@@ -83,12 +84,11 @@ static bool isDisabled(ModifierData *md, int UNUSED(userRenderParams))
static void foreachObjectLink(
ModifierData *md, Object *ob,
- void (*walk)(void *userData, Object *ob, Object **obpoin),
- void *userData)
+ ObjectWalkFunc walk, void *userData)
{
LatticeModifierData *lmd = (LatticeModifierData *) md;
- walk(userData, ob, &lmd->object);
+ walk(userData, ob, &lmd->object, IDWALK_NOP);
}
static void updateDepgraph(ModifierData *md, DagForest *forest,
diff --git a/source/blender/modifiers/intern/MOD_mask.c b/source/blender/modifiers/intern/MOD_mask.c
index 06fbab65d7b..5e01a20d93b 100644
--- a/source/blender/modifiers/intern/MOD_mask.c
+++ b/source/blender/modifiers/intern/MOD_mask.c
@@ -46,6 +46,7 @@
#include "BKE_action.h" /* BKE_pose_channel_find_name */
#include "BKE_cdderivedmesh.h"
+#include "BKE_library_query.h"
#include "BKE_modifier.h"
#include "BKE_deform.h"
@@ -70,11 +71,10 @@ static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *UNUSED(
static void foreachObjectLink(
ModifierData *md, Object *ob,
- void (*walk)(void *userData, Object *ob, Object **obpoin),
- void *userData)
+ ObjectWalkFunc walk, void *userData)
{
MaskModifierData *mmd = (MaskModifierData *)md;
- walk(userData, ob, &mmd->ob_arm);
+ walk(userData, ob, &mmd->ob_arm, IDWALK_NOP);
}
static void updateDepgraph(ModifierData *md, DagForest *forest,
diff --git a/source/blender/modifiers/intern/MOD_meshdeform.c b/source/blender/modifiers/intern/MOD_meshdeform.c
index 5bd33d2a49f..8aa5f281f56 100644
--- a/source/blender/modifiers/intern/MOD_meshdeform.c
+++ b/source/blender/modifiers/intern/MOD_meshdeform.c
@@ -42,6 +42,7 @@
#include "BKE_cdderivedmesh.h"
#include "BKE_global.h"
+#include "BKE_library_query.h"
#include "BKE_modifier.h"
#include "BKE_deform.h"
#include "BKE_editmesh.h"
@@ -114,12 +115,11 @@ static bool isDisabled(ModifierData *md, int UNUSED(useRenderParams))
static void foreachObjectLink(
ModifierData *md, Object *ob,
- void (*walk)(void *userData, Object *ob, Object **obpoin),
- void *userData)
+ ObjectWalkFunc walk, void *userData)
{
MeshDeformModifierData *mmd = (MeshDeformModifierData *) md;
- walk(userData, ob, &mmd->object);
+ walk(userData, ob, &mmd->object, IDWALK_NOP);
}
static void updateDepgraph(ModifierData *md, DagForest *forest,
diff --git a/source/blender/modifiers/intern/MOD_mirror.c b/source/blender/modifiers/intern/MOD_mirror.c
index 3e10fa1d77d..88facb22e0e 100644
--- a/source/blender/modifiers/intern/MOD_mirror.c
+++ b/source/blender/modifiers/intern/MOD_mirror.c
@@ -39,6 +39,7 @@
#include "BLI_math.h"
#include "BKE_cdderivedmesh.h"
+#include "BKE_library_query.h"
#include "BKE_modifier.h"
#include "BKE_deform.h"
@@ -65,13 +66,13 @@ static void copyData(ModifierData *md, ModifierData *target)
modifier_copyData_generic(md, target);
}
-static void foreachObjectLink(ModifierData *md, Object *ob,
- void (*walk)(void *userData, Object *ob, Object **obpoin),
- void *userData)
+static void foreachObjectLink(
+ ModifierData *md, Object *ob,
+ ObjectWalkFunc walk, void *userData)
{
MirrorModifierData *mmd = (MirrorModifierData *) md;
- walk(userData, ob, &mmd->mirror_ob);
+ walk(userData, ob, &mmd->mirror_ob, IDWALK_NOP);
}
static void updateDepgraph(ModifierData *md, DagForest *forest,
diff --git a/source/blender/modifiers/intern/MOD_normal_edit.c b/source/blender/modifiers/intern/MOD_normal_edit.c
index 87d75c6f1a7..a24ed4d6614 100644
--- a/source/blender/modifiers/intern/MOD_normal_edit.c
+++ b/source/blender/modifiers/intern/MOD_normal_edit.c
@@ -38,6 +38,7 @@
#include "BLI_bitmap.h"
#include "BKE_cdderivedmesh.h"
+#include "BKE_library_query.h"
#include "BKE_mesh.h"
#include "BKE_deform.h"
@@ -84,7 +85,7 @@ static void generate_vert_coordinates(
/* Translate our coordinates so that center of ob_center is at (0, 0, 0). */
/* Get ob_center (world) coordinates in ob local coordinates.
- * No need to take into accound ob_center's space here, see T44027. */
+ * No need to take into account ob_center's space here, see T44027. */
invert_m4_m4(inv_obmat, ob->obmat);
mul_v3_m4v3(diff, inv_obmat, ob_center->obmat[3]);
negate_v3(diff);
@@ -387,7 +388,7 @@ static DerivedMesh *normalEditModifier_do(NormalEditModifierData *smd, Object *o
polynors = dm->getPolyDataArray(dm, CD_NORMAL);
if (!polynors) {
polynors = MEM_mallocN(sizeof(*polynors) * num_polys, __func__);
- BKE_mesh_calc_normals_poly(mvert, num_verts, mloop, mpoly, num_loops, num_polys, polynors, false);
+ BKE_mesh_calc_normals_poly(mvert, NULL, num_verts, mloop, mpoly, num_loops, num_polys, polynors, false);
free_polynors = true;
}
@@ -450,14 +451,7 @@ static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk,
{
NormalEditModifierData *smd = (NormalEditModifierData *) md;
- walk(userData, ob, &smd->target);
-}
-
-static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
-{
- NormalEditModifierData *smd = (NormalEditModifierData *) md;
-
- walk(userData, ob, (ID **)&smd->target);
+ walk(userData, ob, &smd->target, IDWALK_NOP);
}
static bool isDisabled(ModifierData *md, int UNUSED(useRenderParams))
@@ -524,6 +518,6 @@ ModifierTypeInfo modifierType_NormalEdit = {
/* dependsOnTime */ NULL,
/* dependsOnNormals */ dependsOnNormals,
/* foreachObjectLink */ foreachObjectLink,
- /* foreachIDLink */ foreachIDLink,
+ /* foreachIDLink */ NULL,
/* foreachTexLink */ NULL,
};
diff --git a/source/blender/modifiers/intern/MOD_ocean.c b/source/blender/modifiers/intern/MOD_ocean.c
index 913c2f25c15..54a7278be72 100644
--- a/source/blender/modifiers/intern/MOD_ocean.c
+++ b/source/blender/modifiers/intern/MOD_ocean.c
@@ -585,4 +585,5 @@ ModifierTypeInfo modifierType_Ocean = {
/* dependsOnNormals */ dependsOnNormals,
/* foreachObjectLink */ NULL,
/* foreachIDLink */ NULL,
+ /* foreachTexLink */ NULL,
};
diff --git a/source/blender/modifiers/intern/MOD_particleinstance.c b/source/blender/modifiers/intern/MOD_particleinstance.c
index cb6234d50b7..289611ad90a 100644
--- a/source/blender/modifiers/intern/MOD_particleinstance.c
+++ b/source/blender/modifiers/intern/MOD_particleinstance.c
@@ -46,6 +46,7 @@
#include "BKE_effect.h"
#include "BKE_global.h"
#include "BKE_lattice.h"
+#include "BKE_library_query.h"
#include "BKE_modifier.h"
#include "BKE_particle.h"
#include "BKE_pointcache.h"
@@ -144,7 +145,7 @@ static void foreachObjectLink(ModifierData *md, Object *ob,
{
ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *) md;
- walk(userData, ob, &pimd->ob);
+ walk(userData, ob, &pimd->ob, IDWALK_NOP);
}
static int particle_skip(ParticleInstanceModifierData *pimd, ParticleSystem *psys, int p)
diff --git a/source/blender/modifiers/intern/MOD_screw.c b/source/blender/modifiers/intern/MOD_screw.c
index 2e431884845..41ebd865720 100644
--- a/source/blender/modifiers/intern/MOD_screw.c
+++ b/source/blender/modifiers/intern/MOD_screw.c
@@ -44,6 +44,7 @@
#include "BLI_utildefines.h"
#include "BKE_cdderivedmesh.h"
+#include "BKE_library_query.h"
#include "depsgraph_private.h"
#include "DEG_depsgraph_build.h"
@@ -766,7 +767,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
}
/* we wont be looping on this data again so copy normals here */
- if (angle < 0.0f)
+ if ((angle < 0.0f) != do_flip)
negate_v3(vc->no);
normalize_v3(vc->no);
@@ -1090,12 +1091,11 @@ static void updateDepsgraph(ModifierData *md,
static void foreachObjectLink(
ModifierData *md, Object *ob,
- void (*walk)(void *userData, Object *ob, Object **obpoin),
- void *userData)
+ ObjectWalkFunc walk, void *userData)
{
ScrewModifierData *ltmd = (ScrewModifierData *) md;
- walk(userData, ob, &ltmd->ob_axis);
+ walk(userData, ob, &ltmd->ob_axis, IDWALK_NOP);
}
ModifierTypeInfo modifierType_Screw = {
diff --git a/source/blender/modifiers/intern/MOD_shrinkwrap.c b/source/blender/modifiers/intern/MOD_shrinkwrap.c
index 91be0c40059..a9919cadd16 100644
--- a/source/blender/modifiers/intern/MOD_shrinkwrap.c
+++ b/source/blender/modifiers/intern/MOD_shrinkwrap.c
@@ -41,6 +41,7 @@
#include "BLI_utildefines.h"
#include "BKE_cdderivedmesh.h"
+#include "BKE_library_query.h"
#include "BKE_modifier.h"
#include "BKE_shrinkwrap.h"
@@ -100,8 +101,8 @@ static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk,
{
ShrinkwrapModifierData *smd = (ShrinkwrapModifierData *) md;
- walk(userData, ob, &smd->target);
- walk(userData, ob, &smd->auxTarget);
+ walk(userData, ob, &smd->target, IDWALK_NOP);
+ walk(userData, ob, &smd->auxTarget, IDWALK_NOP);
}
static void deformVerts(ModifierData *md, Object *ob,
diff --git a/source/blender/modifiers/intern/MOD_simpledeform.c b/source/blender/modifiers/intern/MOD_simpledeform.c
index 706a296f5a1..f4fbfa74076 100644
--- a/source/blender/modifiers/intern/MOD_simpledeform.c
+++ b/source/blender/modifiers/intern/MOD_simpledeform.c
@@ -40,6 +40,7 @@
#include "BLI_utildefines.h"
#include "BKE_cdderivedmesh.h"
+#include "BKE_library_query.h"
#include "BKE_modifier.h"
#include "BKE_deform.h"
@@ -279,11 +280,12 @@ static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
return dataMask;
}
-static void foreachObjectLink(ModifierData *md, Object *ob,
- void (*walk)(void *userData, Object *ob, Object **obpoin), void *userData)
+static void foreachObjectLink(
+ ModifierData *md, Object *ob,
+ ObjectWalkFunc walk, void *userData)
{
SimpleDeformModifierData *smd = (SimpleDeformModifierData *)md;
- walk(userData, ob, &smd->origin);
+ walk(userData, ob, &smd->origin, IDWALK_NOP);
}
static void updateDepgraph(ModifierData *md, DagForest *forest,
diff --git a/source/blender/modifiers/intern/MOD_smoke.c b/source/blender/modifiers/intern/MOD_smoke.c
index 657c4e09d96..f0f235c8ad5 100644
--- a/source/blender/modifiers/intern/MOD_smoke.c
+++ b/source/blender/modifiers/intern/MOD_smoke.c
@@ -48,6 +48,7 @@
#include "BKE_cdderivedmesh.h"
#include "BKE_library.h"
+#include "BKE_library_query.h"
#include "BKE_main.h"
#include "BKE_modifier.h"
#include "BKE_smoke.h"
@@ -339,17 +340,17 @@ static void foreachIDLink(ModifierData *md, Object *ob,
SmokeModifierData *smd = (SmokeModifierData *) md;
if (smd->type == MOD_SMOKE_TYPE_DOMAIN && smd->domain) {
- walk(userData, ob, (ID **)&smd->domain->coll_group);
- walk(userData, ob, (ID **)&smd->domain->fluid_group);
- walk(userData, ob, (ID **)&smd->domain->eff_group);
+ walk(userData, ob, (ID **)&smd->domain->coll_group, IDWALK_NOP);
+ walk(userData, ob, (ID **)&smd->domain->fluid_group, IDWALK_NOP);
+ walk(userData, ob, (ID **)&smd->domain->eff_group, IDWALK_NOP);
if (smd->domain->effector_weights) {
- walk(userData, ob, (ID **)&smd->domain->effector_weights->group);
+ walk(userData, ob, (ID **)&smd->domain->effector_weights->group, IDWALK_NOP);
}
}
if (smd->type == MOD_SMOKE_TYPE_FLOW && smd->flow) {
- walk(userData, ob, (ID **)&smd->flow->noise_texture);
+ walk(userData, ob, (ID **)&smd->flow->noise_texture, IDWALK_USER);
}
}
diff --git a/source/blender/modifiers/intern/MOD_solidify.c b/source/blender/modifiers/intern/MOD_solidify.c
index ca2dcfec3a3..2695f6675c9 100644
--- a/source/blender/modifiers/intern/MOD_solidify.c
+++ b/source/blender/modifiers/intern/MOD_solidify.c
@@ -272,7 +272,7 @@ static DerivedMesh *applyModifier(
/* calculate only face normals */
face_nors = MEM_mallocN(sizeof(*face_nors) * (size_t)numFaces, __func__);
BKE_mesh_calc_normals_poly(
- orig_mvert, (int)numVerts,
+ orig_mvert, NULL, (int)numVerts,
orig_mloop, orig_mpoly,
(int)numLoops, (int)numFaces,
face_nors, true);
diff --git a/source/blender/modifiers/intern/MOD_subsurf.c b/source/blender/modifiers/intern/MOD_subsurf.c
index ab52d798cf8..23ab61821f4 100644
--- a/source/blender/modifiers/intern/MOD_subsurf.c
+++ b/source/blender/modifiers/intern/MOD_subsurf.c
@@ -108,10 +108,8 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
#ifdef WITH_OPENSUBDIV
const bool allow_gpu = (flag & MOD_APPLY_ALLOW_GPU) != 0;
- const bool do_cddm_convert = useRenderParams || (!isFinalCalc && !smd->use_opensubdiv);
-#else
- const bool do_cddm_convert = useRenderParams || !isFinalCalc;
#endif
+ bool do_cddm_convert = useRenderParams || !isFinalCalc;
if (useRenderParams)
subsurf_flags |= SUBSURF_USE_RENDER_PARAMS;
@@ -134,6 +132,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
}
else if ((DAG_get_eval_flags_for_object(md->scene, ob) & DAG_EVAL_NEED_CPU) == 0) {
subsurf_flags |= SUBSURF_USE_GPU_BACKEND;
+ do_cddm_convert = false;
}
else {
modifier_setError(md, "OpenSubdiv is disabled due to dependencies");
@@ -164,11 +163,8 @@ static DerivedMesh *applyModifierEM(ModifierData *md, Object *UNUSED(ob),
SubsurfFlags ss_flags = (flag & MOD_APPLY_ORCO) ? 0 : (SUBSURF_FOR_EDIT_MODE | SUBSURF_IN_EDIT_MODE);
#ifdef WITH_OPENSUBDIV
const bool allow_gpu = (flag & MOD_APPLY_ALLOW_GPU) != 0;
- /* TODO(sergey): Not entirely correct, modifiers on top of subsurf
- * could be disabled.
- */
if (md->next == NULL && allow_gpu && smd->use_opensubdiv) {
- ss_flags |= SUBSURF_USE_GPU_BACKEND;
+ modifier_setError(md, "OpenSubdiv is not supported in edit mode");
}
#endif
diff --git a/source/blender/modifiers/intern/MOD_surface.c b/source/blender/modifiers/intern/MOD_surface.c
index ff5e5f643a7..68987a1d28e 100644
--- a/source/blender/modifiers/intern/MOD_surface.c
+++ b/source/blender/modifiers/intern/MOD_surface.c
@@ -190,6 +190,6 @@ ModifierTypeInfo modifierType_Surface = {
/* dependsOnTime */ dependsOnTime,
/* dependsOnNormals */ NULL,
/* foreachObjectLink */ NULL,
- /* foreachIDLink */ NULL,
- /* foreachTexLink */ NULL,
+ /* foreachIDLink */ NULL,
+ /* foreachTexLink */ NULL,
};
diff --git a/source/blender/modifiers/intern/MOD_uvproject.c b/source/blender/modifiers/intern/MOD_uvproject.c
index 1b1474ee666..fb7668d16e0 100644
--- a/source/blender/modifiers/intern/MOD_uvproject.c
+++ b/source/blender/modifiers/intern/MOD_uvproject.c
@@ -45,6 +45,7 @@
#include "BKE_camera.h"
+#include "BKE_library_query.h"
#include "BKE_mesh.h"
#include "BKE_DerivedMesh.h"
@@ -91,7 +92,7 @@ static void foreachObjectLink(ModifierData *md, Object *ob,
int i;
for (i = 0; i < MOD_UVPROJECT_MAXPROJECTORS; ++i)
- walk(userData, ob, &umd->projectors[i]);
+ walk(userData, ob, &umd->projectors[i], IDWALK_NOP);
}
static void foreachIDLink(ModifierData *md, Object *ob,
@@ -99,10 +100,9 @@ static void foreachIDLink(ModifierData *md, Object *ob,
{
UVProjectModifierData *umd = (UVProjectModifierData *) md;
- walk(userData, ob, (ID **)&umd->image);
+ walk(userData, ob, (ID **)&umd->image, IDWALK_USER);
- foreachObjectLink(md, ob, (ObjectWalkFunc)walk,
- userData);
+ foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData);
}
static void updateDepgraph(ModifierData *md, DagForest *forest,
diff --git a/source/blender/modifiers/intern/MOD_uvwarp.c b/source/blender/modifiers/intern/MOD_uvwarp.c
index 3c4ca66485d..5418c222d13 100644
--- a/source/blender/modifiers/intern/MOD_uvwarp.c
+++ b/source/blender/modifiers/intern/MOD_uvwarp.c
@@ -36,6 +36,7 @@
#include "BKE_action.h" /* BKE_pose_channel_find_name */
#include "BKE_cdderivedmesh.h"
#include "BKE_deform.h"
+#include "BKE_library_query.h"
#include "BKE_modifier.h"
#include "depsgraph_private.h"
@@ -200,8 +201,8 @@ static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk,
{
UVWarpModifierData *umd = (UVWarpModifierData *) md;
- walk(userData, ob, &umd->object_dst);
- walk(userData, ob, &umd->object_src);
+ walk(userData, ob, &umd->object_dst, IDWALK_NOP);
+ walk(userData, ob, &umd->object_src, IDWALK_NOP);
}
static void uv_warp_deps_object_bone(DagForest *forest, DagNode *obNode,
diff --git a/source/blender/modifiers/intern/MOD_warp.c b/source/blender/modifiers/intern/MOD_warp.c
index ae2dbd4a37c..27d3bac59ec 100644
--- a/source/blender/modifiers/intern/MOD_warp.c
+++ b/source/blender/modifiers/intern/MOD_warp.c
@@ -36,6 +36,7 @@
#include "BLI_utildefines.h"
#include "BKE_cdderivedmesh.h"
+#include "BKE_library_query.h"
#include "BKE_modifier.h"
#include "BKE_deform.h"
#include "BKE_texture.h"
@@ -115,20 +116,18 @@ static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk,
{
WarpModifierData *wmd = (WarpModifierData *) md;
- walk(userData, ob, &wmd->object_from);
- walk(userData, ob, &wmd->object_to);
- walk(userData, ob, &wmd->map_object);
+ walk(userData, ob, &wmd->object_from, IDWALK_NOP);
+ walk(userData, ob, &wmd->object_to, IDWALK_NOP);
+ walk(userData, ob, &wmd->map_object, IDWALK_NOP);
}
static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
{
WarpModifierData *wmd = (WarpModifierData *) md;
- walk(userData, ob, (ID **)&wmd->texture);
+ walk(userData, ob, (ID **)&wmd->texture, IDWALK_USER);
- walk(userData, ob, (ID **)&wmd->object_from);
- walk(userData, ob, (ID **)&wmd->object_to);
- walk(userData, ob, (ID **)&wmd->map_object);
+ foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData);
}
static void foreachTexLink(ModifierData *md, Object *ob, TexWalkFunc walk, void *userData)
diff --git a/source/blender/modifiers/intern/MOD_wave.c b/source/blender/modifiers/intern/MOD_wave.c
index 5b98f221489..f13eeb3185e 100644
--- a/source/blender/modifiers/intern/MOD_wave.c
+++ b/source/blender/modifiers/intern/MOD_wave.c
@@ -45,6 +45,7 @@
#include "BKE_deform.h"
#include "BKE_DerivedMesh.h"
#include "BKE_library.h"
+#include "BKE_library_query.h"
#include "BKE_scene.h"
#include "BKE_texture.h"
@@ -110,8 +111,8 @@ static void foreachObjectLink(
{
WaveModifierData *wmd = (WaveModifierData *) md;
- walk(userData, ob, &wmd->objectcenter);
- walk(userData, ob, &wmd->map_object);
+ walk(userData, ob, &wmd->objectcenter, IDWALK_NOP);
+ walk(userData, ob, &wmd->map_object, IDWALK_NOP);
}
static void foreachIDLink(ModifierData *md, Object *ob,
@@ -119,7 +120,7 @@ static void foreachIDLink(ModifierData *md, Object *ob,
{
WaveModifierData *wmd = (WaveModifierData *) md;
- walk(userData, ob, (ID **)&wmd->texture);
+ walk(userData, ob, (ID **)&wmd->texture, IDWALK_USER);
foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData);
}
diff --git a/source/blender/modifiers/intern/MOD_weightvgedit.c b/source/blender/modifiers/intern/MOD_weightvgedit.c
index cba077a2f8d..93567aed2c4 100644
--- a/source/blender/modifiers/intern/MOD_weightvgedit.c
+++ b/source/blender/modifiers/intern/MOD_weightvgedit.c
@@ -42,6 +42,7 @@
#include "BKE_colortools.h" /* CurveMapping. */
#include "BKE_deform.h"
#include "BKE_library.h"
+#include "BKE_library_query.h"
#include "BKE_modifier.h"
#include "BKE_texture.h" /* Texture masking. */
@@ -122,19 +123,17 @@ static bool dependsOnTime(ModifierData *md)
return false;
}
-static void foreachObjectLink(ModifierData *md, Object *ob,
- void (*walk)(void *userData, Object *ob, Object **obpoin),
- void *userData)
+static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData)
{
WeightVGEditModifierData *wmd = (WeightVGEditModifierData *) md;
- walk(userData, ob, &wmd->mask_tex_map_obj);
+ walk(userData, ob, &wmd->mask_tex_map_obj, IDWALK_NOP);
}
static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
{
WeightVGEditModifierData *wmd = (WeightVGEditModifierData *) md;
- walk(userData, ob, (ID **)&wmd->mask_texture);
+ walk(userData, ob, (ID **)&wmd->mask_texture, IDWALK_USER);
foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData);
}
diff --git a/source/blender/modifiers/intern/MOD_weightvgmix.c b/source/blender/modifiers/intern/MOD_weightvgmix.c
index 0649998e42d..01a219d1457 100644
--- a/source/blender/modifiers/intern/MOD_weightvgmix.c
+++ b/source/blender/modifiers/intern/MOD_weightvgmix.c
@@ -39,6 +39,7 @@
#include "BKE_cdderivedmesh.h"
#include "BKE_deform.h"
#include "BKE_library.h"
+#include "BKE_library_query.h"
#include "BKE_modifier.h"
#include "BKE_texture.h" /* Texture masking. */
@@ -171,19 +172,17 @@ static bool dependsOnTime(ModifierData *md)
return false;
}
-static void foreachObjectLink(ModifierData *md, Object *ob,
- void (*walk)(void *userData, Object *ob, Object **obpoin),
- void *userData)
+static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData)
{
WeightVGMixModifierData *wmd = (WeightVGMixModifierData *) md;
- walk(userData, ob, &wmd->mask_tex_map_obj);
+ walk(userData, ob, &wmd->mask_tex_map_obj, IDWALK_NOP);
}
static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
{
WeightVGMixModifierData *wmd = (WeightVGMixModifierData *) md;
- walk(userData, ob, (ID **)&wmd->mask_texture);
+ walk(userData, ob, (ID **)&wmd->mask_texture, IDWALK_USER);
foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData);
}
diff --git a/source/blender/modifiers/intern/MOD_weightvgproximity.c b/source/blender/modifiers/intern/MOD_weightvgproximity.c
index 08d7d77c74e..51c6f5cab3c 100644
--- a/source/blender/modifiers/intern/MOD_weightvgproximity.c
+++ b/source/blender/modifiers/intern/MOD_weightvgproximity.c
@@ -42,6 +42,7 @@
#include "BKE_cdderivedmesh.h"
#include "BKE_deform.h"
#include "BKE_library.h"
+#include "BKE_library_query.h"
#include "BKE_modifier.h"
#include "BKE_texture.h" /* Texture masking. */
@@ -123,7 +124,7 @@ static void get_vert2geom_distance(int numVerts, float (*v_cos)[3],
* If we already had an hit before, we assume this vertex is going to have a close hit to
* that other vertex, so we can initiate the "nearest.dist" with the expected value to that
* last hit.
- * This will lead in prunning of the search tree.
+ * This will lead in pruning of the search tree.
*/
if (dist_v) {
nearest_v.dist_sq = nearest_v.index != -1 ? len_squared_v3v3(tmp_co, nearest_v.co) : FLT_MAX;
@@ -287,20 +288,18 @@ static bool dependsOnTime(ModifierData *md)
return 0;
}
-static void foreachObjectLink(ModifierData *md, Object *ob,
- void (*walk)(void *userData, Object *ob, Object **obpoin),
- void *userData)
+static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData)
{
WeightVGProximityModifierData *wmd = (WeightVGProximityModifierData *) md;
- walk(userData, ob, &wmd->proximity_ob_target);
- walk(userData, ob, &wmd->mask_tex_map_obj);
+ walk(userData, ob, &wmd->proximity_ob_target, IDWALK_NOP);
+ walk(userData, ob, &wmd->mask_tex_map_obj, IDWALK_NOP);
}
static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
{
WeightVGProximityModifierData *wmd = (WeightVGProximityModifierData *) md;
- walk(userData, ob, (ID **)&wmd->mask_texture);
+ walk(userData, ob, (ID **)&wmd->mask_texture, IDWALK_USER);
foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData);
}
diff --git a/source/blender/nodes/shader/node_shader_util.c b/source/blender/nodes/shader/node_shader_util.c
index 49881381253..92b244bae55 100644
--- a/source/blender/nodes/shader/node_shader_util.c
+++ b/source/blender/nodes/shader/node_shader_util.c
@@ -141,7 +141,7 @@ void node_gpu_stack_from_data(struct GPUNodeStack *gs, int type, bNodeStack *ns)
{
memset(gs, 0, sizeof(*gs));
- copy_v4_v4(gs->vec, ns->vec);
+ nodestack_get_vec(gs->vec, type, ns);
gs->link = ns->data;
if (type == SOCK_FLOAT)
diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_hair.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_hair.c
index dbc8807a845..25be59f091d 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bsdf_hair.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_hair.c
@@ -33,7 +33,9 @@ static bNodeSocketTemplate sh_node_bsdf_hair_in[] = {
{ SOCK_RGBA, 1, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 1, N_("Offset"), 0.0f, 0.0f, 0.0f, 0.0f, -M_PI_2, M_PI_2, PROP_ANGLE},
{ SOCK_FLOAT, 1, N_("RoughnessU"), 0.1f, 0.1f, 0.1f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
- { SOCK_FLOAT, 1, N_("RoughnessV"), 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, { -1, 0, "" }
+ { SOCK_FLOAT, 1, N_("RoughnessV"), 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
+ { SOCK_VECTOR, 1, N_("Tangent"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
+ { -1, 0, "" },
};
static bNodeSocketTemplate sh_node_bsdf_hair_out[] = {
diff --git a/source/blender/nodes/shader/nodes/node_shader_math.c b/source/blender/nodes/shader/nodes/node_shader_math.c
index be2e3dcd311..2a1e936570d 100644
--- a/source/blender/nodes/shader/nodes/node_shader_math.c
+++ b/source/blender/nodes/shader/nodes/node_shader_math.c
@@ -230,10 +230,12 @@ static void node_shader_exec_math(void *UNUSED(data), int UNUSED(thread), bNode
static int gpu_shader_math(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
- static const char *names[] = {"math_add", "math_subtract", "math_multiply",
- "math_divide", "math_sine", "math_cosine", "math_tangent", "math_asin",
- "math_acos", "math_atan", "math_pow", "math_log", "math_min", "math_max",
- "math_round", "math_less_than", "math_greater_than", "math_modulo", "math_abs"};
+ static const char *names[] = {
+ "math_add", "math_subtract", "math_multiply",
+ "math_divide", "math_sine", "math_cosine", "math_tangent", "math_asin",
+ "math_acos", "math_atan", "math_pow", "math_log", "math_min", "math_max",
+ "math_round", "math_less_than", "math_greater_than", "math_modulo", "math_abs",
+ };
switch (node->custom1) {
case NODE_MATH_ADD:
diff --git a/source/blender/python/SConscript b/source/blender/python/SConscript
index f7b01259ead..79c53760302 100644
--- a/source/blender/python/SConscript
+++ b/source/blender/python/SConscript
@@ -93,8 +93,8 @@ if env['WITH_BF_PYTHON_SAFETY']:
if env['BF_BUILDINFO']:
defs.append('BUILD_DATE')
-
-# Audaspace is always on currently
+if env['WITH_BF_AUDASPACE']:
+ defs += env['BF_AUDASPACE_DEF']
if env['WITH_BF_BULLET']:
defs.append('WITH_BULLET')
diff --git a/source/blender/python/bmesh/bmesh_py_ops_call.c b/source/blender/python/bmesh/bmesh_py_ops_call.c
index a4c057acac2..1dc70c3d288 100644
--- a/source/blender/python/bmesh/bmesh_py_ops_call.c
+++ b/source/blender/python/bmesh/bmesh_py_ops_call.c
@@ -27,7 +27,7 @@
* \ingroup pybmesh
*
* This file provides __call__ aka BPy_BMO_call for
- * the bmesh operatorand has been given its own file
+ * the bmesh operator and has been given its own file
* because argument conversion is involved.
*/
diff --git a/source/blender/python/bmesh/bmesh_py_types.c b/source/blender/python/bmesh/bmesh_py_types.c
index 728332d755a..bf773d3d9c3 100644
--- a/source/blender/python/bmesh/bmesh_py_types.c
+++ b/source/blender/python/bmesh/bmesh_py_types.c
@@ -27,9 +27,8 @@
* \ingroup pybmesh
*/
-#include <Python.h>
-
#include "BLI_math.h"
+#include "BLI_sort.h"
#include "DNA_mesh_types.h"
#include "DNA_object_types.h"
@@ -41,6 +40,8 @@
#include "bmesh.h"
+#include <Python.h>
+
#include "../mathutils/mathutils.h"
#include "../generic/py_capi_utils.h"
@@ -2442,6 +2443,9 @@ PyDoc_STRVAR(bpy_bmelemseq_sort_doc,
" When the 'key' argument is not provided, the elements are reordered following their current index value.\n"
" In particular this can be used by setting indices manually before calling this method.\n"
"\n"
+" .. warning::\n"
+"\n"
+" Existing references to the N'th element, will continue to point the data at that index.\n"
);
/* Use a static variable here because there is the need to sort some array
@@ -2455,10 +2459,10 @@ PyDoc_STRVAR(bpy_bmelemseq_sort_doc,
* Note: the functions below assumes the keys array has been allocated and it
* has enough elements to complete the task.
*/
-static double *keys = NULL;
-static int bpy_bmelemseq_sort_cmp_by_keys_ascending(const void *index1_v, const void *index2_v)
+static int bpy_bmelemseq_sort_cmp_by_keys_ascending(const void *index1_v, const void *index2_v, void *keys_v)
{
+ const double *keys = keys_v;
const int *index1 = (int *)index1_v;
const int *index2 = (int *)index2_v;
@@ -2467,9 +2471,9 @@ static int bpy_bmelemseq_sort_cmp_by_keys_ascending(const void *index1_v, const
else return 0;
}
-static int bpy_bmelemseq_sort_cmp_by_keys_descending(const void *index1_v, const void *index2_v)
+static int bpy_bmelemseq_sort_cmp_by_keys_descending(const void *index1_v, const void *index2_v, void *keys_v)
{
- return -bpy_bmelemseq_sort_cmp_by_keys_ascending(index1_v, index2_v);
+ return -bpy_bmelemseq_sort_cmp_by_keys_ascending(index1_v, index2_v, keys_v);
}
static PyObject *bpy_bmelemseq_sort(BPy_BMElemSeq *self, PyObject *args, PyObject *kw)
@@ -2484,9 +2488,10 @@ static PyObject *bpy_bmelemseq_sort(BPy_BMElemSeq *self, PyObject *args, PyObjec
BMIter iter;
BMElem *ele;
+ double *keys;
int *elem_idx;
unsigned int *elem_map_idx;
- int (*elem_idx_compare_by_keys)(const void *, const void *);
+ int (*elem_idx_compare_by_keys)(const void *, const void *, void *);
unsigned int *vert_idx = NULL;
unsigned int *edge_idx = NULL;
@@ -2577,7 +2582,7 @@ static PyObject *bpy_bmelemseq_sort(BPy_BMElemSeq *self, PyObject *args, PyObjec
else
elem_idx_compare_by_keys = bpy_bmelemseq_sort_cmp_by_keys_ascending;
- qsort(elem_idx, n_elem, sizeof(*elem_idx), elem_idx_compare_by_keys);
+ BLI_qsort_r(elem_idx, n_elem, sizeof(*elem_idx), elem_idx_compare_by_keys, keys);
elem_map_idx = PyMem_MALLOC(sizeof(*elem_map_idx) * n_elem);
if (elem_map_idx == NULL) {
diff --git a/source/blender/python/bmesh/bmesh_py_types_customdata.c b/source/blender/python/bmesh/bmesh_py_types_customdata.c
index 3adf37f78f0..908f6b5a734 100644
--- a/source/blender/python/bmesh/bmesh_py_types_customdata.c
+++ b/source/blender/python/bmesh/bmesh_py_types_customdata.c
@@ -149,10 +149,9 @@ static PyObject *bpy_bmlayercollection_active_get(BPy_BMLayerItem *self, void *U
BPY_BM_CHECK_OBJ(self);
data = bpy_bm_customdata_get(self->bm, self->htype);
- index = CustomData_get_active_layer_index(data, self->type); /* absolute */
+ index = CustomData_get_active_layer(data, self->type); /* type relative */
if (index != -1) {
- index -= CustomData_get_layer_index(data, self->type); /* make relative */
return BPy_BMLayerItem_CreatePyObject(self->bm, self->htype, self->type, index);
}
else {
@@ -330,15 +329,12 @@ static PyObject *bpy_bmlayercollection_verify(BPy_BMLayerCollection *self)
data = bpy_bm_customdata_get(self->bm, self->htype);
- index = CustomData_get_layer_index(data, self->type);
+ index = CustomData_get_active_layer(data, self->type); /* type relative */
if (index == -1) {
BM_data_layer_add(self->bm, data, self->type);
index = 0;
}
- else {
- index = CustomData_get_active_layer_index(data, self->type) - index; /* make relative */
- }
BLI_assert(index >= 0);
@@ -490,7 +486,7 @@ static PyObject *bpy_bmlayercollection_items(BPy_BMLayerCollection *self)
item = PyTuple_New(2);
PyTuple_SET_ITEMS(item,
PyUnicode_FromString(data->layers[index].name),
- BPy_BMLayerItem_CreatePyObject(self->bm, self->htype, self->type, index));
+ BPy_BMLayerItem_CreatePyObject(self->bm, self->htype, self->type, i));
PyList_SET_ITEM(ret, i++, item);
}
@@ -523,7 +519,7 @@ static PyObject *bpy_bmlayercollection_values(BPy_BMLayerCollection *self)
ret = PyList_New(tot);
for (i = 0; tot-- > 0; index++) {
- item = BPy_BMLayerItem_CreatePyObject(self->bm, self->htype, self->type, index);
+ item = BPy_BMLayerItem_CreatePyObject(self->bm, self->htype, self->type, i);
PyList_SET_ITEM(ret, i++, item);
}
@@ -557,10 +553,9 @@ static PyObject *bpy_bmlayercollection_get(BPy_BMLayerCollection *self, PyObject
int index;
data = bpy_bm_customdata_get(self->bm, self->htype);
- index = CustomData_get_named_layer_index(data, self->type, key); /* absolute index */
+ index = CustomData_get_named_layer(data, self->type, key); /* type relative */
if (index != -1) {
- index -= CustomData_get_layer_index(data, self->type); /* make relative */
return BPy_BMLayerItem_CreatePyObject(self->bm, self->htype, self->type, index);
}
}
@@ -607,10 +602,9 @@ static PyObject *bpy_bmlayercollection_subscript_str(BPy_BMLayerCollection *self
BPY_BM_CHECK_OBJ(self);
data = bpy_bm_customdata_get(self->bm, self->htype);
- index = CustomData_get_named_layer_index(data, self->type, keyname); /* absolute */
+ index = CustomData_get_named_layer(data, self->type, keyname); /* type relative */
if (index != -1) {
- index -= CustomData_get_layer_index(data, self->type); /* make relative */
return BPy_BMLayerItem_CreatePyObject(self->bm, self->htype, self->type, index);
}
else {
diff --git a/source/blender/python/generic/bgl.c b/source/blender/python/generic/bgl.c
index e949972220b..cd6ef3f16a4 100644
--- a/source/blender/python/generic/bgl.c
+++ b/source/blender/python/generic/bgl.c
@@ -1667,6 +1667,13 @@ static void py_module_dict_add_int(PyObject *dict, const char *name, int value)
Py_DECREF(item);
}
+static void py_module_dict_add_int64(PyObject *dict, const char *name, int64_t value)
+{
+ PyObject *item;
+ PyDict_SetItemString(dict, name, item = PyLong_FromLongLong(value));
+ Py_DECREF(item);
+}
+
static void py_module_dict_add_method(PyObject *submodule, PyObject *dict, PyMethodDef *method_def, bool is_valid)
{
if (is_valid) {
@@ -1696,7 +1703,9 @@ PyObject *BPyInit_bgl(void)
Py_INCREF((PyObject *)&BGL_bufferType);
/* needed since some function pointers won't be NULL */
-#pragma GCC diagnostic ignored "-Waddress"
+#ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Waddress"
+#endif
#define PY_MOD_ADD_METHOD(func) \
{ \
@@ -2330,6 +2339,7 @@ PyObject *BPyInit_bgl(void)
}
#define PY_DICT_ADD_INT(x) py_module_dict_add_int(dict, #x, x)
+#define PY_DICT_ADD_INT64(x) py_module_dict_add_int64(dict, #x, x)
/* GL_VERSION_1_1 */
{
@@ -3022,15 +3032,57 @@ PyObject *BPyInit_bgl(void)
/* GL_VERSION_1_4 */
{
+ PY_DICT_ADD_INT(GL_BLEND_DST_ALPHA);
+ PY_DICT_ADD_INT(GL_BLEND_DST_RGB);
+ PY_DICT_ADD_INT(GL_BLEND_SRC_ALPHA);
+ PY_DICT_ADD_INT(GL_BLEND_SRC_RGB);
PY_DICT_ADD_INT(GL_CONSTANT_ALPHA);
PY_DICT_ADD_INT(GL_CONSTANT_COLOR);
+ PY_DICT_ADD_INT(GL_DECR_WRAP);
+ PY_DICT_ADD_INT(GL_DEPTH_COMPONENT16);
+ PY_DICT_ADD_INT(GL_DEPTH_COMPONENT24);
+ PY_DICT_ADD_INT(GL_DEPTH_COMPONENT32);
PY_DICT_ADD_INT(GL_FUNC_ADD);
PY_DICT_ADD_INT(GL_FUNC_REVERSE_SUBTRACT);
PY_DICT_ADD_INT(GL_FUNC_SUBTRACT);
+ PY_DICT_ADD_INT(GL_INCR_WRAP);
PY_DICT_ADD_INT(GL_MAX);
+ PY_DICT_ADD_INT(GL_MAX_TEXTURE_LOD_BIAS);
PY_DICT_ADD_INT(GL_MIN);
+ PY_DICT_ADD_INT(GL_MIRRORED_REPEAT);
PY_DICT_ADD_INT(GL_ONE_MINUS_CONSTANT_ALPHA);
PY_DICT_ADD_INT(GL_ONE_MINUS_CONSTANT_COLOR);
+ PY_DICT_ADD_INT(GL_POINT_FADE_THRESHOLD_SIZE);
+ PY_DICT_ADD_INT(GL_TEXTURE_COMPARE_FUNC);
+ PY_DICT_ADD_INT(GL_TEXTURE_COMPARE_MODE);
+ PY_DICT_ADD_INT(GL_TEXTURE_DEPTH_SIZE);
+ PY_DICT_ADD_INT(GL_TEXTURE_LOD_BIAS);
+ }
+ /* adding in GL_VERSION_1_4 removed from core profile */
+ if (use_deprecated == true) {
+ PY_DICT_ADD_INT(GL_COLOR_SUM);
+ PY_DICT_ADD_INT(GL_COMPARE_R_TO_TEXTURE);
+ PY_DICT_ADD_INT(GL_CURRENT_FOG_COORDINATE);
+ PY_DICT_ADD_INT(GL_CURRENT_SECONDARY_COLOR);
+ PY_DICT_ADD_INT(GL_DEPTH_TEXTURE_MODE);
+ PY_DICT_ADD_INT(GL_FOG_COORDINATE);
+ PY_DICT_ADD_INT(GL_FOG_COORDINATE_ARRAY);
+ PY_DICT_ADD_INT(GL_FOG_COORDINATE_ARRAY_POINTER);
+ PY_DICT_ADD_INT(GL_FOG_COORDINATE_ARRAY_STRIDE);
+ PY_DICT_ADD_INT(GL_FOG_COORDINATE_ARRAY_TYPE);
+ PY_DICT_ADD_INT(GL_FOG_COORDINATE_SOURCE);
+ PY_DICT_ADD_INT(GL_FRAGMENT_DEPTH);
+ PY_DICT_ADD_INT(GL_GENERATE_MIPMAP);
+ PY_DICT_ADD_INT(GL_GENERATE_MIPMAP_HINT);
+ PY_DICT_ADD_INT(GL_POINT_DISTANCE_ATTENUATION);
+ PY_DICT_ADD_INT(GL_POINT_SIZE_MAX);
+ PY_DICT_ADD_INT(GL_POINT_SIZE_MIN);
+ PY_DICT_ADD_INT(GL_SECONDARY_COLOR_ARRAY);
+ PY_DICT_ADD_INT(GL_SECONDARY_COLOR_ARRAY_POINTER);
+ PY_DICT_ADD_INT(GL_SECONDARY_COLOR_ARRAY_SIZE);
+ PY_DICT_ADD_INT(GL_SECONDARY_COLOR_ARRAY_STRIDE);
+ PY_DICT_ADD_INT(GL_SECONDARY_COLOR_ARRAY_TYPE);
+ PY_DICT_ADD_INT(GL_TEXTURE_FILTER_CONTROL);
}
@@ -3214,23 +3266,262 @@ PyObject *BPyInit_bgl(void)
PY_DICT_ADD_INT(GL_SLUMINANCE_ALPHA);
}
-
/* GL_VERSION_3_0 */
{
+ PY_DICT_ADD_INT(GL_BGRA_INTEGER);
+ PY_DICT_ADD_INT(GL_BGR_INTEGER);
+ PY_DICT_ADD_INT(GL_BLUE_INTEGER);
+ PY_DICT_ADD_INT(GL_BUFFER_ACCESS_FLAGS);
+ PY_DICT_ADD_INT(GL_BUFFER_MAP_LENGTH);
+ PY_DICT_ADD_INT(GL_BUFFER_MAP_OFFSET);
+ PY_DICT_ADD_INT(GL_CLAMP_READ_COLOR);
+ PY_DICT_ADD_INT(GL_CLIP_DISTANCE0);
+ PY_DICT_ADD_INT(GL_CLIP_DISTANCE1);
+ PY_DICT_ADD_INT(GL_CLIP_DISTANCE2);
+ PY_DICT_ADD_INT(GL_CLIP_DISTANCE3);
+ PY_DICT_ADD_INT(GL_CLIP_DISTANCE4);
+ PY_DICT_ADD_INT(GL_CLIP_DISTANCE5);
+#if 0
+ PY_DICT_ADD_INT(GL_CLIP_DISTANCE6);
+ PY_DICT_ADD_INT(GL_CLIP_DISTANCE7);
+#endif
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT0);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT1);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT2);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT3);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT4);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT5);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT6);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT7);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT8);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT9);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT10);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT11);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT12);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT13);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT14);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT15);
+#if 0
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT16);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT17);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT18);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT19);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT20);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT21);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT22);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT23);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT24);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT25);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT26);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT27);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT28);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT29);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT30);
+ PY_DICT_ADD_INT(GL_COLOR_ATTACHMENT31);
+#endif
+ PY_DICT_ADD_INT(GL_COMPARE_REF_TO_TEXTURE);
+ PY_DICT_ADD_INT(GL_COMPRESSED_RED);
+ PY_DICT_ADD_INT(GL_COMPRESSED_RED_RGTC1);
+ PY_DICT_ADD_INT(GL_COMPRESSED_RG);
+ PY_DICT_ADD_INT(GL_COMPRESSED_RG_RGTC2);
+ PY_DICT_ADD_INT(GL_COMPRESSED_SIGNED_RED_RGTC1);
+ PY_DICT_ADD_INT(GL_COMPRESSED_SIGNED_RG_RGTC2);
+ PY_DICT_ADD_INT(GL_CONTEXT_FLAGS);
+ PY_DICT_ADD_INT(GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT);
+ PY_DICT_ADD_INT(GL_DEPTH24_STENCIL8);
+ PY_DICT_ADD_INT(GL_DEPTH32F_STENCIL8);
+ PY_DICT_ADD_INT(GL_DEPTH_ATTACHMENT);
+ PY_DICT_ADD_INT(GL_DEPTH_COMPONENT32F);
+ PY_DICT_ADD_INT(GL_DEPTH_STENCIL);
+ PY_DICT_ADD_INT(GL_DEPTH_STENCIL_ATTACHMENT);
+ PY_DICT_ADD_INT(GL_DRAW_FRAMEBUFFER);
+ PY_DICT_ADD_INT(GL_DRAW_FRAMEBUFFER_BINDING);
+ PY_DICT_ADD_INT(GL_FIXED_ONLY);
+ PY_DICT_ADD_INT(GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
+ PY_DICT_ADD_INT(GL_FRAMEBUFFER);
+ PY_DICT_ADD_INT(GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE);
+ PY_DICT_ADD_INT(GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE);
+ PY_DICT_ADD_INT(GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING);
+ PY_DICT_ADD_INT(GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE);
+ PY_DICT_ADD_INT(GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE);
+ PY_DICT_ADD_INT(GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE);
+ PY_DICT_ADD_INT(GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME);
+ PY_DICT_ADD_INT(GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE);
+ PY_DICT_ADD_INT(GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE);
+ PY_DICT_ADD_INT(GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE);
+ PY_DICT_ADD_INT(GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE);
+ PY_DICT_ADD_INT(GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER);
+ PY_DICT_ADD_INT(GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL);
+ PY_DICT_ADD_INT(GL_FRAMEBUFFER_BINDING);
+ PY_DICT_ADD_INT(GL_FRAMEBUFFER_COMPLETE);
+ PY_DICT_ADD_INT(GL_FRAMEBUFFER_DEFAULT);
+ PY_DICT_ADD_INT(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT);
+ PY_DICT_ADD_INT(GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER);
+ PY_DICT_ADD_INT(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT);
+ PY_DICT_ADD_INT(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE);
+ PY_DICT_ADD_INT(GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER);
+ PY_DICT_ADD_INT(GL_FRAMEBUFFER_SRGB);
+ PY_DICT_ADD_INT(GL_FRAMEBUFFER_UNDEFINED);
+ PY_DICT_ADD_INT(GL_FRAMEBUFFER_UNSUPPORTED);
+ PY_DICT_ADD_INT(GL_GREEN_INTEGER);
+ PY_DICT_ADD_INT(GL_HALF_FLOAT);
+ PY_DICT_ADD_INT(GL_INDEX);
+ PY_DICT_ADD_INT(GL_INTERLEAVED_ATTRIBS);
+ PY_DICT_ADD_INT(GL_INT_SAMPLER_1D);
+ PY_DICT_ADD_INT(GL_INT_SAMPLER_1D_ARRAY);
+ PY_DICT_ADD_INT(GL_INT_SAMPLER_2D);
+ PY_DICT_ADD_INT(GL_INT_SAMPLER_2D_ARRAY);
+ PY_DICT_ADD_INT(GL_INT_SAMPLER_3D);
+ PY_DICT_ADD_INT(GL_INT_SAMPLER_CUBE);
+ PY_DICT_ADD_INT(GL_INVALID_FRAMEBUFFER_OPERATION);
+ PY_DICT_ADD_INT(GL_MAJOR_VERSION);
+ PY_DICT_ADD_INT(GL_MAP_FLUSH_EXPLICIT_BIT);
+ PY_DICT_ADD_INT(GL_MAP_INVALIDATE_BUFFER_BIT);
+ PY_DICT_ADD_INT(GL_MAP_INVALIDATE_RANGE_BIT);
+ PY_DICT_ADD_INT(GL_MAP_READ_BIT);
+ PY_DICT_ADD_INT(GL_MAP_UNSYNCHRONIZED_BIT);
+ PY_DICT_ADD_INT(GL_MAP_WRITE_BIT);
+ PY_DICT_ADD_INT(GL_MAX_ARRAY_TEXTURE_LAYERS);
+ PY_DICT_ADD_INT(GL_MAX_CLIP_DISTANCES);
+ PY_DICT_ADD_INT(GL_MAX_COLOR_ATTACHMENTS);
+ PY_DICT_ADD_INT(GL_MAX_PROGRAM_TEXEL_OFFSET);
+ PY_DICT_ADD_INT(GL_MAX_RENDERBUFFER_SIZE);
+ PY_DICT_ADD_INT(GL_MAX_SAMPLES);
+ PY_DICT_ADD_INT(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS);
+ PY_DICT_ADD_INT(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS);
+ PY_DICT_ADD_INT(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS);
+ PY_DICT_ADD_INT(GL_MAX_VARYING_COMPONENTS);
+ PY_DICT_ADD_INT(GL_MINOR_VERSION);
+ PY_DICT_ADD_INT(GL_MIN_PROGRAM_TEXEL_OFFSET);
+ PY_DICT_ADD_INT(GL_NUM_EXTENSIONS);
+ PY_DICT_ADD_INT(GL_PRIMITIVES_GENERATED);
+ PY_DICT_ADD_INT(GL_PROXY_TEXTURE_1D_ARRAY);
+ PY_DICT_ADD_INT(GL_PROXY_TEXTURE_2D_ARRAY);
+ PY_DICT_ADD_INT(GL_QUERY_BY_REGION_NO_WAIT);
+ PY_DICT_ADD_INT(GL_QUERY_BY_REGION_WAIT);
+ PY_DICT_ADD_INT(GL_QUERY_NO_WAIT);
+ PY_DICT_ADD_INT(GL_QUERY_WAIT);
+ PY_DICT_ADD_INT(GL_R11F_G11F_B10F);
+ PY_DICT_ADD_INT(GL_R16);
+ PY_DICT_ADD_INT(GL_R16F);
+ PY_DICT_ADD_INT(GL_R16I);
+ PY_DICT_ADD_INT(GL_R16UI);
+ PY_DICT_ADD_INT(GL_R32F);
+ PY_DICT_ADD_INT(GL_R32I);
+ PY_DICT_ADD_INT(GL_R32UI);
+ PY_DICT_ADD_INT(GL_R8);
+ PY_DICT_ADD_INT(GL_R8I);
+ PY_DICT_ADD_INT(GL_R8UI);
+ PY_DICT_ADD_INT(GL_RASTERIZER_DISCARD);
+ PY_DICT_ADD_INT(GL_READ_FRAMEBUFFER);
+ PY_DICT_ADD_INT(GL_READ_FRAMEBUFFER_BINDING);
+ PY_DICT_ADD_INT(GL_RED_INTEGER);
+ PY_DICT_ADD_INT(GL_RENDERBUFFER);
+ PY_DICT_ADD_INT(GL_RENDERBUFFER_ALPHA_SIZE);
+ PY_DICT_ADD_INT(GL_RENDERBUFFER_BINDING);
+ PY_DICT_ADD_INT(GL_RENDERBUFFER_BLUE_SIZE);
+ PY_DICT_ADD_INT(GL_RENDERBUFFER_DEPTH_SIZE);
+ PY_DICT_ADD_INT(GL_RENDERBUFFER_GREEN_SIZE);
+ PY_DICT_ADD_INT(GL_RENDERBUFFER_HEIGHT);
+ PY_DICT_ADD_INT(GL_RENDERBUFFER_INTERNAL_FORMAT);
+ PY_DICT_ADD_INT(GL_RENDERBUFFER_RED_SIZE);
+ PY_DICT_ADD_INT(GL_RENDERBUFFER_SAMPLES);
+ PY_DICT_ADD_INT(GL_RENDERBUFFER_STENCIL_SIZE);
+ PY_DICT_ADD_INT(GL_RENDERBUFFER_WIDTH);
+ PY_DICT_ADD_INT(GL_RG);
+ PY_DICT_ADD_INT(GL_RG16);
+ PY_DICT_ADD_INT(GL_RG16F);
+ PY_DICT_ADD_INT(GL_RG16I);
+ PY_DICT_ADD_INT(GL_RG16UI);
+ PY_DICT_ADD_INT(GL_RG32F);
+ PY_DICT_ADD_INT(GL_RG32I);
+ PY_DICT_ADD_INT(GL_RG32UI);
+ PY_DICT_ADD_INT(GL_RG8);
+ PY_DICT_ADD_INT(GL_RG8I);
+ PY_DICT_ADD_INT(GL_RG8UI);
+ PY_DICT_ADD_INT(GL_RGB16F);
+ PY_DICT_ADD_INT(GL_RGB16I);
+ PY_DICT_ADD_INT(GL_RGB16UI);
+ PY_DICT_ADD_INT(GL_RGB32F);
+ PY_DICT_ADD_INT(GL_RGB32I);
+ PY_DICT_ADD_INT(GL_RGB32UI);
+ PY_DICT_ADD_INT(GL_RGB8I);
+ PY_DICT_ADD_INT(GL_RGB8UI);
+ PY_DICT_ADD_INT(GL_RGB9_E5);
+ PY_DICT_ADD_INT(GL_RGBA16F);
+ PY_DICT_ADD_INT(GL_RGBA16I);
+ PY_DICT_ADD_INT(GL_RGBA16UI);
+ PY_DICT_ADD_INT(GL_RGBA32F);
+ PY_DICT_ADD_INT(GL_RGBA32I);
+ PY_DICT_ADD_INT(GL_RGBA32UI);
+ PY_DICT_ADD_INT(GL_RGBA8I);
+ PY_DICT_ADD_INT(GL_RGBA8UI);
+ PY_DICT_ADD_INT(GL_RGBA_INTEGER);
+ PY_DICT_ADD_INT(GL_RGB_INTEGER);
+ PY_DICT_ADD_INT(GL_RG_INTEGER);
+ PY_DICT_ADD_INT(GL_SAMPLER_1D_ARRAY);
+ PY_DICT_ADD_INT(GL_SAMPLER_1D_ARRAY_SHADOW);
+ PY_DICT_ADD_INT(GL_SAMPLER_2D_ARRAY);
+ PY_DICT_ADD_INT(GL_SAMPLER_2D_ARRAY_SHADOW);
+ PY_DICT_ADD_INT(GL_SAMPLER_CUBE_SHADOW);
+ PY_DICT_ADD_INT(GL_SEPARATE_ATTRIBS);
+ PY_DICT_ADD_INT(GL_STENCIL_ATTACHMENT);
+ PY_DICT_ADD_INT(GL_STENCIL_INDEX1);
+ PY_DICT_ADD_INT(GL_STENCIL_INDEX16);
+ PY_DICT_ADD_INT(GL_STENCIL_INDEX4);
+ PY_DICT_ADD_INT(GL_STENCIL_INDEX8);
+ PY_DICT_ADD_INT(GL_TEXTURE_1D_ARRAY);
+ PY_DICT_ADD_INT(GL_TEXTURE_2D_ARRAY);
+ PY_DICT_ADD_INT(GL_TEXTURE_ALPHA_TYPE);
+ PY_DICT_ADD_INT(GL_TEXTURE_BINDING_1D_ARRAY);
+ PY_DICT_ADD_INT(GL_TEXTURE_BINDING_2D_ARRAY);
+ PY_DICT_ADD_INT(GL_TEXTURE_BLUE_TYPE);
+ PY_DICT_ADD_INT(GL_TEXTURE_DEPTH_TYPE);
+ PY_DICT_ADD_INT(GL_TEXTURE_GREEN_TYPE);
+ PY_DICT_ADD_INT(GL_TEXTURE_RED_TYPE);
+ PY_DICT_ADD_INT(GL_TEXTURE_SHARED_SIZE);
+ PY_DICT_ADD_INT(GL_TEXTURE_STENCIL_SIZE);
+ PY_DICT_ADD_INT(GL_TRANSFORM_FEEDBACK_BUFFER);
+ PY_DICT_ADD_INT(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING);
+ PY_DICT_ADD_INT(GL_TRANSFORM_FEEDBACK_BUFFER_MODE);
+ PY_DICT_ADD_INT(GL_TRANSFORM_FEEDBACK_BUFFER_SIZE);
+ PY_DICT_ADD_INT(GL_TRANSFORM_FEEDBACK_BUFFER_START);
+ PY_DICT_ADD_INT(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
+ PY_DICT_ADD_INT(GL_TRANSFORM_FEEDBACK_VARYINGS);
+ PY_DICT_ADD_INT(GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH);
+ PY_DICT_ADD_INT(GL_UNSIGNED_INT_10F_11F_11F_REV);
+ PY_DICT_ADD_INT(GL_UNSIGNED_INT_24_8);
+ PY_DICT_ADD_INT(GL_UNSIGNED_INT_5_9_9_9_REV);
+ PY_DICT_ADD_INT(GL_UNSIGNED_INT_SAMPLER_1D);
+ PY_DICT_ADD_INT(GL_UNSIGNED_INT_SAMPLER_1D_ARRAY);
+ PY_DICT_ADD_INT(GL_UNSIGNED_INT_SAMPLER_2D);
+ PY_DICT_ADD_INT(GL_UNSIGNED_INT_SAMPLER_2D_ARRAY);
+ PY_DICT_ADD_INT(GL_UNSIGNED_INT_SAMPLER_3D);
+ PY_DICT_ADD_INT(GL_UNSIGNED_INT_SAMPLER_CUBE);
+ PY_DICT_ADD_INT(GL_UNSIGNED_INT_VEC2);
+ PY_DICT_ADD_INT(GL_UNSIGNED_INT_VEC3);
+ PY_DICT_ADD_INT(GL_UNSIGNED_INT_VEC4);
+ PY_DICT_ADD_INT(GL_UNSIGNED_NORMALIZED);
PY_DICT_ADD_INT(GL_VERTEX_ARRAY_BINDING);
+ PY_DICT_ADD_INT(GL_VERTEX_ATTRIB_ARRAY_INTEGER);
}
/* adding in GL_VERSION_3_0 removed from core profile */
if (use_deprecated == true) {
PY_DICT_ADD_INT(GL_ALPHA_INTEGER);
PY_DICT_ADD_INT(GL_CLAMP_FRAGMENT_COLOR);
PY_DICT_ADD_INT(GL_CLAMP_VERTEX_COLOR);
+ PY_DICT_ADD_INT(GL_TEXTURE_INTENSITY_TYPE);
+ PY_DICT_ADD_INT(GL_TEXTURE_LUMINANCE_TYPE);
}
-
/* GL_VERSION_3_1 */
{
PY_DICT_ADD_INT(GL_ACTIVE_UNIFORM_BLOCKS);
PY_DICT_ADD_INT(GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH);
+ PY_DICT_ADD_INT(GL_COPY_READ_BUFFER);
+ PY_DICT_ADD_INT(GL_COPY_WRITE_BUFFER);
+ PY_DICT_ADD_INT(GL_INT_SAMPLER_2D_RECT);
+ PY_DICT_ADD_INT(GL_INT_SAMPLER_BUFFER);
PY_DICT_ADD_INT(GL_INVALID_INDEX);
PY_DICT_ADD_INT(GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS);
PY_DICT_ADD_INT(GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS);
@@ -3238,9 +3529,31 @@ PyObject *BPyInit_bgl(void)
PY_DICT_ADD_INT(GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS);
PY_DICT_ADD_INT(GL_MAX_FRAGMENT_UNIFORM_BLOCKS);
PY_DICT_ADD_INT(GL_MAX_GEOMETRY_UNIFORM_BLOCKS);
+ PY_DICT_ADD_INT(GL_MAX_RECTANGLE_TEXTURE_SIZE);
+ PY_DICT_ADD_INT(GL_MAX_TEXTURE_BUFFER_SIZE);
PY_DICT_ADD_INT(GL_MAX_UNIFORM_BLOCK_SIZE);
PY_DICT_ADD_INT(GL_MAX_UNIFORM_BUFFER_BINDINGS);
PY_DICT_ADD_INT(GL_MAX_VERTEX_UNIFORM_BLOCKS);
+ PY_DICT_ADD_INT(GL_PRIMITIVE_RESTART);
+ PY_DICT_ADD_INT(GL_PRIMITIVE_RESTART_INDEX);
+ PY_DICT_ADD_INT(GL_PROXY_TEXTURE_RECTANGLE);
+ PY_DICT_ADD_INT(GL_R16_SNORM);
+ PY_DICT_ADD_INT(GL_R8_SNORM);
+ PY_DICT_ADD_INT(GL_RG16_SNORM);
+ PY_DICT_ADD_INT(GL_RG8_SNORM);
+ PY_DICT_ADD_INT(GL_RGB16_SNORM);
+ PY_DICT_ADD_INT(GL_RGB8_SNORM);
+ PY_DICT_ADD_INT(GL_RGBA16_SNORM);
+ PY_DICT_ADD_INT(GL_RGBA8_SNORM);
+ PY_DICT_ADD_INT(GL_SAMPLER_2D_RECT);
+ PY_DICT_ADD_INT(GL_SAMPLER_2D_RECT_SHADOW);
+ PY_DICT_ADD_INT(GL_SAMPLER_BUFFER);
+ PY_DICT_ADD_INT(GL_SIGNED_NORMALIZED);
+ PY_DICT_ADD_INT(GL_TEXTURE_BINDING_BUFFER);
+ PY_DICT_ADD_INT(GL_TEXTURE_BINDING_RECTANGLE);
+ PY_DICT_ADD_INT(GL_TEXTURE_BUFFER);
+ PY_DICT_ADD_INT(GL_TEXTURE_BUFFER_DATA_STORE_BINDING);
+ PY_DICT_ADD_INT(GL_TEXTURE_RECTANGLE);
PY_DICT_ADD_INT(GL_UNIFORM_ARRAY_STRIDE);
PY_DICT_ADD_INT(GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS);
PY_DICT_ADD_INT(GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES);
@@ -3262,34 +3575,98 @@ PyObject *BPyInit_bgl(void)
PY_DICT_ADD_INT(GL_UNIFORM_OFFSET);
PY_DICT_ADD_INT(GL_UNIFORM_SIZE);
PY_DICT_ADD_INT(GL_UNIFORM_TYPE);
+ PY_DICT_ADD_INT(GL_UNSIGNED_INT_SAMPLER_2D_RECT);
+ PY_DICT_ADD_INT(GL_UNSIGNED_INT_SAMPLER_BUFFER);
}
/* GL_VERSION_3_2 */
{
+ PY_DICT_ADD_INT(GL_ALREADY_SIGNALED);
+ PY_DICT_ADD_INT(GL_CONDITION_SATISFIED);
+ PY_DICT_ADD_INT(GL_CONTEXT_COMPATIBILITY_PROFILE_BIT);
+ PY_DICT_ADD_INT(GL_CONTEXT_CORE_PROFILE_BIT);
+ PY_DICT_ADD_INT(GL_CONTEXT_PROFILE_MASK);
+ PY_DICT_ADD_INT(GL_DEPTH_CLAMP);
+ PY_DICT_ADD_INT(GL_FIRST_VERTEX_CONVENTION);
+ PY_DICT_ADD_INT(GL_FRAMEBUFFER_ATTACHMENT_LAYERED);
+ PY_DICT_ADD_INT(GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS);
+ PY_DICT_ADD_INT(GL_GEOMETRY_INPUT_TYPE);
+ PY_DICT_ADD_INT(GL_GEOMETRY_OUTPUT_TYPE);
+ PY_DICT_ADD_INT(GL_GEOMETRY_SHADER);
+ PY_DICT_ADD_INT(GL_GEOMETRY_VERTICES_OUT);
PY_DICT_ADD_INT(GL_INT_SAMPLER_2D_MULTISAMPLE);
PY_DICT_ADD_INT(GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY);
+ PY_DICT_ADD_INT(GL_LAST_VERTEX_CONVENTION);
+ PY_DICT_ADD_INT(GL_LINES_ADJACENCY);
+ PY_DICT_ADD_INT(GL_LINE_STRIP_ADJACENCY);
PY_DICT_ADD_INT(GL_MAX_COLOR_TEXTURE_SAMPLES);
PY_DICT_ADD_INT(GL_MAX_DEPTH_TEXTURE_SAMPLES);
+ PY_DICT_ADD_INT(GL_MAX_FRAGMENT_INPUT_COMPONENTS);
+ PY_DICT_ADD_INT(GL_MAX_GEOMETRY_INPUT_COMPONENTS);
+ PY_DICT_ADD_INT(GL_MAX_GEOMETRY_OUTPUT_COMPONENTS);
+ PY_DICT_ADD_INT(GL_MAX_GEOMETRY_OUTPUT_VERTICES);
+ PY_DICT_ADD_INT(GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS);
+ PY_DICT_ADD_INT(GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS);
+ PY_DICT_ADD_INT(GL_MAX_GEOMETRY_UNIFORM_COMPONENTS);
PY_DICT_ADD_INT(GL_MAX_INTEGER_SAMPLES);
PY_DICT_ADD_INT(GL_MAX_SAMPLE_MASK_WORDS);
+ PY_DICT_ADD_INT(GL_MAX_SERVER_WAIT_TIMEOUT);
+ PY_DICT_ADD_INT(GL_MAX_VERTEX_OUTPUT_COMPONENTS);
+ PY_DICT_ADD_INT(GL_OBJECT_TYPE);
+ PY_DICT_ADD_INT(GL_PROGRAM_POINT_SIZE);
+ PY_DICT_ADD_INT(GL_PROVOKING_VERTEX);
PY_DICT_ADD_INT(GL_PROXY_TEXTURE_2D_MULTISAMPLE);
PY_DICT_ADD_INT(GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY);
+ PY_DICT_ADD_INT(GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION);
PY_DICT_ADD_INT(GL_SAMPLER_2D_MULTISAMPLE);
PY_DICT_ADD_INT(GL_SAMPLER_2D_MULTISAMPLE_ARRAY);
PY_DICT_ADD_INT(GL_SAMPLE_MASK);
PY_DICT_ADD_INT(GL_SAMPLE_MASK_VALUE);
PY_DICT_ADD_INT(GL_SAMPLE_POSITION);
+ PY_DICT_ADD_INT(GL_SIGNALED);
+ PY_DICT_ADD_INT(GL_SYNC_CONDITION);
+ PY_DICT_ADD_INT(GL_SYNC_FENCE);
+ PY_DICT_ADD_INT(GL_SYNC_FLAGS);
+ PY_DICT_ADD_INT(GL_SYNC_FLUSH_COMMANDS_BIT);
+ PY_DICT_ADD_INT(GL_SYNC_GPU_COMMANDS_COMPLETE);
+ PY_DICT_ADD_INT(GL_SYNC_STATUS);
PY_DICT_ADD_INT(GL_TEXTURE_2D_MULTISAMPLE);
PY_DICT_ADD_INT(GL_TEXTURE_2D_MULTISAMPLE_ARRAY);
PY_DICT_ADD_INT(GL_TEXTURE_BINDING_2D_MULTISAMPLE);
PY_DICT_ADD_INT(GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY);
+ PY_DICT_ADD_INT(GL_TEXTURE_CUBE_MAP_SEAMLESS);
PY_DICT_ADD_INT(GL_TEXTURE_FIXED_SAMPLE_LOCATIONS);
PY_DICT_ADD_INT(GL_TEXTURE_SAMPLES);
+ PY_DICT_ADD_INT(GL_TIMEOUT_EXPIRED);
+ PY_DICT_ADD_INT64(GL_TIMEOUT_IGNORED);
+ PY_DICT_ADD_INT(GL_TRIANGLES_ADJACENCY);
+ PY_DICT_ADD_INT(GL_TRIANGLE_STRIP_ADJACENCY);
+ PY_DICT_ADD_INT(GL_UNSIGNALED);
PY_DICT_ADD_INT(GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE);
PY_DICT_ADD_INT(GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY);
+ PY_DICT_ADD_INT(GL_WAIT_FAILED);
}
+ /* GL_VERSION_3_3 */
+ {
+ PY_DICT_ADD_INT(GL_ANY_SAMPLES_PASSED);
+ PY_DICT_ADD_INT(GL_INT_2_10_10_10_REV);
+ PY_DICT_ADD_INT(GL_MAX_DUAL_SOURCE_DRAW_BUFFERS);
+ PY_DICT_ADD_INT(GL_ONE_MINUS_SRC1_ALPHA);
+ PY_DICT_ADD_INT(GL_ONE_MINUS_SRC1_COLOR);
+ PY_DICT_ADD_INT(GL_RGB10_A2UI);
+ PY_DICT_ADD_INT(GL_SAMPLER_BINDING);
+ PY_DICT_ADD_INT(GL_SRC1_COLOR);
+ PY_DICT_ADD_INT(GL_TEXTURE_SWIZZLE_A);
+ PY_DICT_ADD_INT(GL_TEXTURE_SWIZZLE_B);
+ PY_DICT_ADD_INT(GL_TEXTURE_SWIZZLE_G);
+ PY_DICT_ADD_INT(GL_TEXTURE_SWIZZLE_R);
+ PY_DICT_ADD_INT(GL_TEXTURE_SWIZZLE_RGBA);
+ PY_DICT_ADD_INT(GL_TIMESTAMP);
+ PY_DICT_ADD_INT(GL_TIME_ELAPSED);
+ PY_DICT_ADD_INT(GL_VERTEX_ATTRIB_ARRAY_DIVISOR);
+ }
return submodule;
}
diff --git a/source/blender/python/generic/blf_py_api.c b/source/blender/python/generic/blf_py_api.c
index 5364c3bbb9e..0dfff9b4a7b 100644
--- a/source/blender/python/generic/blf_py_api.c
+++ b/source/blender/python/generic/blf_py_api.c
@@ -221,6 +221,29 @@ static PyObject *py_blf_clipping(PyObject *UNUSED(self), PyObject *args)
Py_RETURN_NONE;
}
+PyDoc_STRVAR(py_blf_word_wrap_doc,
+".. function:: word_wrap(fontid, wrap_width)\n"
+"\n"
+" Set the wrap width, enable/disable using WORD_WRAP.\n"
+"\n"
+" :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default font use 0.\n"
+" :type fontid: int\n"
+" :arg wrap_width: The width (in pixels) to wrap words at.\n"
+" :type wrap_width: int\n"
+);
+static PyObject *py_blf_word_wrap(PyObject *UNUSED(self), PyObject *args)
+{
+ int wrap_width;
+ int fontid;
+
+ if (!PyArg_ParseTuple(args, "ii:blf.word_wrap", &fontid, &wrap_width))
+ return NULL;
+
+ BLF_wordwrap(fontid, wrap_width);
+
+ Py_RETURN_NONE;
+}
+
PyDoc_STRVAR(py_blf_disable_doc,
".. function:: disable(fontid, option)\n"
"\n"
@@ -393,6 +416,7 @@ static PyMethodDef BLF_methods[] = {
{"aspect", (PyCFunction) py_blf_aspect, METH_VARARGS, py_blf_aspect_doc},
{"blur", (PyCFunction) py_blf_blur, METH_VARARGS, py_blf_blur_doc},
{"clipping", (PyCFunction) py_blf_clipping, METH_VARARGS, py_blf_clipping_doc},
+ {"word_wrap", (PyCFunction) py_blf_word_wrap, METH_VARARGS, py_blf_word_wrap_doc},
{"disable", (PyCFunction) py_blf_disable, METH_VARARGS, py_blf_disable_doc},
{"dimensions", (PyCFunction) py_blf_dimensions, METH_VARARGS, py_blf_dimensions_doc},
{"draw", (PyCFunction) py_blf_draw, METH_VARARGS, py_blf_draw_doc},
@@ -432,6 +456,7 @@ PyObject *BPyInit_blf(void)
PyModule_AddIntConstant(submodule, "CLIPPING", BLF_CLIPPING);
PyModule_AddIntConstant(submodule, "SHADOW", BLF_SHADOW);
PyModule_AddIntConstant(submodule, "KERNING_DEFAULT", BLF_KERNING_DEFAULT);
+ PyModule_AddIntConstant(submodule, "WORD_WRAP", BLF_WORD_WRAP);
return submodule;
}
diff --git a/source/blender/python/generic/bpy_threads.c b/source/blender/python/generic/bpy_threads.c
index 63a47ff0b20..fbc145660f3 100644
--- a/source/blender/python/generic/bpy_threads.c
+++ b/source/blender/python/generic/bpy_threads.c
@@ -27,11 +27,6 @@
* these functions are slightly different from the original Python API,
* don't throw SIGABRT even if the thread state is NULL. */
-/* grr, python redefines */
-#ifdef _POSIX_C_SOURCE
-# undef _POSIX_C_SOURCE
-#endif
-
#include <Python.h>
#include "BLI_utildefines.h"
diff --git a/source/blender/python/generic/py_capi_utils.c b/source/blender/python/generic/py_capi_utils.c
index 9e6ffe91848..e833dba04c8 100644
--- a/source/blender/python/generic/py_capi_utils.c
+++ b/source/blender/python/generic/py_capi_utils.c
@@ -29,7 +29,6 @@
* BLI_string_utf8() for unicode conversion.
*/
-
#include <Python.h>
#include <frameobject.h>
@@ -666,7 +665,8 @@ void PyC_SetHomePath(const char *py_path_bundle)
bool PyC_IsInterpreterActive(void)
{
- return (((PyThreadState *)_Py_atomic_load_relaxed(&_PyThreadState_Current)) != NULL);
+ /* instead of PyThreadState_Get, which calls Py_FatalError */
+ return (PyThreadState_GetDict() != NULL);
}
/* Would be nice if python had this built in
diff --git a/source/blender/python/intern/CMakeLists.txt b/source/blender/python/intern/CMakeLists.txt
index cd2a9fd8584..f04bca75a8c 100644
--- a/source/blender/python/intern/CMakeLists.txt
+++ b/source/blender/python/intern/CMakeLists.txt
@@ -46,6 +46,7 @@ set(INC_SYS
set(SRC
gpu.c
+ gpu_offscreen.c
bpy.c
bpy_app.c
bpy_app_build_options.c
diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c
index 274b33558d3..d10816b809f 100644
--- a/source/blender/python/intern/bpy_interface.c
+++ b/source/blender/python/intern/bpy_interface.c
@@ -29,12 +29,6 @@
* be accesses from scripts.
*/
-
-/* grr, python redefines */
-#ifdef _POSIX_C_SOURCE
-# undef _POSIX_C_SOURCE
-#endif
-
#include <Python.h>
#ifdef WIN32
@@ -491,7 +485,9 @@ static int python_script_exec(bContext *C, const char *fn, struct Text *text,
* incompatible'.
* So now we load the script file data to a buffer */
{
- const char *pystring = "with open(__file__, 'r') as f: exec(f.read())";
+ const char *pystring =
+ "ns = globals().copy()\n"
+ "with open(__file__, 'rb') as f: exec(compile(f.read(), __file__, 'exec'), ns)";
fclose(fp);
@@ -826,7 +822,7 @@ static void bpy_module_delay_init(PyObject *bpy_proxy)
char filename_abs[1024];
BLI_strncpy(filename_abs, filename_rel, sizeof(filename_abs));
- BLI_path_cwd(filename_abs);
+ BLI_path_cwd(filename_abs, sizeof(filename_abs));
argv[0] = filename_abs;
argv[1] = NULL;
diff --git a/source/blender/python/intern/bpy_library.c b/source/blender/python/intern/bpy_library.c
index a5879f11e51..0912ac0b637 100644
--- a/source/blender/python/intern/bpy_library.c
+++ b/source/blender/python/intern/bpy_library.c
@@ -335,7 +335,7 @@ static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *UNUSED(args))
BKE_main_id_flag_all(bmain, LIB_PRE_EXISTING, true);
/* here appending/linking starts */
- mainl = BLO_library_append_begin(bmain, &(self->blo_handle), self->relpath);
+ mainl = BLO_library_link_begin(bmain, &(self->blo_handle), self->relpath);
{
int idcode_step = 0, idcode;
@@ -358,7 +358,7 @@ static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *UNUSED(args))
// printf(" %s\n", item_str);
if (item_str) {
- ID *id = BLO_library_append_named_part(mainl, &(self->blo_handle), item_str, idcode);
+ ID *id = BLO_library_link_named_part(mainl, &(self->blo_handle), idcode, item_str);
if (id) {
#ifdef USE_RNA_DATABLOCKS
/* swap name for pointer to the id */
@@ -405,7 +405,7 @@ static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *UNUSED(args))
}
else {
Library *lib = mainl->curlib; /* newly added lib, assign before append end */
- BLO_library_append_end(NULL, mainl, &(self->blo_handle), 0, self->flag);
+ BLO_library_link_end(mainl, &(self->blo_handle), self->flag, NULL, NULL);
BLO_blendhandle_close(self->blo_handle);
self->blo_handle = NULL;
diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c
index bd07c7370a4..5414c4e4204 100644
--- a/source/blender/python/intern/bpy_rna.c
+++ b/source/blender/python/intern/bpy_rna.c
@@ -988,15 +988,16 @@ static PyObject *pyrna_prop_repr(BPy_PropertyRNA *self)
path = RNA_path_from_ID_to_property(&self->ptr, self->prop);
if (path) {
+ const char *data_delim = (path[0] == '[') ? "" : ".";
if (GS(id->name) == ID_NT) { /* nodetree paths are not accurate */
ret = PyUnicode_FromFormat("bpy.data...%s",
path);
}
else {
- ret = PyUnicode_FromFormat("bpy.data.%s[%R].%s",
+ ret = PyUnicode_FromFormat("bpy.data.%s[%R]%s%s",
BKE_idcode_to_name_plural(GS(id->name)),
tmp_str,
- path);
+ data_delim, path);
}
MEM_freeN((void *)path);
@@ -3388,6 +3389,21 @@ static PyObject *pyrna_prop_as_bytes(BPy_PropertyRNA *self)
}
}
+PyDoc_STRVAR(pyrna_prop_update_doc,
+".. method:: update()\n"
+"\n"
+" Execute the properties update callback.\n"
+"\n"
+" .. note::\n"
+" This is called when assigning a property,\n"
+" however in rare cases its useful to call explicitly.\n"
+);
+static PyObject *pyrna_prop_update(BPy_PropertyRNA *self)
+{
+ RNA_property_update(BPy_GetContext(), &self->ptr, self->prop);
+ Py_RETURN_NONE;
+}
+
PyDoc_STRVAR(pyrna_struct_type_recast_doc,
".. method:: type_recast()\n"
"\n"
@@ -4721,6 +4737,7 @@ static struct PyMethodDef pyrna_struct_methods[] = {
static struct PyMethodDef pyrna_prop_methods[] = {
{"path_from_id", (PyCFunction)pyrna_prop_path_from_id, METH_NOARGS, pyrna_prop_path_from_id_doc},
{"as_bytes", (PyCFunction)pyrna_prop_as_bytes, METH_NOARGS, pyrna_prop_as_bytes_doc},
+ {"update", (PyCFunction)pyrna_prop_update, METH_NOARGS, pyrna_prop_update_doc},
{"__dir__", (PyCFunction)pyrna_prop_dir, METH_NOARGS, NULL},
{NULL, NULL, 0, NULL}
};
diff --git a/source/blender/python/intern/bpy_rna_callback.c b/source/blender/python/intern/bpy_rna_callback.c
index 87c3a6eb4ef..4ae739407eb 100644
--- a/source/blender/python/intern/bpy_rna_callback.c
+++ b/source/blender/python/intern/bpy_rna_callback.c
@@ -174,7 +174,7 @@ static eSpace_Type rna_Space_refine_reverse(StructRNA *srna)
if (srna == &RNA_SpaceConsole) return SPACE_CONSOLE;
if (srna == &RNA_SpaceUserPreferences) return SPACE_USERPREF;
if (srna == &RNA_SpaceClipEditor) return SPACE_CLIP;
- return -1;
+ return SPACE_EMPTY;
}
PyObject *pyrna_callback_classmethod_add(PyObject *UNUSED(self), PyObject *args)
@@ -220,7 +220,7 @@ PyObject *pyrna_callback_classmethod_add(PyObject *UNUSED(self), PyObject *args)
}
else {
const eSpace_Type spaceid = rna_Space_refine_reverse(srna);
- if (spaceid == -1) {
+ if (spaceid == SPACE_EMPTY) {
PyErr_Format(PyExc_TypeError, "unknown space type '%.200s'", RNA_struct_identifier(srna));
return NULL;
}
@@ -283,7 +283,7 @@ PyObject *pyrna_callback_classmethod_remove(PyObject *UNUSED(self), PyObject *ar
}
else {
const eSpace_Type spaceid = rna_Space_refine_reverse(srna);
- if (spaceid == -1) {
+ if (spaceid == SPACE_EMPTY) {
PyErr_Format(PyExc_TypeError, "unknown space type '%.200s'", RNA_struct_identifier(srna));
return NULL;
}
diff --git a/source/blender/python/intern/gpu.c b/source/blender/python/intern/gpu.c
index f933c02390c..aada3f6fc80 100644
--- a/source/blender/python/intern/gpu.c
+++ b/source/blender/python/intern/gpu.c
@@ -32,11 +32,6 @@
* from blender materials.
*/
-/* python redefines */
-#ifdef _POSIX_C_SOURCE
-#undef _POSIX_C_SOURCE
-#endif
-
#include <Python.h>
#include "DNA_scene_types.h"
@@ -60,7 +55,7 @@
#define PY_MODULE_ADD_CONSTANT(module, name) PyModule_AddIntConstant(module, # name, name)
PyDoc_STRVAR(M_gpu_doc,
-"This module provides access to the GLSL shader."
+"This module provides access to the GLSL shader and Offscreen rendering functionalities."
);
static struct PyModuleDef gpumodule = {
PyModuleDef_HEAD_INIT,
@@ -79,6 +74,13 @@ static PyObject *PyInit_gpu(void)
if (m == NULL)
return NULL;
+
+ /* Take care to update docs when editing: 'doc/python_api/rst/gpu.rst' */
+
+
+ /* -------------------------------------------------------------------- */
+ /* GPUDynamicType */
+
/* device constant groups */
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_GROUP_MISC);
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_GROUP_LAMP);
@@ -90,12 +92,14 @@ static PyObject *PyInit_gpu(void)
/* device constants */
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_NONE);
+ /* GPU_DYNAMIC_GROUP_OBJECT */
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_OBJECT_VIEWMAT);
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_OBJECT_MAT);
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_OBJECT_VIEWIMAT);
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_OBJECT_IMAT);
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_OBJECT_COLOR);
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_OBJECT_AUTOBUMPSCALE);
+ /* GPU_DYNAMIC_GROUP_LAMP */
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_LAMP_DYNVEC);
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_LAMP_DYNCO);
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_LAMP_DYNIMAT);
@@ -105,27 +109,36 @@ static PyObject *PyInit_gpu(void)
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_LAMP_ATT1);
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_LAMP_ATT2);
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_LAMP_DISTANCE);
- PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_LAMP_SPOTBLEND);
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_LAMP_SPOTSIZE);
+ PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_LAMP_SPOTBLEND);
+ PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_LAMP_SPOTSCALE);
+ /* GPU_DYNAMIC_GROUP_SAMPLER */
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_SAMPLER_2DBUFFER);
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_SAMPLER_2DIMAGE);
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_SAMPLER_2DSHADOW);
+ /* GPU_DYNAMIC_GROUP_MIST */
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MIST_ENABLE);
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MIST_START);
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MIST_DISTANCE);
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MIST_INTENSITY);
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MIST_TYPE);
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MIST_COLOR);
+ /* GPU_DYNAMIC_GROUP_WORLD */
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_HORIZON_COLOR);
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_AMBIENT_COLOR);
- PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MAT_ALPHA);
- PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MAT_AMB);
+ /* GPU_DYNAMIC_GROUP_MAT */
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MAT_DIFFRGB);
- PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MAT_EMIT);
- PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MAT_HARD);
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MAT_REF);
- PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MAT_SPEC);
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MAT_SPECRGB);
+ PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MAT_SPEC);
+ PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MAT_HARD);
+ PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MAT_EMIT);
+ PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MAT_AMB);
+ PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MAT_ALPHA);
+
+
+ /* -------------------------------------------------------------------- */
+ /* GPUDataType */
PY_MODULE_ADD_CONSTANT(m, GPU_DATA_1I);
PY_MODULE_ADD_CONSTANT(m, GPU_DATA_1F);
@@ -136,6 +149,12 @@ static PyObject *PyInit_gpu(void)
PY_MODULE_ADD_CONSTANT(m, GPU_DATA_16F);
PY_MODULE_ADD_CONSTANT(m, GPU_DATA_4UB);
+
+ /* -------------------------------------------------------------------- */
+ /* CustomDataType
+ *
+ * Intentionally only include the subset used by the GPU API.
+ */
PY_MODULE_ADD_CONSTANT(m, CD_MTFACE);
PY_MODULE_ADD_CONSTANT(m, CD_ORCO);
PY_MODULE_ADD_CONSTANT(m, CD_TANGENT);
@@ -290,12 +309,25 @@ static PyMethodDef meth_export_shader[] = {
{"export_shader", (PyCFunction)GPU_export_shader, METH_VARARGS | METH_KEYWORDS, GPU_export_shader_doc}
};
+/* -------------------------------------------------------------------- */
+/* Initialize Module */
+
PyObject *GPU_initPython(void)
{
- PyObject *module = PyInit_gpu();
+ PyObject *module;
+ PyObject *submodule;
+ PyObject *sys_modules = PyThreadState_GET()->interp->modules;
+
+ module = PyInit_gpu();
+
PyModule_AddObject(module, "export_shader", (PyObject *)PyCFunction_New(meth_export_shader, NULL));
- PyDict_SetItemString(PyImport_GetModuleDict(), "gpu", module);
+ /* gpu.offscreen */
+ PyModule_AddObject(module, "offscreen", (submodule = BPyInit_gpu_offscreen()));
+ PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule);
+ Py_INCREF(submodule);
+
+ PyDict_SetItemString(PyImport_GetModuleDict(), "gpu", module);
return module;
}
diff --git a/source/blender/python/intern/gpu.h b/source/blender/python/intern/gpu.h
index 82338869b9d..0da44a4eb87 100644
--- a/source/blender/python/intern/gpu.h
+++ b/source/blender/python/intern/gpu.h
@@ -36,4 +36,6 @@
PyObject *GPU_initPython(void);
+PyObject *BPyInit_gpu_offscreen(void);
+
#endif /* __GPU_H__ */
diff --git a/source/blender/python/intern/gpu_offscreen.c b/source/blender/python/intern/gpu_offscreen.c
new file mode 100644
index 00000000000..f8285c6139f
--- /dev/null
+++ b/source/blender/python/intern/gpu_offscreen.c
@@ -0,0 +1,424 @@
+/*
+ * ***** 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.
+ *
+ * Copyright 2015, Blender Foundation.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/intern/gpu_offscreen.c
+ * \ingroup pythonintern
+ *
+ * This file defines the offscreen functionalities of the 'gpu' module
+ * used for off-screen OpenGL rendering.
+ */
+
+#include <Python.h>
+
+#include "BLI_utildefines.h"
+
+#include "WM_types.h"
+
+#include "ED_screen.h"
+
+#include "GPU_extensions.h"
+#include "GPU_compositing.h"
+
+#include "../mathutils/mathutils.h"
+
+#include "../generic/py_capi_utils.h"
+
+#include "gpu.h"
+
+#include "ED_view3d.h"
+
+/* -------------------------------------------------------------------- */
+/* GPU Offscreen PyObject */
+
+typedef struct {
+ PyObject_HEAD
+ GPUOffScreen *ofs;
+} BPy_GPUOffScreen;
+
+static int bpy_gpu_offscreen_valid_check(BPy_GPUOffScreen *py_gpu_ofs)
+{
+ if (UNLIKELY(py_gpu_ofs->ofs == NULL)) {
+ PyErr_SetString(PyExc_ReferenceError, "GPU offscreen was freed, no further access is valid");
+ return -1;
+ }
+ return 0;
+}
+
+#define BPY_GPU_OFFSCREEN_CHECK_OBJ(pygpu) { \
+ if (UNLIKELY(bpy_gpu_offscreen_valid_check(pygpu) == -1)) { \
+ return NULL; \
+ } \
+} ((void)0)
+
+PyDoc_STRVAR(pygpu_offscreen_width_doc, "Texture width.\n\n:type: int");
+static PyObject *pygpu_offscreen_width_get(BPy_GPUOffScreen *self, void *UNUSED(type))
+{
+ BPY_GPU_OFFSCREEN_CHECK_OBJ(self);
+ return PyLong_FromLong(GPU_offscreen_width(self->ofs));
+}
+
+PyDoc_STRVAR(pygpu_offscreen_height_doc, "Texture height.\n\n:type: int");
+static PyObject *pygpu_offscreen_height_get(BPy_GPUOffScreen *self, void *UNUSED(type))
+{
+ BPY_GPU_OFFSCREEN_CHECK_OBJ(self);
+ return PyLong_FromLong(GPU_offscreen_height(self->ofs));
+}
+
+PyDoc_STRVAR(pygpu_offscreen_color_texture_doc, "Color texture.\n\n:type: int");
+static PyObject *pygpu_offscreen_color_texture_get(BPy_GPUOffScreen *self, void *UNUSED(type))
+{
+ BPY_GPU_OFFSCREEN_CHECK_OBJ(self);
+ return PyLong_FromLong(GPU_offscreen_color_texture(self->ofs));
+}
+
+PyDoc_STRVAR(pygpu_offscreen_bind_doc,
+"bind(save=True)\n"
+"\n"
+" Bind the offscreen object.\n"
+"\n"
+" :param save: save OpenGL current states.\n"
+" :type save: bool\n"
+);
+static PyObject *pygpu_offscreen_bind(BPy_GPUOffScreen *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"save", NULL};
+ bool save = true;
+
+ BPY_GPU_OFFSCREEN_CHECK_OBJ(self);
+
+ if (!PyArg_ParseTupleAndKeywords(
+ args, kwds, "|O&:bind", (char **)(kwlist),
+ PyC_ParseBool, &save))
+ {
+ return NULL;
+ }
+
+ GPU_offscreen_bind(self->ofs, save);
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(pygpu_offscreen_unbind_doc,
+"unbind(restore=True)\n"
+"\n"
+" Unbind the offscreen object.\n"
+"\n"
+" :param restore: restore OpenGL previous states.\n"
+" :type restore: bool\n"
+);
+static PyObject *pygpu_offscreen_unbind(BPy_GPUOffScreen *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"restore", NULL};
+ bool restore = true;
+
+ BPY_GPU_OFFSCREEN_CHECK_OBJ(self);
+
+ if (!PyArg_ParseTupleAndKeywords(
+ args, kwds, "|O&:unbind", (char **)(kwlist),
+ PyC_ParseBool, &restore))
+ {
+ return NULL;
+ }
+
+ GPU_offscreen_unbind(self->ofs, restore);
+ Py_RETURN_NONE;
+}
+
+/**
+ * Use with PyArg_ParseTuple's "O&" formatting.
+ */
+static int pygpu_offscreen_check_matrix(PyObject *o, void *p)
+{
+ MatrixObject **pymat_p = p;
+ MatrixObject *pymat = (MatrixObject *)o;
+
+ if (!MatrixObject_Check(pymat)) {
+ PyErr_Format(PyExc_TypeError,
+ "expected a mathutils.Matrix, not a %.200s",
+ Py_TYPE(o)->tp_name);
+ return 0;
+ }
+
+ if (BaseMath_ReadCallback(pymat) == -1) {
+ return 0;
+ }
+
+ if ((pymat->num_col != 4) ||
+ (pymat->num_row != 4))
+ {
+ PyErr_SetString(PyExc_ValueError, "matrix must be 4x4");
+ return 0;
+ }
+
+ *pymat_p = pymat;
+ return 1;
+}
+
+PyDoc_STRVAR(pygpu_offscreen_draw_view3d_doc,
+"draw_view3d(scene, view3d, region, modelview_matrix, projection_matrix)\n"
+"\n"
+" Draw the 3d viewport in the offscreen object.\n"
+"\n"
+" :param scene: Scene to draw.\n"
+" :type scene: :class:`bpy.types.Scene`\n"
+" :param view3d: 3D View to get the drawing settings from.\n"
+" :type view3d: :class:`bpy.types.SpaceView3D`\n"
+" :param region: Region of the 3D View.\n"
+" :type region: :class:`bpy.types.Region`\n"
+" :param modelview_matrix: ModelView Matrix.\n"
+" :type modelview_matrix: :class:`mathutils.Matrix`\n"
+" :param projection_matrix: Projection Matrix.\n"
+" :type projection_matrix: :class:`mathutils.Matrix`\n"
+);
+static PyObject *pygpu_offscreen_draw_view3d(BPy_GPUOffScreen *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"scene", "view3d", "region", "projection_matrix", "modelview_matrix", NULL};
+
+ MatrixObject *py_mat_modelview, *py_mat_projection;
+ PyObject *py_scene, *py_region, *py_view3d;
+
+ Scene *scene;
+ View3D *v3d;
+ ARegion *ar;
+ GPUFX *fx;
+ GPUFXSettings fx_settings;
+
+ BPY_GPU_OFFSCREEN_CHECK_OBJ(self);
+
+ if (!PyArg_ParseTupleAndKeywords(
+ args, kwds, "OOOO&O&:draw_view3d", (char **)(kwlist),
+ &py_scene, &py_view3d, &py_region,
+ pygpu_offscreen_check_matrix, &py_mat_projection,
+ pygpu_offscreen_check_matrix, &py_mat_modelview) ||
+ (!(scene = PyC_RNA_AsPointer(py_scene, "Scene")) ||
+ !(v3d = PyC_RNA_AsPointer(py_view3d, "SpaceView3D")) ||
+ !(ar = PyC_RNA_AsPointer(py_region, "Region"))))
+ {
+ return NULL;
+ }
+
+ fx = GPU_fx_compositor_create();
+
+ fx_settings = v3d->fx_settings; /* full copy */
+
+ ED_view3d_draw_offscreen_init(scene, v3d);
+
+ GPU_offscreen_bind(self->ofs, true); /* bind */
+
+ ED_view3d_draw_offscreen(
+ scene, v3d, ar, GPU_offscreen_width(self->ofs), GPU_offscreen_height(self->ofs),
+ (float(*)[4])py_mat_modelview->matrix, (float(*)[4])py_mat_projection->matrix,
+ false, true, true, "",
+ fx, &fx_settings,
+ self->ofs);
+
+ GPU_fx_compositor_destroy(fx);
+ GPU_offscreen_unbind(self->ofs, true); /* unbind */
+
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(pygpu_offscreen_free_doc,
+"free()\n"
+"\n"
+" Free the offscreen object\n"
+" The framebuffer, texture and render objects will no longer be accessible.\n"
+);
+static PyObject *pygpu_offscreen_free(BPy_GPUOffScreen *self)
+{
+ BPY_GPU_OFFSCREEN_CHECK_OBJ(self);
+
+ GPU_offscreen_free(self->ofs);
+ self->ofs = NULL;
+ Py_RETURN_NONE;
+}
+
+static void BPy_GPUOffScreen__tp_dealloc(BPy_GPUOffScreen *self)
+{
+ if (self->ofs)
+ GPU_offscreen_free(self->ofs);
+ Py_TYPE(self)->tp_free((PyObject *)self);
+}
+
+static PyGetSetDef bpy_gpu_offscreen_getseters[] = {
+ {(char *)"color_texture", (getter)pygpu_offscreen_color_texture_get, (setter)NULL, pygpu_offscreen_color_texture_doc, NULL},
+ {(char *)"width", (getter)pygpu_offscreen_width_get, (setter)NULL, pygpu_offscreen_width_doc, NULL},
+ {(char *)"height", (getter)pygpu_offscreen_height_get, (setter)NULL, pygpu_offscreen_height_doc, NULL},
+ {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
+};
+
+static struct PyMethodDef bpy_gpu_offscreen_methods[] = {
+ {"bind", (PyCFunction)pygpu_offscreen_bind, METH_VARARGS | METH_KEYWORDS, pygpu_offscreen_bind_doc},
+ {"unbind", (PyCFunction)pygpu_offscreen_unbind, METH_VARARGS | METH_KEYWORDS, pygpu_offscreen_unbind_doc},
+ {"draw_view3d", (PyCFunction)pygpu_offscreen_draw_view3d, METH_VARARGS | METH_KEYWORDS, pygpu_offscreen_draw_view3d_doc},
+ {"free", (PyCFunction)pygpu_offscreen_free, METH_NOARGS, pygpu_offscreen_free_doc},
+ {NULL, NULL, 0, NULL}
+};
+
+PyDoc_STRVAR(py_gpu_offscreen_doc,
+".. class:: GPUOffscreen"
+"\n"
+" This object gives access to off screen buffers.\n"
+);
+static PyTypeObject BPy_GPUOffScreen_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GPUOffScreen", /* tp_name */
+ sizeof(BPy_GPUOffScreen), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ /* methods */
+ (destructor)BPy_GPUOffScreen__tp_dealloc, /* tp_dealloc */
+ NULL, /* tp_print */
+ NULL, /* tp_getattr */
+ NULL, /* tp_setattr */
+ NULL, /* tp_compare */
+ NULL, /* tp_repr */
+ NULL, /* tp_as_number */
+ NULL, /* tp_as_sequence */
+ NULL, /* tp_as_mapping */
+ NULL, /* tp_hash */
+ NULL, /* tp_call */
+ NULL, /* tp_str */
+ NULL, /* tp_getattro */
+ NULL, /* tp_setattro */
+ NULL, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+ py_gpu_offscreen_doc, /* Documentation string */
+ NULL, /* tp_traverse */
+ NULL, /* tp_clear */
+ NULL, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ NULL, /* tp_iter */
+ NULL, /* tp_iternext */
+ bpy_gpu_offscreen_methods, /* tp_methods */
+ NULL, /* tp_members */
+ bpy_gpu_offscreen_getseters, /* tp_getset */
+ NULL, /* tp_base */
+ NULL, /* tp_dict */
+ NULL, /* tp_descr_get */
+ NULL, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ NULL, /* tp_alloc */
+ NULL, /* tp_new */
+ (freefunc)0, /* tp_free */
+ NULL, /* tp_is_gc */
+ NULL, /* tp_bases */
+ NULL, /* tp_mro */
+ NULL, /* tp_cache */
+ NULL, /* tp_subclasses */
+ NULL, /* tp_weaklist */
+ (destructor) NULL /* tp_del */
+};
+
+/* -------------------------------------------------------------------- */
+/* GPU offscreen methods */
+
+static PyObject *BPy_GPU_OffScreen_CreatePyObject(GPUOffScreen *ofs)
+{
+ BPy_GPUOffScreen *self;
+ self = PyObject_New(BPy_GPUOffScreen, &BPy_GPUOffScreen_Type);
+ self->ofs = ofs;
+ return (PyObject *)self;
+}
+
+PyDoc_STRVAR(pygpu_offscreen_new_doc,
+"new(width, height, samples=0)\n"
+"\n"
+" Return a GPUOffScreen.\n"
+"\n"
+" :param width: Horizontal dimension of the buffer.\n"
+" :type width: int`\n"
+" :param height: Vertical dimension of the buffer.\n"
+" :type height: int`\n"
+" :param samples: OpenGL samples to use for MSAA or zero to disable.\n"
+" :type samples: int\n"
+" :return: Newly created off-screen buffer.\n"
+" :rtype: :class:`gpu.GPUOffscreen`\n"
+);
+static PyObject *pygpu_offscreen_new(PyObject *UNUSED(self), PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"width", "height", "samples", NULL};
+
+ GPUOffScreen *ofs;
+ int width, height, samples = 0;
+ char err_out[256];
+
+ if (!PyArg_ParseTupleAndKeywords(
+ args, kwds, "ii|i:new", (char **)(kwlist),
+ &width, &height, &samples))
+ {
+ return NULL;
+ }
+
+ ofs = GPU_offscreen_create(width, height, samples, err_out);
+
+ if (ofs == NULL) {
+ PyErr_Format(PyExc_RuntimeError,
+ "gpu.offscreen.new(...) failed with '%s'",
+ err_out[0] ? err_out : "unknown error");
+ return NULL;
+ }
+
+ return BPy_GPU_OffScreen_CreatePyObject(ofs);
+}
+
+static struct PyMethodDef BPy_GPU_offscreen_methods[] = {
+ {"new", (PyCFunction)pygpu_offscreen_new, METH_VARARGS | METH_KEYWORDS, pygpu_offscreen_new_doc},
+ {NULL, NULL, 0, NULL}
+};
+
+PyDoc_STRVAR(BPy_GPU_offscreen_doc,
+"This module provides access to offscreen rendering functions."
+);
+static PyModuleDef BPy_GPU_offscreen_module_def = {
+ PyModuleDef_HEAD_INIT,
+ "gpu.offscreen", /* m_name */
+ BPy_GPU_offscreen_doc, /* m_doc */
+ 0, /* m_size */
+ BPy_GPU_offscreen_methods, /* m_methods */
+ NULL, /* m_reload */
+ NULL, /* m_traverse */
+ NULL, /* m_clear */
+ NULL, /* m_free */
+};
+
+PyObject *BPyInit_gpu_offscreen(void)
+{
+ PyObject *submodule;
+
+ /* Register the 'GPUOffscreen' class */
+ if (PyType_Ready(&BPy_GPUOffScreen_Type)) {
+ return NULL;
+ }
+
+ submodule = PyModule_Create(&BPy_GPU_offscreen_module_def);
+
+#define MODULE_TYPE_ADD(s, t) \
+ PyModule_AddObject(s, t.tp_name, (PyObject *)&t); Py_INCREF((PyObject *)&t)
+
+ MODULE_TYPE_ADD(submodule, BPy_GPUOffScreen_Type);
+
+#undef MODULE_TYPE_ADD
+
+ return submodule;
+}
+
+#undef BPY_GPU_OFFSCREEN_CHECK_OBJ
diff --git a/source/blender/python/mathutils/mathutils.c b/source/blender/python/mathutils/mathutils.c
index 16d8d6477a5..635090869ea 100644
--- a/source/blender/python/mathutils/mathutils.c
+++ b/source/blender/python/mathutils/mathutils.c
@@ -355,7 +355,7 @@ int mathutils_any_to_rotmat(float rmat[3][3], PyObject *value, const char *error
/* XXX We may want to use 'safer' BLI's compare_ff_relative ultimately?
* LomontRRDCompare4() is an optimized version of Dawson's AlmostEqual2sComplement() (see [1] and [2]).
* Dawson himself now claims this is not a 'safe' thing to do (pushing ULP method beyond its limits),
- * an recommands using work from [3] instead, which is done in BLI func...
+ * an recommends using work from [3] instead, which is done in BLI func...
*
* [1] http://www.randydillon.org/Papers/2007/everfast.htm
* [2] http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
diff --git a/source/blender/python/mathutils/mathutils_bvhtree.c b/source/blender/python/mathutils/mathutils_bvhtree.c
index 8a488fdfd08..9deb57d6760 100644
--- a/source/blender/python/mathutils/mathutils_bvhtree.c
+++ b/source/blender/python/mathutils/mathutils_bvhtree.c
@@ -277,7 +277,7 @@ static void py_bvhtree_raycast_cb(void *userdata, int index, const BVHTreeRay *r
{
const PyBVHTree *self = userdata;
- const float (*coords)[3] = self->coords;
+ const float (*coords)[3] = (const float (*)[3])self->coords;
const unsigned int *tri = self->tris[index];
const float *tri_co[3] = {coords[tri[0]], coords[tri[1]], coords[tri[2]]};
float dist;
@@ -306,7 +306,7 @@ static void py_bvhtree_nearest_point_cb(void *userdata, int index, const float c
{
PyBVHTree *self = userdata;
- const float (*coords)[3] = self->coords;
+ const float (*coords)[3] = (const float (*)[3])self->coords;
const unsigned int *tri = self->tris[index];
const float *tri_co[3] = {coords[tri[0]], coords[tri[1]], coords[tri[2]]};
float nearest_tmp[3], dist_sq;
@@ -352,7 +352,7 @@ static PyObject *py_bvhtree_ray_cast(PyBVHTree *self, PyObject *args)
if (!PyArg_ParseTuple(
args, (char *)"OO|f:ray_cast",
- &py_co, &py_direction, max_dist))
+ &py_co, &py_direction, &max_dist))
{
return NULL;
}
diff --git a/source/blender/python/mathutils/mathutils_geometry.c b/source/blender/python/mathutils/mathutils_geometry.c
index 81d000991d0..a4ca2520919 100644
--- a/source/blender/python/mathutils/mathutils_geometry.c
+++ b/source/blender/python/mathutils/mathutils_geometry.c
@@ -415,7 +415,9 @@ static PyObject *M_Geometry_volume_tetrahedron(PyObject *UNUSED(self), PyObject
PyDoc_STRVAR(M_Geometry_intersect_line_line_2d_doc,
".. function:: intersect_line_line_2d(lineA_p1, lineA_p2, lineB_p1, lineB_p2)\n"
"\n"
-" Takes 2 lines (as 4 vectors) and returns a vector for their point of intersection or None.\n"
+" Takes 2 segments (defined by 4 vectors) and returns a vector for their point of intersection or None.\n"
+"\n"
+" .. warning:: Despite its name, this function works on segments, and not on lines..."
"\n"
" :arg lineA_p1: First point of the first line\n"
" :type lineA_p1: :class:`mathutils.Vector`\n"
@@ -530,6 +532,7 @@ static PyObject *M_Geometry_intersect_plane_plane(PyObject *UNUSED(self), PyObje
PyObject *ret, *ret_co, *ret_no;
PyObject *py_plane_a_co, *py_plane_a_no, *py_plane_b_co, *py_plane_b_no;
float plane_a_co[3], plane_a_no[3], plane_b_co[3], plane_b_no[3];
+ float plane_a[4], plane_b[4];
float isect_co[3];
float isect_no[3];
@@ -549,9 +552,12 @@ static PyObject *M_Geometry_intersect_plane_plane(PyObject *UNUSED(self), PyObje
return NULL;
}
- if (isect_plane_plane_v3(isect_co, isect_no,
- plane_a_co, plane_a_no,
- plane_b_co, plane_b_no))
+ plane_from_point_normal_v3(plane_a, plane_a_co, plane_a_no);
+ plane_from_point_normal_v3(plane_b, plane_b_co, plane_b_no);
+
+ if (isect_plane_plane_v3(
+ plane_a, plane_b,
+ isect_co, isect_no))
{
normalize_v3(isect_no);
diff --git a/source/blender/quicktime/apple/qtkit_export.m b/source/blender/quicktime/apple/qtkit_export.m
index a4ee398da5d..9bc4ec444bb 100644
--- a/source/blender/quicktime/apple/qtkit_export.m
+++ b/source/blender/quicktime/apple/qtkit_export.m
@@ -378,8 +378,7 @@ int start_qt(
}
else {
makeqtstring(rd, name, preview);
- qtexport->filename = [[NSString alloc] initWithCString:name
- encoding:[NSString defaultCStringEncoding]];
+ qtexport->filename = [[NSString alloc] initWithUTF8String:name];
qtexport->movie = nil;
qtexport->audioFile = NULL;
diff --git a/source/blender/quicktime/quicktime_export.h b/source/blender/quicktime/quicktime_export.h
index 8a10a4a05d6..41db83fb1c9 100644
--- a/source/blender/quicktime/quicktime_export.h
+++ b/source/blender/quicktime/quicktime_export.h
@@ -46,7 +46,7 @@
typedef struct QuicktimeCodecTypeDesc {
int codecType;
int rnatmpvalue;
- char *codecName;
+ const char *codecName;
} QuicktimeCodecTypeDesc;
// quicktime movie output functions
diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h
index 2a679f0f0d0..fd56c47c309 100644
--- a/source/blender/render/extern/include/RE_pipeline.h
+++ b/source/blender/render/extern/include/RE_pipeline.h
@@ -207,6 +207,10 @@ void RE_InitRenderCB(struct Render *re);
void RE_FreeRender(struct Render *re);
/* only called on exit */
void RE_FreeAllRender(void);
+/* Free memory used by persistent data.
+ * Invoked when loading new file.
+ */
+void RE_FreeAllPersistentData(void);
/* only call on file load */
void RE_FreeAllRenderResults(void);
/* for external render engines that can keep persistent data */
diff --git a/source/blender/render/extern/include/RE_render_ext.h b/source/blender/render/extern/include/RE_render_ext.h
index 6e1f128b7a5..85a9dc9fccd 100644
--- a/source/blender/render/extern/include/RE_render_ext.h
+++ b/source/blender/render/extern/include/RE_render_ext.h
@@ -63,7 +63,11 @@ void RE_sample_material_color(
struct PointDensity;
-void RE_sample_point_density(struct Scene *scene, struct PointDensity *pd, int resolution, float *values);
+void RE_sample_point_density(struct Scene *scene,
+ struct PointDensity *pd,
+ const int resolution,
+ const bool use_render_params,
+ float *values);
void RE_init_texture_rng(void);
void RE_exit_texture_rng(void);
diff --git a/source/blender/render/intern/include/renderdatabase.h b/source/blender/render/intern/include/renderdatabase.h
index da45a2bfead..224974454e8 100644
--- a/source/blender/render/intern/include/renderdatabase.h
+++ b/source/blender/render/intern/include/renderdatabase.h
@@ -115,7 +115,9 @@ struct HaloRen *RE_inithalo_particle(struct Render *re, struct ObjectRen *obr, s
struct StrandBuffer *RE_addStrandBuffer(struct ObjectRen *obr, int totvert);
struct ObjectRen *RE_addRenderObject(struct Render *re, struct Object *ob, struct Object *par, int index, int psysindex, int lay);
-struct ObjectInstanceRen *RE_addRenderInstance(struct Render *re, struct ObjectRen *obr, struct Object *ob, struct Object *par, int index, int psysindex, float mat[4][4], int lay);
+struct ObjectInstanceRen *RE_addRenderInstance(
+ struct Render *re, struct ObjectRen *obr, struct Object *ob, struct Object *par,
+ int index, int psysindex, float mat[4][4], int lay, const struct DupliObject *dob);
void RE_makeRenderInstances(struct Render *re);
void RE_instance_rotate_ray_start(struct ObjectInstanceRen *obi, struct Isect *is);
diff --git a/source/blender/render/intern/source/bake.c b/source/blender/render/intern/source/bake.c
index 0210bec5ab4..30036c27b5d 100644
--- a/source/blender/render/intern/source/bake.c
+++ b/source/blender/render/intern/source/bake.c
@@ -320,7 +320,7 @@ static void bake_shade(void *handle, Object *ob, ShadeInput *shi, int UNUSED(qua
}
else {
unsigned char *imcol = (unsigned char *)(bs->rect + bs->rectx * y + x);
- copy_v4_v4_char((char *)imcol, (char *)col);
+ copy_v4_v4_uchar(imcol, col);
}
}
@@ -375,8 +375,8 @@ static void bake_displacement(void *handle, ShadeInput *UNUSED(shi), float dist,
bs->vcol->b = col[2];
}
else {
- char *imcol = (char *)(bs->rect + bs->rectx * y + x);
- copy_v4_v4_char(imcol, (char *)col);
+ unsigned char *imcol = (unsigned char *)(bs->rect + bs->rectx * y + x);
+ copy_v4_v4_uchar(imcol, col);
}
}
if (bs->rect_mask) {
diff --git a/source/blender/render/intern/source/bake_api.c b/source/blender/render/intern/source/bake_api.c
index dee75d43f36..77f6ab9cfc2 100644
--- a/source/blender/render/intern/source/bake_api.c
+++ b/source/blender/render/intern/source/bake_api.c
@@ -356,22 +356,26 @@ static bool cast_ray_highpoly(
* This function populates an array of verts for the triangles of a mesh
* Tangent and Normals are also stored
*/
-static void mesh_calc_tri_tessface(
- TriTessFace *triangles, Mesh *me, bool tangent, DerivedMesh *dm)
+static TriTessFace *mesh_calc_tri_tessface(
+ Mesh *me, bool tangent, DerivedMesh *dm)
{
int i;
MVert *mvert;
TSpace *tspace;
float *precomputed_normals = NULL;
bool calculate_normal;
+
const int tottri = poly_to_tri_count(me->totpoly, me->totloop);
MLoopTri *looptri;
+ TriTessFace *triangles;
+
/* calculate normal for each polygon only once */
unsigned int mpoly_prev = UINT_MAX;
float no[3];
mvert = CustomData_get_layer(&me->vdata, CD_MVERT);
looptri = MEM_mallocN(sizeof(*looptri) * tottri, __func__);
+ triangles = MEM_mallocN(sizeof(TriTessFace) * tottri, __func__);
if (tangent) {
DM_ensure_normals(dm);
@@ -419,6 +423,8 @@ static void mesh_calc_tri_tessface(
}
MEM_freeN(looptri);
+
+ return triangles;
}
bool RE_bake_pixels_populate_from_objects(
@@ -451,26 +457,20 @@ bool RE_bake_pixels_populate_from_objects(
if (!is_cage) {
dm_low = CDDM_from_mesh(me_low);
- tris_low = MEM_mallocN(sizeof(TriTessFace) * (me_low->totface * 2), "MVerts Lowpoly Mesh");
- mesh_calc_tri_tessface(tris_low, me_low, true, dm_low);
+ tris_low = mesh_calc_tri_tessface(me_low, true, dm_low);
}
else if (is_custom_cage) {
- tris_low = MEM_mallocN(sizeof(TriTessFace) * (me_low->totface * 2), "MVerts Lowpoly Mesh");
- mesh_calc_tri_tessface(tris_low, me_low, false, NULL);
-
- tris_cage = MEM_mallocN(sizeof(TriTessFace) * (me_low->totface * 2), "MVerts Cage Mesh");
- mesh_calc_tri_tessface(tris_cage, me_cage, false, NULL);
+ tris_low = mesh_calc_tri_tessface(me_low, false, NULL);
+ tris_cage = mesh_calc_tri_tessface(me_cage, false, NULL);
}
else {
- tris_cage = MEM_mallocN(sizeof(TriTessFace) * (me_low->totface * 2), "MVerts Cage Mesh");
- mesh_calc_tri_tessface(tris_cage, me_cage, false, NULL);
+ tris_cage = mesh_calc_tri_tessface(me_cage, false, NULL);
}
invert_m4_m4(imat_low, mat_low);
for (i = 0; i < tot_highpoly; i++) {
- tris_high[i] = MEM_mallocN(sizeof(TriTessFace) * highpoly[i].me->totface, "MVerts Highpoly Mesh");
- mesh_calc_tri_tessface(tris_high[i], highpoly[i].me, false, NULL);
+ tris_high[i] = mesh_calc_tri_tessface(highpoly[i].me, false, NULL);
dm_highpoly[i] = CDDM_from_mesh(highpoly[i].me);
DM_ensure_tessface(dm_highpoly[i]);
@@ -583,13 +583,26 @@ void RE_bake_pixels_populate(
size_t i;
int a, p_id;
- MTFace *mtface;
- MFace *mface;
+ const MLoopUV *mloopuv;
+ const int tottri = poly_to_tri_count(me->totpoly, me->totloop);
+ MLoopTri *looptri;
/* we can't bake in edit mode */
if (me->edit_btmesh)
return;
+ if ((uv_layer == NULL) || (uv_layer[0] == '\0')) {
+ mloopuv = CustomData_get_layer(&me->ldata, CD_MLOOPUV);
+ }
+ else {
+ int uv_id = CustomData_get_named_layer(&me->ldata, CD_MLOOPUV, uv_layer);
+ mloopuv = CustomData_get_layer_n(&me->ldata, CD_MTFACE, uv_id);
+ }
+
+ if (mloopuv == NULL)
+ return;
+
+
bd.pixel_array = pixel_array;
bd.zspan = MEM_callocN(sizeof(ZSpan) * bake_images->size, "bake zspan");
@@ -602,54 +615,45 @@ void RE_bake_pixels_populate(
zbuf_alloc_span(&bd.zspan[i], bake_images->data[i].width, bake_images->data[i].height, R.clipcrop);
}
- if ((uv_layer == NULL) || (uv_layer[0] == '\0')) {
- mtface = CustomData_get_layer(&me->fdata, CD_MTFACE);
- }
- else {
- int uv_id = CustomData_get_named_layer(&me->fdata, CD_MTFACE, uv_layer);
- mtface = CustomData_get_layer_n(&me->fdata, CD_MTFACE, uv_id);
- }
-
- mface = CustomData_get_layer(&me->fdata, CD_MFACE);
+ looptri = MEM_mallocN(sizeof(*looptri) * tottri, __func__);
- if (mtface == NULL)
- return;
+ BKE_mesh_recalc_looptri(
+ me->mloop, me->mpoly,
+ me->mvert,
+ me->totloop, me->totpoly,
+ looptri);
p_id = -1;
- for (i = 0; i < me->totface; i++) {
- float vec[4][2];
- MTFace *mtf = &mtface[i];
- MFace *mf = &mface[i];
- int mat_nr = mf->mat_nr;
+ for (i = 0; i < tottri; i++) {
+ const MLoopTri *lt = &looptri[i];
+ const MPoly *mp = &me->mpoly[lt->poly];
+ float vec[3][2];
+ int mat_nr = mp->mat_nr;
int image_id = bake_images->lookup[mat_nr];
bd.bk_image = &bake_images->data[image_id];
bd.primitive_id = ++p_id;
- for (a = 0; a < 4; a++) {
+ for (a = 0; a < 3; a++) {
+ const float *uv = mloopuv[lt->tri[a]].uv;
+
/* Note, workaround for pixel aligned UVs which are common and can screw up our intersection tests
* where a pixel gets in between 2 faces or the middle of a quad,
* camera aligned quads also have this problem but they are less common.
* Add a small offset to the UVs, fixes bug #18685 - Campbell */
- vec[a][0] = mtf->uv[a][0] * (float)bd.bk_image->width - (0.5f + 0.001f);
- vec[a][1] = mtf->uv[a][1] * (float)bd.bk_image->height - (0.5f + 0.002f);
+ vec[a][0] = uv[0] * (float)bd.bk_image->width - (0.5f + 0.001f);
+ vec[a][1] = uv[1] * (float)bd.bk_image->height - (0.5f + 0.002f);
}
bake_differentials(&bd, vec[0], vec[1], vec[2]);
zspan_scanconvert(&bd.zspan[image_id], (void *)&bd, vec[0], vec[1], vec[2], store_bake_pixel);
-
- /* 4 vertices in the face */
- if (mf->v4 != 0) {
- bd.primitive_id = ++p_id;
-
- bake_differentials(&bd, vec[0], vec[2], vec[3]);
- zspan_scanconvert(&bd.zspan[image_id], (void *)&bd, vec[0], vec[2], vec[3], store_bake_pixel);
- }
}
for (i = 0; i < bake_images->size; i++) {
zbuf_free_span(&bd.zspan[i]);
}
+
+ MEM_freeN(looptri);
MEM_freeN(bd.zspan);
}
@@ -718,8 +722,7 @@ void RE_bake_normal_world_to_tangent(
DerivedMesh *dm = CDDM_from_mesh(me);
- triangles = MEM_mallocN(sizeof(TriTessFace) * (me->totface * 2), "MVerts Mesh");
- mesh_calc_tri_tessface(triangles, me, true, dm);
+ triangles = mesh_calc_tri_tessface(me, true, dm);
BLI_assert(num_pixels >= 3);
diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c
index ee28c3b286f..0adcc16514e 100644
--- a/source/blender/render/intern/source/convertblender.c
+++ b/source/blender/render/intern/source/convertblender.c
@@ -4658,7 +4658,7 @@ static void add_render_object(Render *re, Object *ob, Object *par, DupliObject *
/* only add instance for objects that have not been used for dupli */
if (!(ob->transflag & OB_RENDER_DUPLI)) {
- obi= RE_addRenderInstance(re, obr, ob, par, index, 0, NULL, ob->lay);
+ obi = RE_addRenderInstance(re, obr, ob, par, index, 0, NULL, ob->lay, dob);
if (dob) set_dupli_tex_mat(re, obi, dob, omat);
}
else
@@ -4692,7 +4692,7 @@ static void add_render_object(Render *re, Object *ob, Object *par, DupliObject *
/* only add instance for objects that have not been used for dupli */
if (!(ob->transflag & OB_RENDER_DUPLI)) {
- obi= RE_addRenderInstance(re, obr, ob, par, index, psysindex, NULL, ob->lay);
+ obi = RE_addRenderInstance(re, obr, ob, par, index, psysindex, NULL, ob->lay, dob);
if (dob) set_dupli_tex_mat(re, obi, dob, omat);
}
else
@@ -5053,7 +5053,7 @@ static void database_init_objects(Render *re, unsigned int renderlay, int nolamp
if (dob->type != OB_DUPLIGROUP || (obr=find_dupligroup_dupli(re, obd, 0))) {
mul_m4_m4m4(mat, re->viewmat, dob->mat);
/* ob = particle system, use that layer */
- obi= RE_addRenderInstance(re, NULL, obd, ob, dob->persistent_id[0], 0, mat, ob->lay);
+ obi = RE_addRenderInstance(re, NULL, obd, ob, dob->persistent_id[0], 0, mat, ob->lay, dob);
/* fill in instance variables for texturing */
set_dupli_tex_mat(re, obi, dob, dob_extra->obmat);
@@ -5080,7 +5080,7 @@ static void database_init_objects(Render *re, unsigned int renderlay, int nolamp
if (dob->type != OB_DUPLIGROUP || (obr=find_dupligroup_dupli(re, obd, psysindex))) {
if (obi == NULL)
mul_m4_m4m4(mat, re->viewmat, dob->mat);
- obi= RE_addRenderInstance(re, NULL, obd, ob, dob->persistent_id[0], psysindex++, mat, obd->lay);
+ obi = RE_addRenderInstance(re, NULL, obd, ob, dob->persistent_id[0], psysindex++, mat, obd->lay, dob);
set_dupli_tex_mat(re, obi, dob, dob_extra->obmat);
if (dob->type != OB_DUPLIGROUP) {
diff --git a/source/blender/render/intern/source/envmap.c b/source/blender/render/intern/source/envmap.c
index b9b908f550b..d70cc4b1ee0 100644
--- a/source/blender/render/intern/source/envmap.c
+++ b/source/blender/render/intern/source/envmap.c
@@ -262,7 +262,6 @@ static void env_set_imats(Render *re)
void env_rotate_scene(Render *re, float mat[4][4], int do_rotate)
{
- GroupObject *go;
ObjectRen *obr;
ObjectInstanceRen *obi;
LampRen *lar = NULL;
@@ -321,19 +320,18 @@ void env_rotate_scene(Render *re, float mat[4][4], int do_rotate)
invert_m4(obr->ob->imat_ren);
}
- for (go = re->lights.first; go; go = go->next) {
- lar = go->lampren;
-
+ for (lar = re->lampren.first; lar; lar = lar->next) {
+ float lamp_imat[4][4];
+
/* copy from add_render_lamp */
if (do_rotate == 1)
mul_m4_m4m4(tmpmat, re->viewmat, lar->lampmat);
else
mul_m4_m4m4(tmpmat, re->viewmat_orig, lar->lampmat);
- invert_m4_m4(go->ob->imat, tmpmat);
-
+
+ invert_m4_m4(lamp_imat, tmpmat);
copy_m3_m4(lar->mat, tmpmat);
-
- copy_m3_m4(lar->imat, go->ob->imat);
+ copy_m3_m4(lar->imat, lamp_imat);
lar->vec[0]= -tmpmat[2][0];
lar->vec[1]= -tmpmat[2][1];
diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c
index fef453efce2..8adac7c7770 100644
--- a/source/blender/render/intern/source/external_engine.c
+++ b/source/blender/render/intern/source/external_engine.c
@@ -361,10 +361,12 @@ void RE_engine_set_error_message(RenderEngine *engine, const char *msg)
Render *re = engine->re;
if (re != NULL) {
RenderResult *rr = RE_AcquireResultRead(re);
- if (rr->error != NULL) {
- MEM_freeN(rr->error);
+ if (rr) {
+ if (rr->error != NULL) {
+ MEM_freeN(rr->error);
+ }
+ rr->error = BLI_strdup(msg);
}
- rr->error = BLI_strdup(msg);
RE_ReleaseResult(re);
}
}
diff --git a/source/blender/render/intern/source/multires_bake.c b/source/blender/render/intern/source/multires_bake.c
index 5fbd980e387..dcc33b99742 100644
--- a/source/blender/render/intern/source/multires_bake.c
+++ b/source/blender/render/intern/source/multires_bake.c
@@ -612,7 +612,7 @@ static void get_ccgdm_data(DerivedMesh *lodm, DerivedMesh *hidm,
int col = cell_index % polys_per_grid_side;
/* S is the vertex whose grid we are examining */
- S = loc_cage_poly_offs / (polys_per_grid_side * polys_per_grid_side);
+ S = poly_index / (1 << (2 * (lvl - 1))) - grid_offset[cage_face_index];
/* get offset of grid data for original cage face */
g_index = grid_offset[cage_face_index];
@@ -1179,20 +1179,20 @@ static void apply_ao_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, void
static void count_images(MultiresBakeRender *bkr)
{
- int a, totface;
+ int a, totpoly;
DerivedMesh *dm = bkr->lores_dm;
- MTFace *mtface = CustomData_get_layer(&dm->faceData, CD_MTFACE);
+ MTexPoly *mtexpoly = CustomData_get_layer(&dm->polyData, CD_MTEXPOLY);
BLI_listbase_clear(&bkr->image);
bkr->tot_image = 0;
- totface = dm->getNumTessFaces(dm);
+ totpoly = dm->getNumPolys(dm);
- for (a = 0; a < totface; a++)
- mtface[a].tpage->id.flag &= ~LIB_DOIT;
+ for (a = 0; a < totpoly; a++)
+ mtexpoly[a].tpage->id.flag &= ~LIB_DOIT;
- for (a = 0; a < totface; a++) {
- Image *ima = mtface[a].tpage;
+ for (a = 0; a < totpoly; a++) {
+ Image *ima = mtexpoly[a].tpage;
if ((ima->id.flag & LIB_DOIT) == 0) {
LinkData *data = BLI_genericNodeN(ima);
BLI_addtail(&bkr->image, data);
@@ -1201,8 +1201,8 @@ static void count_images(MultiresBakeRender *bkr)
}
}
- for (a = 0; a < totface; a++)
- mtface[a].tpage->id.flag &= ~LIB_DOIT;
+ for (a = 0; a < totpoly; a++)
+ mtexpoly[a].tpage->id.flag &= ~LIB_DOIT;
}
static void bake_images(MultiresBakeRender *bkr, MultiresBakeResult *result)
diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c
index 96039b7116c..d6ba97533b5 100644
--- a/source/blender/render/intern/source/pipeline.c
+++ b/source/blender/render/intern/source/pipeline.c
@@ -533,6 +533,17 @@ void RE_FreeAllRender(void)
#endif
}
+void RE_FreeAllPersistentData(void)
+{
+ Render *re;
+ for (re = RenderGlobal.renderlist.first; re != NULL; re = re->next) {
+ if ((re->r.mode & R_PERSISTENT_DATA) != 0 && re->engine != NULL) {
+ RE_engine_free(re->engine);
+ re->engine = NULL;
+ }
+ }
+}
+
/* on file load, free all re */
void RE_FreeAllRenderResults(void)
{
@@ -1270,8 +1281,11 @@ static void main_render_result_new(Render *re)
BLI_rw_mutex_unlock(&re->resultmutex);
- if (re->result->do_exr_tile)
- render_result_exr_file_begin(re);
+ if (re->result) {
+ if (re->result->do_exr_tile) {
+ render_result_exr_file_begin(re);
+ }
+ }
}
static void threaded_tile_processor(Render *re)
@@ -3154,11 +3168,17 @@ void RE_RenderFreestyleStrokes(Render *re, Main *bmain, Scene *scene, int render
void RE_RenderFreestyleExternal(Render *re)
{
if (!re->test_break(re->tbh)) {
- RE_Database_FromScene(re, re->main, re->scene, re->lay, 1);
- RE_Database_Preprocess(re);
+ RenderView *rv;
+
init_freestyle(re);
- add_freestyle(re, 1);
- RE_Database_Free(re);
+
+ for (rv = re->result->views.first; rv; rv = rv->next) {
+ RE_SetActiveRenderView(re, rv->name);
+ RE_Database_FromScene(re, re->main, re->scene, re->lay, 1);
+ RE_Database_Preprocess(re);
+ add_freestyle(re, 1);
+ RE_Database_Free(re);
+ }
}
}
#endif
@@ -3503,6 +3523,11 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_overri
get_videos_dimensions(re, &rd, &width, &height);
mh = BKE_movie_handle_get(scene->r.im_format.imtype);
+ if (mh == NULL) {
+ BKE_report(re->reports, RPT_ERROR, "Movie format unsupported");
+ return;
+ }
+
re->movie_ctx_arr = MEM_mallocN(sizeof(void *) * totvideos, "Movies' Context");
for (i = 0; i < totvideos; i++) {
diff --git a/source/blender/render/intern/source/pointdensity.c b/source/blender/render/intern/source/pointdensity.c
index b8d8cc37ae3..9b58bde730a 100644
--- a/source/blender/render/intern/source/pointdensity.c
+++ b/source/blender/render/intern/source/pointdensity.c
@@ -121,7 +121,8 @@ static void pointdensity_cache_psys(Scene *scene,
ParticleSystem *psys,
float viewmat[4][4],
float winmat[4][4],
- int winx, int winy)
+ int winx, int winy,
+ const bool use_render_params)
{
DerivedMesh *dm;
ParticleKey state;
@@ -140,9 +141,20 @@ static void pointdensity_cache_psys(Scene *scene,
}
/* Just to create a valid rendering context for particles */
- psys_render_set(ob, psys, viewmat, winmat, winx, winy, 0);
+ if (use_render_params) {
+ psys_render_set(ob, psys, viewmat, winmat, winx, winy, 0);
+ }
- dm = mesh_create_derived_render(scene, ob, CD_MASK_BAREMESH | CD_MASK_MTFACE | CD_MASK_MCOL);
+ if (use_render_params) {
+ dm = mesh_create_derived_render(scene,
+ ob,
+ CD_MASK_BAREMESH | CD_MASK_MTFACE | CD_MASK_MCOL);
+ }
+ else {
+ dm = mesh_get_derived_final(scene,
+ ob,
+ CD_MASK_BAREMESH | CD_MASK_MTFACE | CD_MASK_MCOL);
+ }
if ( !psys_check_enabled(ob, psys)) {
psys_render_restore(ob, psys);
@@ -240,17 +252,32 @@ static void pointdensity_cache_psys(Scene *scene,
psys->lattice_deform_data = NULL;
}
- psys_render_restore(ob, psys);
+ if (use_render_params) {
+ psys_render_restore(ob, psys);
+ }
}
-static void pointdensity_cache_object(Scene *scene, PointDensity *pd, Object *ob)
+static void pointdensity_cache_object(Scene *scene,
+ PointDensity *pd,
+ Object *ob,
+ const bool use_render_params)
{
int i;
DerivedMesh *dm;
MVert *mvert = NULL;
- dm = mesh_create_derived_render(scene, ob, CD_MASK_BAREMESH | CD_MASK_MTFACE | CD_MASK_MCOL);
+ if (use_render_params) {
+ dm = mesh_create_derived_render(scene,
+ ob,
+ CD_MASK_BAREMESH | CD_MASK_MTFACE | CD_MASK_MCOL);
+ }
+ else {
+ dm = mesh_get_derived_final(scene,
+ ob,
+ CD_MASK_BAREMESH | CD_MASK_MTFACE | CD_MASK_MCOL);
+
+ }
mvert = dm->getVertArray(dm); /* local object space */
pd->totpoints = dm->getNumVerts(dm);
@@ -290,7 +317,8 @@ static void cache_pointdensity_ex(Scene *scene,
PointDensity *pd,
float viewmat[4][4],
float winmat[4][4],
- int winx, int winy)
+ int winx, int winy,
+ const bool use_render_params)
{
if (pd == NULL) {
return;
@@ -314,18 +342,28 @@ static void cache_pointdensity_ex(Scene *scene,
return;
}
- pointdensity_cache_psys(scene, pd, ob, psys, viewmat, winmat, winx, winy);
+ pointdensity_cache_psys(scene,
+ pd,
+ ob,
+ psys,
+ viewmat, winmat,
+ winx, winy,
+ use_render_params);
}
else if (pd->source == TEX_PD_OBJECT) {
Object *ob = pd->object;
if (ob && ob->type == OB_MESH)
- pointdensity_cache_object(scene, pd, ob);
+ pointdensity_cache_object(scene, pd, ob, use_render_params);
}
}
void cache_pointdensity(Render *re, PointDensity *pd)
{
- cache_pointdensity_ex(re->scene, pd, re->viewmat, re->winmat, re->winx, re->winy);
+ cache_pointdensity_ex(re->scene,
+ pd,
+ re->viewmat, re->winmat,
+ re->winx, re->winy,
+ true);
}
void free_pointdensity(PointDensity *pd)
@@ -597,6 +635,9 @@ int pointdensitytex(Tex *tex, const float texvec[3], TexResult *texres)
BRICONT;
+ if (pd->color_source == TEX_PD_COLOR_CONSTANT)
+ return retval;
+
retval |= pointdensity_color(pd, texres, age, vec);
BRICONTRGB;
@@ -614,33 +655,71 @@ static void sample_dummy_point_density(int resolution, float *values)
memset(values, 0, sizeof(float) * 4 * resolution * resolution * resolution);
}
-static void particle_system_minmax(Object *object,
+static void particle_system_minmax(Scene *scene,
+ Object *object,
ParticleSystem *psys,
float radius,
+ const bool use_render_params,
float min[3], float max[3])
{
+ const float size[3] = {radius, radius, radius};
+ const float cfra = BKE_scene_frame_get(scene);
ParticleSettings *part = psys->part;
- float imat[4][4];
- float size[3] = {radius, radius, radius};
- PARTICLE_P;
+ ParticleSimulationData sim = {NULL};
+ ParticleData *pa = NULL;
+ int i;
+ int total_particles;
+ float mat[4][4], imat[4][4];
+
INIT_MINMAX(min, max);
if (part->type == PART_HAIR) {
/* TOOD(sergey): Not supported currently. */
return;
}
+
+ unit_m4(mat);
+ if (use_render_params) {
+ psys_render_set(object, psys, mat, mat, 1, 1, 0);
+ }
+
+ sim.scene = scene;
+ sim.ob = object;
+ sim.psys = psys;
+ sim.psmd = psys_get_modifier(object, psys);
+
invert_m4_m4(imat, object->obmat);
- LOOP_PARTICLES {
+ total_particles = psys->totpart + psys->totchild;
+ psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
+
+ for (i = 0, pa = psys->particles; i < total_particles; i++, pa++) {
float co_object[3], co_min[3], co_max[3];
- mul_v3_m4v3(co_object, imat, pa->state.co);
+ ParticleKey state;
+ state.time = cfra;
+ if (!psys_get_particle_state(&sim, i, &state, 0)) {
+ continue;
+ }
+ mul_v3_m4v3(co_object, imat, state.co);
sub_v3_v3v3(co_min, co_object, size);
add_v3_v3v3(co_max, co_object, size);
minmax_v3v3_v3(min, max, co_min);
minmax_v3v3_v3(min, max, co_max);
}
+
+ if (psys->lattice_deform_data) {
+ end_latt_deform(psys->lattice_deform_data);
+ psys->lattice_deform_data = NULL;
+ }
+
+ if (use_render_params) {
+ psys_render_restore(object, psys);
+ }
}
-void RE_sample_point_density(Scene *scene, PointDensity *pd,
- int resolution, float *values)
+void RE_sample_point_density(Scene *scene,
+ PointDensity *pd,
+ const int resolution,
+ const bool use_render_params,
+ float *values)
{
const size_t resolution2 = resolution * resolution;
Object *object = pd->object;
@@ -663,7 +742,12 @@ void RE_sample_point_density(Scene *scene, PointDensity *pd,
sample_dummy_point_density(resolution, values);
return;
}
- particle_system_minmax(object, psys, pd->radius, min, max);
+ particle_system_minmax(scene,
+ object,
+ psys,
+ pd->radius,
+ use_render_params,
+ min, max);
}
else {
float radius[3] = {pd->radius, pd->radius, pd->radius};
@@ -686,7 +770,7 @@ void RE_sample_point_density(Scene *scene, PointDensity *pd,
unit_m4(mat);
BLI_mutex_lock(&sample_mutex);
- cache_pointdensity_ex(scene, pd, mat, mat, 1, 1);
+ cache_pointdensity_ex(scene, pd, mat, mat, 1, 1, use_render_params);
for (z = 0; z < resolution; ++z) {
for (y = 0; y < resolution; ++y) {
for (x = 0; x < resolution; ++x) {
diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c
index 70a8fdf3ba3..900312ee984 100644
--- a/source/blender/render/intern/source/rayshade.c
+++ b/source/blender/render/intern/source/rayshade.c
@@ -736,6 +736,7 @@ static void traceray(ShadeInput *origshi, ShadeResult *origshr, short depth, con
//shi.sample= 0; // memset above, so don't need this
shi.xs= origshi->xs;
shi.ys= origshi->ys;
+ shi.do_manage= origshi->do_manage;
shi.lay= origshi->lay;
shi.passflag= SCE_PASS_COMBINED; /* result of tracing needs no pass info */
shi.combinedflag= 0xFFFFFF; /* ray trace does all options */
@@ -1622,6 +1623,7 @@ static void ray_trace_shadow_tra(Isect *is, ShadeInput *origshi, int depth, int
shi.xs= origshi->xs;
shi.ys= origshi->ys;
+ shi.do_manage= origshi->do_manage;
shi.lay= origshi->lay;
shi.nodes= origshi->nodes;
diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c
index 894ade42a1f..910ea16607e 100644
--- a/source/blender/render/intern/source/rendercore.c
+++ b/source/blender/render/intern/source/rendercore.c
@@ -1971,9 +1971,9 @@ void add_halo_flare(Render *re)
rect = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, re->viewname);
- if (rl==NULL || rect)
- return;
-
+ if (rect==NULL)
+ continue;
+
mode= R.r.mode;
R.r.mode &= ~R_PANORAMA;
diff --git a/source/blender/render/intern/source/renderdatabase.c b/source/blender/render/intern/source/renderdatabase.c
index d271592af5f..5f78c8a52db 100644
--- a/source/blender/render/intern/source/renderdatabase.c
+++ b/source/blender/render/intern/source/renderdatabase.c
@@ -1363,7 +1363,9 @@ void project_renderdata(Render *re,
/* ------------------------------------------------------------------------- */
-ObjectInstanceRen *RE_addRenderInstance(Render *re, ObjectRen *obr, Object *ob, Object *par, int index, int psysindex, float mat[4][4], int lay)
+ObjectInstanceRen *RE_addRenderInstance(
+ Render *re, ObjectRen *obr, Object *ob, Object *par,
+ int index, int psysindex, float mat[4][4], int lay, const DupliObject *dob)
{
ObjectInstanceRen *obi;
float mat3[3][3];
@@ -1377,33 +1379,30 @@ ObjectInstanceRen *RE_addRenderInstance(Render *re, ObjectRen *obr, Object *ob,
obi->lay= lay;
/* Fill particle info */
- if (obi->psysindex >= 0) {
- int psysindex = 0;
- int index;
- ParticleSystem *psys;
- if (obi->par) {
- for (psys = obi->par->particlesystem.first; psys; psys = psys->next) {
- if (psysindex == obi->psysindex)
- break;
- ++psysindex;
+ if (par && dob) {
+ const ParticleSystem *psys = dob->particle_system;
+ if (psys) {
+ int index;
+ if (obi->index < psys->totpart) {
+ index = obi->index;
}
- if (psys) {
- if (obi->index < psys->totpart)
- index = obi->index;
- else {
- index = psys->child[obi->index - psys->totpart].parent;
- }
- if (index >= 0) {
- ParticleData* p = &psys->particles[index];
- obi->part_index = index;
- obi->part_size = p->size;
- obi->part_age = RE_GetStats(re)->cfra - p->time;
- obi->part_lifetime = p->lifetime;
-
- copy_v3_v3(obi->part_co, p->state.co);
- copy_v3_v3(obi->part_vel, p->state.vel);
- copy_v3_v3(obi->part_avel, p->state.ave);
- }
+ else if (psys->child) {
+ index = psys->child[obi->index - psys->totpart].parent;
+ }
+ else {
+ index = -1;
+ }
+
+ if (index >= 0) {
+ const ParticleData *p = &psys->particles[index];
+ obi->part_index = index;
+ obi->part_size = p->size;
+ obi->part_age = RE_GetStats(re)->cfra - p->time;
+ obi->part_lifetime = p->lifetime;
+
+ copy_v3_v3(obi->part_co, p->state.co);
+ copy_v3_v3(obi->part_vel, p->state.vel);
+ copy_v3_v3(obi->part_avel, p->state.ave);
}
}
}
diff --git a/source/blender/render/intern/source/shadeoutput.c b/source/blender/render/intern/source/shadeoutput.c
index 39dfa48d3f1..91f9723897c 100644
--- a/source/blender/render/intern/source/shadeoutput.c
+++ b/source/blender/render/intern/source/shadeoutput.c
@@ -1815,7 +1815,7 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr)
shr->combined[1]= shi->g;
shr->combined[2]= shi->b;
shr->alpha= shi->alpha;
- return;
+ goto finally_shadeless;
}
if ( (ma->mode & (MA_VERTEXCOL|MA_VERTEXCOLP))== MA_VERTEXCOL ) { /* vertexcolor light */
@@ -2006,7 +2006,11 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr)
add_v3_v3(shr->combined, shr->emit);
if (shi->combinedflag & SCE_PASS_SPEC)
add_v3_v3(shr->combined, shr->spec);
-
+
+
+ /* Last section of this function applies to shadeless colors too */
+finally_shadeless:
+
/* modulate by the object color */
if ((ma->shade_flag & MA_OBCOLOR) && shi->obr->ob) {
if (!(ma->sss_flag & MA_DIFF_SSS) || !sss_pass_done(&R, ma)) {
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index 2164d457426..f0dbc4d4108 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -95,18 +95,19 @@ void WM_init_splash (struct bContext *C);
void WM_check (struct bContext *C);
-struct wmWindow *WM_window_open (struct bContext *C, const struct rcti *rect);
-
int WM_window_pixels_x (struct wmWindow *win);
int WM_window_pixels_y (struct wmWindow *win);
bool WM_window_is_fullscreen (struct wmWindow *win);
/* defines for 'type' WM_window_open_temp */
-#define WM_WINDOW_RENDER 0
-#define WM_WINDOW_USERPREFS 1
-// #define WM_WINDOW_FILESEL 2 // UNUSED
+enum {
+ WM_WINDOW_RENDER = 1,
+ WM_WINDOW_USERPREFS,
+ // WM_WINDOW_FILESEL // UNUSED
+};
-void WM_window_open_temp (struct bContext *C, struct rcti *position, int type);
+struct wmWindow *WM_window_open(struct bContext *C, const struct rcti *rect);
+struct wmWindow *WM_window_open_temp(struct bContext *C, const struct rcti *rect_init, int type);
/* returns true if draw method is triple buffer */
bool WM_is_draw_triple(struct wmWindow *win);
@@ -138,6 +139,7 @@ void WM_paint_cursor_end(struct wmWindowManager *wm, void *handle);
void WM_paint_cursor_tag_redraw(struct wmWindow *win, struct ARegion *ar);
void WM_cursor_warp (struct wmWindow *win, int x, int y);
+void WM_cursor_compatible_xy(wmWindow *win, int *x, int *y);
float WM_cursor_pressure (const struct wmWindow *win);
/* event map */
@@ -296,6 +298,7 @@ void WM_operator_properties_gesture_straightline(struct wmOperatorType *ot, int
void WM_operator_properties_select_all(struct wmOperatorType *ot);
void WM_operator_properties_select_action(struct wmOperatorType *ot, int default_action);
void WM_operator_properties_select_action_simple(struct wmOperatorType *ot, int default_action);
+void WM_operator_properties_select_random(struct wmOperatorType *ot);
bool WM_operator_check_ui_enabled(const struct bContext *C, const char *idname);
wmOperator *WM_operator_last_redo(const struct bContext *C);
diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c
index b43425ef6cb..fd46d9bd1d0 100644
--- a/source/blender/windowmanager/intern/wm.c
+++ b/source/blender/windowmanager/intern/wm.c
@@ -376,7 +376,7 @@ void WM_check(bContext *C)
}
/* case: no open windows at all, for old file reads */
- wm_window_add_ghostwindows(wm);
+ wm_window_ghostwindows_ensure(wm);
}
/* case: fileread */
@@ -467,11 +467,13 @@ void wm_close_and_free(bContext *C, wmWindowManager *wm)
void wm_close_and_free_all(bContext *C, ListBase *wmlist)
{
+ Main *bmain = CTX_data_main(C);
wmWindowManager *wm;
while ((wm = wmlist->first)) {
wm_close_and_free(C, wm);
BLI_remlink(wmlist, wm);
+ BKE_libblock_free_data(bmain, &wm->id);
MEM_freeN(wm);
}
}
diff --git a/source/blender/windowmanager/intern/wm_cursors.c b/source/blender/windowmanager/intern/wm_cursors.c
index d84b65847ca..d9466cbd035 100644
--- a/source/blender/windowmanager/intern/wm_cursors.c
+++ b/source/blender/windowmanager/intern/wm_cursors.c
@@ -199,14 +199,10 @@ void WM_cursor_grab_enable(wmWindow *win, bool wrap, bool hide, int bounds[4])
* It helps not to get a stuck WM when hitting a breakpoint
* */
GHOST_TGrabCursorMode mode = GHOST_kGrabNormal;
- float fac = GHOST_GetNativePixelSize(win->ghostwin);
- /* in case pixel coords differ from window/mouse coords */
if (bounds) {
- bounds[0] /= fac;
- bounds[1] /= fac;
- bounds[2] /= fac;
- bounds[3] /= fac;
+ wm_cursor_position_to_ghost(win, &bounds[0], &bounds[1]);
+ wm_cursor_position_to_ghost(win, &bounds[2], &bounds[3]);
}
if (hide) {
@@ -234,7 +230,15 @@ void WM_cursor_grab_disable(wmWindow *win, const int mouse_ungrab_xy[2])
{
if ((G.debug & G_DEBUG) == 0) {
if (win && win->ghostwin) {
- GHOST_SetCursorGrab(win->ghostwin, GHOST_kGrabDisable, NULL, mouse_ungrab_xy);
+ if (mouse_ungrab_xy) {
+ int mouse_xy[2] = {mouse_ungrab_xy[0], mouse_ungrab_xy[1]};
+ wm_cursor_position_to_ghost(win, &mouse_xy[0], &mouse_xy[1]);
+ GHOST_SetCursorGrab(win->ghostwin, GHOST_kGrabDisable, NULL, mouse_xy);
+ }
+ else {
+ GHOST_SetCursorGrab(win->ghostwin, GHOST_kGrabDisable, NULL, NULL);
+ }
+
win->grabcursor = GHOST_kGrabDisable;
}
}
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index 5a78dcf2361..2a9de6f5029 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -1801,7 +1801,13 @@ static int wm_handler_fileselect_do(bContext *C, ListBase *handlers, wmEventHand
const SpaceLink *sl = sa->spacedata.first;
const bool was_prev_temp = (sl->next && sl->next->spacetype == SPACE_IMAGE);
- ED_screen_full_prevspace(C, sa, was_prev_temp);
+ if (sa->full) {
+ ED_screen_full_prevspace(C, sa, was_prev_temp);
+ }
+ /* user may have left fullscreen */
+ else {
+ ED_area_prevspace(C, sa);
+ }
}
wm_handler_op_context(C, handler, CTX_wm_window(C)->eventstate);
diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c
index a4f69b24351..8288b2ed1ef 100644
--- a/source/blender/windowmanager/intern/wm_files.c
+++ b/source/blender/windowmanager/intern/wm_files.c
@@ -76,10 +76,12 @@
#include "BKE_context.h"
#include "BKE_depsgraph.h"
#include "BKE_global.h"
+#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_packedFile.h"
#include "BKE_report.h"
#include "BKE_sound.h"
+#include "BKE_scene.h"
#include "BKE_screen.h"
#include "BLO_readfile.h"
@@ -105,6 +107,9 @@
#include "GPU_draw.h"
+/* only to report a missing engine */
+#include "RE_engine.h"
+
#ifdef WITH_PYTHON
#include "BPY_extern.h"
#endif
@@ -334,11 +339,13 @@ static void wm_init_userdef(bContext *C, const bool from_memory)
#define BKE_READ_EXOTIC_FAIL_FORMAT -2 /* file format is not supported */
#define BKE_READ_EXOTIC_FAIL_OPEN -1 /* Can't open the file */
#define BKE_READ_EXOTIC_OK_BLEND 0 /* .blend file */
+#if 0
#define BKE_READ_EXOTIC_OK_OTHER 1 /* other supported formats */
+#endif
/* intended to check for non-blender formats but for now it only reads blends */
-static int wm_read_exotic(Scene *UNUSED(scene), const char *name)
+static int wm_read_exotic(const char *name)
{
int len;
gzFile gzfile;
@@ -400,6 +407,104 @@ void WM_file_autoexec_init(const char *filepath)
}
}
+void wm_file_read_report(bContext *C)
+{
+ ReportList *reports = NULL;
+ Scene *sce;
+
+ for (sce = G.main->scene.first; sce; sce = sce->id.next) {
+ if (sce->r.engine[0] &&
+ BLI_findstring(&R_engines, sce->r.engine, offsetof(RenderEngineType, idname)) == NULL)
+ {
+ if (reports == NULL) {
+ reports = CTX_wm_reports(C);
+ }
+
+ BKE_reportf(reports, RPT_ERROR,
+ "Engine '%s' not available for scene '%s' "
+ "(an addon may need to be installed or enabled)",
+ sce->r.engine, sce->id.name + 2);
+ }
+ }
+
+ if (reports) {
+ if (!G.background) {
+ WM_report_banner_show(C);
+ }
+ }
+}
+
+/**
+ * Logic shared between #WM_file_read & #wm_homefile_read,
+ * updates to make after reading a file.
+ */
+static void wm_file_read_post(bContext *C, bool is_startup_file)
+{
+ bool addons_loaded = false;
+ wmWindowManager *wm = CTX_wm_manager(C);
+
+ if (!G.background) {
+ /* remove windows which failed to be added via WM_check */
+ wm_window_ghostwindows_remove_invalid(C, wm);
+ }
+
+ CTX_wm_window_set(C, wm->windows.first);
+
+ ED_editors_init(C);
+ DAG_on_visible_update(CTX_data_main(C), true);
+
+#ifdef WITH_PYTHON
+ if (is_startup_file) {
+ /* possible python hasn't been initialized */
+ if (CTX_py_init_get(C)) {
+ /* sync addons, these may have changed from the defaults */
+ BPY_string_exec(C, "__import__('addon_utils').reset_all()");
+
+ BPY_python_reset(C);
+ addons_loaded = true;
+ }
+ }
+ else {
+ /* run any texts that were loaded in and flagged as modules */
+ BPY_python_reset(C);
+ addons_loaded = true;
+ }
+#endif /* WITH_PYTHON */
+
+ WM_operatortype_last_properties_clear_all();
+
+ /* important to do before NULL'ing the context */
+ BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_VERSION_UPDATE);
+ BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_POST);
+
+ /* would otherwise be handled by event loop */
+ if (G.background) {
+ Main *bmain = CTX_data_main(C);
+ BKE_scene_update_tagged(bmain->eval_ctx, bmain, CTX_data_scene(C));
+ }
+
+ WM_event_add_notifier(C, NC_WM | ND_FILEREAD, NULL);
+
+ /* report any errors.
+ * currently disabled if addons aren't yet loaded */
+ if (addons_loaded) {
+ wm_file_read_report(C);
+ }
+
+ if (!G.background) {
+ /* in background mode this makes it hard to load
+ * a blend file and do anything since the screen
+ * won't be set to a valid value again */
+ CTX_wm_window_set(C, NULL); /* exits queues */
+ }
+
+ if (!G.background) {
+// undo_editmode_clear();
+ BKE_undo_reset();
+ BKE_undo_write(C, "original"); /* save current state */
+ }
+}
+
bool WM_file_read(bContext *C, const char *filepath, ReportList *reports)
{
/* assume automated tasks with background, don't write recent file list */
@@ -419,7 +524,7 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports)
/* first try to append data from exotic file formats... */
/* it throws error box when file doesn't exist and returns -1 */
/* note; it should set some error message somewhere... (ton) */
- retval = wm_read_exotic(CTX_data_scene(C), filepath);
+ retval = wm_read_exotic(filepath);
/* we didn't succeed, now try to read Blender file */
if (retval == BKE_READ_EXOTIC_OK_BLEND) {
@@ -464,58 +569,14 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports)
}
}
-
- WM_event_add_notifier(C, NC_WM | ND_FILEREAD, NULL);
-// refresh_interface_font();
-
- CTX_wm_window_set(C, CTX_wm_manager(C)->windows.first);
-
- ED_editors_init(C);
- DAG_on_visible_update(CTX_data_main(C), true);
-
-#ifdef WITH_PYTHON
- /* run any texts that were loaded in and flagged as modules */
- BPY_python_reset(C);
-#endif
-
- WM_operatortype_last_properties_clear_all();
-
- /* important to do before NULL'ing the context */
- BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_VERSION_UPDATE);
- BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_POST);
-
- if (!G.background) {
- /* in background mode this makes it hard to load
- * a blend file and do anything since the screen
- * won't be set to a valid value again */
- CTX_wm_window_set(C, NULL); /* exits queues */
- }
-
-#if 0
- /* gives popups on windows but not linux, bug in report API
- * but disable for now to stop users getting annoyed */
- /* TODO, make this show in header info window */
- {
- Scene *sce;
- for (sce = G.main->scene.first; sce; sce = sce->id.next) {
- if (sce->r.engine[0] &&
- BLI_findstring(&R_engines, sce->r.engine, offsetof(RenderEngineType, idname)) == NULL)
- {
- BKE_reportf(reports, RPT_ERROR, "Engine '%s' not available for scene '%s' "
- "(an addon may need to be installed or enabled)",
- sce->r.engine, sce->id.name + 2);
- }
- }
- }
-#endif
-
- BKE_undo_reset();
- BKE_undo_write(C, "original"); /* save current state */
+ wm_file_read_post(C, false);
success = true;
}
+#if 0
else if (retval == BKE_READ_EXOTIC_OK_OTHER)
BKE_undo_write(C, "Import file");
+#endif
else if (retval == BKE_READ_EXOTIC_FAIL_OPEN) {
BKE_reportf(reports, RPT_ERROR, "Cannot read file '%s': %s", filepath,
errno ? strerror(errno) : TIP_("unable to open the file"));
@@ -672,36 +733,7 @@ int wm_homefile_read(bContext *C, ReportList *reports, bool from_memory, const c
G.save_over = 0; // start with save preference untitled.blend
G.fileflags &= ~G_FILE_AUTOPLAY; /* disable autoplay in startup.blend... */
-// refresh_interface_font();
-
-// undo_editmode_clear();
- BKE_undo_reset();
- BKE_undo_write(C, "original"); /* save current state */
-
- ED_editors_init(C);
- DAG_on_visible_update(CTX_data_main(C), true);
-
-#ifdef WITH_PYTHON
- if (CTX_py_init_get(C)) {
- /* sync addons, these may have changed from the defaults */
- BPY_string_exec(C, "__import__('addon_utils').reset_all()");
-
- BPY_python_reset(C);
- }
-#endif
-
- WM_operatortype_last_properties_clear_all();
-
- /* important to do before NULL'ing the context */
- BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_VERSION_UPDATE);
- BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_POST);
-
- WM_event_add_notifier(C, NC_WM | ND_FILEREAD, NULL);
-
- /* in background mode the scene will stay NULL */
- if (!G.background) {
- CTX_wm_window_set(C, NULL); /* exits queues */
- }
+ wm_file_read_post(C, true);
return true;
}
@@ -864,11 +896,11 @@ static void wm_history_file_update(void)
/* screen can be NULL */
-static ImBuf *blend_file_thumb(Scene *scene, bScreen *screen, int **thumb_pt)
+static ImBuf *blend_file_thumb(Scene *scene, bScreen *screen, BlendThumbnail **thumb_pt)
{
/* will be scaled down, but gives some nice oversampling */
ImBuf *ibuf;
- int *thumb;
+ BlendThumbnail *thumb;
char err_out[256] = "unknown";
/* screen if no camera found */
@@ -876,7 +908,11 @@ static ImBuf *blend_file_thumb(Scene *scene, bScreen *screen, int **thumb_pt)
ARegion *ar = NULL;
View3D *v3d = NULL;
- *thumb_pt = NULL;
+ /* In case we are given a valid thumbnail data, just generate image from it. */
+ if (*thumb_pt) {
+ thumb = *thumb_pt;
+ return BKE_main_thumbnail_to_imbuf(NULL, thumb);
+ }
/* scene can be NULL if running a script at startup and calling the save operator */
if (G.background || scene == NULL)
@@ -896,13 +932,18 @@ static ImBuf *blend_file_thumb(Scene *scene, bScreen *screen, int **thumb_pt)
/* gets scaled to BLEN_THUMB_SIZE */
if (scene->camera) {
- ibuf = ED_view3d_draw_offscreen_imbuf_simple(scene, scene->camera,
- BLEN_THUMB_SIZE * 2, BLEN_THUMB_SIZE * 2,
- IB_rect, OB_SOLID, false, false, false, R_ALPHAPREMUL, NULL, err_out);
+ ibuf = ED_view3d_draw_offscreen_imbuf_simple(
+ scene, scene->camera,
+ BLEN_THUMB_SIZE * 2, BLEN_THUMB_SIZE * 2,
+ IB_rect, OB_SOLID, false, false, false, R_ALPHAPREMUL, 0, NULL,
+ NULL, err_out);
}
else {
- ibuf = ED_view3d_draw_offscreen_imbuf(scene, v3d, ar, BLEN_THUMB_SIZE * 2, BLEN_THUMB_SIZE * 2,
- IB_rect, false, R_ALPHAPREMUL, NULL, err_out);
+ ibuf = ED_view3d_draw_offscreen_imbuf(
+ scene, v3d, ar,
+ BLEN_THUMB_SIZE * 2, BLEN_THUMB_SIZE * 2,
+ IB_rect, false, R_ALPHAPREMUL, 0, NULL,
+ NULL, err_out);
}
if (ibuf) {
@@ -914,13 +955,7 @@ static ImBuf *blend_file_thumb(Scene *scene, bScreen *screen, int **thumb_pt)
/* add pretty overlay */
IMB_thumb_overlay_blend(ibuf->rect, ibuf->x, ibuf->y, aspect);
- /* first write into thumb buffer */
- thumb = MEM_mallocN(((2 + (BLEN_THUMB_SIZE * BLEN_THUMB_SIZE))) * sizeof(int), "write_file thumb");
-
- thumb[0] = BLEN_THUMB_SIZE;
- thumb[1] = BLEN_THUMB_SIZE;
-
- memcpy(thumb + 2, ibuf->rect, BLEN_THUMB_SIZE * BLEN_THUMB_SIZE * sizeof(int));
+ thumb = BKE_main_thumbnail_from_imbuf(NULL, ibuf);
}
else {
/* '*thumb_pt' needs to stay NULL to prevent a bad thumbnail from being handled */
@@ -959,25 +994,26 @@ int wm_file_write(bContext *C, const char *filepath, int fileflags, ReportList *
{
Library *li;
int len;
- int *thumb = NULL;
+ int ret = -1;
+ BlendThumbnail *thumb, *main_thumb;
ImBuf *ibuf_thumb = NULL;
len = strlen(filepath);
if (len == 0) {
BKE_report(reports, RPT_ERROR, "Path is empty, cannot save");
- return -1;
+ return ret;
}
if (len >= FILE_MAX) {
BKE_report(reports, RPT_ERROR, "Path too long, cannot save");
- return -1;
+ return ret;
}
/* Check if file write permission is ok */
if (BLI_exists(filepath) && !BLI_file_is_writable(filepath)) {
BKE_reportf(reports, RPT_ERROR, "Cannot save blend file, path '%s' is not writable", filepath);
- return -1;
+ return ret;
}
/* note: used to replace the file extension (to ensure '.blend'),
@@ -988,18 +1024,21 @@ int wm_file_write(bContext *C, const char *filepath, int fileflags, ReportList *
for (li = G.main->library.first; li; li = li->id.next) {
if (BLI_path_cmp(li->filepath, filepath) == 0) {
BKE_reportf(reports, RPT_ERROR, "Cannot overwrite used library '%.240s'", filepath);
- return -1;
+ return ret;
}
}
+ /* Call pre-save callbacks befores writing preview, that way you can generate custom file thumbnail... */
+ BLI_callback_exec(G.main, NULL, BLI_CB_EVT_SAVE_PRE);
+
/* blend file thumbnail */
/* save before exit_editmode, otherwise derivedmeshes for shared data corrupt #27765) */
+ /* Main now can store a .blend thumbnail, usefull for background mode or thumbnail customization. */
+ main_thumb = thumb = CTX_data_main(C)->blen_thumb;
if ((U.flag & USER_SAVE_PREVIEWS) && BLI_thread_is_main()) {
ibuf_thumb = blend_file_thumb(CTX_data_scene(C), CTX_wm_screen(C), &thumb);
}
- BLI_callback_exec(G.main, NULL, BLI_CB_EVT_SAVE_PRE);
-
/* operator now handles overwrite checks */
if (G.fileflags & G_AUTOPACK) {
@@ -1044,22 +1083,21 @@ int wm_file_write(bContext *C, const char *filepath, int fileflags, ReportList *
if (ibuf_thumb) {
IMB_thumb_delete(filepath, THB_FAIL); /* without this a failed thumb overrides */
ibuf_thumb = IMB_thumb_create(filepath, THB_LARGE, THB_SOURCE_BLEND, ibuf_thumb);
- IMB_freeImBuf(ibuf_thumb);
}
- if (thumb) MEM_freeN(thumb);
+ ret = 0; /* Success. */
}
- else {
- if (ibuf_thumb) IMB_freeImBuf(ibuf_thumb);
- if (thumb) MEM_freeN(thumb);
-
- WM_cursor_wait(0);
- return -1;
+
+ if (ibuf_thumb) {
+ IMB_freeImBuf(ibuf_thumb);
+ }
+ if (thumb && thumb != main_thumb) {
+ MEM_freeN(thumb);
}
WM_cursor_wait(0);
-
- return 0;
+
+ return ret;
}
/**
diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c
index adf28cb7c8b..a60a2d28acb 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -159,7 +159,9 @@ void WM_init(bContext *C, int argc, const char **argv)
BKE_library_callback_free_editor_id_reference_set(WM_main_remove_editor_id_reference); /* library.c */
BKE_blender_callback_test_break_set(wm_window_testbreak); /* blender.c */
BKE_spacedata_callback_id_unref_set(ED_spacedata_id_unref); /* screen.c */
- DAG_editors_update_cb(ED_render_id_flush_update, ED_render_scene_update); /* depsgraph.c */
+ DAG_editors_update_cb(ED_render_id_flush_update,
+ ED_render_scene_update,
+ ED_render_scene_update_pre); /* depsgraph.c */
ED_spacetypes_init(); /* editors/space_api/spacetype.c */
@@ -174,6 +176,10 @@ void WM_init(bContext *C, int argc, const char **argv)
ED_spacedropwidgets_init();
+ /* reports cant be initialized before the wm,
+ * but keep before file reading, since that may report errors */
+ wm_init_reports(C);
+
/* get the default database, plus a wm */
wm_homefile_read(C, NULL, G.factory_startup, NULL);
@@ -191,6 +197,10 @@ void WM_init(bContext *C, int argc, const char **argv)
GPU_set_anisotropic(U.anisotropic_filter);
GPU_set_gpu_mipmapping(U.use_gpu_mipmap);
+#ifdef WITH_OPENSUBDIV
+ openSubdiv_init();
+#endif
+
UI_init();
}
else {
@@ -225,8 +235,6 @@ void WM_init(bContext *C, int argc, const char **argv)
if (!G.background && !wm_start_with_console)
GHOST_toggleConsole(3);
- wm_init_reports(C); /* reports cant be initialized before the wm */
-
clear_matcopybuf();
ED_render_clear_mtex_copybuf();
@@ -255,13 +263,24 @@ void WM_init(bContext *C, int argc, const char **argv)
/* that prevents loading both the kept session, and the file on the command line */
}
else {
+ /* note, logic here is from wm_file_read_post,
+ * call functions that depend on Python being initialized. */
+
/* normally 'wm_homefile_read' will do this,
* however python is not initialized when called from this function.
*
* unlikely any handlers are set but its possible,
* note that recovering the last session does its own callbacks. */
+ CTX_wm_window_set(C, CTX_wm_manager(C)->windows.first);
+
BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_VERSION_UPDATE);
BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_POST);
+
+ wm_file_read_report(C);
+
+ if (!G.background) {
+ CTX_wm_window_set(C, NULL);
+ }
}
}
@@ -500,9 +519,6 @@ void WM_exit_ext(bContext *C, const bool do_python)
ED_clipboard_posebuf_free();
BKE_node_clipboard_clear();
- /* widgetmaps after freeing blender, so no deleted data get accessed during cleaning up of areas */
- WM_widgetmaptypes_free();
-
BLF_exit();
#ifdef WITH_INTERNATIONAL
diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c
index e658396fb16..016583e69a5 100644
--- a/source/blender/windowmanager/intern/wm_keymap.c
+++ b/source/blender/windowmanager/intern/wm_keymap.c
@@ -586,8 +586,23 @@ static void wm_keymap_patch(wmKeyMap *km, wmKeyMap *diff_km)
/* Do not re-add an already existing keymap item! See T42088. */
/* We seek only for exact copy here! See T42137. */
kmi_add = wm_keymap_find_item_equals(km, kmdi->add_item);
+
+ /* If kmi_add is same as kmi_remove (can happen in some cases, typically when we got kmi_remove
+ * from wm_keymap_find_item_equals_result()), no need to add or remove anything, see T45579. */
+ /* Note: This typically happens when we apply user-defined keymap diff to a base one that was exported
+ * with that customized keymap already. In that case:
+ * - wm_keymap_find_item_equals(km, kmdi->remove_item) finds nothing (because actual shortcut of
+ * current base does not match kmdi->remove_item any more).
+ * - wm_keymap_find_item_equals_result(km, kmdi->remove_item) finds the current kmi from
+ * base keymap (because it does exactly the same thing).
+ * - wm_keymap_find_item_equals(km, kmdi->add_item) finds the same kmi, since base keymap was
+ * exported with that user-defined shortcut already!
+ * Maybe we should rather keep user-defined keymaps specific to a given base one? */
+ if (kmi_add != NULL && kmi_add == kmi_remove) {
+ kmi_remove = NULL;
+ }
/* only if nothing to remove or item to remove found */
- if (!kmi_add && (!kmdi->remove_item || kmi_remove)) {
+ else if (!kmi_add && (!kmdi->remove_item || kmi_remove)) {
kmi_add = wm_keymap_item_copy(kmdi->add_item);
kmi_add->flag |= KMI_USER_MODIFIED;
@@ -888,15 +903,21 @@ static void wm_user_modal_keymap_set_items(wmWindowManager *wm, wmKeyMap *km)
const char *WM_key_event_string(const short type, const bool compact)
{
- const char *name = NULL;
+ EnumPropertyItem *it;
+ const int i = RNA_enum_from_value(event_type_items, (int)type);
+
+ if (i == -1) {
+ return "";
+ }
+ it = &event_type_items[i];
+
/* We first try enum items' description (abused as shortname here), and fall back to usual name if empty. */
- if ((compact && RNA_enum_description(event_type_items, (int)type, &name) && name[0]) ||
- RNA_enum_name(event_type_items, (int)type, &name))
- {
- return IFACE_(name);
+ if (compact && it->description[0]) {
+ /* XXX No context for enum descriptions... In practice shall not be an issue though. */
+ return IFACE_(it->description);
}
- return "";
+ return CTX_IFACE_(BLT_I18NCONTEXT_UI_EVENTS, it->name);
}
/* TODO: also support (some) value, like e.g. double-click? */
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index 8d37e21da7e..0f0e6c9b771 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -59,10 +59,13 @@
#include "PIL_time.h"
#include "BLI_blenlib.h"
+#include "BLI_bitmap.h"
#include "BLI_dial.h"
#include "BLI_dynstr.h" /*for WM_operator_pystring */
+#include "BLI_linklist.h"
#include "BLI_linklist_stack.h"
#include "BLI_math.h"
+#include "BLI_memarena.h"
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
@@ -1212,10 +1215,10 @@ void WM_operator_properties_filesel(wmOperatorType *ot, int filter, short type,
PropertyRNA *prop;
static EnumPropertyItem file_display_items[] = {
- {FILE_DEFAULTDISPLAY, "FILE_DEFAULTDISPLAY", 0, "Default", "Automatically determine display type for files"},
- {FILE_SHORTDISPLAY, "FILE_SHORTDISPLAY", ICON_SHORTDISPLAY, "Short List", "Display files as short list"},
- {FILE_LONGDISPLAY, "FILE_LONGDISPLAY", ICON_LONGDISPLAY, "Long List", "Display files as a detailed list"},
- {FILE_IMGDISPLAY, "FILE_IMGDISPLAY", ICON_IMGDISPLAY, "Thumbnails", "Display files as thumbnails"},
+ {FILE_DEFAULTDISPLAY, "DEFAULT", 0, "Default", "Automatically determine display type for files"},
+ {FILE_SHORTDISPLAY, "LIST_SHORT", ICON_SHORTDISPLAY, "Short List", "Display files as short list"},
+ {FILE_LONGDISPLAY, "LIST_LONG", ICON_LONGDISPLAY, "Long List", "Display files as a detailed list"},
+ {FILE_IMGDISPLAY, "THUMBNAIL", ICON_IMGDISPLAY, "Thumbnails", "Display files as thumbnails"},
{0, NULL, 0, NULL, NULL}
};
@@ -1320,6 +1323,22 @@ void WM_operator_properties_select_action_simple(wmOperatorType *ot, int default
wm_operator_properties_select_action_ex(ot, default_action, select_actions);
}
+/**
+ * Use for all select random operators.
+ * Adds properties: percent, seed, action.
+ */
+void WM_operator_properties_select_random(wmOperatorType *ot)
+{
+ RNA_def_float_percentage(
+ ot->srna, "percent", 50.f, 0.0f, 100.0f,
+ "Percent", "Percentage of objects to select randomly", 0.f, 100.0f);
+ RNA_def_int(
+ ot->srna, "seed", 0, 0, INT_MAX,
+ "Random Seed", "Seed for the random number generator", 0, 255);
+
+ WM_operator_properties_select_action_simple(ot, SEL_SELECT);
+}
+
void WM_operator_properties_select_all(wmOperatorType *ot)
{
WM_operator_properties_select_action(ot, SEL_TOGGLE);
@@ -1539,6 +1558,8 @@ static uiBlock *wm_block_create_redo(bContext *C, ARegion *ar, void *arg_op)
if (op->type->flag & OPTYPE_MACRO) {
for (op = op->macro.first; op; op = op->next) {
uiLayoutOperatorButs(C, layout, op, NULL, 'H', UI_LAYOUT_OP_SHOW_TITLE);
+ if (op->next)
+ uiItemS(layout);
}
}
else {
@@ -2226,6 +2247,17 @@ static int wm_operator_winactive_normal(bContext *C)
return 1;
}
+/* included for script-access */
+static void WM_OT_window_close(wmOperatorType *ot)
+{
+ ot->name = "Close Window";
+ ot->idname = "WM_OT_window_close";
+ ot->description = "Close the current Blender window";
+
+ ot->exec = wm_window_close_exec;
+ ot->poll = WM_operator_winactive;
+}
+
static void WM_OT_window_duplicate(wmOperatorType *ot)
{
ot->name = "Duplicate Window";
@@ -2588,106 +2620,150 @@ static int wm_link_append_invoke(bContext *C, wmOperator *op, const wmEvent *UNU
static short wm_link_append_flag(wmOperator *op)
{
+ PropertyRNA *prop;
short flag = 0;
- if (RNA_boolean_get(op->ptr, "autoselect")) flag |= FILE_AUTOSELECT;
- if (RNA_boolean_get(op->ptr, "active_layer")) flag |= FILE_ACTIVELAY;
- if (RNA_struct_find_property(op->ptr, "relative_path") && RNA_boolean_get(op->ptr, "relative_path")) flag |= FILE_RELPATH;
- if (RNA_boolean_get(op->ptr, "link")) flag |= FILE_LINK;
- if (RNA_boolean_get(op->ptr, "instance_groups")) flag |= FILE_GROUP_INSTANCE;
+ if (RNA_boolean_get(op->ptr, "autoselect"))
+ flag |= FILE_AUTOSELECT;
+ if (RNA_boolean_get(op->ptr, "active_layer"))
+ flag |= FILE_ACTIVELAY;
+ if ((prop = RNA_struct_find_property(op->ptr, "relative_path")) && RNA_property_boolean_get(op->ptr, prop))
+ flag |= FILE_RELPATH;
+ if (RNA_boolean_get(op->ptr, "link"))
+ flag |= FILE_LINK;
+ if (RNA_boolean_get(op->ptr, "instance_groups"))
+ flag |= FILE_GROUP_INSTANCE;
return flag;
}
-/* Helper.
- * if `name` is non-NULL, we assume a single-item link/append.
- * else if `*todo_libraries` is NULL we assume first-run.
- */
-static void wm_link_append_do_libgroup(
- bContext *C, wmOperator *op, const char *root, const char *libname, char *group, char *name,
- const short flag, GSet **todo_libraries)
+typedef struct WMLinkAppendDataItem {
+ char *name;
+ BLI_bitmap *libraries; /* All libs (from WMLinkAppendData.libraries) to try to load this ID from. */
+ short idcode;
+
+ ID *new_id;
+ void *customdata;
+} WMLinkAppendDataItem;
+
+typedef struct WMLinkAppendData {
+ LinkNodePair libraries;
+ LinkNodePair items;
+ int num_libraries;
+ int num_items;
+ short flag;
+
+ /* Internal 'private' data */
+ MemArena *memarena;
+} WMLinkAppendData;
+
+static WMLinkAppendData *wm_link_append_data_new(const int flag)
{
- Main *bmain = CTX_data_main(C);
- Main *mainl;
- BlendHandle *bh;
- Library *lib;
+ MemArena *ma = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
+ WMLinkAppendData *lapp_data = BLI_memarena_calloc(ma, sizeof(*lapp_data));
- char path[FILE_MAX_LIBEXTRA], relname[FILE_MAX];
- int idcode;
- const bool is_first_run = (*todo_libraries == NULL);
+ lapp_data->flag = flag;
+ lapp_data->memarena = ma;
- BLI_assert(group);
- idcode = BKE_idcode_from_name(group);
+ return lapp_data;
+}
- bh = BLO_blendhandle_from_file(libname, op->reports);
+static void wm_link_append_data_free(WMLinkAppendData *lapp_data)
+{
+ BLI_memarena_free(lapp_data->memarena);
+}
- if (bh == NULL) {
- /* unlikely since we just browsed it, but possible
- * error reports will have been made by BLO_blendhandle_from_file() */
- return;
- }
+/* WARNING! *Never* call wm_link_append_data_library_add() after having added some items! */
+
+static void wm_link_append_data_library_add(WMLinkAppendData *lapp_data, const char *libname)
+{
+ size_t len = strlen(libname) + 1;
+ char *libpath = BLI_memarena_alloc(lapp_data->memarena, len);
- /* here appending/linking starts */
- mainl = BLO_library_append_begin(bmain, &bh, libname);
- lib = mainl->curlib;
- BLI_assert(lib);
+ BLI_strncpy(libpath, libname, len);
+ BLI_linklist_append_arena(&lapp_data->libraries, libpath, lapp_data->memarena);
+ lapp_data->num_libraries++;
+}
- if (mainl->versionfile < 250) {
- BKE_reportf(op->reports, RPT_WARNING,
- "Linking or appending from a very old .blend file format (%d.%d), no animation conversion will "
- "be done! You may want to re-save your lib file with current Blender",
- mainl->versionfile, mainl->subversionfile);
- }
+static WMLinkAppendDataItem *wm_link_append_data_item_add(
+ WMLinkAppendData *lapp_data, const char *idname, const short idcode, void *customdata)
+{
+ WMLinkAppendDataItem *item = BLI_memarena_alloc(lapp_data->memarena, sizeof(*item));
+ size_t len = strlen(idname) + 1;
- if (name) {
- BLO_library_append_named_part_ex(C, mainl, &bh, name, idcode, flag);
- }
- else {
- if (is_first_run) {
- *todo_libraries = BLI_gset_new(BLI_ghashutil_strhash_p, BLI_ghashutil_strcmp, __func__);
- }
+ item->name = BLI_memarena_alloc(lapp_data->memarena, len);
+ BLI_strncpy(item->name, idname, len);
+ item->idcode = idcode;
+ item->libraries = BLI_BITMAP_NEW_MEMARENA(lapp_data->memarena, lapp_data->num_libraries);
- RNA_BEGIN (op->ptr, itemptr, "files")
- {
- char curr_libname[FILE_MAX];
- int curr_idcode;
+ item->new_id = NULL;
+ item->customdata = customdata;
- RNA_string_get(&itemptr, "name", relname);
+ BLI_linklist_append_arena(&lapp_data->items, item, lapp_data->memarena);
+ lapp_data->num_items++;
- BLI_join_dirfile(path, sizeof(path), root, relname);
+ return item;
+}
- if (BLO_library_path_explode(path, curr_libname, &group, &name)) {
- if (!group || !name) {
- continue;
- }
+static void wm_link_do(
+ WMLinkAppendData *lapp_data, ReportList *reports, Main *bmain, Scene *scene, View3D *v3d)
+{
+ Main *mainl;
+ BlendHandle *bh;
+ Library *lib;
- curr_idcode = BKE_idcode_from_name(group);
+ const int flag = lapp_data->flag;
- if ((idcode == curr_idcode) && (BLI_path_cmp(curr_libname, libname) == 0)) {
- BLO_library_append_named_part_ex(C, mainl, &bh, name, idcode, flag);
- }
- else if (is_first_run) {
- BLI_join_dirfile(path, sizeof(path), curr_libname, group);
- if (!BLI_gset_haskey(*todo_libraries, path)) {
- BLI_gset_insert(*todo_libraries, BLI_strdup(path));
- }
- }
- }
+ LinkNode *liblink, *itemlink;
+ int lib_idx, item_idx;
+
+ BLI_assert(lapp_data->num_items && lapp_data->num_libraries);
+
+ for (lib_idx = 0, liblink = lapp_data->libraries.list; liblink; lib_idx++, liblink = liblink->next) {
+ char *libname = liblink->link;
+
+ bh = BLO_blendhandle_from_file(libname, reports);
+
+ if (bh == NULL) {
+ /* Unlikely since we just browsed it, but possible
+ * Error reports will have been made by BLO_blendhandle_from_file() */
+ continue;
}
- RNA_END;
- }
- BLO_library_append_end(C, mainl, &bh, idcode, flag);
- BLO_blendhandle_close(bh);
+ /* here appending/linking starts */
+ mainl = BLO_library_link_begin(bmain, &bh, libname);
+ lib = mainl->curlib;
+ BLI_assert(lib);
+ UNUSED_VARS_NDEBUG(lib);
+
+ if (mainl->versionfile < 250) {
+ BKE_reportf(reports, RPT_WARNING,
+ "Linking or appending from a very old .blend file format (%d.%d), no animation conversion will "
+ "be done! You may want to re-save your lib file with current Blender",
+ mainl->versionfile, mainl->subversionfile);
+ }
- /* mark all library linked objects to be updated */
- BKE_main_lib_objects_recalc_all(bmain);
- IMB_colormanagement_check_file_config(bmain);
+ /* For each lib file, we try to link all items belonging to that lib,
+ * and tag those successful to not try to load them again with the other libs. */
+ for (item_idx = 0, itemlink = lapp_data->items.list; itemlink; item_idx++, itemlink = itemlink->next) {
+ WMLinkAppendDataItem *item = itemlink->link;
+ ID *new_id;
- /* append, rather than linking */
- if ((flag & FILE_LINK) == 0) {
- BLI_assert(BLI_findindex(&bmain->library, lib) != -1);
- BKE_library_make_local(bmain, lib, true);
+ if (!BLI_BITMAP_TEST(item->libraries, lib_idx)) {
+ continue;
+ }
+
+ new_id = BLO_library_link_named_part_ex(mainl, &bh, item->idcode, item->name, flag, scene, v3d);
+ if (new_id) {
+ /* If the link is sucessful, clear item's libs 'todo' flags.
+ * This avoids trying to link same item with other libraries to come. */
+ BLI_BITMAP_SET_ALL(item->libraries, false, lapp_data->num_libraries);
+ item->new_id = new_id;
+ }
+ }
+
+ BLO_library_link_end(mainl, &bh, flag, scene, v3d);
+ BLO_blendhandle_close(bh);
}
}
@@ -2696,13 +2772,12 @@ static int wm_link_append_exec(bContext *C, wmOperator *op)
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
PropertyRNA *prop;
+ WMLinkAppendData *lapp_data;
char path[FILE_MAX_LIBEXTRA], root[FILE_MAXDIR], libname[FILE_MAX], relname[FILE_MAX];
char *group, *name;
int totfiles = 0;
short flag;
- GSet *todo_libraries = NULL;
-
RNA_string_get(op->ptr, "filename", relname);
RNA_string_get(op->ptr, "directory", root);
@@ -2710,15 +2785,15 @@ static int wm_link_append_exec(bContext *C, wmOperator *op)
/* test if we have a valid data */
if (!BLO_library_path_explode(path, libname, &group, &name)) {
- BKE_report(op->reports, RPT_ERROR, "Not a library");
+ BKE_reportf(op->reports, RPT_ERROR, "'%s': not a library", path);
return OPERATOR_CANCELLED;
}
else if (!group) {
- BKE_report(op->reports, RPT_ERROR, "Nothing indicated");
+ BKE_reportf(op->reports, RPT_ERROR, "'%s': nothing indicated", path);
return OPERATOR_CANCELLED;
}
else if (BLI_path_cmp(bmain->name, libname) == 0) {
- BKE_report(op->reports, RPT_ERROR, "Cannot use current file as library");
+ BKE_reportf(op->reports, RPT_ERROR, "'%s': cannot use current file as library", path);
return OPERATOR_CANCELLED;
}
@@ -2728,55 +2803,112 @@ static int wm_link_append_exec(bContext *C, wmOperator *op)
totfiles = RNA_property_collection_length(op->ptr, prop);
if (totfiles == 0) {
if (!name) {
- BKE_report(op->reports, RPT_ERROR, "Nothing indicated");
+ BKE_reportf(op->reports, RPT_ERROR, "'%s': nothing indicated", path);
return OPERATOR_CANCELLED;
}
}
}
else if (!name) {
- BKE_report(op->reports, RPT_ERROR, "Nothing indicated");
+ BKE_reportf(op->reports, RPT_ERROR, "'%s': nothing indicated", path);
return OPERATOR_CANCELLED;
}
flag = wm_link_append_flag(op);
/* sanity checks for flag */
- if (scene->id.lib && (flag & FILE_GROUP_INSTANCE)) {
- /* TODO, user never gets this message */
- BKE_reportf(op->reports, RPT_WARNING, "Scene '%s' is linked, group instance disabled", scene->id.name + 2);
+ if (scene && scene->id.lib) {
+ BKE_reportf(op->reports, RPT_WARNING,
+ "Scene '%s' is linked, instantiation of objects & groups is disabled", scene->id.name + 2);
flag &= ~FILE_GROUP_INSTANCE;
+ scene = NULL;
}
/* from here down, no error returns */
- /* now we have or selected, or an indicated file */
- if (RNA_boolean_get(op->ptr, "autoselect"))
+ if (scene && RNA_boolean_get(op->ptr, "autoselect")) {
BKE_scene_base_deselect_all(scene);
+ }
/* tag everything, all untagged data can be made local
* its also generally useful to know what is new
*
- * take extra care BKE_main_id_flag_all(LIB_LINK_TAG, false) is called after! */
- BKE_main_id_flag_all(bmain, LIB_PRE_EXISTING, 1);
+ * take extra care BKE_main_id_flag_all(bmain, LIB_PRE_EXISTING, false) is called after! */
+ BKE_main_id_flag_all(bmain, LIB_PRE_EXISTING, true);
+ /* We define our working data...
+ * Note that here, each item 'uses' one library, and only one. */
+ lapp_data = wm_link_append_data_new(flag);
if (totfiles != 0) {
- name = NULL;
- }
+ GHash *libraries = BLI_ghash_new(BLI_ghashutil_strhash_p, BLI_ghashutil_strcmp, __func__);
+ int lib_idx = 0;
+
+ RNA_BEGIN (op->ptr, itemptr, "files")
+ {
+ RNA_string_get(&itemptr, "name", relname);
+
+ BLI_join_dirfile(path, sizeof(path), root, relname);
+
+ if (BLO_library_path_explode(path, libname, &group, &name)) {
+ if (!group || !name) {
+ continue;
+ }
- wm_link_append_do_libgroup(C, op, root, libname, group, name, flag, &todo_libraries);
+ if (!BLI_ghash_haskey(libraries, libname)) {
+ BLI_ghash_insert(libraries, BLI_strdup(libname), SET_INT_IN_POINTER(lib_idx));
+ lib_idx++;
+ wm_link_append_data_library_add(lapp_data, libname);
+ }
+ }
+ }
+ RNA_END;
- if (todo_libraries) {
- GSetIterator libs_it;
+ RNA_BEGIN (op->ptr, itemptr, "files")
+ {
+ RNA_string_get(&itemptr, "name", relname);
- GSET_ITER(libs_it, todo_libraries) {
- char *libpath = (char *)BLI_gsetIterator_getKey(&libs_it);
+ BLI_join_dirfile(path, sizeof(path), root, relname);
- BLO_library_path_explode(libpath, libname, &group, NULL);
+ if (BLO_library_path_explode(path, libname, &group, &name)) {
+ WMLinkAppendDataItem *item;
+ if (!group || !name) {
+ printf("skipping %s\n", path);
+ continue;
+ }
+
+ lib_idx = GET_INT_FROM_POINTER(BLI_ghash_lookup(libraries, libname));
- wm_link_append_do_libgroup(C, op, root, libname, group, NULL, flag, &todo_libraries);
+ item = wm_link_append_data_item_add(lapp_data, name, BKE_idcode_from_name(group), NULL);
+ BLI_BITMAP_ENABLE(item->libraries, lib_idx);
+ }
}
+ RNA_END;
- BLI_gset_free(todo_libraries, MEM_freeN);
+ BLI_ghash_free(libraries, MEM_freeN, NULL);
+ }
+ else {
+ WMLinkAppendDataItem *item;
+
+ wm_link_append_data_library_add(lapp_data, libname);
+ item = wm_link_append_data_item_add(lapp_data, name, BKE_idcode_from_name(group), NULL);
+ BLI_BITMAP_ENABLE(item->libraries, 0);
+ }
+
+ /* XXX We'd need re-entrant locking on Main for this to work... */
+ /* BKE_main_lock(bmain); */
+
+ wm_link_do(lapp_data, op->reports, bmain, scene, CTX_wm_view3d(C));
+
+ /* BKE_main_unlock(bmain); */
+
+ wm_link_append_data_free(lapp_data);
+
+ /* mark all library linked objects to be updated */
+ BKE_main_lib_objects_recalc_all(bmain);
+ IMB_colormanagement_check_file_config(bmain);
+
+ /* append, rather than linking */
+ if ((flag & FILE_LINK) == 0) {
+ BKE_library_make_local(bmain, NULL, true);
}
/* important we unset, otherwise these object wont
@@ -4448,7 +4580,7 @@ static void radial_control_cancel(bContext *C, wmOperator *op)
static int radial_control_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
RadialControl *rc = op->customdata;
- float new_value, dist, zoom[2];
+ float new_value, dist = 0.0f, zoom[2];
float delta[2], ret = OPERATOR_RUNNING_MODAL;
bool snap;
float angle_precision = 0.0f;
@@ -5004,7 +5136,7 @@ static void WM_OT_previews_ensure(wmOperatorType *ot)
static EnumPropertyItem preview_id_type_items[] = {
{FILTER_ID_SCE, "SCENE", 0, "Scenes", ""},
{FILTER_ID_GR, "GROUP", 0, "Groups", ""},
- {FILTER_ID_OB, "OBJECT", 0, "Objects", ""},
+ {FILTER_ID_OB, "OBJECT", 0, "Objects", ""},
{FILTER_ID_MA, "MATERIAL", 0, "Materials", ""},
{FILTER_ID_LA, "LAMP", 0, "Lamps", ""},
{FILTER_ID_WO, "WORLD", 0, "Worlds", ""},
@@ -5159,6 +5291,7 @@ void wm_operatortype_init(void)
/* reserve size is set based on blender default setup */
global_ops_hash = BLI_ghash_str_new_ex("wm_operatortype_init gh", 2048);
+ WM_operatortype_append(WM_OT_window_close);
WM_operatortype_append(WM_OT_window_duplicate);
WM_operatortype_append(WM_OT_read_history);
WM_operatortype_append(WM_OT_read_homefile);
diff --git a/source/blender/windowmanager/intern/wm_playanim.c b/source/blender/windowmanager/intern/wm_playanim.c
index e63b4661870..2150d94d9b0 100644
--- a/source/blender/windowmanager/intern/wm_playanim.c
+++ b/source/blender/windowmanager/intern/wm_playanim.c
@@ -77,10 +77,10 @@
# include AUD_SOUND_H
# include AUD_SPECIAL_H
-AUD_Sound *source = NULL;
-AUD_Handle *playback_handle = NULL;
-AUD_Handle *scrub_handle = NULL;
-AUD_Device *audio_device = NULL;
+static AUD_Sound *source = NULL;
+static AUD_Handle *playback_handle = NULL;
+static AUD_Handle *scrub_handle = NULL;
+static AUD_Device *audio_device = NULL;
#endif
/* simple limiter to avoid flooding memory */
@@ -383,7 +383,6 @@ static void build_pict_list_ex(PlayState *ps, const char *first, int totframes,
// short val;
PlayAnimPict *picture = NULL;
struct ImBuf *ibuf = NULL;
- char str[32 + FILE_MAX];
struct anim *anim;
if (IMB_isanim(first)) {
@@ -402,8 +401,7 @@ static void build_pict_list_ex(PlayState *ps, const char *first, int totframes,
picture->anim = anim;
picture->frame = pic;
picture->IB_flags = IB_rect;
- BLI_snprintf(str, sizeof(str), "%s : %4.d", first, pic + 1);
- picture->name = strdup(str);
+ picture->name = BLI_sprintfN("%s : %4.d", first, pic + 1);
BLI_addtail(&picsbase, picture);
}
}
@@ -414,7 +412,14 @@ static void build_pict_list_ex(PlayState *ps, const char *first, int totframes,
else {
int count = 0;
+ int fp_framenr;
+ struct {
+ char head[FILE_MAX], tail[FILE_MAX];
+ unsigned short digits;
+ } fp_decoded;
+
BLI_strncpy(filepath, first, sizeof(filepath));
+ fp_framenr = BLI_stringdec(filepath, fp_decoded.head, fp_decoded.tail, &fp_decoded.digits);
pupdate_time();
ptottime = 1.0;
@@ -480,8 +485,8 @@ static void build_pict_list_ex(PlayState *ps, const char *first, int totframes,
}
picture->mem = mem;
- picture->name = strdup(filepath);
- picture->frame = count; /* not exact but should work for positioning */
+ picture->name = BLI_strdup(filepath);
+ picture->frame = count;
close(file);
BLI_addtail(&picsbase, picture);
count++;
@@ -505,7 +510,9 @@ static void build_pict_list_ex(PlayState *ps, const char *first, int totframes,
ptottime = 0.0;
}
- BLI_newname(filepath, +fstep);
+ /* create a new filepath each time */
+ fp_framenr += fstep;
+ BLI_stringenc(filepath, fp_decoded.head, fp_decoded.tail, fp_decoded.digits, fp_framenr);
while ((hasevent = GHOST_ProcessEvents(g_WS.ghost_system, 0))) {
if (hasevent) {
@@ -544,17 +551,16 @@ static void update_sound_fps(void)
static void change_frame(PlayState *ps, int cx)
{
int sizex, sizey;
- int i;
+ int i, i_last;
- playanim_window_get_size(&sizex, &sizey);
- ps->picture = picsbase.first;
- /* TODO - store in ps direct? */
- i = 0;
- while (ps->picture) {
- i++;
- ps->picture = ps->picture->next;
+ if (BLI_listbase_is_empty(&picsbase)) {
+ return;
}
- i = (i * cx) / sizex;
+
+ playanim_window_get_size(&sizex, &sizey);
+ i_last = ((struct PlayAnimPict *)picsbase.last)->frame;
+ i = (i_last * cx) / sizex;
+ CLAMP(i, 0, i_last);
#ifdef WITH_AUDASPACE
if (scrub_handle) {
@@ -588,11 +594,8 @@ static void change_frame(PlayState *ps, int cx)
}
#endif
- ps->picture = picsbase.first;
- for (; i > 0; i--) {
- if (ps->picture->next == NULL) break;
- ps->picture = ps->picture->next;
- }
+ ps->picture = BLI_findlink(&picsbase, i);
+ BLI_assert(ps->picture != NULL);
ps->sstep = true;
ps->wait2 = false;
@@ -977,6 +980,19 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void)
GHOST_TEventCursorData *cd = GHOST_GetEventData(evt);
int cx, cy;
+ /* Ignore 'in-between' events, since they can make scrubbing lag.
+ *
+ * Ideally we would keep into the event queue and see if this is the last motion event.
+ * however the API currently doesn't support this. */
+ {
+ int x_test, y_test;
+ GHOST_GetCursorPosition(g_WS.ghost_system, &x_test, &y_test);
+ if (x_test != cd->x || y_test != cd->y) {
+ /* we're not the last event... skipping */
+ break;
+ }
+ }
+
GHOST_ScreenToClient(g_WS.ghost_window, cd->x, cd->y, &cx, &cy);
change_frame(ps, cx);
@@ -1093,7 +1109,6 @@ static char *wm_main_playanim_intern(int argc, const char **argv)
GHOST_TUns32 maxwinx, maxwiny;
int i;
/* This was done to disambiguate the name for use under c++. */
- struct anim *anim = NULL;
int start_x = 0, start_y = 0;
int sfra = -1;
int efra = -1;
@@ -1101,20 +1116,6 @@ static char *wm_main_playanim_intern(int argc, const char **argv)
PlayState ps = {0};
-#ifdef WITH_AUDASPACE
- AUD_DeviceSpecs specs;
-
- specs.rate = AUD_RATE_44100;
- specs.format = AUD_FORMAT_S16;
- specs.channels = AUD_CHANNELS_STEREO;
-
- AUD_initOnce();
-
- if (!(audio_device = AUD_init("OpenAL", specs, 1024, "Blender")))
- audio_device = AUD_init("Null", specs, 0, "Blender");
-
-#endif
-
/* ps.doubleb = true;*/ /* UNUSED */
ps.go = true;
ps.direction = true;
@@ -1208,12 +1209,13 @@ static char *wm_main_playanim_intern(int argc, const char **argv)
BLI_strncpy(filepath, argv[1], sizeof(filepath));
}
else {
- BLI_current_working_dir(filepath, sizeof(filepath));
- BLI_add_slash(filepath);
+ printf("%s: no filepath argument given\n", __func__);
+ exit(1);
}
if (IMB_isanim(filepath)) {
/* OCIO_TODO: support different input color spaces */
+ struct anim *anim;
anim = IMB_open_anim(filepath, IB_rect, 0, NULL);
if (anim) {
ibuf = IMB_anim_absolute(anim, 0, IMB_TC_NONE, IMB_PROXY_NONE);
@@ -1485,13 +1487,13 @@ static char *wm_main_playanim_intern(int argc, const char **argv)
}
}
}
- ps.picture = picsbase.first;
- anim = NULL;
- while (ps.picture) {
- if (ps.picture && ps.picture->anim && (anim != ps.picture->anim)) {
- // to prevent divx crashes
- anim = ps.picture->anim;
- IMB_close_anim(anim);
+ while ((ps.picture = BLI_pophead(&picsbase))) {
+ if (ps.picture->anim) {
+ if ((ps.picture->next == NULL) ||
+ (ps.picture->next->anim != ps.picture->anim))
+ {
+ IMB_close_anim(ps.picture->anim);
+ }
}
if (ps.picture->ibuf) {
@@ -1501,7 +1503,8 @@ static char *wm_main_playanim_intern(int argc, const char **argv)
MEM_freeN(ps.picture->mem);
}
- ps.picture = ps.picture->next;
+ MEM_freeN((void *)ps.picture->name);
+ MEM_freeN(ps.picture);
}
/* cleanup */
@@ -1514,12 +1517,16 @@ static char *wm_main_playanim_intern(int argc, const char **argv)
added_images = 0;
#ifdef WITH_AUDASPACE
- if (playback_handle)
+ if (playback_handle) {
AUD_Handle_stop(playback_handle);
- if (scrub_handle)
+ playback_handle = NULL;
+ }
+ if (scrub_handle) {
AUD_Handle_stop(scrub_handle);
+ scrub_handle = NULL;
+ }
AUD_Sound_free(source);
- AUD_exit(audio_device);
+ source = NULL;
#endif
#if 0 // XXX25
@@ -1557,18 +1564,43 @@ static char *wm_main_playanim_intern(int argc, const char **argv)
void WM_main_playanim(int argc, const char **argv)
{
+ const char *argv_next[2];
bool looping = true;
+#ifdef WITH_AUDASPACE
+ {
+ AUD_DeviceSpecs specs;
+
+ specs.rate = AUD_RATE_44100;
+ specs.format = AUD_FORMAT_S16;
+ specs.channels = AUD_CHANNELS_STEREO;
+
+ AUD_initOnce();
+
+ if (!(audio_device = AUD_init("OpenAL", specs, 1024, "Blender"))) {
+ audio_device = AUD_init("Null", specs, 0, "Blender");
+ }
+ }
+#endif
+
while (looping) {
const char *filepath = wm_main_playanim_intern(argc, argv);
if (filepath) { /* use simple args */
- argv[1] = "-a";
- argv[2] = filepath;
- argc = 3;
+ argv_next[0] = argv[0];
+ argv_next[1] = filepath;
+ argc = 2;
+
+ /* continue with new args */
+ argv = argv_next;
}
else {
looping = false;
}
}
+
+#ifdef WITH_AUDASPACE
+ AUD_exit(audio_device);
+ AUD_exitOnce();
+#endif
}
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c
index af7e9c8ca33..d8e6671afda 100644
--- a/source/blender/windowmanager/intern/wm_window.c
+++ b/source/blender/windowmanager/intern/wm_window.c
@@ -329,12 +329,17 @@ void wm_window_close(bContext *C, wmWindowManager *wm, wmWindow *win)
CTX_wm_window_set(C, win); /* needed by handlers */
WM_event_remove_handlers(C, &win->handlers);
WM_event_remove_handlers(C, &win->modalhandlers);
- ED_screen_exit(C, win, win->screen);
+
+ /* for regular use this will _never_ be NULL,
+ * however we may be freeing an improperly initialized window. */
+ if (win->screen) {
+ ED_screen_exit(C, win, win->screen);
+ }
wm_window_free(C, wm, win);
/* if temp screen, delete it after window free (it stops jobs that can access it) */
- if (screen->temp) {
+ if (screen && screen->temp) {
Main *bmain = CTX_data_main(C);
BKE_libblock_free(bmain, screen);
}
@@ -380,7 +385,7 @@ float wm_window_pixelsize(wmWindow *win)
}
/* belongs to below */
-static void wm_window_add_ghostwindow(wmWindowManager *wm, const char *title, wmWindow *win)
+static void wm_window_ghostwindow_add(wmWindowManager *wm, const char *title, wmWindow *win)
{
GHOST_WindowHandle ghostwin;
GHOST_GLSettings glSettings = {0};
@@ -466,14 +471,26 @@ static void wm_window_add_ghostwindow(wmWindowManager *wm, const char *title, wm
}
}
-/* for wmWindows without ghostwin, open these and clear */
-/* window size is read from window, if 0 it uses prefsize */
-/* called in WM_check, also inits stuff after file read */
-void wm_window_add_ghostwindows(wmWindowManager *wm)
+/**
+ * Initialize #wmWindows without ghostwin, open these and clear.
+ *
+ * window size is read from window, if 0 it uses prefsize
+ * called in #WM_check, also inits stuff after file read.
+ *
+ * \warning
+ * After running, 'win->ghostwin' can be NULL in rare cases
+ * (where OpenGL driver fails to create a context for eg).
+ * We could remove them with #wm_window_ghostwindows_remove_invalid
+ * but better not since caller may continue to use.
+ * Instead, caller needs to handle the error case and cleanup.
+ */
+void wm_window_ghostwindows_ensure(wmWindowManager *wm)
{
wmKeyMap *keymap;
wmWindow *win;
+ BLI_assert(G.background == false);
+
/* no commandline prefsize? then we set this.
* Note that these values will be used only
* when there is no startup.blend yet.
@@ -521,7 +538,7 @@ void wm_window_add_ghostwindows(wmWindowManager *wm)
win->cursor = CURSOR_STD;
}
- wm_window_add_ghostwindow(wm, "Blender", win);
+ wm_window_ghostwindow_add(wm, "Blender", win);
}
/* happens after fileread */
if (win->eventstate == NULL)
@@ -546,11 +563,33 @@ void wm_window_add_ghostwindows(wmWindowManager *wm)
}
}
-/* new window, no screen yet, but we open ghostwindow for it */
-/* also gets the window level handlers */
-/* area-rip calls this */
+/**
+ * Call after #wm_window_ghostwindows_ensure or #WM_check
+ * (after loading a new file) in the unlikely event a window couldn't be created.
+ */
+void wm_window_ghostwindows_remove_invalid(bContext *C, wmWindowManager *wm)
+{
+ wmWindow *win, *win_next;
+
+ BLI_assert(G.background == false);
+
+ for (win = wm->windows.first; win; win = win_next) {
+ win_next = win->next;
+ if (win->ghostwin == NULL) {
+ wm_window_close(C, wm, win);
+ }
+ }
+}
+
+/**
+ * new window, no screen yet, but we open ghostwindow for it,
+ * also gets the window level handlers
+ * \note area-rip calls this.
+ * \return the window or NULL.
+ */
wmWindow *WM_window_open(bContext *C, const rcti *rect)
{
+ wmWindow *win_prev = CTX_wm_window(C);
wmWindow *win = wm_window_new(C);
win->posx = rect->xmin;
@@ -561,22 +600,35 @@ wmWindow *WM_window_open(bContext *C, const rcti *rect)
win->drawmethod = U.wmdrawmethod;
WM_check(C);
-
- return win;
-}
-/* uses screen->temp tag to define what to do, currently it limits
- * to only one "temp" window for render out, preferences, filewindow, etc */
-/* type is defined in WM_api.h */
+ if (win->ghostwin) {
+ return win;
+ }
+ else {
+ wm_window_close(C, CTX_wm_manager(C), win);
+ CTX_wm_window_set(C, win_prev);
+ return NULL;
+ }
+}
-void WM_window_open_temp(bContext *C, rcti *position, int type)
+/**
+ * Uses `screen->temp` tag to define what to do, currently it limits
+ * to only one "temp" window for render out, preferences, filewindow, etc...
+ *
+ * \param type: WM_WINDOW_RENDER, WM_WINDOW_USERPREFS...
+ * \return the window or NULL.
+ */
+wmWindow *WM_window_open_temp(bContext *C, const rcti *rect_init, int type)
{
+ wmWindow *win_prev = CTX_wm_window(C);
wmWindow *win;
ScrArea *sa;
Scene *scene = CTX_data_scene(C);
-
+ const char *title;
+ rcti rect = *rect_init;
+
/* changes rect to fit within desktop */
- wm_window_check_position(position);
+ wm_window_check_position(&rect);
/* test if we have a temp screen already */
for (win = CTX_wm_manager(C)->windows.first; win; win = win->next)
@@ -587,12 +639,12 @@ void WM_window_open_temp(bContext *C, rcti *position, int type)
if (win == NULL) {
win = wm_window_new(C);
- win->posx = position->xmin;
- win->posy = position->ymin;
+ win->posx = rect.xmin;
+ win->posy = rect.ymin;
}
- win->sizex = BLI_rcti_size_x(position);
- win->sizey = BLI_rcti_size_y(position);
+ win->sizex = BLI_rcti_size_x(&rect);
+ win->sizey = BLI_rcti_size_y(&rect);
if (win->ghostwin) {
wm_window_set_size(win, win->sizex, win->sizey);
@@ -614,7 +666,13 @@ void WM_window_open_temp(bContext *C, rcti *position, int type)
/* make window active, and validate/resize */
CTX_wm_window_set(C, win);
WM_check(C);
-
+
+ /* It's possible `win->ghostwin == NULL`.
+ * instead of attempting to cleanup here (in a half finished state),
+ * finish setting up the screen, then free it at the end of the function,
+ * to avoid having to take into account a partially-created window.
+ */
+
/* ensure it shows the right spacetype editor */
sa = win->screen->areabase.first;
CTX_wm_area_set(C, sa);
@@ -630,18 +688,38 @@ void WM_window_open_temp(bContext *C, rcti *position, int type)
ED_screen_refresh(CTX_wm_manager(C), win); /* test scale */
if (sa->spacetype == SPACE_IMAGE)
- GHOST_SetTitle(win->ghostwin, IFACE_("Blender Render"));
+ title = IFACE_("Blender Render");
else if (ELEM(sa->spacetype, SPACE_OUTLINER, SPACE_USERPREF))
- GHOST_SetTitle(win->ghostwin, IFACE_("Blender User Preferences"));
+ title = IFACE_("Blender User Preferences");
else if (sa->spacetype == SPACE_FILE)
- GHOST_SetTitle(win->ghostwin, IFACE_("Blender File View"));
+ title = IFACE_("Blender File View");
else
- GHOST_SetTitle(win->ghostwin, "Blender");
+ title = "Blender";
+
+ if (win->ghostwin) {
+ GHOST_SetTitle(win->ghostwin, title);
+ return win;
+ }
+ else {
+ /* very unlikely! but opening a new window can fail */
+ wm_window_close(C, CTX_wm_manager(C), win);
+ CTX_wm_window_set(C, win_prev);
+
+ return NULL;
+ }
}
/* ****************** Operators ****************** */
+int wm_window_close_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ wmWindowManager *wm = CTX_wm_manager(C);
+ wmWindow *win = CTX_wm_window(C);
+ wm_window_close(C, wm, win);
+ return OPERATOR_FINISHED;
+}
+
/* operator callback */
int wm_window_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
{
@@ -676,7 +754,7 @@ int wm_window_fullscreen_toggle_exec(bContext *C, wmOperator *UNUSED(op))
/* ************ events *************** */
-static void wm_convert_cursor_position(wmWindow *win, int *x, int *y)
+void wm_cursor_position_from_ghost(wmWindow *win, int *x, int *y)
{
float fac = GHOST_GetNativePixelSize(win->ghostwin);
@@ -687,11 +765,21 @@ static void wm_convert_cursor_position(wmWindow *win, int *x, int *y)
*y *= fac;
}
+void wm_cursor_position_to_ghost(wmWindow *win, int *x, int *y)
+{
+ float fac = GHOST_GetNativePixelSize(win->ghostwin);
+
+ *x /= fac;
+ *y /= fac;
+ *y = win->sizey - *y - 1;
+
+ GHOST_ClientToScreen(win->ghostwin, *x, *y, x, y);
+}
void wm_get_cursor_position(wmWindow *win, int *x, int *y)
{
GHOST_GetCursorPosition(g_system, x, y);
- wm_convert_cursor_position(win, x, y);
+ wm_cursor_position_from_ghost(win, x, y);
}
typedef enum {
@@ -1017,9 +1105,12 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr
#if defined(__APPLE__) || defined(WIN32)
/* OSX and Win32 don't return to the mainloop while resize */
- wm_event_do_handlers(C);
wm_event_do_notifiers(C);
wm_draw_update(C);
+
+ /* Warning! code above nulls 'C->wm.window', causing BGE to quit, see: T45699.
+ * Further, its easier to match behavior across platforms, so restore the window. */
+ CTX_wm_window_set(C, win);
#endif
}
}
@@ -1115,7 +1206,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr
{
GHOST_TEventTrackpadData *pd = data;
- wm_convert_cursor_position(win, &pd->x, &pd->y);
+ wm_cursor_position_from_ghost(win, &pd->x, &pd->y);
wm_event_add_ghostevent(wm, win, type, time, data);
break;
}
@@ -1123,7 +1214,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr
{
GHOST_TEventCursorData *cd = data;
- wm_convert_cursor_position(win, &cd->x, &cd->y);
+ wm_cursor_position_from_ghost(win, &cd->x, &cd->y);
wm_event_add_ghostevent(wm, win, type, time, data);
break;
}
@@ -1274,7 +1365,7 @@ void WM_event_timer_sleep(wmWindowManager *wm, wmWindow *UNUSED(win), wmTimer *t
wmTimer *WM_event_add_timer(wmWindowManager *wm, wmWindow *win, int event_type, double timestep)
{
wmTimer *wt = MEM_callocN(sizeof(wmTimer), "window timer");
-
+
wt->event_type = event_type;
wt->ltime = PIL_check_seconds_timer();
wt->ntime = wt->ltime + timestep;
@@ -1538,14 +1629,9 @@ void WM_init_native_pixels(bool do_it)
void WM_cursor_warp(wmWindow *win, int x, int y)
{
if (win && win->ghostwin) {
- float f = GHOST_GetNativePixelSize(win->ghostwin);
int oldx = x, oldy = y;
- x = x / f;
- y = y / f;
- y = win->sizey - y - 1;
-
- GHOST_ClientToScreen(win->ghostwin, x, y, &x, &y);
+ wm_cursor_position_to_ghost(win, &x, &y);
GHOST_SetCursorPosition(g_system, x, y);
win->eventstate->prevx = oldx;
@@ -1557,6 +1643,18 @@ void WM_cursor_warp(wmWindow *win, int x, int y)
}
/**
+ * Set x, y to values we can actually position the cursor to.
+ */
+void WM_cursor_compatible_xy(wmWindow *win, int *x, int *y)
+{
+ float f = GHOST_GetNativePixelSize(win->ghostwin);
+ if (f != 1.0f) {
+ *x = (int)(*x / f) * f;
+ *y = (int)(*y / f) * f;
+ }
+}
+
+/**
* Get the cursor pressure, in most cases you'll want to use wmTabletData from the event
*/
float WM_cursor_pressure(const struct wmWindow *win)
diff --git a/source/blender/windowmanager/wm_files.h b/source/blender/windowmanager/wm_files.h
index 467926aa770..4b35f662a99 100644
--- a/source/blender/windowmanager/wm_files.h
+++ b/source/blender/windowmanager/wm_files.h
@@ -38,6 +38,7 @@ int wm_homefile_read_exec(struct bContext *C, struct wmOperator *op);
int wm_homefile_read(struct bContext *C, struct ReportList *reports, bool from_memory, const char *filepath);
int wm_homefile_write_exec(struct bContext *C, struct wmOperator *op);
int wm_userpref_write_exec(struct bContext *C, struct wmOperator *op);
+void wm_file_read_report(bContext *C);
#endif /* __WM_FILES_H__ */
diff --git a/source/blender/windowmanager/wm_window.h b/source/blender/windowmanager/wm_window.h
index a104f6aba39..c106f9d7851 100644
--- a/source/blender/windowmanager/wm_window.h
+++ b/source/blender/windowmanager/wm_window.h
@@ -48,7 +48,8 @@ void wm_window_free (bContext *C, wmWindowManager *wm, wmWindow *win);
void wm_window_close (bContext *C, wmWindowManager *wm, wmWindow *win);
void wm_window_title (wmWindowManager *wm, wmWindow *win);
-void wm_window_add_ghostwindows (wmWindowManager *wm);
+void wm_window_ghostwindows_ensure(wmWindowManager *wm);
+void wm_window_ghostwindows_remove_invalid(bContext *C, wmWindowManager *wm);
void wm_window_process_events (const bContext *C);
void wm_window_process_events_nosleep(void);
@@ -64,7 +65,9 @@ bool wm_window_get_swap_interval(wmWindow *win, int *intervalOut);
float wm_window_pixelsize(wmWindow *win);
-void wm_get_cursor_position (wmWindow *win, int *x, int *y);
+void wm_get_cursor_position (wmWindow *win, int *x, int *y);
+void wm_cursor_position_from_ghost (wmWindow *win, int *x, int *y);
+void wm_cursor_position_to_ghost (wmWindow *win, int *x, int *y);
void wm_window_testbreak (void);
@@ -74,6 +77,7 @@ void wm_window_IME_end (wmWindow *win);
#endif
/* *************** window operators ************** */
+int wm_window_close_exec(bContext *C, struct wmOperator *op);
int wm_window_duplicate_exec(bContext *C, struct wmOperator *op);
int wm_window_fullscreen_toggle_exec(bContext *C, struct wmOperator *op);