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:
-rw-r--r--CMakeLists.txt7
-rw-r--r--GNUmakefile50
-rw-r--r--build_files/cmake/platform/platform_win32.cmake24
-rw-r--r--build_files/windows/configure_msbuild.cmd5
-rw-r--r--build_files/windows/configure_ninja.cmd7
-rw-r--r--build_files/windows/parse_arguments.cmd2
-rw-r--r--build_files/windows/reset_variables.cmd1
-rw-r--r--doc/doxygen/Doxyfile2
-rw-r--r--intern/cycles/blender/addon/ui.py235
-rw-r--r--intern/dualcon/dualcon.h2
-rw-r--r--intern/dualcon/intern/octree.cpp2
-rw-r--r--intern/libmv/libmv/simple_pipeline/bundle.cc378
-rw-r--r--intern/mantaflow/extern/manta_fluid_API.h1
-rw-r--r--intern/mantaflow/intern/MANTA_main.cpp51
-rw-r--r--intern/mantaflow/intern/MANTA_main.h5
-rw-r--r--intern/mantaflow/intern/manta_fluid_API.cpp4
-rw-r--r--intern/mantaflow/intern/strings/fluid_script.h13
-rw-r--r--intern/mantaflow/intern/strings/liquid_script.h10
-rw-r--r--intern/mantaflow/intern/strings/smoke_script.h5
-rw-r--r--release/datafiles/userdef/userdef_default_theme.c6
-rw-r--r--release/scripts/modules/rna_keymap_ui.py7
-rw-r--r--release/scripts/presets/interface_theme/blender_light.xml2
-rw-r--r--release/scripts/presets/keyconfig/keymap_data/blender_default.py18
-rw-r--r--release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py4
-rw-r--r--release/scripts/startup/bl_operators/__init__.py1
-rw-r--r--release/scripts/startup/bl_operators/simulation.py39
-rw-r--r--release/scripts/startup/bl_operators/userpref.py36
-rw-r--r--release/scripts/startup/bl_operators/view3d.py23
-rw-r--r--release/scripts/startup/bl_operators/wm.py4
-rw-r--r--release/scripts/startup/bl_ui/properties_data_armature.py7
-rw-r--r--release/scripts/startup/bl_ui/properties_data_camera.py44
-rw-r--r--release/scripts/startup/bl_ui/properties_data_curve.py12
-rw-r--r--release/scripts/startup/bl_ui/properties_data_empty.py8
-rw-r--r--release/scripts/startup/bl_ui/properties_data_mesh.py42
-rw-r--r--release/scripts/startup/bl_ui/properties_data_modifier.py21
-rw-r--r--release/scripts/startup/bl_ui/properties_grease_pencil_common.py2
-rw-r--r--release/scripts/startup/bl_ui/properties_object.py67
-rw-r--r--release/scripts/startup/bl_ui/properties_output.py57
-rw-r--r--release/scripts/startup/bl_ui/properties_paint_common.py30
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_common.py39
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_fluid.py5
-rw-r--r--release/scripts/startup/bl_ui/properties_render.py33
-rw-r--r--release/scripts/startup/bl_ui/properties_view_layer.py53
-rw-r--r--release/scripts/startup/bl_ui/space_filebrowser.py5
-rw-r--r--release/scripts/startup/bl_ui/space_image.py5
-rw-r--r--release/scripts/startup/bl_ui/space_node.py8
-rw-r--r--release/scripts/startup/bl_ui/space_sequencer.py86
-rw-r--r--release/scripts/startup/bl_ui/space_text.py21
-rw-r--r--release/scripts/startup/bl_ui/space_toolsystem_toolbar.py19
-rw-r--r--release/scripts/startup/bl_ui/space_topbar.py7
-rw-r--r--release/scripts/startup/bl_ui/space_userpref.py321
-rw-r--r--release/scripts/startup/bl_ui/space_view3d.py42
-rw-r--r--release/scripts/startup/bl_ui/space_view3d_toolbar.py117
-rw-r--r--release/scripts/startup/nodeitems_builtins.py70
-rw-r--r--source/blender/blenkernel/BKE_animsys.h6
-rw-r--r--source/blender/blenkernel/BKE_armature.h2
-rw-r--r--source/blender/blenkernel/BKE_blender_version.h6
-rw-r--r--source/blender/blenkernel/BKE_curve.h2
-rw-r--r--source/blender/blenkernel/BKE_fluid.h1
-rw-r--r--source/blender/blenkernel/BKE_idtype.h1
-rw-r--r--source/blender/blenkernel/BKE_main.h3
-rw-r--r--source/blender/blenkernel/BKE_node.h34
-rw-r--r--source/blender/blenkernel/BKE_simulation.h33
-rw-r--r--source/blender/blenkernel/BKE_tracking.h14
-rw-r--r--source/blender/blenkernel/CMakeLists.txt2
-rw-r--r--source/blender/blenkernel/intern/action.c2
-rw-r--r--source/blender/blenkernel/intern/anim_data.c7
-rw-r--r--source/blender/blenkernel/intern/anim_sys.c26
-rw-r--r--source/blender/blenkernel/intern/blendfile.c3
-rw-r--r--source/blender/blenkernel/intern/colortools.c69
-rw-r--r--source/blender/blenkernel/intern/constraint.c2
-rw-r--r--source/blender/blenkernel/intern/curve.c14
-rw-r--r--source/blender/blenkernel/intern/dynamicpaint.c33
-rw-r--r--source/blender/blenkernel/intern/fluid.c680
-rw-r--r--source/blender/blenkernel/intern/idtype.c5
-rw-r--r--source/blender/blenkernel/intern/lib_id.c63
-rw-r--r--source/blender/blenkernel/intern/lib_id_delete.c62
-rw-r--r--source/blender/blenkernel/intern/lib_query.c62
-rw-r--r--source/blender/blenkernel/intern/light.c2
-rw-r--r--source/blender/blenkernel/intern/linestyle.c2
-rw-r--r--source/blender/blenkernel/intern/main.c3
-rw-r--r--source/blender/blenkernel/intern/material.c4
-rw-r--r--source/blender/blenkernel/intern/mesh_evaluate.c2
-rw-r--r--source/blender/blenkernel/intern/movieclip.c3
-rw-r--r--source/blender/blenkernel/intern/node.c159
-rw-r--r--source/blender/blenkernel/intern/object.c11
-rw-r--r--source/blender/blenkernel/intern/ocean.c16
-rw-r--r--source/blender/blenkernel/intern/particle_system.c17
-rw-r--r--source/blender/blenkernel/intern/pointcloud.c2
-rw-r--r--source/blender/blenkernel/intern/scene.c2
-rw-r--r--source/blender/blenkernel/intern/seqprefetch.c3
-rw-r--r--source/blender/blenkernel/intern/sequencer.c6
-rw-r--r--source/blender/blenkernel/intern/simulation.cc110
-rw-r--r--source/blender/blenkernel/intern/subdiv_ccg.c18
-rw-r--r--source/blender/blenkernel/intern/subdiv_foreach.c6
-rw-r--r--source/blender/blenkernel/intern/texture.c2
-rw-r--r--source/blender/blenkernel/intern/tracking.c28
-rw-r--r--source/blender/blenkernel/intern/world.c2
-rw-r--r--source/blender/blenlib/BLI_allocator.hh (renamed from source/blender/blenlib/BLI_allocator.h)6
-rw-r--r--source/blender/blenlib/BLI_array.hh (renamed from source/blender/blenlib/BLI_array_cxx.h)14
-rw-r--r--source/blender/blenlib/BLI_array_ref.hh (renamed from source/blender/blenlib/BLI_array_ref.h)10
-rw-r--r--source/blender/blenlib/BLI_color.hh92
-rw-r--r--source/blender/blenlib/BLI_float2.hh86
-rw-r--r--source/blender/blenlib/BLI_float3.hh218
-rw-r--r--source/blender/blenlib/BLI_float4x4.hh115
-rw-r--r--source/blender/blenlib/BLI_hash.h2
-rw-r--r--source/blender/blenlib/BLI_hash.hh (renamed from source/blender/blenlib/BLI_hash_cxx.h)6
-rw-r--r--source/blender/blenlib/BLI_index_range.hh (renamed from source/blender/blenlib/BLI_index_range.h)6
-rw-r--r--source/blender/blenlib/BLI_listbase_wrapper.hh (renamed from source/blender/blenlib/BLI_listbase_wrapper.h)12
-rw-r--r--source/blender/blenlib/BLI_map.hh (renamed from source/blender/blenlib/BLI_map.h)12
-rw-r--r--source/blender/blenlib/BLI_memory_utils.hh (renamed from source/blender/blenlib/BLI_memory_utils_cxx.h)6
-rw-r--r--source/blender/blenlib/BLI_open_addressing.hh (renamed from source/blender/blenlib/BLI_open_addressing.h)10
-rw-r--r--source/blender/blenlib/BLI_optional.hh (renamed from source/blender/blenlib/BLI_optional.h)8
-rw-r--r--source/blender/blenlib/BLI_set.hh (renamed from source/blender/blenlib/BLI_set.h)12
-rw-r--r--source/blender/blenlib/BLI_stack.hh (renamed from source/blender/blenlib/BLI_stack_cxx.h)8
-rw-r--r--source/blender/blenlib/BLI_string_map.hh (renamed from source/blender/blenlib/BLI_string_map.h)14
-rw-r--r--source/blender/blenlib/BLI_string_ref.hh (renamed from source/blender/blenlib/BLI_string_ref.h)8
-rw-r--r--source/blender/blenlib/BLI_task.h20
-rw-r--r--source/blender/blenlib/BLI_utility_mixins.hh (renamed from source/blender/blenlib/BLI_utility_mixins.h)6
-rw-r--r--source/blender/blenlib/BLI_vector.hh (renamed from source/blender/blenlib/BLI_vector.h)25
-rw-r--r--source/blender/blenlib/BLI_vector_set.hh (renamed from source/blender/blenlib/BLI_vector_set.h)12
-rw-r--r--source/blender/blenlib/CMakeLists.txt38
-rw-r--r--source/blender/blenlib/intern/BLI_index_range.cc8
-rw-r--r--source/blender/blenlib/intern/task_iterator.c89
-rw-r--r--source/blender/blenlib/intern/task_pool.cc6
-rw-r--r--source/blender/blenloader/CMakeLists.txt1
-rw-r--r--source/blender/blenloader/intern/readfile.c153
-rw-r--r--source/blender/blenloader/intern/readfile.h1
-rw-r--r--source/blender/blenloader/intern/versioning_290.c66
-rw-r--r--source/blender/blenloader/intern/versioning_defaults.c2
-rw-r--r--source/blender/blenloader/intern/writefile.c32
-rw-r--r--source/blender/blentranslation/BLT_translation.h2
-rw-r--r--source/blender/bmesh/intern/bmesh_opdefines.c1
-rw-r--r--source/blender/bmesh/operators/bmo_extrude.c65
-rw-r--r--source/blender/bmesh/tools/bmesh_bevel.c12
-rw-r--r--source/blender/compositor/operations/COM_MovieDistortionOperation.cpp3
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.cc17
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.h2
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.cc25
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.h2
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc2
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval.cc2
-rw-r--r--source/blender/draw/engines/eevee/eevee_motion_blur.c3
-rw-r--r--source/blender/editors/animation/anim_channels_defines.c79
-rw-r--r--source/blender/editors/animation/anim_channels_edit.c15
-rw-r--r--source/blender/editors/animation/anim_filter.c13
-rw-r--r--source/blender/editors/armature/pose_transform.c2
-rw-r--r--source/blender/editors/include/ED_anim_api.h3
-rw-r--r--source/blender/editors/include/ED_node.h6
-rw-r--r--source/blender/editors/include/ED_transform.h2
-rw-r--r--source/blender/editors/include/UI_interface.h25
-rw-r--r--source/blender/editors/interface/interface.c36
-rw-r--r--source/blender/editors/interface/interface_anim.c53
-rw-r--r--source/blender/editors/interface/interface_icons.c3
-rw-r--r--source/blender/editors/interface/interface_intern.h7
-rw-r--r--source/blender/editors/interface/interface_layout.c291
-rw-r--r--source/blender/editors/interface/interface_panel.c24
-rw-r--r--source/blender/editors/interface/interface_templates.c432
-rw-r--r--source/blender/editors/interface/interface_utils.c16
-rw-r--r--source/blender/editors/interface/interface_widgets.c121
-rw-r--r--source/blender/editors/interface/view2d.c78
-rw-r--r--source/blender/editors/mesh/editmesh_extrude.c18
-rw-r--r--source/blender/editors/mesh/mesh_ops.c12
-rw-r--r--source/blender/editors/object/CMakeLists.txt1
-rw-r--r--source/blender/editors/object/object_edit.c192
-rw-r--r--source/blender/editors/object/object_modifier.c9
-rw-r--r--source/blender/editors/object/object_transform.c18
-rw-r--r--source/blender/editors/physics/particle_edit.c24
-rw-r--r--source/blender/editors/physics/physics_fluid.c4
-rw-r--r--source/blender/editors/render/render_opengl.c3
-rw-r--r--source/blender/editors/screen/area.c11
-rw-r--r--source/blender/editors/screen/screen_ops.c1
-rw-r--r--source/blender/editors/space_clip/clip_draw.c14
-rw-r--r--source/blender/editors/space_clip/clip_editor.c6
-rw-r--r--source/blender/editors/space_clip/clip_ops.c2
-rw-r--r--source/blender/editors/space_clip/clip_utils.c3
-rw-r--r--source/blender/editors/space_file/filelist.c6
-rw-r--r--source/blender/editors/space_image/space_image.c1
-rw-r--r--source/blender/editors/space_nla/nla_buttons.c29
-rw-r--r--source/blender/editors/space_nla/nla_channels.c3
-rw-r--r--source/blender/editors/space_node/CMakeLists.txt4
-rw-r--r--source/blender/editors/space_node/drawnode.c108
-rw-r--r--source/blender/editors/space_node/node_buttons.c2
-rw-r--r--source/blender/editors/space_node/node_draw.c262
-rw-r--r--source/blender/editors/space_node/node_edit.c6
-rw-r--r--source/blender/editors/space_node/node_group.c9
-rw-r--r--source/blender/editors/space_node/node_intern.h14
-rw-r--r--source/blender/editors/space_node/node_templates.c30
-rw-r--r--source/blender/editors/space_node/space_node.c5
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c4
-rw-r--r--source/blender/editors/space_outliner/outliner_intern.h3
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.c2
-rw-r--r--source/blender/editors/space_outliner/outliner_tree.c8
-rw-r--r--source/blender/editors/space_sequencer/sequencer_scopes.c20
-rw-r--r--source/blender/editors/transform/transform.h4
-rw-r--r--source/blender/editors/transform/transform_convert.c18
-rw-r--r--source/blender/editors/transform/transform_convert_armature.c6
-rw-r--r--source/blender/editors/transform/transform_generics.c18
-rw-r--r--source/blender/editors/transform/transform_ops.c11
-rw-r--r--source/blender/editors/uvedit/uvedit_draw.c33
-rw-r--r--source/blender/gpencil_modifiers/CMakeLists.txt1
-rw-r--r--source/blender/gpencil_modifiers/MOD_gpencil_modifiertypes.h1
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c1
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpenciltexture.c165
-rw-r--r--source/blender/gpu/intern/gpu_shader_interface.c6
-rw-r--r--source/blender/gpu/intern/gpu_viewport.c8
-rw-r--r--source/blender/imbuf/intern/imageprocess.c4
-rw-r--r--source/blender/makesdna/DNA_ID.h9
-rw-r--r--source/blender/makesdna/DNA_fluid_types.h4
-rw-r--r--source/blender/makesdna/DNA_gpencil_modifier_types.h47
-rw-r--r--source/blender/makesdna/DNA_node_types.h44
-rw-r--r--source/blender/makesdna/DNA_simulation_defaults.h40
-rw-r--r--source/blender/makesdna/DNA_simulation_types.h41
-rw-r--r--source/blender/makesdna/DNA_space_types.h4
-rw-r--r--source/blender/makesdna/DNA_userdef_types.h3
-rw-r--r--source/blender/makesdna/intern/CMakeLists.txt1
-rw-r--r--source/blender/makesdna/intern/dna_defaults.c8
-rw-r--r--source/blender/makesdna/intern/makesdna.c2
-rw-r--r--source/blender/makesrna/RNA_access.h8
-rw-r--r--source/blender/makesrna/RNA_enum_types.h10
-rw-r--r--source/blender/makesrna/intern/CMakeLists.txt12
-rw-r--r--source/blender/makesrna/intern/makesrna.c3
-rw-r--r--source/blender/makesrna/intern/rna_ID.c14
-rw-r--r--source/blender/makesrna/intern/rna_access.c117
-rw-r--r--source/blender/makesrna/intern/rna_fluid.c342
-rw-r--r--source/blender/makesrna/intern/rna_gpencil.c2
-rw-r--r--source/blender/makesrna/intern/rna_gpencil_modifier.c143
-rw-r--r--source/blender/makesrna/intern/rna_internal.h2
-rw-r--r--source/blender/makesrna/intern/rna_main.c11
-rw-r--r--source/blender/makesrna/intern/rna_main_api.c57
-rw-r--r--source/blender/makesrna/intern/rna_modifier.c2
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c418
-rw-r--r--source/blender/makesrna/intern/rna_object.c1
-rw-r--r--source/blender/makesrna/intern/rna_scene.c18
-rw-r--r--source/blender/makesrna/intern/rna_simulation.c56
-rw-r--r--source/blender/makesrna/intern/rna_space.c61
-rw-r--r--source/blender/makesrna/intern/rna_ui_api.c31
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c4
-rw-r--r--source/blender/modifiers/intern/MOD_mask.cc10
-rw-r--r--source/blender/modifiers/intern/MOD_surfacedeform.c2
-rw-r--r--source/blender/nodes/CMakeLists.txt27
-rw-r--r--source/blender/nodes/NOD_common.h8
-rw-r--r--source/blender/nodes/NOD_function.h32
-rw-r--r--source/blender/nodes/NOD_simulation.h47
-rw-r--r--source/blender/nodes/NOD_static_types.h20
-rw-r--r--source/blender/nodes/function/node_function_util.cc30
-rw-r--r--source/blender/nodes/function/node_function_util.h40
-rw-r--r--source/blender/nodes/function/nodes/node_fn_boolean_math.cc62
-rw-r--r--source/blender/nodes/function/nodes/node_fn_float_compare.cc66
-rw-r--r--source/blender/nodes/function/nodes/node_fn_switch.cc76
-rw-r--r--source/blender/nodes/intern/node_common.h8
-rw-r--r--source/blender/nodes/intern/node_socket.c54
-rw-r--r--source/blender/nodes/intern/node_util.h8
-rw-r--r--source/blender/nodes/shader/node_shader_util.c11
-rw-r--r--source/blender/nodes/shader/node_shader_util.h2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_brightness.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_clamp.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_gamma.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_hueSatVal.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_invert.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_map_range.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_math.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_mixRgb.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_sepcombHSV.c4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_sepcombRGB.c4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_sepcombXYZ.c4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c3
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_noise.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_white_noise.c3
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_valToRgb.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_vector_math.c2
-rw-r--r--source/blender/nodes/simulation/node_simulation_tree.cc45
-rw-r--r--source/blender/nodes/simulation/node_simulation_util.cc29
-rw-r--r--source/blender/nodes/simulation/node_simulation_util.h40
-rw-r--r--source/blender/nodes/simulation/nodes/node_sim_common.cc45
-rw-r--r--source/blender/nodes/simulation/nodes/node_sim_emit_particles.cc38
-rw-r--r--source/blender/nodes/simulation/nodes/node_sim_execute_condition.cc39
-rw-r--r--source/blender/nodes/simulation/nodes/node_sim_force.cc36
-rw-r--r--source/blender/nodes/simulation/nodes/node_sim_multi_execute.cc38
-rw-r--r--source/blender/nodes/simulation/nodes/node_sim_particle_attribute.cc52
-rw-r--r--source/blender/nodes/simulation/nodes/node_sim_particle_birth_event.cc37
-rw-r--r--source/blender/nodes/simulation/nodes/node_sim_particle_mesh_collision_event.cc40
-rw-r--r--source/blender/nodes/simulation/nodes/node_sim_particle_mesh_emitter.cc40
-rw-r--r--source/blender/nodes/simulation/nodes/node_sim_particle_simulation.cc39
-rw-r--r--source/blender/nodes/simulation/nodes/node_sim_particle_time_step_event.cc37
-rw-r--r--source/blender/nodes/simulation/nodes/node_sim_set_particle_attribute.cc57
-rw-r--r--source/blender/nodes/simulation/nodes/node_sim_simulation_time.cc31
-rw-r--r--source/blender/render/intern/source/pipeline.c2
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c39
-rw-r--r--tests/gtests/CMakeLists.txt1
-rw-r--r--tests/gtests/blenkernel/BKE_armature_test.cc89
-rw-r--r--tests/gtests/blenkernel/CMakeLists.txt37
-rw-r--r--tests/gtests/blenlib/BLI_array_ref_test.cc4
-rw-r--r--tests/gtests/blenlib/BLI_array_test.cc2
-rw-r--r--tests/gtests/blenlib/BLI_index_range_test.cc4
-rw-r--r--tests/gtests/blenlib/BLI_linklist_lockfree_test.cc2
-rw-r--r--tests/gtests/blenlib/BLI_map_test.cc4
-rw-r--r--tests/gtests/blenlib/BLI_optional_test.cc2
-rw-r--r--tests/gtests/blenlib/BLI_set_test.cc4
-rw-r--r--tests/gtests/blenlib/BLI_stack_cxx_test.cc2
-rw-r--r--tests/gtests/blenlib/BLI_string_map_test.cc4
-rw-r--r--tests/gtests/blenlib/BLI_string_ref_test.cc4
-rw-r--r--tests/gtests/blenlib/BLI_task_test.cc32
-rw-r--r--tests/gtests/blenlib/BLI_vector_set_test.cc2
-rw-r--r--tests/gtests/blenlib/BLI_vector_test.cc6
-rw-r--r--tests/python/modules/mesh_test.py35
306 files changed, 7320 insertions, 2807 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5fb0393dcda..b6b271c8085 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -323,6 +323,10 @@ option(WITH_FREESTYLE "Enable Freestyle (advanced edges rendering)" ON)
option(WITH_NEW_OBJECT_TYPES "Enable new hair and pointcloud objects (use for development only, don't save in files)" OFF)
mark_as_advanced(WITH_NEW_OBJECT_TYPES)
+# New simulation data block
+option(WITH_NEW_SIMULATION_TYPE "Enable simulation data block (use for development only, don't save in files)" OFF)
+mark_as_advanced(WITH_NEW_SIMULATION_TYPE)
+
# Misc
if(WIN32)
option(WITH_INPUT_IME "Enable Input Method Editor (IME) for complex Asian character input" ON)
@@ -532,6 +536,9 @@ if(WIN32)
option(WITH_WINDOWS_BUNDLE_CRT "Bundle the C runtime for install free distribution." ON)
mark_as_advanced(WITH_WINDOWS_BUNDLE_CRT)
+ option(WITH_WINDOWS_SCCACHE "Use sccache to speed up builds (Ninja builder only)" OFF)
+ mark_as_advanced(WITH_WINDOWS_SCCACHE)
+
endif()
# The following only works with the Ninja generator in CMake >= 3.0.
diff --git a/GNUmakefile b/GNUmakefile
index 98bfded4ec7..e3bb3eaff7a 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -71,17 +71,6 @@ Testing Targets
which are tagged to use the stricter formatting
* test_deprecated:
Checks for deprecation tags in our code which may need to be removed
- * test_style_c:
- Checks C/C++ conforms with blenders style guide:
- https://wiki.blender.org/wiki/Source/Code_Style
- * test_style_c_qtc:
- Same as test_style but outputs QtCreator tasks format
- * test_style_osl:
- Checks OpenShadingLanguage conforms with blenders style guide:
- https://wiki.blender.org/wiki/Source/Code_Style
- * test_style_osl_qtc:
- Checks OpenShadingLanguage conforms with blenders style guide:
- https://wiki.blender.org/wiki/Source/Code_Style
Static Source Code Checking
Not associated with building Blender.
@@ -402,45 +391,6 @@ test_cmake: .FORCE
test_deprecated: .FORCE
$(PYTHON) tests/check_deprecated.py
-test_style_c: .FORCE
- # run our own checks on C/C++ style
- PYTHONIOENCODING=utf_8 $(PYTHON) \
- "$(BLENDER_DIR)/source/tools/check_source/check_style_c.py" \
- "$(BLENDER_DIR)/source/blender" \
- "$(BLENDER_DIR)/source/creator" \
- --no-length-check
-
-test_style_c_qtc: .FORCE
- # run our own checks on C/C++ style
- USE_QTC_TASK=1 \
- PYTHONIOENCODING=utf_8 $(PYTHON) \
- "$(BLENDER_DIR)/source/tools/check_source/check_style_c.py" \
- "$(BLENDER_DIR)/source/blender" \
- "$(BLENDER_DIR)/source/creator" \
- --no-length-check \
- > \
- "$(BLENDER_DIR)/test_style.tasks"
- @echo "written: test_style.tasks"
-
-
-test_style_osl: .FORCE
- # run our own checks on C/C++ style
- PYTHONIOENCODING=utf_8 $(PYTHON) \
- "$(BLENDER_DIR)/source/tools/check_source/check_style_c.py" \
- "$(BLENDER_DIR)/intern/cycles/kernel/shaders" \
- "$(BLENDER_DIR)/release/scripts/templates_osl"
-
-
-test_style_osl_qtc: .FORCE
- # run our own checks on C/C++ style
- USE_QTC_TASK=1 \
- PYTHONIOENCODING=utf_8 $(PYTHON) \
- "$(BLENDER_DIR)/source/tools/check_source/check_style_c.py" \
- "$(BLENDER_DIR)/intern/cycles/kernel/shaders" \
- "$(BLENDER_DIR)/release/scripts/templates_osl" \
- > \
- "$(BLENDER_DIR)/test_style.tasks"
- @echo "written: test_style.tasks"
# -----------------------------------------------------------------------------
# Project Files
diff --git a/build_files/cmake/platform/platform_win32.cmake b/build_files/cmake/platform/platform_win32.cmake
index 1ecde8635c8..f882ff6238b 100644
--- a/build_files/cmake/platform/platform_win32.cmake
+++ b/build_files/cmake/platform/platform_win32.cmake
@@ -134,7 +134,7 @@ add_definitions(-D_ALLOW_KEYWORD_MACROS)
# We want to support Windows 7 level ABI
add_definitions(-D_WIN32_WINNT=0x601)
include(build_files/cmake/platform/platform_win32_bundle_crt.cmake)
-remove_cc_flag("/MDd" "/MD")
+remove_cc_flag("/MDd" "/MD" "/Zi")
if(MSVC_CLANG) # Clangs version of cl doesn't support all flags
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_WARN_FLAGS} /nologo /J /Gd /EHsc -Wno-unused-command-line-argument -Wno-microsoft-enum-forward-reference ")
@@ -151,16 +151,30 @@ if(MSVC_VERSION GREATER 1911 AND NOT MSVC_CLANG)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Zc:twoPhase-")
endif()
+if(WITH_WINDOWS_SCCACHE AND CMAKE_VS_MSBUILD_COMMAND)
+ message(WARNING "Disabling sccache, sccache is not supported with msbuild")
+ set(WITH_WINDOWS_SCCACHE Off)
+endif()
-set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MDd /ZI")
-set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /MDd /ZI")
+if(WITH_WINDOWS_SCCACHE)
+ set(CMAKE_C_COMPILER_LAUNCHER sccache)
+ set(CMAKE_CXX_COMPILER_LAUNCHER sccache)
+ set(SYMBOL_FORMAT /Z7)
+else()
+ unset(CMAKE_C_COMPILER_LAUNCHER)
+ unset(CMAKE_CXX_COMPILER_LAUNCHER)
+ set(SYMBOL_FORMAT /ZI)
+endif()
+
+set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MDd ${SYMBOL_FORMAT}")
+set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /MDd ${SYMBOL_FORMAT}")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MD")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /MD")
set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} /MD")
set(CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL} /MD")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /MD")
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} /MD")
-
+unset(SYMBOL_FORMAT)
# JMC is available on msvc 15.8 (1915) and up
if(MSVC_VERSION GREATER 1914 AND NOT MSVC_CLANG)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /JMC")
@@ -209,7 +223,7 @@ endif()
# Mark libdir as system headers with a lower warn level, to resolve some warnings
# that we have very little control over
-if(MSVC_VERSION GREATER_EQUAL 1914 AND NOT MSVC_CLANG)
+if(MSVC_VERSION GREATER_EQUAL 1914 AND NOT MSVC_CLANG AND NOT WITH_WINDOWS_SCCACHE)
add_compile_options(/experimental:external /external:templates- /external:I "${LIBDIR}" /external:W0)
endif()
diff --git a/build_files/windows/configure_msbuild.cmd b/build_files/windows/configure_msbuild.cmd
index 3c1194011cd..4956f1e3ea1 100644
--- a/build_files/windows/configure_msbuild.cmd
+++ b/build_files/windows/configure_msbuild.cmd
@@ -2,6 +2,11 @@ set BUILD_GENERATOR_POST=
set BUILD_PLATFORM_SELECT=
set MSBUILD_PLATFORM=x64
+if "%BUILD_WITH_SCCACHE%"=="1" (
+ echo sccache is only supported with ninja as the build system.
+ exit /b 1
+)
+
if "%WITH_CLANG%"=="1" (
set CLANG_CMAKE_ARGS=-T"llvm"
if "%WITH_ASAN%"=="1" (
diff --git a/build_files/windows/configure_ninja.cmd b/build_files/windows/configure_ninja.cmd
index 1650e43cda9..20692847bef 100644
--- a/build_files/windows/configure_ninja.cmd
+++ b/build_files/windows/configure_ninja.cmd
@@ -6,6 +6,13 @@ if %ERRORLEVEL% NEQ 0 (
set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -G "Ninja" %TESTS_CMAKE_ARGS% -DCMAKE_BUILD_TYPE=%BUILD_TYPE%
+if "%BUILD_WITH_SCCACHE%"=="1" (
+ set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -DWITH_WINDOWS_SCCACHE=On
+ if NOT "%verbose%" == "" (
+ echo Enabling sccache
+ )
+)
+
if "%WITH_CLANG%" == "1" (
set LLVM_DIR=
for /F "usebackq skip=2 tokens=1-2*" %%A IN (`REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\LLVM\LLVM" /ve 2^>nul`) DO set LLVM_DIR=%%C
diff --git a/build_files/windows/parse_arguments.cmd b/build_files/windows/parse_arguments.cmd
index 4ee05bfde7d..54dc41ece87 100644
--- a/build_files/windows/parse_arguments.cmd
+++ b/build_files/windows/parse_arguments.cmd
@@ -86,6 +86,8 @@ if NOT "%1" == "" (
set BUILD_UPDATE_ARGS="--no-libraries"
) else if "%1" == "ninja" (
SET BUILD_WITH_NINJA=1
+ ) else if "%1" == "sccache" (
+ SET BUILD_WITH_SCCACHE=1
) else if "%1" == "clean" (
set MUST_CLEAN=1
) else if "%1" == "verbose" (
diff --git a/build_files/windows/reset_variables.cmd b/build_files/windows/reset_variables.cmd
index 48a61aff44a..262874713eb 100644
--- a/build_files/windows/reset_variables.cmd
+++ b/build_files/windows/reset_variables.cmd
@@ -30,3 +30,4 @@ set WITH_PYDEBUG=
set PYDEBUG_CMAKE_ARGS=
set FORMAT=
set TEST=
+set BUILD_WITH_SCCACHE=
diff --git a/doc/doxygen/Doxyfile b/doc/doxygen/Doxyfile
index ecd60957f2b..dea06a8cfdb 100644
--- a/doc/doxygen/Doxyfile
+++ b/doc/doxygen/Doxyfile
@@ -38,7 +38,7 @@ PROJECT_NAME = Blender
# could be handy for archiving the generated documentation or if some version
# control system is used.
-PROJECT_NUMBER = "V2.83"
+PROJECT_NUMBER = "V2.90"
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index 7cf615620a3..92f0a8fb830 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -500,8 +500,9 @@ class CYCLES_RENDER_PT_light_paths_caustics(CyclesButtonsPanel, Panel):
col = layout.column()
col.prop(cscene, "blur_glossy")
- col.prop(cscene, "caustics_reflective")
- col.prop(cscene, "caustics_refractive")
+ col = layout.column(heading="Caustics", align=True)
+ col.prop(cscene, "caustics_reflective", text="Reflective")
+ col.prop(cscene, "caustics_refractive", text="Refractive")
class CYCLES_RENDER_PT_motion_blur(CyclesButtonsPanel, Panel):
@@ -762,20 +763,13 @@ class CYCLES_RENDER_PT_filter(CyclesButtonsPanel, Panel):
rd = scene.render
view_layer = context.view_layer
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
-
- col = flow.column()
+ col = layout.column(heading="Include")
col.prop(view_layer, "use_sky", text="Environment")
- col = flow.column()
col.prop(view_layer, "use_ao", text="Ambient Occlusion")
- col = flow.column()
col.prop(view_layer, "use_solid", text="Surfaces")
- col = flow.column()
col.prop(view_layer, "use_strand", text="Hair")
- col = flow.column()
col.prop(view_layer, "use_volumes", text="Volumes")
if with_freestyle:
- col = flow.column()
col.prop(view_layer, "use_freestyle", text="Freestyle")
col.active = rd.use_freestyle
@@ -819,36 +813,27 @@ class CYCLES_RENDER_PT_passes_data(CyclesButtonsPanel, Panel):
view_layer = context.view_layer
cycles_view_layer = view_layer.cycles
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
- col = flow.column()
+ col = layout.column(heading="Include", align=True)
col.prop(view_layer, "use_pass_combined")
- col = flow.column()
col.prop(view_layer, "use_pass_z")
- col = flow.column()
col.prop(view_layer, "use_pass_mist")
- col = flow.column()
col.prop(view_layer, "use_pass_normal")
- col = flow.column()
- col.prop(view_layer, "use_pass_vector")
- col.active = not rd.use_motion_blur
- col = flow.column()
+ sub = col.column()
+ sub.active = not rd.use_motion_blur
+ sub.prop(view_layer, "use_pass_vector")
col.prop(view_layer, "use_pass_uv")
- col = flow.column()
+
+ col.prop(cycles_view_layer, "denoising_store_passes", text="Denoising Data")
+
+ col = layout.column(heading="Indexes", align=True)
col.prop(view_layer, "use_pass_object_index")
- col = flow.column()
col.prop(view_layer, "use_pass_material_index")
- layout.separator()
-
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
- col = flow.column()
- col.prop(cycles_view_layer, "denoising_store_passes", text="Denoising Data")
- col = flow.column()
+ col = layout.column(heading="Debug", align=True)
col.prop(cycles_view_layer, "pass_debug_render_time", text="Render Time")
- col = flow.column()
col.prop(cycles_view_layer, "pass_debug_sample_count", text="Sample Count")
- layout.separator()
+
layout.prop(view_layer, "pass_alpha_threshold")
@@ -866,38 +851,26 @@ class CYCLES_RENDER_PT_passes_light(CyclesButtonsPanel, Panel):
view_layer = context.view_layer
cycles_view_layer = view_layer.cycles
- split = layout.split(factor=0.35)
- split.use_property_split = False
- split.label(text="Diffuse")
- row = split.row(align=True)
- row.prop(view_layer, "use_pass_diffuse_direct", text="Direct", toggle=True)
- row.prop(view_layer, "use_pass_diffuse_indirect", text="Indirect", toggle=True)
- row.prop(view_layer, "use_pass_diffuse_color", text="Color", toggle=True)
-
- split = layout.split(factor=0.35)
- split.use_property_split = False
- split.label(text="Glossy")
- row = split.row(align=True)
- row.prop(view_layer, "use_pass_glossy_direct", text="Direct", toggle=True)
- row.prop(view_layer, "use_pass_glossy_indirect", text="Indirect", toggle=True)
- row.prop(view_layer, "use_pass_glossy_color", text="Color", toggle=True)
-
- split = layout.split(factor=0.35)
- split.use_property_split = False
- split.label(text="Transmission")
- row = split.row(align=True)
- row.prop(view_layer, "use_pass_transmission_direct", text="Direct", toggle=True)
- row.prop(view_layer, "use_pass_transmission_indirect", text="Indirect", toggle=True)
- row.prop(view_layer, "use_pass_transmission_color", text="Color", toggle=True)
-
- split = layout.split(factor=0.35)
- split.use_property_split = False
- split.label(text="Volume")
- row = split.row(align=True)
- row.prop(cycles_view_layer, "use_pass_volume_direct", text="Direct", toggle=True)
- row.prop(cycles_view_layer, "use_pass_volume_indirect", text="Indirect", toggle=True)
+ col = layout.column(heading="Diffuse", align=True)
+ col.prop(view_layer, "use_pass_diffuse_direct", text="Direct")
+ col.prop(view_layer, "use_pass_diffuse_indirect", text="Indirect")
+ col.prop(view_layer, "use_pass_diffuse_color", text="Color")
- col = layout.column(align=True)
+ col = layout.column(heading="Glossy", align=True)
+ col.prop(view_layer, "use_pass_glossy_direct", text="Direct")
+ col.prop(view_layer, "use_pass_glossy_indirect", text="Indirect")
+ col.prop(view_layer, "use_pass_glossy_color", text="Color")
+
+ col = layout.column(heading="Transmission", align=True)
+ col.prop(view_layer, "use_pass_transmission_direct", text="Direct")
+ col.prop(view_layer, "use_pass_transmission_indirect", text="Indirect")
+ col.prop(view_layer, "use_pass_transmission_color", text="Color")
+
+ col = layout.column(heading="Volume", align=True)
+ col.prop(cycles_view_layer, "use_pass_volume_direct", text="Direct")
+ col.prop(cycles_view_layer, "use_pass_volume_indirect", text="Indirect")
+
+ col = layout.column(heading="Other", align=True)
col.prop(view_layer, "use_pass_emit", text="Emission")
col.prop(view_layer, "use_pass_environment")
col.prop(view_layer, "use_pass_shadow")
@@ -918,11 +891,10 @@ class CYCLES_RENDER_PT_passes_crypto(CyclesButtonsPanel, Panel):
cycles_view_layer = context.view_layer.cycles
- row = layout.row(align=True)
- row.use_property_split = False
- row.prop(cycles_view_layer, "use_pass_crypto_object", text="Object", toggle=True)
- row.prop(cycles_view_layer, "use_pass_crypto_material", text="Material", toggle=True)
- row.prop(cycles_view_layer, "use_pass_crypto_asset", text="Asset", toggle=True)
+ col = layout.column(heading="Include", align=True)
+ col.prop(cycles_view_layer, "use_pass_crypto_object", text="Object")
+ col.prop(cycles_view_layer, "use_pass_crypto_material", text="Material")
+ col.prop(cycles_view_layer, "use_pass_crypto_asset", text="Asset")
layout.prop(cycles_view_layer, "pass_crypto_depth", text="Levels")
@@ -1012,10 +984,9 @@ class CYCLES_RENDER_PT_denoising(CyclesButtonsPanel, Panel):
view_layer = context.view_layer
cycles_view_layer = view_layer.cycles
- split = layout.split()
- split.active = cycles_view_layer.use_denoising
+ layout.active = cycles_view_layer.use_denoising
- col = split.column(align=True)
+ col = layout.column()
if show_optix_denoising(context):
col.prop(cycles_view_layer, "use_optix_denoising")
@@ -1026,51 +997,29 @@ class CYCLES_RENDER_PT_denoising(CyclesButtonsPanel, Panel):
return
col.prop(cycles_view_layer, "denoising_radius", text="Radius")
+
+ col = layout.column()
col.prop(cycles_view_layer, "denoising_strength", slider=True, text="Strength")
col.prop(cycles_view_layer, "denoising_feature_strength", slider=True, text="Feature Strength")
col.prop(cycles_view_layer, "denoising_relative_pca")
layout.separator()
- split = layout.split(factor=0.5)
- split.active = cycles_view_layer.use_denoising or cycles_view_layer.denoising_store_passes
-
- col = split.column()
- col.alignment = 'RIGHT'
- col.label(text="Diffuse")
+ col = layout.column()
+ col.active = cycles_view_layer.use_denoising or cycles_view_layer.denoising_store_passes
- row = split.row(align=True)
- row.use_property_split = False
+ row = col.row(heading="Diffuse", align=True)
row.prop(cycles_view_layer, "denoising_diffuse_direct", text="Direct", toggle=True)
row.prop(cycles_view_layer, "denoising_diffuse_indirect", text="Indirect", toggle=True)
- split = layout.split(factor=0.5)
- split.active = cycles_view_layer.use_denoising or cycles_view_layer.denoising_store_passes
-
- col = split.column()
- col.alignment = 'RIGHT'
- col.label(text="Glossy")
-
- row = split.row(align=True)
- row.use_property_split = False
+ row = col.row(heading="Glossy", align=True)
row.prop(cycles_view_layer, "denoising_glossy_direct", text="Direct", toggle=True)
row.prop(cycles_view_layer, "denoising_glossy_indirect", text="Indirect", toggle=True)
- split = layout.split(factor=0.5)
- split.active = cycles_view_layer.use_denoising or cycles_view_layer.denoising_store_passes
-
- col = split.column()
- col.alignment = 'RIGHT'
- col.label(text="Transmission")
-
- row = split.row(align=True)
- row.use_property_split = False
+ row = col.row(heading="Transmission", align=True)
row.prop(cycles_view_layer, "denoising_transmission_direct", text="Direct", toggle=True)
row.prop(cycles_view_layer, "denoising_transmission_indirect", text="Indirect", toggle=True)
- split = layout.split(factor=0.5)
- split.active = cycles_view_layer.use_denoising or cycles_view_layer.denoising_store_passes
-
class CYCLES_PT_post_processing(CyclesButtonsPanel, Panel):
bl_label = "Post Processing"
@@ -1084,7 +1033,7 @@ class CYCLES_PT_post_processing(CyclesButtonsPanel, Panel):
rd = context.scene.render
- col = layout.column(align=True)
+ col = layout.column(align=True, heading="Pipeline")
col.prop(rd, "use_compositing")
col.prop(rd, "use_sequencer")
@@ -1273,22 +1222,18 @@ class CYCLES_OBJECT_PT_visibility(CyclesButtonsPanel, Panel):
layout = self.layout
layout.use_property_split = True
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
- layout = self.layout
ob = context.object
- col = flow.column()
- col.prop(ob, "hide_viewport", text="Show in Viewports", invert_checkbox=True, toggle=False)
- col = flow.column()
- col.prop(ob, "hide_render", text="Show in Renders", invert_checkbox=True, toggle=False)
- col = flow.column()
- col.prop(ob, "hide_select", text="Selectable", invert_checkbox=True, toggle=False)
+ layout.prop(ob, "hide_select", text="Selectable", invert_checkbox=True, toggle=False)
+
+ col = layout.column(heading="Show in")
+ col.prop(ob, "hide_viewport", text="Viewports", invert_checkbox=True, toggle=False)
+ col.prop(ob, "hide_render", text="Renders", invert_checkbox=True, toggle=False)
if has_geometry_visibility(ob):
cob = ob.cycles
- col = flow.column()
+ col = layout.column(heading="Mask")
col.prop(cob, "is_shadow_catcher")
- col = flow.column()
col.prop(cob, "is_holdout")
@@ -1312,24 +1257,16 @@ class CYCLES_OBJECT_PT_visibility_ray_visibility(CyclesButtonsPanel, Panel):
cob = ob.cycles
visibility = ob.cycles_visibility
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
-
- col = flow.column()
+ col = layout.column()
col.prop(visibility, "camera")
- col = flow.column()
col.prop(visibility, "diffuse")
- col = flow.column()
col.prop(visibility, "glossy")
- col = flow.column()
col.prop(visibility, "transmission")
- col = flow.column()
col.prop(visibility, "scatter")
if ob.type != 'LIGHT':
- col = flow.column()
- col.prop(visibility, "shadow")
-
- layout.separator()
+ sub = col.column()
+ sub.prop(visibility, "shadow")
class CYCLES_OBJECT_PT_visibility_culling(CyclesButtonsPanel, Panel):
@@ -1352,15 +1289,13 @@ class CYCLES_OBJECT_PT_visibility_culling(CyclesButtonsPanel, Panel):
ob = context.object
cob = ob.cycles
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
-
- col = flow.column()
- col.active = scene.render.use_simplify and cscene.use_camera_cull
- col.prop(cob, "use_camera_cull")
+ row = layout.row()
+ row.active = scene.render.use_simplify and cscene.use_camera_cull
+ row.prop(cob, "use_camera_cull")
- col = flow.column()
- col.active = scene.render.use_simplify and cscene.use_distance_cull
- col.prop(cob, "use_distance_cull")
+ row = layout.row()
+ row.active = scene.render.use_simplify and cscene.use_distance_cull
+ row.prop(cob, "use_distance_cull")
def panel_node_draw(layout, id_data, output_type, input_name):
@@ -1906,26 +1841,24 @@ class CYCLES_RENDER_PT_bake_influence(CyclesButtonsPanel, Panel):
sub.prop(cbk, "normal_b", text="B")
elif cscene.bake_type == 'COMBINED':
- row = col.row(align=True)
- row.use_property_split = False
- row.prop(cbk, "use_pass_direct", toggle=True)
- row.prop(cbk, "use_pass_indirect", toggle=True)
- flow = col.grid_flow(row_major=False, columns=0, even_columns=False, even_rows=False, align=True)
+ col = layout.column(heading="Lighting", align=True)
+ col.prop(cbk, "use_pass_direct")
+ col.prop(cbk, "use_pass_indirect")
- flow.active = cbk.use_pass_direct or cbk.use_pass_indirect
- flow.prop(cbk, "use_pass_diffuse")
- flow.prop(cbk, "use_pass_glossy")
- flow.prop(cbk, "use_pass_transmission")
- flow.prop(cbk, "use_pass_ambient_occlusion")
- flow.prop(cbk, "use_pass_emit")
+ col = layout.column(heading="Contributions", align=True)
+ col.active = cbk.use_pass_direct or cbk.use_pass_indirect
+ col.prop(cbk, "use_pass_diffuse")
+ col.prop(cbk, "use_pass_glossy")
+ col.prop(cbk, "use_pass_transmission")
+ col.prop(cbk, "use_pass_ambient_occlusion")
+ col.prop(cbk, "use_pass_emit")
elif cscene.bake_type in {'DIFFUSE', 'GLOSSY', 'TRANSMISSION'}:
- row = col.row(align=True)
- row.use_property_split = False
- row.prop(cbk, "use_pass_direct", toggle=True)
- row.prop(cbk, "use_pass_indirect", toggle=True)
- row.prop(cbk, "use_pass_color", toggle=True)
+ col = layout.column(heading="Contributions", align=True)
+ col.prop(cbk, "use_pass_direct")
+ col.prop(cbk, "use_pass_indirect")
+ col.prop(cbk, "use_pass_color")
class CYCLES_RENDER_PT_bake_selected_to_active(CyclesButtonsPanel, Panel):
@@ -2131,17 +2064,17 @@ class CYCLES_RENDER_PT_simplify_culling(CyclesButtonsPanel, Panel):
layout.active = rd.use_simplify
- col = layout.column()
- col.prop(cscene, "use_camera_cull")
- sub = col.column()
+ row = layout.row(heading="Camera Culling")
+ row.prop(cscene, "use_camera_cull", text="")
+ sub = row.column()
sub.active = cscene.use_camera_cull
- sub.prop(cscene, "camera_cull_margin")
+ sub.prop(cscene, "camera_cull_margin", text="")
- col = layout.column()
- col.prop(cscene, "use_distance_cull")
- sub = col.column()
+ row = layout.row(heading="Distance Culling")
+ row.prop(cscene, "use_distance_cull", text="")
+ sub = row.column()
sub.active = cscene.use_distance_cull
- sub.prop(cscene, "distance_cull_margin", text="Distance")
+ sub.prop(cscene, "distance_cull_margin", text="")
class CYCLES_VIEW3D_PT_shading_render_pass(Panel):
diff --git a/intern/dualcon/dualcon.h b/intern/dualcon/dualcon.h
index e9bff72a1ce..60cec101545 100644
--- a/intern/dualcon/dualcon.h
+++ b/intern/dualcon/dualcon.h
@@ -29,7 +29,7 @@ typedef float (*DualConCo)[3];
typedef unsigned int (*DualConTri)[3];
-typedef unsigned int(*DualConLoop);
+typedef unsigned int *DualConLoop;
typedef struct DualConInput {
DualConLoop mloop;
diff --git a/intern/dualcon/intern/octree.cpp b/intern/dualcon/intern/octree.cpp
index 70b3b8bb457..c9d5639cb5d 100644
--- a/intern/dualcon/intern/octree.cpp
+++ b/intern/dualcon/intern/octree.cpp
@@ -480,7 +480,7 @@ void Octree::trace()
if (chdpath != NULL) {
dc_printf("there are incomplete rings.\n");
printPaths(chdpath);
- };
+ }
}
Node *Octree::trace(Node *newnode, int *st, int len, int depth, PathList *&paths)
diff --git a/intern/libmv/libmv/simple_pipeline/bundle.cc b/intern/libmv/libmv/simple_pipeline/bundle.cc
index e61650fb371..2976dd5053f 100644
--- a/intern/libmv/libmv/simple_pipeline/bundle.cc
+++ b/intern/libmv/libmv/simple_pipeline/bundle.cc
@@ -66,18 +66,87 @@ enum {
namespace {
-// Cost functor which computes reprojection error of 3D point X
-// on camera defined by angle-axis rotation and it's translation
-// (which are in the same block due to optimization reasons).
+// Apply distortion model (distort the input) on the input point in the
+// normalized space to get distorted coordinate in the image space.
//
-// This functor uses a radial distortion model.
-struct OpenCVReprojectionError {
- OpenCVReprojectionError(const DistortionModelType distortion_model,
- const double observed_x,
- const double observed_y,
- const double weight)
- : distortion_model_(distortion_model),
- observed_x_(observed_x), observed_y_(observed_y),
+// Using intrinsics values from the parameter block, which makes this function
+// suitable for use from a cost functor.
+//
+// Only use for distortion models which are analytically defined for their
+// Apply() function.
+//
+// The invariant_intrinsics are used to access intrinsics which are never
+// packed into parameter block: for example, distortion model type and image
+// dimension.
+template<typename T>
+void ApplyDistortionModelUsingIntrinsicsBlock(
+ const CameraIntrinsics *invariant_intrinsics,
+ const T* const intrinsics_block,
+ const T& normalized_x, const T& normalized_y,
+ T* distorted_x, T* distorted_y) {
+ // Unpack the intrinsics.
+ const T& focal_length = intrinsics_block[OFFSET_FOCAL_LENGTH];
+ const T& principal_point_x = intrinsics_block[OFFSET_PRINCIPAL_POINT_X];
+ const T& principal_point_y = intrinsics_block[OFFSET_PRINCIPAL_POINT_Y];
+
+ // Apply distortion to the normalized points to get (xd, yd).
+ //
+ // TODO(keir): Do early bailouts for zero distortion; these are expensive
+ // jet operations.
+ switch (invariant_intrinsics->GetDistortionModelType()) {
+ case DISTORTION_MODEL_POLYNOMIAL:
+ {
+ const T& k1 = intrinsics_block[OFFSET_K1];
+ const T& k2 = intrinsics_block[OFFSET_K2];
+ const T& k3 = intrinsics_block[OFFSET_K3];
+ const T& p1 = intrinsics_block[OFFSET_P1];
+ const T& p2 = intrinsics_block[OFFSET_P2];
+
+ ApplyPolynomialDistortionModel(focal_length,
+ focal_length,
+ principal_point_x,
+ principal_point_y,
+ k1, k2, k3,
+ p1, p2,
+ normalized_x, normalized_y,
+ distorted_x, distorted_y);
+ return;
+ }
+
+ case DISTORTION_MODEL_DIVISION:
+ {
+ const T& k1 = intrinsics_block[OFFSET_K1];
+ const T& k2 = intrinsics_block[OFFSET_K2];
+
+ ApplyDivisionDistortionModel(focal_length,
+ focal_length,
+ principal_point_x,
+ principal_point_y,
+ k1, k2,
+ normalized_x, normalized_y,
+ distorted_x, distorted_y);
+ return;
+ }
+ }
+
+ LOG(FATAL) << "Unknown distortion model.";
+}
+
+// Cost functor which computes reprojection error of 3D point X on camera
+// defined by angle-axis rotation and it's translation (which are in the same
+// block due to optimization reasons).
+//
+// This functor can only be used for distortion models which have analytically
+// defined Apply() function.
+struct ReprojectionErrorApplyIntrinsics {
+ ReprojectionErrorApplyIntrinsics(
+ const CameraIntrinsics *invariant_intrinsics,
+ const double observed_distorted_x,
+ const double observed_distorted_y,
+ const double weight)
+ : invariant_intrinsics_(invariant_intrinsics),
+ observed_distorted_x_(observed_distorted_x),
+ observed_distorted_y_(observed_distorted_y),
weight_(weight) {}
template <typename T>
@@ -86,11 +155,6 @@ struct OpenCVReprojectionError {
// followed with translation
const T* const X, // Point coordinates 3x1.
T* residuals) const {
- // Unpack the intrinsics.
- const T& focal_length = intrinsics[OFFSET_FOCAL_LENGTH];
- const T& principal_point_x = intrinsics[OFFSET_PRINCIPAL_POINT_X];
- const T& principal_point_y = intrinsics[OFFSET_PRINCIPAL_POINT_Y];
-
// Compute projective coordinates: x = RX + t.
T x[3];
@@ -108,63 +172,26 @@ struct OpenCVReprojectionError {
T xn = x[0] / x[2];
T yn = x[1] / x[2];
- T predicted_x, predicted_y;
-
- // Apply distortion to the normalized points to get (xd, yd).
- // TODO(keir): Do early bailouts for zero distortion; these are expensive
- // jet operations.
- switch (distortion_model_) {
- case DISTORTION_MODEL_POLYNOMIAL:
- {
- const T& k1 = intrinsics[OFFSET_K1];
- const T& k2 = intrinsics[OFFSET_K2];
- const T& k3 = intrinsics[OFFSET_K3];
- const T& p1 = intrinsics[OFFSET_P1];
- const T& p2 = intrinsics[OFFSET_P2];
-
- ApplyPolynomialDistortionModel(focal_length,
- focal_length,
- principal_point_x,
- principal_point_y,
- k1, k2, k3,
- p1, p2,
- xn, yn,
- &predicted_x,
- &predicted_y);
- break;
- }
- case DISTORTION_MODEL_DIVISION:
- {
- const T& k1 = intrinsics[OFFSET_K1];
- const T& k2 = intrinsics[OFFSET_K2];
-
- ApplyDivisionDistortionModel(focal_length,
- focal_length,
- principal_point_x,
- principal_point_y,
- k1, k2,
- xn, yn,
- &predicted_x,
- &predicted_y);
- break;
- }
- default:
- LOG(FATAL) << "Unknown distortion model";
- }
+ T predicted_distorted_x, predicted_distorted_y;
+ ApplyDistortionModelUsingIntrinsicsBlock(
+ invariant_intrinsics_,
+ intrinsics,
+ xn, yn,
+ &predicted_distorted_x, &predicted_distorted_y);
// The error is the difference between the predicted and observed position.
- residuals[0] = (predicted_x - T(observed_x_)) * weight_;
- residuals[1] = (predicted_y - T(observed_y_)) * weight_;
+ residuals[0] = (predicted_distorted_x - T(observed_distorted_x_)) * weight_;
+ residuals[1] = (predicted_distorted_y - T(observed_distorted_y_)) * weight_;
return true;
}
- const DistortionModelType distortion_model_;
- const double observed_x_;
- const double observed_y_;
+ const CameraIntrinsics *invariant_intrinsics_;
+ const double observed_distorted_x_;
+ const double observed_distorted_y_;
const double weight_;
};
-// Print a message to the log which camera intrinsics are gonna to be optimixed.
+// Print a message to the log which camera intrinsics are gonna to be optimized.
void BundleIntrinsicsLogMessage(const int bundle_intrinsics) {
if (bundle_intrinsics == BUNDLE_NO_INTRINSICS) {
LOG(INFO) << "Bundling only camera positions.";
@@ -193,29 +220,29 @@ void BundleIntrinsicsLogMessage(const int bundle_intrinsics) {
// Pack intrinsics from object to an array for easier
// and faster minimization.
void PackIntrinisicsIntoArray(const CameraIntrinsics &intrinsics,
- double ceres_intrinsics[OFFSET_MAX]) {
- ceres_intrinsics[OFFSET_FOCAL_LENGTH] = intrinsics.focal_length();
- ceres_intrinsics[OFFSET_PRINCIPAL_POINT_X] = intrinsics.principal_point_x();
- ceres_intrinsics[OFFSET_PRINCIPAL_POINT_Y] = intrinsics.principal_point_y();
+ double intrinsics_block[OFFSET_MAX]) {
+ intrinsics_block[OFFSET_FOCAL_LENGTH] = intrinsics.focal_length();
+ intrinsics_block[OFFSET_PRINCIPAL_POINT_X] = intrinsics.principal_point_x();
+ intrinsics_block[OFFSET_PRINCIPAL_POINT_Y] = intrinsics.principal_point_y();
int num_distortion_parameters = intrinsics.num_distortion_parameters();
assert(num_distortion_parameters <= NUM_DISTORTION_COEFFICIENTS);
const double *distortion_parameters = intrinsics.distortion_parameters();
for (int i = 0; i < num_distortion_parameters; ++i) {
- ceres_intrinsics[FIRST_DISTORTION_COEFFICIENT + i] =
+ intrinsics_block[FIRST_DISTORTION_COEFFICIENT + i] =
distortion_parameters[i];
}
}
// Unpack intrinsics back from an array to an object.
-void UnpackIntrinsicsFromArray(const double ceres_intrinsics[OFFSET_MAX],
+void UnpackIntrinsicsFromArray(const double intrinsics_block[OFFSET_MAX],
CameraIntrinsics *intrinsics) {
- intrinsics->SetFocalLength(ceres_intrinsics[OFFSET_FOCAL_LENGTH],
- ceres_intrinsics[OFFSET_FOCAL_LENGTH]);
+ intrinsics->SetFocalLength(intrinsics_block[OFFSET_FOCAL_LENGTH],
+ intrinsics_block[OFFSET_FOCAL_LENGTH]);
- intrinsics->SetPrincipalPoint(ceres_intrinsics[OFFSET_PRINCIPAL_POINT_X],
- ceres_intrinsics[OFFSET_PRINCIPAL_POINT_Y]);
+ intrinsics->SetPrincipalPoint(intrinsics_block[OFFSET_PRINCIPAL_POINT_X],
+ intrinsics_block[OFFSET_PRINCIPAL_POINT_Y]);
int num_distortion_parameters = intrinsics->num_distortion_parameters();
assert(num_distortion_parameters <= NUM_DISTORTION_COEFFICIENTS);
@@ -223,7 +250,7 @@ void UnpackIntrinsicsFromArray(const double ceres_intrinsics[OFFSET_MAX],
double *distortion_parameters = intrinsics->distortion_parameters();
for (int i = 0; i < num_distortion_parameters; ++i) {
distortion_parameters[i] =
- ceres_intrinsics[FIRST_DISTORTION_COEFFICIENT + i];
+ intrinsics_block[FIRST_DISTORTION_COEFFICIENT + i];
}
}
@@ -302,68 +329,106 @@ void EuclideanBundlerPerformEvaluation(const Tracks &tracks,
vector<Vec6> *all_cameras_R_t,
ceres::Problem *problem,
BundleEvaluation *evaluation) {
- int max_track = tracks.MaxTrack();
- // Number of camera rotations equals to number of translation,
- int num_cameras = all_cameras_R_t->size();
- int num_points = 0;
-
- vector<EuclideanPoint*> minimized_points;
- for (int i = 0; i <= max_track; i++) {
- EuclideanPoint *point = reconstruction->PointForTrack(i);
- if (point) {
- // We need to know whether the track is constant zero weight,
- // and it so it wouldn't have parameter block in the problem.
- //
- // Getting all markers for track is not so bac currently since
- // this code is only used by keyframe selection when there are
- // not so much tracks and only 2 frames anyway.
- vector<Marker> markera_of_track = tracks.MarkersForTrack(i);
- for (int j = 0; j < markera_of_track.size(); j++) {
- if (markera_of_track.at(j).weight != 0.0) {
- minimized_points.push_back(point);
- num_points++;
- break;
- }
+ int max_track = tracks.MaxTrack();
+ // Number of camera rotations equals to number of translation,
+ int num_cameras = all_cameras_R_t->size();
+ int num_points = 0;
+
+ vector<EuclideanPoint*> minimized_points;
+ for (int i = 0; i <= max_track; i++) {
+ EuclideanPoint *point = reconstruction->PointForTrack(i);
+ if (point) {
+ // We need to know whether the track is a constant zero weight.
+ // If it is so it wouldn't have a parameter block in the problem.
+ //
+ // Usually getting all markers of a track is considered slow, but this
+ // code is only used by the keyframe selection code where there aren't
+ // that many tracks in the storage and there are only 2 frames for each
+ // of the tracks.
+ vector<Marker> markera_of_track = tracks.MarkersForTrack(i);
+ for (int j = 0; j < markera_of_track.size(); j++) {
+ if (markera_of_track.at(j).weight != 0.0) {
+ minimized_points.push_back(point);
+ num_points++;
+ break;
}
}
}
+ }
- LG << "Number of cameras " << num_cameras;
- LG << "Number of points " << num_points;
+ LG << "Number of cameras " << num_cameras;
+ LG << "Number of points " << num_points;
- evaluation->num_cameras = num_cameras;
- evaluation->num_points = num_points;
+ evaluation->num_cameras = num_cameras;
+ evaluation->num_points = num_points;
- if (evaluation->evaluate_jacobian) { // Evaluate jacobian matrix.
- ceres::CRSMatrix evaluated_jacobian;
- ceres::Problem::EvaluateOptions eval_options;
+ if (evaluation->evaluate_jacobian) { // Evaluate jacobian matrix.
+ ceres::CRSMatrix evaluated_jacobian;
+ ceres::Problem::EvaluateOptions eval_options;
- // Cameras goes first in the ordering.
- int max_image = tracks.MaxImage();
- for (int i = 0; i <= max_image; i++) {
- const EuclideanCamera *camera = reconstruction->CameraForImage(i);
- if (camera) {
- double *current_camera_R_t = &(*all_cameras_R_t)[i](0);
+ // Cameras goes first in the ordering.
+ int max_image = tracks.MaxImage();
+ for (int i = 0; i <= max_image; i++) {
+ const EuclideanCamera *camera = reconstruction->CameraForImage(i);
+ if (camera) {
+ double *current_camera_R_t = &(*all_cameras_R_t)[i](0);
- // All cameras are variable now.
- problem->SetParameterBlockVariable(current_camera_R_t);
+ // All cameras are variable now.
+ problem->SetParameterBlockVariable(current_camera_R_t);
- eval_options.parameter_blocks.push_back(current_camera_R_t);
- }
+ eval_options.parameter_blocks.push_back(current_camera_R_t);
}
+ }
- // Points goes at the end of ordering,
- for (int i = 0; i < minimized_points.size(); i++) {
- EuclideanPoint *point = minimized_points.at(i);
- eval_options.parameter_blocks.push_back(&point->X(0));
- }
+ // Points goes at the end of ordering,
+ for (int i = 0; i < minimized_points.size(); i++) {
+ EuclideanPoint *point = minimized_points.at(i);
+ eval_options.parameter_blocks.push_back(&point->X(0));
+ }
- problem->Evaluate(eval_options,
- NULL, NULL, NULL,
- &evaluated_jacobian);
+ problem->Evaluate(eval_options,
+ NULL, NULL, NULL,
+ &evaluated_jacobian);
- CRSMatrixToEigenMatrix(evaluated_jacobian, &evaluation->jacobian);
- }
+ CRSMatrixToEigenMatrix(evaluated_jacobian, &evaluation->jacobian);
+ }
+}
+
+template<typename CostFunction>
+void AddResidualBlockToProblemImpl(const CameraIntrinsics *invariant_intrinsics,
+ double observed_x, double observed_y,
+ double weight,
+ double intrinsics_block[OFFSET_MAX],
+ double *camera_R_t,
+ EuclideanPoint *point,
+ ceres::Problem* problem) {
+ problem->AddResidualBlock(new ceres::AutoDiffCostFunction<
+ CostFunction, 2, OFFSET_MAX, 6, 3>(
+ new CostFunction(
+ invariant_intrinsics,
+ observed_x, observed_y,
+ weight)),
+ NULL,
+ intrinsics_block,
+ camera_R_t,
+ &point->X(0));
+}
+
+void AddResidualBlockToProblem(const CameraIntrinsics *invariant_intrinsics,
+ const Marker &marker,
+ double marker_weight,
+ double intrinsics_block[OFFSET_MAX],
+ double *camera_R_t,
+ EuclideanPoint *point,
+ ceres::Problem* problem) {
+ AddResidualBlockToProblemImpl<ReprojectionErrorApplyIntrinsics>(
+ invariant_intrinsics,
+ marker.x, marker.y,
+ marker_weight,
+ intrinsics_block,
+ camera_R_t,
+ point,
+ problem);
}
// This is an utility function to only bundle 3D position of
@@ -375,10 +440,10 @@ void EuclideanBundlerPerformEvaluation(const Tracks &tracks,
//
// At this point we only need to bundle points positions, cameras
// are to be totally still here.
-void EuclideanBundlePointsOnly(const DistortionModelType distortion_model,
+void EuclideanBundlePointsOnly(const CameraIntrinsics *invariant_intrinsics,
const vector<Marker> &markers,
vector<Vec6> &all_cameras_R_t,
- double ceres_intrinsics[OFFSET_MAX],
+ double intrinsics_block[OFFSET_MAX],
EuclideanReconstruction *reconstruction) {
ceres::Problem::Options problem_options;
ceres::Problem problem(problem_options);
@@ -392,20 +457,16 @@ void EuclideanBundlePointsOnly(const DistortionModelType distortion_model,
}
// Rotation of camera denoted in angle axis followed with
- // camera translaiton.
+ // camera translation.
double *current_camera_R_t = &all_cameras_R_t[camera->image](0);
- problem.AddResidualBlock(new ceres::AutoDiffCostFunction<
- OpenCVReprojectionError, 2, OFFSET_MAX, 6, 3>(
- new OpenCVReprojectionError(
- distortion_model,
- marker.x,
- marker.y,
- 1.0)),
- NULL,
- ceres_intrinsics,
- current_camera_R_t,
- &point->X(0));
+ AddResidualBlockToProblem(invariant_intrinsics,
+ marker,
+ 1.0,
+ intrinsics_block,
+ current_camera_R_t,
+ point,
+ &problem);
problem.SetParameterBlockConstant(current_camera_R_t);
num_residuals++;
@@ -417,7 +478,7 @@ void EuclideanBundlePointsOnly(const DistortionModelType distortion_model,
return;
}
- problem.SetParameterBlockConstant(ceres_intrinsics);
+ problem.SetParameterBlockConstant(intrinsics_block);
// Configure the solver.
ceres::Solver::Options options;
@@ -438,7 +499,6 @@ void EuclideanBundlePointsOnly(const DistortionModelType distortion_model,
ceres::Solve(options, &problem, &summary);
LG << "Final report:\n" << summary.FullReport();
-
}
} // namespace
@@ -464,14 +524,14 @@ void EuclideanBundleCommonIntrinsics(
LG << "Original intrinsics: " << *intrinsics;
vector<Marker> markers = tracks.AllMarkers();
- // N-th element denotes whether track N is a constant zero-weigthed track.
+ // N-th element denotes whether track N is a constant zero-weighted track.
vector<bool> zero_weight_tracks_flags(tracks.MaxTrack() + 1, true);
// Residual blocks with 10 parameters are unwieldly with Ceres, so pack the
// intrinsics into a single block and rely on local parameterizations to
// control which intrinsics are allowed to vary.
- double ceres_intrinsics[OFFSET_MAX];
- PackIntrinisicsIntoArray(*intrinsics, ceres_intrinsics);
+ double intrinsics_block[OFFSET_MAX];
+ PackIntrinisicsIntoArray(*intrinsics, intrinsics_block);
// Convert cameras rotations to angle axis and merge with translation
// into single parameter block for maximal minimization speed.
@@ -509,24 +569,20 @@ void EuclideanBundleCommonIntrinsics(
}
// Rotation of camera denoted in angle axis followed with
- // camera translaiton.
+ // camera translation.
double *current_camera_R_t = &all_cameras_R_t[camera->image](0);
// Skip residual block for markers which does have absolutely
// no affect on the final solution.
// This way ceres is not gonna to go crazy.
if (marker.weight != 0.0) {
- problem.AddResidualBlock(new ceres::AutoDiffCostFunction<
- OpenCVReprojectionError, 2, OFFSET_MAX, 6, 3>(
- new OpenCVReprojectionError(
- intrinsics->GetDistortionModelType(),
- marker.x,
- marker.y,
- marker.weight)),
- NULL,
- ceres_intrinsics,
- current_camera_R_t,
- &point->X(0));
+ AddResidualBlockToProblem(intrinsics,
+ marker,
+ marker.weight,
+ intrinsics_block,
+ current_camera_R_t,
+ point,
+ &problem);
// We lock the first camera to better deal with scene orientation ambiguity.
if (!have_locked_camera) {
@@ -561,7 +617,7 @@ void EuclideanBundleCommonIntrinsics(
if (bundle_intrinsics == BUNDLE_NO_INTRINSICS) {
// No camera intrinsics are being refined,
// set the whole parameter block as constant for best performance.
- problem.SetParameterBlockConstant(ceres_intrinsics);
+ problem.SetParameterBlockConstant(intrinsics_block);
} else {
// Set the camera intrinsics that are not to be bundled as
// constant using some macro trickery.
@@ -586,7 +642,7 @@ void EuclideanBundleCommonIntrinsics(
ceres::SubsetParameterization *subset_parameterization =
new ceres::SubsetParameterization(OFFSET_MAX, constant_intrinsics);
- problem.SetParameterization(ceres_intrinsics, subset_parameterization);
+ problem.SetParameterization(intrinsics_block, subset_parameterization);
}
// Configure the solver.
@@ -616,7 +672,7 @@ void EuclideanBundleCommonIntrinsics(
// Copy intrinsics back.
if (bundle_intrinsics != BUNDLE_NO_INTRINSICS)
- UnpackIntrinsicsFromArray(ceres_intrinsics, intrinsics);
+ UnpackIntrinsicsFromArray(intrinsics_block, intrinsics);
LG << "Final intrinsics: " << *intrinsics;
@@ -641,10 +697,10 @@ void EuclideanBundleCommonIntrinsics(
if (zero_weight_markers.size()) {
LG << "Refining position of constant zero-weighted tracks";
- EuclideanBundlePointsOnly(intrinsics->GetDistortionModelType(),
+ EuclideanBundlePointsOnly(intrinsics,
zero_weight_markers,
all_cameras_R_t,
- ceres_intrinsics,
+ intrinsics_block,
reconstruction);
}
}
diff --git a/intern/mantaflow/extern/manta_fluid_API.h b/intern/mantaflow/extern/manta_fluid_API.h
index 85cc04b4a52..7825ad14d7d 100644
--- a/intern/mantaflow/extern/manta_fluid_API.h
+++ b/intern/mantaflow/extern/manta_fluid_API.h
@@ -107,6 +107,7 @@ float *manta_get_phistatic_in(struct MANTA *fluid);
float *manta_get_phiobs_in(struct MANTA *fluid);
float *manta_get_phiobsstatic_in(struct MANTA *fluid);
float *manta_get_phiout_in(struct MANTA *fluid);
+float *manta_get_phioutstatic_in(struct MANTA *fluid);
/* Smoke functions */
void manta_smoke_export_script(struct MANTA *smoke, struct FluidModifierData *mmd);
diff --git a/intern/mantaflow/intern/MANTA_main.cpp b/intern/mantaflow/intern/MANTA_main.cpp
index 79c8625ec48..a56ce4c1f60 100644
--- a/intern/mantaflow/intern/MANTA_main.cpp
+++ b/intern/mantaflow/intern/MANTA_main.cpp
@@ -61,28 +61,29 @@ int MANTA::with_debug(0);
MANTA::MANTA(int *res, FluidModifierData *mmd) : mCurrentID(++solverID)
{
if (with_debug)
- std::cout << "MANTA: " << mCurrentID << " with res(" << res[0] << ", " << res[1] << ", "
+ std::cout << "FLUID: " << mCurrentID << " with res(" << res[0] << ", " << res[1] << ", "
<< res[2] << ")" << std::endl;
mmd->domain->fluid = this;
mUsingLiquid = (mmd->domain->type == FLUID_DOMAIN_TYPE_LIQUID);
mUsingSmoke = (mmd->domain->type == FLUID_DOMAIN_TYPE_GAS);
- mUsingHeat = (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_HEAT) && mUsingSmoke;
- mUsingFire = (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_FIRE) && mUsingSmoke;
- mUsingColors = (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_COLORS) && mUsingSmoke;
mUsingNoise = (mmd->domain->flags & FLUID_DOMAIN_USE_NOISE) && mUsingSmoke;
mUsingFractions = (mmd->domain->flags & FLUID_DOMAIN_USE_FRACTIONS) && mUsingLiquid;
+ mUsingMesh = (mmd->domain->flags & FLUID_DOMAIN_USE_MESH) && mUsingLiquid;
+ mUsingMVel = (mmd->domain->flags & FLUID_DOMAIN_USE_SPEED_VECTORS) && mUsingLiquid;
+ mUsingGuiding = (mmd->domain->flags & FLUID_DOMAIN_USE_GUIDE);
mUsingDrops = (mmd->domain->particle_type & FLUID_DOMAIN_PARTICLE_SPRAY) && mUsingLiquid;
mUsingBubbles = (mmd->domain->particle_type & FLUID_DOMAIN_PARTICLE_BUBBLE) && mUsingLiquid;
mUsingFloats = (mmd->domain->particle_type & FLUID_DOMAIN_PARTICLE_FOAM) && mUsingLiquid;
mUsingTracers = (mmd->domain->particle_type & FLUID_DOMAIN_PARTICLE_TRACER) && mUsingLiquid;
- mUsingMesh = (mmd->domain->flags & FLUID_DOMAIN_USE_MESH) && mUsingLiquid;
- mUsingMVel = (mmd->domain->flags & FLUID_DOMAIN_USE_SPEED_VECTORS) && mUsingLiquid;
+
+ mUsingHeat = (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_HEAT) && mUsingSmoke;
+ mUsingFire = (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_FIRE) && mUsingSmoke;
+ mUsingColors = (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_COLORS) && mUsingSmoke;
mUsingObstacle = (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_OBSTACLE);
mUsingInvel = (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_INVEL);
mUsingOutflow = (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_OUTFLOW);
- mUsingGuiding = (mmd->domain->flags & FLUID_DOMAIN_USE_GUIDE);
// Simulation constants
mTempAmb = 0; // TODO: Maybe use this later for buoyancy calculation
@@ -140,6 +141,7 @@ MANTA::MANTA(int *res, FluidModifierData *mmd) : mCurrentID(++solverID)
mPhiIn = nullptr;
mPhiStaticIn = nullptr;
mPhiOutIn = nullptr;
+ mPhiOutStaticIn = nullptr;
mPhi = nullptr;
// Mesh
@@ -566,7 +568,7 @@ bool MANTA::runPythonString(std::vector<std::string> commands)
void MANTA::initializeMantaflow()
{
if (with_debug)
- std::cout << "Fluid: Initializing Mantaflow framework." << std::endl;
+ std::cout << "Fluid: Initializing Mantaflow framework" << std::endl;
std::string filename = "manta_scene_" + std::to_string(mCurrentID) + ".py";
std::vector<std::string> fill = std::vector<std::string>();
@@ -581,7 +583,7 @@ void MANTA::initializeMantaflow()
void MANTA::terminateMantaflow()
{
if (with_debug)
- std::cout << "Fluid: Releasing Mantaflow framework." << std::endl;
+ std::cout << "Fluid: Releasing Mantaflow framework" << std::endl;
PyGILState_STATE gilstate = PyGILState_Ensure();
Pb::finalize(); // Namespace from Mantaflow (registry)
@@ -1078,8 +1080,7 @@ bool MANTA::updateFlipStructures(FluidModifierData *mmd, int framenr)
assert(result == expected);
}
- mFlipFromFile = true;
- return (result == expected);
+ return mFlipFromFile = (result == expected);
}
bool MANTA::updateMeshStructures(FluidModifierData *mmd, int framenr)
@@ -1126,8 +1127,7 @@ bool MANTA::updateMeshStructures(FluidModifierData *mmd, int framenr)
}
}
- mMeshFromFile = true;
- return (result == expected);
+ return mMeshFromFile = (result == expected);
}
bool MANTA::updateParticleStructures(FluidModifierData *mmd, int framenr)
@@ -1177,8 +1177,7 @@ bool MANTA::updateParticleStructures(FluidModifierData *mmd, int framenr)
assert(result == expected);
}
- mParticlesFromFile = true;
- return (result == expected);
+ return mParticlesFromFile = (result == expected);
}
bool MANTA::updateSmokeStructures(FluidModifierData *mmd, int framenr)
@@ -1268,8 +1267,7 @@ bool MANTA::updateSmokeStructures(FluidModifierData *mmd, int framenr)
}
}
- mSmokeFromFile = true;
- return (result == expected);
+ return mSmokeFromFile = (result == expected);
}
bool MANTA::updateNoiseStructures(FluidModifierData *mmd, int framenr)
@@ -1351,8 +1349,7 @@ bool MANTA::updateNoiseStructures(FluidModifierData *mmd, int framenr)
}
}
- mNoiseFromFile = true;
- return (result == expected);
+ return mNoiseFromFile = (result == expected);
}
/* Dirty hack: Needed to format paths from python code that is run via PyRun_SimpleString */
@@ -1930,6 +1927,7 @@ void MANTA::exportSmokeScript(FluidModifierData *mmd)
bool obstacle = mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_OBSTACLE;
bool guiding = mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_GUIDE;
bool invel = mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_INVEL;
+ bool outflow = mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_OUTFLOW;
std::string manta_script;
@@ -1972,6 +1970,8 @@ void MANTA::exportSmokeScript(FluidModifierData *mmd)
manta_script += fluid_alloc_obstacle;
if (invel)
manta_script += fluid_alloc_invel;
+ if (outflow)
+ manta_script += fluid_alloc_outflow;
// Noise field
if (noise)
@@ -2036,6 +2036,7 @@ void MANTA::exportLiquidScript(FluidModifierData *mmd)
bool fractions = mmd->domain->flags & FLUID_DOMAIN_USE_FRACTIONS;
bool guiding = mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_GUIDE;
bool invel = mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_INVEL;
+ bool outflow = mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_OUTFLOW;
std::string manta_script;
@@ -2074,6 +2075,8 @@ void MANTA::exportLiquidScript(FluidModifierData *mmd)
manta_script += fluid_alloc_fractions;
if (invel)
manta_script += fluid_alloc_invel;
+ if (outflow)
+ manta_script += fluid_alloc_outflow;
// Domain init
manta_script += header_gridinit + liquid_init_phi;
@@ -2748,10 +2751,10 @@ bool MANTA::updateParticlesFromUni(std::string filename, bool isSecondarySys, bo
return false;
}
if (!ibuffer[0]) { // Any particles present?
- std::cerr << "Fluid Error -- updateParticlesFromUni(): No particles present in file: "
- << filename << std::endl;
+ if (with_debug)
+ std::cout << "Fluid: No particles present in file: " << filename << std::endl;
gzclose(gzf);
- return false;
+ return true; // return true since having no particles in a cache file is valid
}
numParticles = ibuffer[0];
@@ -3123,6 +3126,8 @@ void MANTA::updatePointers()
if (mUsingOutflow) {
mPhiOutIn = (float *)pyObjectToPointer(callPythonFunction("phiOutIn" + solver_ext, func));
+ mPhiOutStaticIn = (float *)pyObjectToPointer(
+ callPythonFunction("phiOutSIn" + solver_ext, func));
}
if (mUsingObstacle) {
mPhiObsIn = (float *)pyObjectToPointer(callPythonFunction("phiObsIn" + solver_ext, func));
@@ -3234,7 +3239,7 @@ bool MANTA::hasConfig(FluidModifierData *mmd, int framenr)
bool MANTA::hasData(FluidModifierData *mmd, int framenr)
{
- std::string filename = (mUsingSmoke) ? FLUID_DOMAIN_FILE_DENSITY : FLUID_DOMAIN_FILE_PHI;
+ std::string filename = (mUsingSmoke) ? FLUID_DOMAIN_FILE_DENSITY : FLUID_DOMAIN_FILE_PP;
std::string extension = getCacheFileEnding(mmd->domain->cache_data_format);
return BLI_exists(getFile(mmd, FLUID_DOMAIN_DIR_DATA, filename, extension, framenr).c_str());
}
diff --git a/intern/mantaflow/intern/MANTA_main.h b/intern/mantaflow/intern/MANTA_main.h
index caac63d8e39..21946431f28 100644
--- a/intern/mantaflow/intern/MANTA_main.h
+++ b/intern/mantaflow/intern/MANTA_main.h
@@ -405,6 +405,10 @@ struct MANTA {
{
return mPhiOutIn;
}
+ inline float *getPhiOutStaticIn()
+ {
+ return mPhiOutStaticIn;
+ }
inline float *getPhi()
{
return mPhi;
@@ -844,6 +848,7 @@ struct MANTA {
float *mPhiObsStaticIn;
float *mPhiGuideIn;
float *mPhiOutIn;
+ float *mPhiOutStaticIn;
float *mPhi;
// Mesh fields
diff --git a/intern/mantaflow/intern/manta_fluid_API.cpp b/intern/mantaflow/intern/manta_fluid_API.cpp
index b4582051c3c..49bc224b3fa 100644
--- a/intern/mantaflow/intern/manta_fluid_API.cpp
+++ b/intern/mantaflow/intern/manta_fluid_API.cpp
@@ -390,6 +390,10 @@ float *manta_get_phiout_in(MANTA *fluid)
{
return fluid->getPhiOutIn();
}
+float *manta_get_phioutstatic_in(MANTA *fluid)
+{
+ return fluid->getPhiOutStaticIn();
+}
/* Smoke functions */
void manta_smoke_export_script(MANTA *smoke, FluidModifierData *mmd)
diff --git a/intern/mantaflow/intern/strings/fluid_script.h b/intern/mantaflow/intern/strings/fluid_script.h
index 0aad0546aea..dd2111db7d7 100644
--- a/intern/mantaflow/intern/strings/fluid_script.h
+++ b/intern/mantaflow/intern/strings/fluid_script.h
@@ -261,7 +261,7 @@ const std::string fluid_alloc_obstacle =
"\n\
mantaMsg('Allocating obstacle data')\n\
numObs_s$ID$ = s$ID$.create(RealGrid)\n\
-phiObsSIn_s$ID$ = s$ID$.create(LevelsetGrid) # helper for static obstacles\n\
+phiObsSIn_s$ID$ = s$ID$.create(LevelsetGrid) # helper for static obstacle objects\n\
phiObsIn_s$ID$ = s$ID$.create(LevelsetGrid)\n\
obvel_s$ID$ = s$ID$.create(MACGrid)\n\
obvelC_s$ID$ = s$ID$.create(Vec3Grid)\n\
@@ -311,7 +311,15 @@ z_invel_s$ID$ = s$ID$.create(RealGrid)\n";
const std::string fluid_alloc_outflow =
"\n\
mantaMsg('Allocating outflow data')\n\
-phiOutIn_s$ID$ = s$ID$.create(LevelsetGrid)\n";
+phiOutSIn_s$ID$ = s$ID$.create(LevelsetGrid) # helper for static outflow objects\n\
+phiOutIn_s$ID$ = s$ID$.create(LevelsetGrid)\n\
+\n\
+# Set some initial values\n\
+phiOutSIn_s$ID$.setConst(9999)\n\
+phiOutIn_s$ID$.setConst(9999)\n\
+\n\
+if 'fluid_data_dict_resume_s$ID$' in globals():\n\
+ fluid_data_dict_resume_s$ID$.update(phiOutIn=phiOutIn_s$ID$)\n";
//////////////////////////////////////////////////////////////////////
// PRE / POST STEP
@@ -527,7 +535,6 @@ def bake_noise_process_$ID$(framenr, format_data, format_noise, path_data, path_
sn$ID$.timestep = frameLength_s$ID$ # no adaptive timestep for noise\n\
\n\
smoke_step_noise_$ID$(framenr)\n\
- smoke_save_noise_$ID$(path_noise, framenr, format_noise, resumable)\n\
\n\
def bake_noise_$ID$(path_data, path_noise, framenr, format_data, format_noise, resumable):\n\
if not withMPBake or isWindows:\n\
diff --git a/intern/mantaflow/intern/strings/liquid_script.h b/intern/mantaflow/intern/strings/liquid_script.h
index b0bf6f85914..f20b218427c 100644
--- a/intern/mantaflow/intern/strings/liquid_script.h
+++ b/intern/mantaflow/intern/strings/liquid_script.h
@@ -173,14 +173,14 @@ def liquid_adaptive_step_$ID$(framenr):\n\
if using_obstacle_s$ID$:\n\
mantaMsg('Initializing obstacle levelset')\n\
phiObsIn_s$ID$.join(phiObsSIn_s$ID$) # Join static obstacle map\n\
- phiObsIn_s$ID$.fillHoles(maxDepth=int(res_s$ID$), boundaryWidth=2)\n\
+ phiObsIn_s$ID$.fillHoles(maxDepth=int(res_s$ID$), boundaryWidth=1)\n\
extrapolateLsSimple(phi=phiObsIn_s$ID$, distance=6, inside=True)\n\
extrapolateLsSimple(phi=phiObsIn_s$ID$, distance=3, inside=False)\n\
phiObs_s$ID$.join(phiObsIn_s$ID$)\n\
\n\
# Using boundaryWidth=2 to not search beginning from walls (just a performance optimization)\n\
# Additional sanity check: fill holes in phiObs which can result after joining with phiObsIn\n\
- phiObs_s$ID$.fillHoles(maxDepth=int(res_s$ID$), boundaryWidth=2)\n\
+ phiObs_s$ID$.fillHoles(maxDepth=int(res_s$ID$), boundaryWidth=2 if using_fractions_s$ID$ else 1)\n\
extrapolateLsSimple(phi=phiObs_s$ID$, distance=6, inside=True)\n\
extrapolateLsSimple(phi=phiObs_s$ID$, distance=3)\n\
\n\
@@ -191,6 +191,7 @@ def liquid_adaptive_step_$ID$(framenr):\n\
phi_s$ID$.join(phiIn_s$ID$)\n\
\n\
if using_outflow_s$ID$:\n\
+ phiOutIn_s$ID$.join(phiOutSIn_s$ID$) # Join static outflow map\n\
phiOut_s$ID$.join(phiOutIn_s$ID$)\n\
\n\
if using_fractions_s$ID$:\n\
@@ -206,6 +207,9 @@ def liquid_adaptive_step_$ID$(framenr):\n\
extrapolateVec3Simple(vel=invelC_s$ID$, phi=phiIn_s$ID$, distance=6, inside=True)\n\
resampleVec3ToMac(source=invelC_s$ID$, target=invel_s$ID$)\n\
pVel_pp$ID$.setSource(invel_s$ID$, isMAC=True)\n\
+ # ensure that pvel has vel as source (important when resuming bake jobs)\n\
+ else:\n\
+ pVel_pp$ID$.setSource(vel_s$ID$, isMAC=True)\n\
\n\
sampleLevelsetWithParticles(phi=phiIn_s$ID$, flags=flags_s$ID$, parts=pp_s$ID$, discretization=particleNumber_s$ID$, randomness=randomness_s$ID$)\n\
flags_s$ID$.updateFromLevelset(phi_s$ID$)\n\
@@ -363,7 +367,7 @@ def liquid_step_particles_$ID$():\n\
interpolateGrid(target=phiOut_sp$ID$, source=phiOut_s$ID$)\n\
\n\
# phiIn not needed, bwidth to 0 because we are omitting flags.initDomain()\n\
- setObstacleFlags(flags=flags_sp$ID$, phiObs=phiObs_sp$ID$, phiOut=None, phiIn=None, boundaryWidth=0)\n\
+ setObstacleFlags(flags=flags_sp$ID$, phiObs=phiObs_sp$ID$, phiOut=phiOut_sp$ID$, phiIn=None, boundaryWidth=0)\n\
flags_sp$ID$.updateFromLevelset(levelset=phi_sp$ID$)\n\
\n\
# Actual secondary particle simulation\n\
diff --git a/intern/mantaflow/intern/strings/smoke_script.h b/intern/mantaflow/intern/strings/smoke_script.h
index 7a855ff2cb8..146106fd147 100644
--- a/intern/mantaflow/intern/strings/smoke_script.h
+++ b/intern/mantaflow/intern/strings/smoke_script.h
@@ -279,14 +279,14 @@ def smoke_adaptive_step_$ID$(framenr):\n\
if using_obstacle_s$ID$:\n\
mantaMsg('Initializing obstacle levelset')\n\
phiObsIn_s$ID$.join(phiObsSIn_s$ID$) # Join static obstacle map\n\
- phiObsIn_s$ID$.fillHoles(maxDepth=int(res_s$ID$), boundaryWidth=2)\n\
+ phiObsIn_s$ID$.fillHoles(maxDepth=int(res_s$ID$), boundaryWidth=1)\n\
extrapolateLsSimple(phi=phiObsIn_s$ID$, distance=6, inside=True)\n\
extrapolateLsSimple(phi=phiObsIn_s$ID$, distance=3, inside=False)\n\
phiObs_s$ID$.join(phiObsIn_s$ID$)\n\
\n\
# Using boundaryWidth=2 to not search beginning from walls (just a performance optimization)\n\
# Additional sanity check: fill holes in phiObs which can result after joining with phiObsIn\n\
- phiObs_s$ID$.fillHoles(maxDepth=int(res_s$ID$), boundaryWidth=2)\n\
+ phiObs_s$ID$.fillHoles(maxDepth=int(res_s$ID$), boundaryWidth=1)\n\
extrapolateLsSimple(phi=phiObs_s$ID$, distance=6, inside=True)\n\
extrapolateLsSimple(phi=phiObs_s$ID$, distance=3, inside=False)\n\
\n\
@@ -296,6 +296,7 @@ def smoke_adaptive_step_$ID$(framenr):\n\
extrapolateLsSimple(phi=phiIn_s$ID$, distance=3, inside=False)\n\
\n\
if using_outflow_s$ID$:\n\
+ phiOutIn_s$ID$.join(phiOutSIn_s$ID$) # Join static outflow map\n\
phiOut_s$ID$.join(phiOutIn_s$ID$)\n\
\n\
setObstacleFlags(flags=flags_s$ID$, phiObs=phiObs_s$ID$, phiOut=phiOut_s$ID$, phiIn=phiIn_s$ID$, boundaryWidth=1)\n\
diff --git a/release/datafiles/userdef/userdef_default_theme.c b/release/datafiles/userdef/userdef_default_theme.c
index de3583db2bb..4d48bb8eaac 100644
--- a/release/datafiles/userdef/userdef_default_theme.c
+++ b/release/datafiles/userdef/userdef_default_theme.c
@@ -279,8 +279,8 @@ const bTheme U_theme_default = {
.button_text_hi = RGBA(0xffffffff),
.navigation_bar = RGBA(0x232323ff),
.panelcolors = {
- .header = RGBA(0x42424200),
- .back = RGBA(0x00000028),
+ .header = RGBA(0x424242ff),
+ .back = RGBA(0x383838ff),
.sub_back = RGBA(0x00000024),
},
.vertex_size = 3,
@@ -697,7 +697,7 @@ const bTheme U_theme_default = {
.vertex_size = 3,
.outline_width = 1,
.facedot_size = 3,
- .editmesh_active = RGBA(0xffffff80),
+ .editmesh_active = RGBA(0xffffff40),
.handle_vertex_select = RGBA(0xffff00ff),
.handle_vertex_size = 5,
.gp_vertex_size = 3,
diff --git a/release/scripts/modules/rna_keymap_ui.py b/release/scripts/modules/rna_keymap_ui.py
index 22be5186186..844daded570 100644
--- a/release/scripts/modules/rna_keymap_ui.py
+++ b/release/scripts/modules/rna_keymap_ui.py
@@ -161,7 +161,12 @@ def draw_kmi(display_keymaps, kc, km, kmi, layout, level):
if (not kmi.is_user_defined) and kmi.is_user_modified:
row.operator("preferences.keyitem_restore", text="", icon='BACK').item_id = kmi.id
else:
- row.operator("preferences.keyitem_remove", text="", icon='X').item_id = kmi.id
+ row.operator(
+ "preferences.keyitem_remove",
+ text="",
+ # Abusing the tracking icon, but it works pretty well here.
+ icon=('TRACKING_CLEAR_BACKWARDS' if kmi.is_user_defined else 'X')
+ ).item_id = kmi.id
# Expanded, additional event settings
if kmi.show_expanded:
diff --git a/release/scripts/presets/interface_theme/blender_light.xml b/release/scripts/presets/interface_theme/blender_light.xml
index f4ec8233df3..48ad0a8367e 100644
--- a/release/scripts/presets/interface_theme/blender_light.xml
+++ b/release/scripts/presets/interface_theme/blender_light.xml
@@ -724,7 +724,7 @@
freestyle_face_mark="#7fff7f33"
face_back="#00000000"
face_front="#00000000"
- editmesh_active="#ffffff80"
+ editmesh_active="#ffffff40"
wire_edit="#c0c0c0"
edge_select="#ff8500"
scope_back="#727272ff"
diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py b/release/scripts/presets/keyconfig/keymap_data/blender_default.py
index 7be6ddb5bca..09e9556cf2c 100644
--- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py
+++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py
@@ -5872,6 +5872,23 @@ def km_3d_view_tool_edit_mesh_extrude_region(params):
]},
)
+def km_3d_view_tool_edit_mesh_extrude_dissolve_and_intersect(params):
+ return (
+ "3D View Tool: Edit Mesh, Extrude Dissolve and Intersect",
+ {"space_type": 'VIEW_3D', "region_type": 'WINDOW'},
+ {"items": [
+ ("mesh.extrude_region_dissolve_move_intersect", {"type": params.tool_tweak, "value": 'ANY'},
+ {"properties": [
+ ("MESH_OT_extrude_region", [("use_dissolve_ortho_edges", True)]),
+ ("TRANSFORM_OT_translate", [
+ ("release_confirm", True),
+ ("use_automerge_and_split", True),
+ ("constraint_axis", (False, False, True)),
+ ("orient_type", 'NORMAL'),
+ ]),
+ ]}),
+ ]},
+ )
def km_3d_view_tool_edit_mesh_extrude_along_normals(params):
return (
@@ -6722,6 +6739,7 @@ def generate_keymaps(params=None):
km_3d_view_tool_edit_armature_extrude_to_cursor(params),
km_3d_view_tool_edit_mesh_add_cube(params),
km_3d_view_tool_edit_mesh_extrude_region(params),
+ km_3d_view_tool_edit_mesh_extrude_dissolve_and_intersect(params),
km_3d_view_tool_edit_mesh_extrude_along_normals(params),
km_3d_view_tool_edit_mesh_extrude_individual(params),
km_3d_view_tool_edit_mesh_extrude_to_cursor(params),
diff --git a/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py b/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py
index 0005e7dd3d2..38070d1c400 100644
--- a/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py
+++ b/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py
@@ -3377,6 +3377,10 @@ def km_sculpt(params):
# Remesh
("object.voxel_remesh", {"type": 'R', "value": 'PRESS', "ctrl": True}, None),
("object.quadriflow_remesh", {"type": 'R', "value": 'PRESS', "ctrl": True, "alt": True}, None),
+ # Remesh
+ ("object.voxel_remesh", {"type": 'R', "value": 'PRESS', "ctrl": True}, None),
+ ("object.voxel_size_edit", {"type": 'R', "value": 'PRESS', "shift": True}, None),
+ ("object.quadriflow_remesh", {"type": 'R', "value": 'PRESS', "ctrl": True, "alt": True}, None),
# Brush properties
("brush.scale_size", {"type": 'LEFT_BRACKET', "value": 'PRESS'},
{"properties": [("scalar", 0.9)]}),
diff --git a/release/scripts/startup/bl_operators/__init__.py b/release/scripts/startup/bl_operators/__init__.py
index 5af2bd22222..d7df29f1769 100644
--- a/release/scripts/startup/bl_operators/__init__.py
+++ b/release/scripts/startup/bl_operators/__init__.py
@@ -42,6 +42,7 @@ _modules = [
"rigidbody",
"screen_play_rendered_anim",
"sequencer",
+ "simulation",
"userpref",
"uvcalc_follow_active",
"uvcalc_lightmap",
diff --git a/release/scripts/startup/bl_operators/simulation.py b/release/scripts/startup/bl_operators/simulation.py
new file mode 100644
index 00000000000..5d9c9476318
--- /dev/null
+++ b/release/scripts/startup/bl_operators/simulation.py
@@ -0,0 +1,39 @@
+# ##### 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 #####
+
+import bpy
+
+class NewSimulation(bpy.types.Operator):
+ """Create a new simulation data block and edit it in the opened simulation editor"""
+
+ bl_idname = "simulation.new"
+ bl_label = "New Simulation"
+ bl_options = {'REGISTER', 'UNDO'}
+
+ @classmethod
+ def poll(cls, context):
+ return context.area.type == 'NODE_EDITOR' and context.space_data.tree_type == 'SimulationNodeTree'
+
+ def execute(self, context):
+ simulation = bpy.data.simulations.new("Simulation")
+ context.space_data.simulation = simulation
+ return {'FINISHED'}
+
+classes = (
+ NewSimulation,
+)
diff --git a/release/scripts/startup/bl_operators/userpref.py b/release/scripts/startup/bl_operators/userpref.py
index f78ee026927..a4c19d5a8da 100644
--- a/release/scripts/startup/bl_operators/userpref.py
+++ b/release/scripts/startup/bl_operators/userpref.py
@@ -110,20 +110,30 @@ class PREFERENCES_OT_copy_prev(Operator):
bl_idname = "preferences.copy_prev"
bl_label = "Copy Previous Settings"
- @staticmethod
- def previous_version():
- ver = bpy.app.version
- ver_old = ((ver[0] * 100) + ver[1]) - 1
- return ver_old // 100, ver_old % 100
+ @classmethod
+ def _old_version_path(cls, version):
+ return bpy.utils.resource_path('USER', version[0], version[1])
- @staticmethod
- def _old_path():
- ver = bpy.app.version
- ver_old = ((ver[0] * 100) + ver[1]) - 1
- return bpy.utils.resource_path('USER', ver_old // 100, ver_old % 100)
+ @classmethod
+ def previous_version(cls):
+ # Find config folder from previous version.
+ import os
+ version = bpy.app.version
+ version_old = ((version[0] * 100) + version[1]) - 1
+ while version_old % 10 > 0:
+ version_split = version_old // 100, version_old % 100
+ if os.path.isdir(cls._old_version_path(version_split)):
+ return version_split
+ version_old = version_old - 1
+ return None
- @staticmethod
- def _new_path():
+ @classmethod
+ def _old_path(cls):
+ version_old = cls.previous_version()
+ return cls._old_version_path(version_old) if version_old else None
+
+ @classmethod
+ def _new_path(cls):
return bpy.utils.resource_path('USER')
@classmethod
@@ -132,6 +142,8 @@ class PREFERENCES_OT_copy_prev(Operator):
old = cls._old_path()
new = cls._new_path()
+ if not old:
+ return False
# Disable operator in case config path is overridden with environment
# variable. That case has no automatic per-version configuration.
diff --git a/release/scripts/startup/bl_operators/view3d.py b/release/scripts/startup/bl_operators/view3d.py
index fcabee94a89..88fa06a913f 100644
--- a/release/scripts/startup/bl_operators/view3d.py
+++ b/release/scripts/startup/bl_operators/view3d.py
@@ -72,13 +72,19 @@ class VIEW3D_OT_edit_mesh_extrude_move(Operator):
bl_label = "Extrude and Move on Normals"
bl_idname = "view3d.edit_mesh_extrude_move_normal"
+ dissolve_and_intersect: BoolProperty(
+ name="dissolve_and_intersect",
+ default=False,
+ description="Dissolves adjacent faces and intersects new geometry"
+ )
+
@classmethod
def poll(cls, context):
obj = context.active_object
return (obj is not None and obj.mode == 'EDIT')
@staticmethod
- def extrude_region(context, use_vert_normals):
+ def extrude_region(context, use_vert_normals, dissolve_and_intersect):
mesh = context.object.data
totface = mesh.total_face_sel
@@ -91,6 +97,17 @@ class VIEW3D_OT_edit_mesh_extrude_move(Operator):
'INVOKE_REGION_WIN',
TRANSFORM_OT_shrink_fatten={},
)
+ elif dissolve_and_intersect:
+ bpy.ops.mesh.extrude_region_dissolve_move_intersect(
+ 'INVOKE_REGION_WIN',
+ MESH_OT_extrude_region={
+ "use_dissolve_ortho_edges": True,
+ },
+ TRANSFORM_OT_translate={
+ "orient_type": 'NORMAL',
+ "constraint_axis": (False, False, True),
+ },
+ )
else:
bpy.ops.mesh.extrude_region_move(
'INVOKE_REGION_WIN',
@@ -119,7 +136,7 @@ class VIEW3D_OT_edit_mesh_extrude_move(Operator):
return {'FINISHED'}
def execute(self, context):
- return VIEW3D_OT_edit_mesh_extrude_move.extrude_region(context, False)
+ return VIEW3D_OT_edit_mesh_extrude_move.extrude_region(context, False, self.dissolve_and_intersect)
def invoke(self, context, _event):
return self.execute(context)
@@ -136,7 +153,7 @@ class VIEW3D_OT_edit_mesh_extrude_shrink_fatten(Operator):
return (obj is not None and obj.mode == 'EDIT')
def execute(self, context):
- return VIEW3D_OT_edit_mesh_extrude_move.extrude_region(context, True)
+ return VIEW3D_OT_edit_mesh_extrude_move.extrude_region(context, True, False)
def invoke(self, context, _event):
return self.execute(context)
diff --git a/release/scripts/startup/bl_operators/wm.py b/release/scripts/startup/bl_operators/wm.py
index 8c97157f234..f900b0ee3df 100644
--- a/release/scripts/startup/bl_operators/wm.py
+++ b/release/scripts/startup/bl_operators/wm.py
@@ -2483,8 +2483,8 @@ class WM_MT_splash(Menu):
row = layout.row()
sub = row.row()
- if bpy.types.PREFERENCES_OT_copy_prev.poll(context):
- old_version = bpy.types.PREFERENCES_OT_copy_prev.previous_version()
+ old_version = bpy.types.PREFERENCES_OT_copy_prev.previous_version()
+ if bpy.types.PREFERENCES_OT_copy_prev.poll(context) and old_version:
sub.operator("preferences.copy_prev", text="Load %d.%d Settings" % old_version)
sub.operator("wm.save_userpref", text="Save New Settings")
else:
diff --git a/release/scripts/startup/bl_ui/properties_data_armature.py b/release/scripts/startup/bl_ui/properties_data_armature.py
index d44af702d46..05abfa02500 100644
--- a/release/scripts/startup/bl_ui/properties_data_armature.py
+++ b/release/scripts/startup/bl_ui/properties_data_armature.py
@@ -84,17 +84,12 @@ class DATA_PT_display(ArmatureButtonsPanel, Panel):
layout.prop(arm, "display_type", text="Display As")
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=False, even_rows=False, align=True)
- col = flow.column()
+ col = layout.column(heading="Show")
col.prop(arm, "show_names", text="Names")
- col = flow.column()
col.prop(arm, "show_axes", text="Axes")
- col = flow.column()
col.prop(arm, "show_bone_custom_shapes", text="Shapes")
- col = flow.column()
col.prop(arm, "show_group_colors", text="Group Colors")
if ob:
- col = flow.column()
col.prop(ob, "show_in_front", text="In Front")
diff --git a/release/scripts/startup/bl_ui/properties_data_camera.py b/release/scripts/startup/bl_ui/properties_data_camera.py
index aee909e3a6c..62dffa3b6ba 100644
--- a/release/scripts/startup/bl_ui/properties_data_camera.py
+++ b/release/scripts/startup/bl_ui/properties_data_camera.py
@@ -360,8 +360,9 @@ class DATA_PT_camera_background_image(CameraButtonsPanel, Panel):
col.prop(bg, "rotation")
col.prop(bg, "scale")
- col.prop(bg, "use_flip_x")
- col.prop(bg, "use_flip_y")
+ col = box.column(heading="Flip")
+ col.prop(bg, "use_flip_x", text="X")
+ col.prop(bg, "use_flip_y", text="Y")
class DATA_PT_camera_display(CameraButtonsPanel, Panel):
@@ -377,21 +378,12 @@ class DATA_PT_camera_display(CameraButtonsPanel, Panel):
col = layout.column(align=True)
- col.separator()
-
col.prop(cam, "display_size", text="Size")
- col.separator()
-
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=False, even_rows=False, align=False)
-
- col = flow.column()
+ col = layout.column(heading="Show")
col.prop(cam, "show_limits", text="Limits")
- col = flow.column()
col.prop(cam, "show_mist", text="Mist")
- col = flow.column()
col.prop(cam, "show_sensor", text="Sensor")
- col = flow.column()
col.prop(cam, "show_name", text="Name")
@@ -407,24 +399,20 @@ class DATA_PT_camera_display_composition_guides(CameraButtonsPanel, Panel):
cam = context.camera
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=False, even_rows=False, align=False)
+ layout.prop(cam, "show_composition_thirds")
- col = flow.column()
+ col = layout.column(heading="Center", align=True)
col.prop(cam, "show_composition_center")
- col = flow.column()
- col.prop(cam, "show_composition_center_diagonal")
- col = flow.column()
- col.prop(cam, "show_composition_thirds")
- col = flow.column()
- col.prop(cam, "show_composition_golden")
- col = flow.column()
- col.prop(cam, "show_composition_golden_tria_a")
- col = flow.column()
- col.prop(cam, "show_composition_golden_tria_b")
- col = flow.column()
- col.prop(cam, "show_composition_harmony_tri_a")
- col = flow.column()
- col.prop(cam, "show_composition_harmony_tri_b")
+ col.prop(cam, "show_composition_center_diagonal", text="Diagonal")
+
+ col = layout.column(heading="Golden", align=True)
+ col.prop(cam, "show_composition_golden", text="Ratio")
+ col.prop(cam, "show_composition_golden_tria_a", text="Triangle A")
+ col.prop(cam, "show_composition_golden_tria_b", text="Triangle B")
+
+ col = layout.column(heading="Harmony", align=True)
+ col.prop(cam, "show_composition_harmony_tri_a", text="Triangle A")
+ col.prop(cam, "show_composition_harmony_tri_b", text="Triangle B")
class DATA_PT_camera_display_passepartout(CameraButtonsPanel, Panel):
diff --git a/release/scripts/startup/bl_ui/properties_data_curve.py b/release/scripts/startup/bl_ui/properties_data_curve.py
index b694062dfc5..7e7488f4cf1 100644
--- a/release/scripts/startup/bl_ui/properties_data_curve.py
+++ b/release/scripts/startup/bl_ui/properties_data_curve.py
@@ -276,23 +276,23 @@ class DATA_PT_active_spline(CurveButtonsPanelActive, Panel):
col.prop(act_spline, "use_smooth")
else:
- sub = col.column(align=True)
- sub.prop(act_spline, "use_cyclic_u")
+ sub = col.column(heading="Cyclic", align=True)
+ sub.prop(act_spline, "use_cyclic_u", text="U")
if is_surf:
sub.prop(act_spline, "use_cyclic_v", text="V")
if act_spline.type == 'NURBS':
- sub = col.column(align=True)
+ sub = col.column(heading="Bezier", align=True)
# sub.active = (not act_spline.use_cyclic_u)
- sub.prop(act_spline, "use_bezier_u", text="Bezier U")
+ sub.prop(act_spline, "use_bezier_u", text="U")
if is_surf:
subsub = sub.column()
subsub.active = (not act_spline.use_cyclic_v)
subsub.prop(act_spline, "use_bezier_v", text="V")
- sub = col.column(align=True)
- sub.prop(act_spline, "use_endpoint_u", text="Endpoint U")
+ sub = col.column(heading="Endpoint", align=True)
+ sub.prop(act_spline, "use_endpoint_u", text="U")
if is_surf:
subsub = sub.column()
diff --git a/release/scripts/startup/bl_ui/properties_data_empty.py b/release/scripts/startup/bl_ui/properties_data_empty.py
index 898ab2e4359..1523f69536f 100644
--- a/release/scripts/startup/bl_ui/properties_data_empty.py
+++ b/release/scripts/startup/bl_ui/properties_data_empty.py
@@ -53,9 +53,11 @@ class DATA_PT_empty(DataButtonsPanel, Panel):
depth_row.enabled = not ob.show_in_front
depth_row.prop(ob, "empty_image_depth", text="Depth", expand=True)
col.row().prop(ob, "empty_image_side", text="Side", expand=True)
- col.prop(ob, "show_empty_image_orthographic", text="Display Orthographic")
- col.prop(ob, "show_empty_image_perspective", text="Display Perspective")
- col.prop(ob, "show_empty_image_only_axis_aligned")
+
+ col = layout.column(heading="Show in", align=True)
+ col.prop(ob, "show_empty_image_orthographic", text="Orthographic")
+ col.prop(ob, "show_empty_image_perspective", text="Perspective")
+ col.prop(ob, "show_empty_image_only_axis_aligned", text="Only Axis Aligned")
class DATA_PT_empty_alpha(DataButtonsPanel, Panel):
diff --git a/release/scripts/startup/bl_ui/properties_data_mesh.py b/release/scripts/startup/bl_ui/properties_data_mesh.py
index d91b2ceb7f7..425c94dfdcd 100644
--- a/release/scripts/startup/bl_ui/properties_data_mesh.py
+++ b/release/scripts/startup/bl_ui/properties_data_mesh.py
@@ -190,27 +190,20 @@ class DATA_PT_normals(MeshButtonsPanel, Panel):
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
def draw(self, context):
- pass
-
-
-class DATA_PT_normals_auto_smooth(MeshButtonsPanel, Panel):
- bl_label = "Auto Smooth"
- bl_parent_id = "DATA_PT_normals"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
-
- def draw_header(self, context):
- mesh = context.mesh
-
- self.layout.prop(mesh, "use_auto_smooth", text="")
-
- def draw(self, context):
layout = self.layout
layout.use_property_split = True
mesh = context.mesh
- layout.active = mesh.use_auto_smooth and not mesh.has_custom_normals
- layout.prop(mesh, "auto_smooth_angle", text="Angle")
+ col = layout.column(align=False, heading="Auto Smooth")
+ col.use_property_decorate = False
+ row = col.row(align=True)
+ sub = row.row(align=True)
+ sub.prop(mesh, "use_auto_smooth", text="")
+ sub = sub.row(align=True)
+ sub.active = mesh.use_auto_smooth and not mesh.has_custom_normals
+ sub.prop(mesh, "auto_smooth_angle", text="")
+ row.prop_decorator(mesh, "auto_smooth_angle")
class DATA_PT_texture_space(MeshButtonsPanel, Panel):
@@ -485,9 +478,11 @@ class DATA_PT_remesh(MeshButtonsPanel, Panel):
col.prop(mesh, "remesh_voxel_adaptivity")
col.prop(mesh, "use_remesh_fix_poles")
col.prop(mesh, "use_remesh_smooth_normals")
- col.prop(mesh, "use_remesh_preserve_volume")
- col.prop(mesh, "use_remesh_preserve_paint_mask")
- col.prop(mesh, "use_remesh_preserve_sculpt_face_sets")
+
+ col = layout.column(heading="Preserve")
+ col.prop(mesh, "use_remesh_preserve_volume", text="Volume")
+ col.prop(mesh, "use_remesh_preserve_paint_mask", text="Paint Mask")
+ col.prop(mesh, "use_remesh_preserve_sculpt_face_sets", text="Face Sets")
col.operator("object.voxel_remesh", text="Voxel Remesh")
else:
col.operator("object.quadriflow_remesh", text="QuadriFlow Remesh")
@@ -515,12 +510,12 @@ class DATA_PT_customdata(MeshButtonsPanel, Panel):
else:
col.operator("mesh.customdata_custom_splitnormals_add", icon='ADD')
- col = layout.column()
+ col = layout.column(heading="Store")
col.enabled = obj is not None and obj.mode != 'EDIT'
- col.prop(me, "use_customdata_vertex_bevel")
- col.prop(me, "use_customdata_edge_bevel")
- col.prop(me, "use_customdata_edge_crease")
+ col.prop(me, "use_customdata_vertex_bevel", text="Vertex Bevel Weight")
+ col.prop(me, "use_customdata_edge_bevel", text="Edge Bevel Weight")
+ col.prop(me, "use_customdata_edge_crease", text="Edge Crease")
class DATA_PT_custom_props_mesh(MeshButtonsPanel, PropertyPanel, Panel):
@@ -544,7 +539,6 @@ classes = (
DATA_PT_vertex_colors,
DATA_PT_face_maps,
DATA_PT_normals,
- DATA_PT_normals_auto_smooth,
DATA_PT_texture_space,
DATA_PT_remesh,
DATA_PT_customdata,
diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py
index b9fc7431a9a..03debee4384 100644
--- a/release/scripts/startup/bl_ui/properties_data_modifier.py
+++ b/release/scripts/startup/bl_ui/properties_data_modifier.py
@@ -1976,6 +1976,27 @@ class DATA_PT_gpencil_modifiers(ModifierButtonsPanel, Panel):
self.gpencil_masking(layout, ob, md, True, True)
+ def GP_TEXTURE(self, layout, ob, md):
+ col = layout.column()
+
+ col.prop(md, "mode")
+ if md.mode in {'STROKE', 'STROKE_AND_FILL'}:
+ col.label(text="Stroke Texture Control:")
+ col.prop(md, "fit_method")
+ col.prop(md, "uv_offset")
+ col.prop(md, "uv_scale")
+
+ if md.mode == 'STROKE_AND_FILL':
+ col.separator()
+
+ if md.mode in {'FILL', 'STROKE_AND_FILL'}:
+ col.label(text="Fill Texture Control:")
+ col.prop(md, "fill_rotation", text="Rotation")
+ col.prop(md, "fill_offset", text="Location")
+ col.prop(md, "fill_scale", text="Scale")
+
+ self.gpencil_masking(layout, ob, md, True)
+
def GP_TINT(self, layout, ob, md):
layout.row().prop(md, "tint_type", expand=True)
diff --git a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py
index 5647f35383a..0f6a51ad2d0 100644
--- a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py
+++ b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py
@@ -520,7 +520,7 @@ class AnnotationOnionSkin:
if gpl is None:
return False
- return True
+ return True
def draw_header(self, context):
gpl = context.active_annotation_layer
diff --git a/release/scripts/startup/bl_ui/properties_object.py b/release/scripts/startup/bl_ui/properties_object.py
index a805b965af2..8ce53ed30eb 100644
--- a/release/scripts/startup/bl_ui/properties_object.py
+++ b/release/scripts/startup/bl_ui/properties_object.py
@@ -212,7 +212,6 @@ class OBJECT_PT_display(ObjectButtonsPanel, Panel):
layout = self.layout
layout.use_property_split = True
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
obj = context.object
obj_type = obj.type
@@ -222,35 +221,22 @@ class OBJECT_PT_display(ObjectButtonsPanel, Panel):
is_dupli = (obj.instance_type != 'NONE')
is_gpencil = (obj_type == 'GPENCIL')
- col = flow.column()
+ col = layout.column(heading="Show")
col.prop(obj, "show_name", text="Name")
-
- col = flow.column()
col.prop(obj, "show_axis", text="Axis")
# Makes no sense for cameras, armatures, etc.!
# but these settings do apply to dupli instances
if is_geometry or is_dupli:
- col = flow.column()
col.prop(obj, "show_wire", text="Wireframe")
if obj_type == 'MESH' or is_dupli:
- col = flow.column()
col.prop(obj, "show_all_edges", text="All Edges")
-
- col = flow.column()
if is_geometry:
col.prop(obj, "show_texture_space", text="Texture Space")
- col = flow.column()
col.prop(obj.display, "show_shadows", text="Shadow")
-
- col = flow.column()
col.prop(obj, "show_in_front", text="In Front")
# if obj_type == 'MESH' or is_empty_image:
# col.prop(obj, "show_transparent", text="Transparency")
-
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
-
- col = flow.column()
if is_wire:
# wire objects only use the max. display type for duplis
col.active = is_dupli
@@ -258,28 +244,17 @@ class OBJECT_PT_display(ObjectButtonsPanel, Panel):
if is_geometry or is_dupli or is_empty_image or is_gpencil:
# Only useful with object having faces/materials...
- col = flow.column()
col.prop(obj, "color")
-
-class OBJECT_PT_display_bounds(ObjectButtonsPanel, Panel):
- bl_label = "Bounds"
- bl_parent_id = "OBJECT_PT_display"
- bl_options = {'DEFAULT_CLOSED'}
-
- def draw_header(self, context):
-
- obj = context.object
-
- self.layout.prop(obj, "show_bounds", text="")
-
- def draw(self, context):
- layout = self.layout
- obj = context.object
- layout.use_property_split = True
-
- layout.active = obj.show_bounds or (obj.display_type == 'BOUNDS')
- layout.prop(obj, "display_bounds_type", text="Shape")
+ col = layout.column(align=False, heading="Bounds")
+ col.use_property_decorate = False
+ row = col.row(align=True)
+ sub = row.row(align=True)
+ sub.prop(obj, "show_bounds", text="")
+ sub = sub.row(align=True)
+ sub.active = obj.show_bounds or (obj.display_type == 'BOUNDS')
+ sub.prop(obj, "display_bounds_type", text="")
+ row.prop_decorator(obj, "display_bounds_type")
class OBJECT_PT_instancing(ObjectButtonsPanel, Panel):
@@ -295,7 +270,6 @@ class OBJECT_PT_instancing(ObjectButtonsPanel, Panel):
row.prop(ob, "instance_type", expand=True)
layout.use_property_split = True
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
if ob.instance_type == 'VERTS':
layout.prop(ob, "use_instance_vertices_rotation", text="Align to Vertex Normal")
@@ -305,9 +279,9 @@ class OBJECT_PT_instancing(ObjectButtonsPanel, Panel):
col.prop(ob, "instance_collection", text="Collection")
if ob.instance_type != 'NONE' or ob.particle_systems:
- col = flow.column(align=True)
- col.prop(ob, "show_instancer_for_viewport")
- col.prop(ob, "show_instancer_for_render")
+ col = layout.column(heading="Show Instancer", align=True)
+ col.prop(ob, "show_instancer_for_viewport", text="Viewport")
+ col.prop(ob, "show_instancer_for_render", text="Render")
class OBJECT_PT_instancing_size(ObjectButtonsPanel, Panel):
@@ -385,19 +359,17 @@ class OBJECT_PT_visibility(ObjectButtonsPanel, Panel):
layout = self.layout
layout.use_property_split = True
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
layout = self.layout
ob = context.object
- col = flow.column()
- col.prop(ob, "hide_viewport", text="Show in Viewports", toggle=False, invert_checkbox=True)
- col = flow.column()
- col.prop(ob, "hide_render", text="Show in Renders", toggle=False, invert_checkbox=True)
- col = flow.column()
- col.prop(ob, "hide_select", text="Selectable", toggle=False, invert_checkbox=True)
+ layout.prop(ob, "hide_select", text="Selectable", toggle=False, invert_checkbox=True)
+
+ col = layout.column(heading="Show in")
+ col.prop(ob, "hide_viewport", text="Viewports", toggle=False, invert_checkbox=True)
+ col.prop(ob, "hide_render", text="Renders", toggle=False, invert_checkbox=True)
if context.object.type == 'GPENCIL':
- col = flow.column()
+ col = layout.column(heading="Grease Pencil")
col.prop(ob, "use_grease_pencil_lights", toggle=False)
@@ -419,7 +391,6 @@ classes = (
OBJECT_PT_motion_paths,
OBJECT_PT_motion_paths_display,
OBJECT_PT_display,
- OBJECT_PT_display_bounds,
OBJECT_PT_visibility,
OBJECT_PT_custom_props,
)
diff --git a/release/scripts/startup/bl_ui/properties_output.py b/release/scripts/startup/bl_ui/properties_output.py
index 748961bb40f..e859798c085 100644
--- a/release/scripts/startup/bl_ui/properties_output.py
+++ b/release/scripts/startup/bl_ui/properties_output.py
@@ -94,14 +94,14 @@ class RENDER_PT_dimensions(RenderOutputButtonsPanel, Panel):
return args
@staticmethod
- def draw_framerate(layout, sub, rd):
+ def draw_framerate(layout, rd):
if RENDER_PT_dimensions._preset_class is None:
RENDER_PT_dimensions._preset_class = bpy.types.RENDER_MT_framerate_presets
args = rd.fps, rd.fps_base, RENDER_PT_dimensions._preset_class.bl_label
fps_label_text, show_framerate = RENDER_PT_dimensions._draw_framerate_label(*args)
- sub.menu("RENDER_MT_framerate_presets", text=fps_label_text)
+ layout.menu("RENDER_MT_framerate_presets", text=fps_label_text)
if show_framerate:
col = layout.column(align=True)
@@ -136,10 +136,8 @@ class RENDER_PT_dimensions(RenderOutputButtonsPanel, Panel):
col.prop(scene, "frame_end", text="End")
col.prop(scene, "frame_step", text="Step")
- col = layout.split()
- col.alignment = 'RIGHT'
- col.label(text="Frame Rate")
- self.draw_framerate(layout, col, rd)
+ col = layout.column(heading="Frame Rate")
+ self.draw_framerate(col, rd)
class RENDER_PT_frame_remapping(RenderOutputButtonsPanel, Panel):
@@ -171,10 +169,8 @@ class RENDER_PT_post_processing(RenderOutputButtonsPanel, Panel):
rd = context.scene.render
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
- col = flow.column()
+ col = layout.column(heading="Pipeline")
col.prop(rd, "use_compositing")
- col = flow.column()
col.prop(rd, "use_sequencer")
layout.prop(rd, "dither_intensity", text="Dither", slider=True)
@@ -192,44 +188,23 @@ class RENDER_PT_stamp(RenderOutputButtonsPanel, Panel):
rd = context.scene.render
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
+ if rd.use_sequencer:
+ layout.prop(rd, "metadata_input")
- col = flow.column()
+ col = layout.column(heading="Include")
col.prop(rd, "use_stamp_date", text="Date")
- col = flow.column()
col.prop(rd, "use_stamp_time", text="Time")
-
- col = flow.column()
col.prop(rd, "use_stamp_render_time", text="Render Time")
- col = flow.column()
col.prop(rd, "use_stamp_frame", text="Frame")
- col = flow.column()
col.prop(rd, "use_stamp_frame_range", text="Frame Range")
- col = flow.column()
col.prop(rd, "use_stamp_memory", text="Memory")
- col = flow.column()
col.prop(rd, "use_stamp_hostname", text="Hostname")
-
- col = flow.column()
col.prop(rd, "use_stamp_camera", text="Camera")
- col = flow.column()
col.prop(rd, "use_stamp_lens", text="Lens")
-
- col = flow.column()
col.prop(rd, "use_stamp_scene", text="Scene")
- col = flow.column()
col.prop(rd, "use_stamp_marker", text="Marker")
-
- col = flow.column()
col.prop(rd, "use_stamp_filename", text="Filename")
- col = flow.column()
- col.prop(rd, "use_stamp_sequencer_strip", text="Strip Name")
-
- if rd.use_sequencer:
- col = flow.column()
- col.prop(rd, "use_stamp_strip_meta", text="Use Strip Metadata")
-
class RENDER_PT_stamp_note(RenderOutputButtonsPanel, Panel):
bl_label = "Note"
@@ -293,21 +268,17 @@ class RENDER_PT_output(RenderOutputButtonsPanel, Panel):
layout.use_property_split = True
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
-
- col = flow.column()
- col.active = not rd.is_movie_format
- col.prop(rd, "use_overwrite")
- col = flow.column()
- col.active = not rd.is_movie_format
- col.prop(rd, "use_placeholder")
- col = flow.column()
+ col = layout.column(heading="Saving")
col.prop(rd, "use_file_extension")
- col = flow.column()
col.prop(rd, "use_render_cache")
layout.template_image_settings(image_settings, color_management=False)
+ if not rd.is_movie_format:
+ col = layout.column(heading="Image Sequence")
+ col.prop(rd, "use_overwrite")
+ col.prop(rd, "use_placeholder")
+
class RENDER_PT_output_views(RenderOutputButtonsPanel, Panel):
bl_label = "Views"
diff --git a/release/scripts/startup/bl_ui/properties_paint_common.py b/release/scripts/startup/bl_ui/properties_paint_common.py
index a13f39da4a9..bc467c4f42f 100644
--- a/release/scripts/startup/bl_ui/properties_paint_common.py
+++ b/release/scripts/startup/bl_ui/properties_paint_common.py
@@ -587,10 +587,12 @@ def brush_settings(layout, context, brush, popover=False):
slider=True,
)
- layout.prop(brush, "use_plane_trim", text="Plane Trim")
- row = layout.row()
- row.active = brush.use_plane_trim
- row.prop(brush, "plane_trim", slider=True, text="Distance")
+ row = layout.row(heading="Plane Trim")
+ row.prop(brush, "use_plane_trim", text="")
+ sub = row.row()
+ sub.active = brush.use_plane_trim
+ sub.prop(brush, "plane_trim", slider=True, text="")
+
layout.separator()
# height
@@ -808,23 +810,27 @@ def brush_settings_advanced(layout, context, brush, popover=False):
use_accumulate = capabilities.has_accumulate
use_frontface = True
+ col = layout.column(heading="Auto-Masking", align=True)
+
# topology automasking
- layout.prop(brush, "use_automasking_topology")
+ col.prop(brush, "use_automasking_topology", text="Topology")
# face masks automasking
- layout.prop(brush, "use_automasking_face_sets")
-
+ col.prop(brush, "use_automasking_face_sets", text="Face Sets")
+
# boundary edges/face sets automasking
- layout.prop(brush, "use_automasking_boundary_edges")
- layout.prop(brush, "use_automasking_boundary_face_sets")
- layout.prop(brush, "automasking_boundary_edges_propagation_steps")
+ col.prop(brush, "use_automasking_boundary_edges", text="Mesh Boundary")
+ col.prop(brush, "use_automasking_boundary_face_sets", text="Face Sets")
+ col.prop(brush, "automasking_boundary_edges_propagation_steps")
+ layout.separator()
# sculpt plane settings
if capabilities.has_sculpt_plane:
layout.prop(brush, "sculpt_plane")
- layout.prop(brush, "use_original_normal")
- layout.prop(brush, "use_original_plane")
+ col = layout.column(heading="Use Original", align=True)
+ col.prop(brush, "use_original_normal", text="Normal")
+ col.prop(brush, "use_original_plane", text="Plane")
layout.separator()
# 3D and 2D Texture Paint.
diff --git a/release/scripts/startup/bl_ui/properties_physics_common.py b/release/scripts/startup/bl_ui/properties_physics_common.py
index 479782f1e3b..0cd99efcca9 100644
--- a/release/scripts/startup/bl_ui/properties_physics_common.py
+++ b/release/scripts/startup/bl_ui/properties_physics_common.py
@@ -310,8 +310,10 @@ def basic_force_field_settings_ui(self, field):
else:
col.prop(field, "flow")
- col.prop(field, "apply_to_location", text="Affect Location")
- col.prop(field, "apply_to_rotation", text="Affect Rotation")
+ sub = col.column(heading="Affect")
+
+ sub.prop(field, "apply_to_location", text="Location")
+ sub.prop(field, "apply_to_rotation", text="Rotation")
col = flow.column()
sub = col.column(align=True)
@@ -336,26 +338,29 @@ def basic_force_field_falloff_ui(self, field):
if not field or field.type == 'NONE':
return
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
-
- col = flow.column()
+ col = layout.column()
col.prop(field, "z_direction")
col.prop(field, "falloff_power", text="Power")
- col = flow.column()
- col.prop(field, "use_min_distance", text="Use Minimum")
-
- sub = col.column(align=True)
+ col = layout.column(align=False, heading="Min Distance")
+ col.use_property_decorate = False
+ row = col.row(align=True)
+ sub = row.row(align=True)
+ sub.prop(field, "use_min_distance", text="")
+ sub = sub.row(align=True)
sub.active = field.use_min_distance
- sub.prop(field, "distance_min", text="Min Distance")
-
- col = flow.column()
- col.prop(field, "use_max_distance", text="Use Maximum")
-
- sub = col.column(align=True)
+ sub.prop(field, "distance_min", text="")
+ row.prop_decorator(field, "distance_min")
+
+ col = layout.column(align=False, heading="Max Distance")
+ col.use_property_decorate = False
+ row = col.row(align=True)
+ sub = row.row(align=True)
+ sub.prop(field, "use_max_distance", text="")
+ sub = sub.row(align=True)
sub.active = field.use_max_distance
- sub.prop(field, "distance_max", text="Max Distance")
-
+ sub.prop(field, "distance_max", text="")
+ row.prop_decorator(field, "distance_max")
classes = (
PHYSICS_PT_add,
diff --git a/release/scripts/startup/bl_ui/properties_physics_fluid.py b/release/scripts/startup/bl_ui/properties_physics_fluid.py
index 390b5de7d37..d6d2526384a 100644
--- a/release/scripts/startup/bl_ui/properties_physics_fluid.py
+++ b/release/scripts/startup/bl_ui/properties_physics_fluid.py
@@ -236,8 +236,8 @@ class PHYSICS_PT_settings(PhysicButtonsPanel, Panel):
col = grid.column()
col.prop(flow, "flow_behavior", expand=False)
- if flow.flow_behavior in {'INFLOW'}:
- col.prop(flow, "use_inflow", text="Use Inflow")
+ if flow.flow_behavior in {'INFLOW', 'OUTFLOW'}:
+ col.prop(flow, "use_inflow", text="Use Flow")
col.prop(flow, "subframes", text="Sampling Substeps")
@@ -988,6 +988,7 @@ class PHYSICS_PT_diffusion(PhysicButtonsPanel, Panel):
layout.use_property_split = True
domain = context.fluid.domain_settings
+ layout.active = domain.use_diffusion
is_baking_any = domain.is_cache_baking_any
has_baked_any = domain.has_cache_baked_any
diff --git a/release/scripts/startup/bl_ui/properties_render.py b/release/scripts/startup/bl_ui/properties_render.py
index fd4859f3620..2d13aed617c 100644
--- a/release/scripts/startup/bl_ui/properties_render.py
+++ b/release/scripts/startup/bl_ui/properties_render.py
@@ -475,33 +475,21 @@ class RENDER_PT_eevee_film(RenderButtonsPanel, Panel):
scene = context.scene
rd = scene.render
+ props = scene.eevee
col = layout.column()
col.prop(rd, "filter_size")
col.prop(rd, "film_transparent", text="Transparent")
-
-class RENDER_PT_eevee_film_overscan(RenderButtonsPanel, Panel):
- bl_label = "Overscan"
- bl_parent_id = "RENDER_PT_eevee_film"
- bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_EEVEE'}
-
- def draw_header(self, context):
-
- scene = context.scene
- props = scene.eevee
-
- self.layout.prop(props, "use_overscan", text="")
-
- def draw(self, context):
- layout = self.layout
- layout.use_property_split = True
- scene = context.scene
- props = scene.eevee
-
- layout.active = props.use_overscan
- layout.prop(props, "overscan_size", text="Size")
+ col = layout.column(align=False, heading="Overscan")
+ col.use_property_decorate = False
+ row = col.row(align=True)
+ sub = row.row(align=True)
+ sub.prop(props, "use_overscan", text="")
+ sub = sub.row(align=True)
+ sub.active = props.use_overscan
+ sub.prop(props, "overscan_size", text="")
+ row.prop_decorator(props, "overscan_size")
class RENDER_PT_eevee_hair(RenderButtonsPanel, Panel):
@@ -696,7 +684,6 @@ classes = (
RENDER_PT_eevee_indirect_lighting,
RENDER_PT_eevee_indirect_lighting_display,
RENDER_PT_eevee_film,
- RENDER_PT_eevee_film_overscan,
RENDER_PT_opengl_sampling,
RENDER_PT_opengl_lighting,
RENDER_PT_opengl_color,
diff --git a/release/scripts/startup/bl_ui/properties_view_layer.py b/release/scripts/startup/bl_ui/properties_view_layer.py
index 5fe06ebbb6e..3645f0dc2f2 100644
--- a/release/scripts/startup/bl_ui/properties_view_layer.py
+++ b/release/scripts/startup/bl_ui/properties_view_layer.py
@@ -40,17 +40,12 @@ class VIEWLAYER_PT_layer(ViewLayerButtonsPanel, Panel):
layout.use_property_split = True
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
-
- layout.use_property_split = True
-
scene = context.scene
rd = scene.render
layer = context.view_layer
- col = flow.column()
+ col = layout.column()
col.prop(layer, "use", text="Use for Rendering")
- col = flow.column()
col.prop(rd, "use_single_layer", text="Render Single Layer")
@@ -77,14 +72,10 @@ class VIEWLAYER_PT_eevee_layer_passes_data(ViewLayerButtonsPanel, Panel):
rd = scene.render
view_layer = context.view_layer
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
- col = flow.column()
+ col = layout.column()
col.prop(view_layer, "use_pass_combined")
- col = flow.column()
col.prop(view_layer, "use_pass_z")
- col = flow.column()
col.prop(view_layer, "use_pass_mist")
- col = flow.column()
col.prop(view_layer, "use_pass_normal")
@@ -104,29 +95,19 @@ class VIEWLAYER_PT_eevee_layer_passes_light(ViewLayerButtonsPanel, Panel):
scene = context.scene
scene_eevee = scene.eevee
- split = layout.split(factor=0.35)
- split.use_property_split = False
- split.label(text="Diffuse")
- row = split.row(align=True)
- row.prop(view_layer, "use_pass_diffuse_direct", text="Light", toggle=True)
- row.prop(view_layer, "use_pass_diffuse_color", text="Color", toggle=True)
-
- split = layout.split(factor=0.35)
- split.use_property_split = False
- split.label(text="Specular")
- row = split.row(align=True)
- row.prop(view_layer, "use_pass_glossy_direct", text="Light", toggle=True)
- row.prop(view_layer, "use_pass_glossy_color", text="Color", toggle=True)
-
- split = layout.split(factor=0.35)
- split.use_property_split = False
- split.label(text="Volume")
- row = split.row(align=True)
- row.prop(view_layer_eevee, "use_pass_volume_transmittance", text="Transmittance", toggle=True)
- row.prop(view_layer_eevee, "use_pass_volume_scatter", text="Scatter", toggle=True)
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
-
- col = layout.column(align=True)
+ col = layout.column(heading="Diffuse", align=True)
+ col.prop(view_layer, "use_pass_diffuse_direct", text="Light")
+ col.prop(view_layer, "use_pass_diffuse_color", text="Color")
+
+ col = layout.column(heading="Specular", align=True)
+ col.prop(view_layer, "use_pass_glossy_direct", text="Light")
+ col.prop(view_layer, "use_pass_glossy_color", text="Color")
+
+ col = layout.column(heading="Volume", align=True)
+ col.prop(view_layer_eevee, "use_pass_volume_transmittance", text="Transmittance")
+ col.prop(view_layer_eevee, "use_pass_volume_scatter", text="Scatter")
+
+ col = layout.column(heading="Other", align=True)
col.prop(view_layer, "use_pass_emit", text="Emission")
col.prop(view_layer, "use_pass_environment")
col.prop(view_layer, "use_pass_shadow")
@@ -146,14 +127,12 @@ class VIEWLAYER_PT_eevee_layer_passes_effects(ViewLayerButtonsPanel, Panel):
layout.use_property_split = True
layout.use_property_decorate = False
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
-
view_layer = context.view_layer
view_layer_eevee = view_layer.eevee
scene = context.scene
scene_eevee = scene.eevee
- col = flow.column()
+ col = layout.column()
col.prop(view_layer_eevee, "use_pass_bloom", text="Bloom")
col.active = scene_eevee.use_bloom
diff --git a/release/scripts/startup/bl_ui/space_filebrowser.py b/release/scripts/startup/bl_ui/space_filebrowser.py
index 3bf5bbf7b46..53fc812a619 100644
--- a/release/scripts/startup/bl_ui/space_filebrowser.py
+++ b/release/scripts/startup/bl_ui/space_filebrowser.py
@@ -66,8 +66,9 @@ class FILEBROWSER_PT_display(Panel):
if params.display_type == 'THUMBNAIL':
layout.prop(params, "display_size", text="Size")
else:
- layout.prop(params, "show_details_size", text="Size")
- layout.prop(params, "show_details_datetime", text="Date")
+ col = layout.column(heading="Columns", align=True)
+ col.prop(params, "show_details_size", text="Size")
+ col.prop(params, "show_details_datetime", text="Date")
layout.prop(params, "recursion_level", text="Recursions")
diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py
index 4506307067e..324c1238db3 100644
--- a/release/scripts/startup/bl_ui/space_image.py
+++ b/release/scripts/startup/bl_ui/space_image.py
@@ -384,6 +384,10 @@ class IMAGE_MT_uvs(Menu):
layout.separator()
+ layout.operator("uv.reset")
+
+ layout.separator()
+
class IMAGE_MT_uvs_select_mode(Menu):
bl_label = "UV Select Mode"
@@ -955,6 +959,7 @@ class IMAGE_PT_view_display_uv_edit_overlays(Panel):
col = layout.column()
col.prop(uvedit, "show_smooth_edges", text="Smooth")
col.prop(uvedit, "show_modified_edges", text="Modified")
+ col.prop(uvedit, "uv_opacity")
class IMAGE_PT_view_display_uv_edit_overlays_stretch(Panel):
diff --git a/release/scripts/startup/bl_ui/space_node.py b/release/scripts/startup/bl_ui/space_node.py
index bdda0ebbe9a..b5926692324 100644
--- a/release/scripts/startup/bl_ui/space_node.py
+++ b/release/scripts/startup/bl_ui/space_node.py
@@ -151,6 +151,14 @@ class NODE_HT_header(Header):
if snode_id:
layout.prop(snode_id, "use_nodes")
+ elif snode.tree_type == 'SimulationNodeTree':
+ row = layout.row(align=True)
+ row.prop(snode, "simulation", text="")
+ row.operator("simulation.new", text="", icon='ADD')
+ simulation = snode.simulation
+ if simulation:
+ row.prop(snode.simulation, "use_fake_user", text="")
+
else:
# Custom node tree is edited as independent ID block
NODE_MT_editor_menus.draw_collapsible(context, layout)
diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py
index c0a2b8a1230..0e2af8f8f2f 100644
--- a/release/scripts/startup/bl_ui/space_sequencer.py
+++ b/release/scripts/startup/bl_ui/space_sequencer.py
@@ -29,6 +29,7 @@ from bpy.app.translations import (
)
from bl_ui.properties_grease_pencil_common import (
AnnotationDataPanel,
+ AnnotationOnionSkin,
)
from bl_ui.space_toolsystem_common import (
ToolActivePanelHelper,
@@ -1687,18 +1688,15 @@ class SEQUENCER_PT_adjust_transform(SequencerButtonsPanel, Panel):
layout = self.layout
strip = act_strip(context)
- layout.active = not strip.mute
-
- split = layout.split()
+ layout.use_property_split = True
+ layout.use_property_decorate = False
- col = split.column()
- col.alignment = 'RIGHT'
- col.label(text="Mirror")
+ layout.active = not strip.mute
- col = split.column()
- row = col.row(align=True)
- row.prop(strip, "use_flip_x", text="X", toggle=True)
- row.prop(strip, "use_flip_y", text="Y", toggle=True)
+ row = layout.row(heading="Mirror")
+ sub = row.row(align=True)
+ sub.prop(strip, "use_flip_x", text="X", toggle=True)
+ sub.prop(strip, "use_flip_y", text="Y", toggle=True)
class SEQUENCER_PT_adjust_video(SequencerButtonsPanel, Panel):
@@ -1802,12 +1800,12 @@ class SEQUENCER_PT_cache_settings(SequencerButtonsPanel, Panel):
ed = context.scene.sequence_editor
- col = layout.column()
+ col = layout.column(heading="Cache", align=True)
- col.prop(ed, "use_cache_raw")
- col.prop(ed, "use_cache_preprocessed")
- col.prop(ed, "use_cache_composite")
- col.prop(ed, "use_cache_final")
+ col.prop(ed, "use_cache_raw", text="Raw")
+ col.prop(ed, "use_cache_preprocessed", text="Pre-Processed")
+ col.prop(ed, "use_cache_composite", text="Composite")
+ col.prop(ed, "use_cache_final", text="Final")
col.separator()
col.prop(ed, "recycle_max_cost")
@@ -1871,21 +1869,19 @@ class SEQUENCER_PT_strip_proxy(SequencerButtonsPanel, Panel):
flow = layout.column_flow()
if ed.proxy_storage == 'PER_STRIP':
- flow.prop(proxy, "use_proxy_custom_directory")
- flow.prop(proxy, "use_proxy_custom_file")
-
+ col = layout.column(heading="Custom Proxy")
+ col.prop(proxy, "use_proxy_custom_directory", text="Directory")
if proxy.use_proxy_custom_directory and not proxy.use_proxy_custom_file:
- flow.prop(proxy, "directory")
+ col.prop(proxy, "directory")
+ col.prop(proxy, "use_proxy_custom_file", text="File")
if proxy.use_proxy_custom_file:
- flow.prop(proxy, "filepath")
+ col.prop(proxy, "filepath")
- box = layout.box()
- row = box.row(align=True)
- row.prop(strip.proxy, "build_25")
- row.prop(strip.proxy, "build_75")
- row = box.row(align=True)
- row.prop(strip.proxy, "build_50")
- row.prop(strip.proxy, "build_100")
+ row = layout.row(heading="Resolutions", align=True)
+ row.prop(strip.proxy, "build_25", toggle=True)
+ row.prop(strip.proxy, "build_75", toggle=True)
+ row.prop(strip.proxy, "build_50", toggle=True)
+ row.prop(strip.proxy, "build_100", toggle=True)
layout.use_property_split = True
layout.use_property_decorate = False
@@ -1926,10 +1922,10 @@ class SEQUENCER_PT_strip_cache(SequencerButtonsPanel, Panel):
strip = act_strip(context)
layout.active = strip.override_cache_settings
- col = layout.column()
- col.prop(strip, "use_cache_raw")
- col.prop(strip, "use_cache_preprocessed")
- col.prop(strip, "use_cache_composite")
+ col = layout.column(heading="Cache")
+ col.prop(strip, "use_cache_raw", text="Raw")
+ col.prop(strip, "use_cache_preprocessed", text="Pre-Processed")
+ col.prop(strip, "use_cache_composite", text="Composite")
class SEQUENCER_PT_preview(SequencerButtonsPanel_Output, Panel):
@@ -2162,6 +2158,33 @@ class SEQUENCER_PT_annotation(AnnotationDataPanel, SequencerButtonsPanel_Output,
# But, it should only show up when there are images in the preview region
+class SEQUENCER_PT_annotation_onion(AnnotationOnionSkin, SequencerButtonsPanel_Output, Panel):
+ bl_space_type = 'SEQUENCE_EDITOR'
+ bl_region_type = 'UI'
+ bl_category = "View"
+
+ @staticmethod
+ def has_preview(context):
+ st = context.space_data
+ return st.view_type in {'PREVIEW', 'SEQUENCER_PREVIEW'}
+
+ @classmethod
+ def poll(cls, context):
+ if context.annotation_data_owner is None:
+ return False
+ elif type(context.annotation_data_owner) is bpy.types.Object:
+ return False
+ else:
+ gpl = context.active_annotation_layer
+ if gpl is None:
+ return False
+
+ return cls.has_preview(context)
+
+ # NOTE: this is just a wrapper around the generic GP Panel
+ # But, it should only show up when there are images in the preview region
+
+
class SEQUENCER_PT_custom_props(SequencerButtonsPanel, PropertyPanel, Panel):
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
_context_path = "scene.sequence_editor.active_strip"
@@ -2235,6 +2258,7 @@ classes = (
SEQUENCER_PT_view_safe_areas_center_cut,
SEQUENCER_PT_annotation,
+ SEQUENCER_PT_annotation_onion,
)
if __name__ == "__main__": # only for live edit.
diff --git a/release/scripts/startup/bl_ui/space_text.py b/release/scripts/startup/bl_ui/space_text.py
index b7c5dcd5437..f6f22ad464f 100644
--- a/release/scripts/startup/bl_ui/space_text.py
+++ b/release/scripts/startup/bl_ui/space_text.py
@@ -129,18 +129,21 @@ class TEXT_PT_properties(Panel):
layout.use_property_decorate = False
st = context.space_data
- flow = layout.column_flow()
if not st.text:
- flow.active = False
- row = flow.row(align=True)
+ layout.active = False
+
st = context.space_data
- row.prop(st, "show_margin", text="Margin")
- rowsub = row.row()
- rowsub.active = st.show_margin
- rowsub.prop(st, "margin_column", text="")
- flow.prop(st, "font_size")
- flow.prop(st, "tab_width")
+ col = layout.column(align=False, heading="Margin")
+ row = col.row(align=True)
+ sub = row.row(align=True)
+ sub.prop(st, "show_margin", text="")
+ sub = sub.row(align=True)
+ sub.active = st.show_margin
+ sub.prop(st, "margin_column", text="")
+
+ layout.prop(st, "font_size")
+ layout.prop(st, "tab_width")
text = st.text
if text:
diff --git a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
index 3c9355d0017..8638f1a2a27 100644
--- a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
@@ -628,9 +628,10 @@ class _defs_edit_mesh:
layout.prop(props, "vertex_only")
layout.prop(props, "clamp_overlap")
layout.prop(props, "loop_slide")
- layout.prop(props, "mark_seam")
- layout.prop(props, "mark_sharp")
layout.prop(props, "harden_normals")
+ col = layout.column(heading="Mark")
+ col.prop(props, "mark_seam", text="Seam")
+ col.prop(props, "mark_sharp", text="Sharp")
layout.prop(props, "material")
@@ -671,6 +672,19 @@ class _defs_edit_mesh:
)
@ToolDef.from_fn
+ def extrude_dissolve_and_intersect():
+ return dict(
+ idname="builtin.extrude_dissolve_and_intersect",
+ label="Extrude Dissolve and Intersect",
+ description=(
+ "Extrude, dissolves edges whose faces form a flat surface and intersect new edges"
+ ),
+ icon="none",
+ widget="VIEW3D_GGT_tool_generic_handle_normal",
+ keymap=(),
+ )
+
+ @ToolDef.from_fn
def extrude_normals():
def draw_settings(_context, layout, tool):
props = tool.operator_properties("mesh.extrude_region_shrink_fatten")
@@ -2114,6 +2128,7 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
None,
(
_defs_edit_mesh.extrude,
+ _defs_edit_mesh.extrude_dissolve_and_intersect,
_defs_edit_mesh.extrude_normals,
_defs_edit_mesh.extrude_individual,
_defs_edit_mesh.extrude_cursor,
diff --git a/release/scripts/startup/bl_ui/space_topbar.py b/release/scripts/startup/bl_ui/space_topbar.py
index 1e6f03c2b0c..7a23eb9282c 100644
--- a/release/scripts/startup/bl_ui/space_topbar.py
+++ b/release/scripts/startup/bl_ui/space_topbar.py
@@ -580,6 +580,8 @@ class TOPBAR_MT_edit(Menu):
def draw(self, context):
layout = self.layout
+ show_developer = context.preferences.view.show_developer_ui
+
layout.operator("ed.undo")
layout.operator("ed.redo")
@@ -598,8 +600,9 @@ class TOPBAR_MT_edit(Menu):
layout.separator()
- layout.operator("wm.search_menu",
- text="Operator Search...", icon='VIEWZOOM')
+ layout.operator("wm.search_menu", text="Menu Search...", icon='VIEWZOOM')
+ if show_developer:
+ layout.operator("wm.search_operator", text="Operator Search...", icon='VIEWZOOM')
layout.separator()
diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py
index 3d579053a97..bb68eeb4447 100644
--- a/release/scripts/startup/bl_ui/space_userpref.py
+++ b/release/scripts/startup/bl_ui/space_userpref.py
@@ -200,19 +200,16 @@ class USERPREF_PT_interface_display(InterfacePanel, CenterAlignMixIn, Panel):
prefs = context.preferences
view = prefs.view
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
-
- flow.prop(view, "ui_scale", text="Resolution Scale")
- flow.prop(view, "ui_line_width", text="Line Width")
-
- layout.separator()
+ col = layout.column()
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
+ col.prop(view, "ui_scale", text="Resolution Scale")
+ col.prop(view, "ui_line_width", text="Line Width")
+ col.prop(view, "show_splash", text="Splash Screen")
+ col.prop(view, "show_developer_ui")
- flow.prop(view, "show_splash", text="Splash Screen")
- flow.prop(view, "show_tooltips")
- flow.prop(view, "show_tooltips_python")
- flow.prop(view, "show_developer_ui")
+ col = layout.column(heading="Tooltips")
+ col.prop(view, "show_tooltips")
+ col.prop(view, "show_tooltips_python")
class USERPREF_PT_interface_text(InterfacePanel, CenterAlignMixIn, Panel):
@@ -248,12 +245,11 @@ class USERPREF_PT_interface_translation(InterfacePanel, CenterAlignMixIn, Panel)
layout.prop(view, "language")
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
- flow.active = (bpy.app.translations.locale != 'en_US')
-
- flow.prop(view, "use_translate_tooltips", text="Tooltips")
- flow.prop(view, "use_translate_interface", text="Interface")
- flow.prop(view, "use_translate_new_dataname", text="New Data")
+ col = layout.column(heading="Affect")
+ col.active = (bpy.app.translations.locale != 'en_US')
+ col.prop(view, "use_translate_tooltips", text="Tooltips")
+ col.prop(view, "use_translate_interface", text="Interface")
+ col.prop(view, "use_translate_new_dataname", text="New Data")
class USERPREF_PT_interface_editors(InterfacePanel, CenterAlignMixIn, Panel):
@@ -264,14 +260,13 @@ class USERPREF_PT_interface_editors(InterfacePanel, CenterAlignMixIn, Panel):
view = prefs.view
system = prefs.system
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
-
- flow.prop(system, "use_region_overlap")
- flow.prop(view, "show_layout_ui", text="Corner Splitting")
- flow.prop(view, "show_navigate_ui")
- flow.prop(view, "color_picker_type")
- flow.row().prop(view, "header_align")
- flow.prop(view, "factor_display_type")
+ col = layout.column()
+ col.prop(system, "use_region_overlap")
+ col.prop(view, "show_layout_ui", text="Corner Splitting")
+ col.prop(view, "show_navigate_ui")
+ col.prop(view, "color_picker_type")
+ col.row().prop(view, "header_align")
+ col.prop(view, "factor_display_type")
class USERPREF_PT_interface_temporary_windows(InterfacePanel, CenterAlignMixIn, Panel):
@@ -283,10 +278,9 @@ class USERPREF_PT_interface_temporary_windows(InterfacePanel, CenterAlignMixIn,
prefs = context.preferences
view = prefs.view
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
-
- flow.prop(view, "render_display_type", text="Render in")
- flow.prop(view, "filebrowser_display_type", text="File Browser")
+ col = layout.column()
+ col.prop(view, "render_display_type", text="Render in")
+ col.prop(view, "filebrowser_display_type", text="File Browser")
class USERPREF_PT_interface_menus(InterfacePanel, Panel):
@@ -376,6 +370,8 @@ class USERPREF_PT_edit_objects_duplicate_data(EditingPanel, CenterAlignMixIn, Pa
prefs = context.preferences
edit = prefs.edit
+ layout.use_property_split = False
+
flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=True)
col = flow.column()
@@ -409,10 +405,9 @@ class USERPREF_PT_edit_cursor(EditingPanel, CenterAlignMixIn, Panel):
prefs = context.preferences
edit = prefs.edit
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
-
- flow.prop(edit, "use_mouse_depth_cursor")
- flow.prop(edit, "use_cursor_lock_adjust")
+ col = layout.column()
+ col.prop(edit, "use_mouse_depth_cursor")
+ col.prop(edit, "use_cursor_lock_adjust")
class USERPREF_PT_edit_gpencil(EditingPanel, CenterAlignMixIn, Panel):
@@ -423,10 +418,9 @@ class USERPREF_PT_edit_gpencil(EditingPanel, CenterAlignMixIn, Panel):
prefs = context.preferences
edit = prefs.edit
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
-
- flow.prop(edit, "grease_pencil_manhattan_distance", text="Manhattan Distance")
- flow.prop(edit, "grease_pencil_euclidean_distance", text="Euclidean Distance")
+ col = layout.column(heading="Distance")
+ col.prop(edit, "grease_pencil_manhattan_distance", text="Manhattan")
+ col.prop(edit, "grease_pencil_euclidean_distance", text="Euclidean")
class USERPREF_PT_edit_annotations(EditingPanel, CenterAlignMixIn, Panel):
@@ -436,10 +430,9 @@ class USERPREF_PT_edit_annotations(EditingPanel, CenterAlignMixIn, Panel):
prefs = context.preferences
edit = prefs.edit
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
-
- flow.prop(edit, "grease_pencil_default_color", text="Default Color")
- flow.prop(edit, "grease_pencil_eraser_radius", text="Eraser Radius")
+ col = layout.column()
+ col.prop(edit, "grease_pencil_default_color", text="Default Color")
+ col.prop(edit, "grease_pencil_eraser_radius", text="Eraser Radius")
class USERPREF_PT_edit_weight_paint(EditingPanel, CenterAlignMixIn, Panel):
@@ -450,6 +443,8 @@ class USERPREF_PT_edit_weight_paint(EditingPanel, CenterAlignMixIn, Panel):
prefs = context.preferences
view = prefs.view
+ layout.use_property_split = False
+
layout.prop(view, "use_weight_color_range", text="Use Custom Colors")
col = layout.column()
@@ -465,10 +460,9 @@ class USERPREF_PT_edit_misc(EditingPanel, CenterAlignMixIn, Panel):
prefs = context.preferences
edit = prefs.edit
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
-
- flow.prop(edit, "sculpt_paint_overlay_color", text="Sculpt Overlay Color")
- flow.prop(edit, "node_margin", text="Node Auto-offset Margin")
+ col = layout.column()
+ col.prop(edit, "sculpt_paint_overlay_color", text="Sculpt Overlay Color")
+ col.prop(edit, "node_margin", text="Node Auto-offset Margin")
# -----------------------------------------------------------------------------
@@ -488,20 +482,16 @@ class USERPREF_PT_animation_timeline(AnimationPanel, CenterAlignMixIn, Panel):
view = prefs.view
edit = prefs.edit
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
- flow.prop(edit, "use_negative_frames")
-
- layout.separator()
-
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
+ col = layout.column()
+ col.prop(edit, "use_negative_frames")
- flow.prop(view, "view2d_grid_spacing_min", text="Minimum Grid Spacing")
- flow.prop(view, "timecode_style")
- flow.prop(view, "view_frame_type")
+ col.prop(view, "view2d_grid_spacing_min", text="Minimum Grid Spacing")
+ col.prop(view, "timecode_style")
+ col.prop(view, "view_frame_type")
if view.view_frame_type == 'SECONDS':
- flow.prop(view, "view_frame_seconds")
+ col.prop(view, "view_frame_seconds")
elif view.view_frame_type == 'KEYFRAMES':
- flow.prop(view, "view_frame_keyframes")
+ col.prop(view, "view_frame_keyframes")
class USERPREF_PT_animation_keyframes(AnimationPanel, CenterAlignMixIn, Panel):
@@ -511,25 +501,14 @@ class USERPREF_PT_animation_keyframes(AnimationPanel, CenterAlignMixIn, Panel):
prefs = context.preferences
edit = prefs.edit
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
-
- flow.prop(edit, "use_visual_keying")
- flow.prop(edit, "use_keyframe_insert_needed", text="Only Insert Needed")
-
-
-class USERPREF_PT_animation_autokey(AnimationPanel, CenterAlignMixIn, Panel):
- bl_label = "Auto-Keyframing"
- bl_parent_id = "USERPREF_PT_animation_keyframes"
-
- def draw_centered(self, context, layout):
- prefs = context.preferences
- edit = prefs.edit
-
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
+ col = layout.column()
+ col.prop(edit, "use_visual_keying")
+ col.prop(edit, "use_keyframe_insert_needed", text="Only Insert Needed")
- flow.prop(edit, "use_auto_keying_warning", text="Show Warning")
- flow.prop(edit, "use_keyframe_insert_available", text="Only Insert Available")
- flow.prop(edit, "use_auto_keying", text="Enable in New Scenes")
+ col = layout.column(heading="Auto-Keyframing")
+ col.prop(edit, "use_auto_keying_warning", text="Show Warning")
+ col.prop(edit, "use_keyframe_insert_available", text="Only Insert Available")
+ col.prop(edit, "use_auto_keying", text="Enable in New Scenes")
class USERPREF_PT_animation_fcurves(AnimationPanel, CenterAlignMixIn, Panel):
@@ -605,23 +584,27 @@ class USERPREF_PT_system_memory(SystemPanel, CenterAlignMixIn, Panel):
system = prefs.system
edit = prefs.edit
- layout.prop(edit, "undo_steps", text="Undo Steps")
- layout.prop(edit, "undo_memory_limit", text="Undo Memory Limit")
- layout.prop(edit, "use_global_undo")
+ col = layout.column()
+ col.prop(edit, "undo_steps", text="Undo Steps")
+ col.prop(edit, "undo_memory_limit", text="Undo Memory Limit")
+ col.prop(edit, "use_global_undo")
layout.separator()
- layout.prop(system, "texture_time_out", text="Texture Time Out")
- layout.prop(system, "texture_collection_rate", text="Garbage Collection Rate")
+ col = layout.column()
+ col.prop(system, "scrollback", text="Console Scrollback Lines")
layout.separator()
- layout.prop(system, "vbo_time_out", text="Vbo Time Out")
- layout.prop(system, "vbo_collection_rate", text="Garbage Collection Rate")
+ col = layout.column()
+ col.prop(system, "texture_time_out", text="Texture Time Out")
+ col.prop(system, "texture_collection_rate", text="Garbage Collection Rate")
layout.separator()
- layout.prop(system, "scrollback", text="Console Scrollback Lines")
+ col = layout.column()
+ col.prop(system, "vbo_time_out", text="Vbo Time Out")
+ col.prop(system, "vbo_collection_rate", text="Garbage Collection Rate")
class USERPREF_PT_system_video_sequencer(SystemPanel, CenterAlignMixIn, Panel):
@@ -660,23 +643,19 @@ class USERPREF_PT_viewport_display(ViewportPanel, CenterAlignMixIn, Panel):
prefs = context.preferences
view = prefs.view
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
-
- flow.prop(view, "show_object_info", text="Object Info")
- flow.prop(view, "show_view_name", text="View Name")
- flow.prop(view, "show_playback_fps", text="Playback FPS")
+ col = layout.column(heading="Show")
+ col.prop(view, "show_object_info", text="Object Info")
+ col.prop(view, "show_view_name", text="View Name")
+ col.prop(view, "show_playback_fps", text="Playback FPS")
layout.separator()
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
-
- col = flow.column()
+ col = layout.column()
col.prop(view, "gizmo_size")
col.prop(view, "lookdev_sphere_size")
- flow.separator()
+ col.separator()
- col = flow.column()
col.prop(view, "mini_axis_type", text="3D Viewport Axis")
if view.mini_axis_type == 'MINIMAL':
@@ -691,11 +670,12 @@ class USERPREF_PT_viewport_quality(ViewportPanel, CenterAlignMixIn, Panel):
prefs = context.preferences
system = prefs.system
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
+ col = layout.column()
+ col.prop(system, "viewport_aa")
- flow.prop(system, "viewport_aa")
- flow.prop(system, "use_overlay_smooth_wire")
- flow.prop(system, "use_edit_mode_smooth_wire")
+ col = layout.column(heading="Smooth Wires")
+ col.prop(system, "use_overlay_smooth_wire", text="Overlay")
+ col.prop(system, "use_edit_mode_smooth_wire", text="Edit Mode")
class USERPREF_PT_viewport_textures(ViewportPanel, CenterAlignMixIn, Panel):
@@ -705,12 +685,11 @@ class USERPREF_PT_viewport_textures(ViewportPanel, CenterAlignMixIn, Panel):
prefs = context.preferences
system = prefs.system
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
-
- flow.prop(system, "gl_texture_limit", text="Limit Size")
- flow.prop(system, "anisotropic_filter")
- flow.prop(system, "gl_clip_alpha", slider=True)
- flow.prop(system, "image_draw_method", text="Image Display Method")
+ col = layout.column()
+ col.prop(system, "gl_texture_limit", text="Limit Size")
+ col.prop(system, "anisotropic_filter")
+ col.prop(system, "gl_clip_alpha", slider=True)
+ col.prop(system, "image_draw_method", text="Image Display Method")
class USERPREF_PT_viewport_selection(ViewportPanel, CenterAlignMixIn, Panel):
@@ -721,9 +700,7 @@ class USERPREF_PT_viewport_selection(ViewportPanel, CenterAlignMixIn, Panel):
prefs = context.preferences
system = prefs.system
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
-
- flow.prop(system, "use_select_pick_depth")
+ layout.prop(system, "use_select_pick_depth")
# -----------------------------------------------------------------------------
@@ -1331,37 +1308,40 @@ class USERPREF_PT_saveload_blend(SaveLoadPanel, CenterAlignMixIn, Panel):
paths = prefs.filepaths
view = prefs.view
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
-
- flow.prop(paths, "use_relative_paths")
- flow.prop(paths, "use_file_compression")
- flow.prop(paths, "use_load_ui")
- flow.prop(paths, "use_save_preview_images")
- flow.prop(paths, "use_tabs_as_spaces")
- flow.prop(view, "use_save_prompt")
+ col = layout.column(heading="Save")
+ col.prop(view, "use_save_prompt")
+ col.prop(paths, "use_save_preview_images")
- layout.separator()
+ col = layout.column(heading="Default to")
+ col.prop(paths, "use_relative_paths")
+ col.prop(paths, "use_file_compression")
+ col.prop(paths, "use_load_ui")
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
+ col = layout.column(heading="Text Files")
+ col.prop(paths, "use_tabs_as_spaces")
- flow.prop(paths, "save_version")
- flow.prop(paths, "recent_files")
+ col = layout.column()
+ col.prop(paths, "save_version")
+ col.prop(paths, "recent_files")
class USERPREF_PT_saveload_blend_autosave(SaveLoadPanel, CenterAlignMixIn, Panel):
bl_label = "Auto Save"
bl_parent_id = "USERPREF_PT_saveload_blend"
- def draw_centered(self, context, layout):
+ def draw_header(self, context):
prefs = context.preferences
paths = prefs.filepaths
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
+ self.layout.prop(paths, "use_auto_save_temporary_files", text="")
- flow.prop(paths, "use_auto_save_temporary_files")
- sub = flow.column()
- sub.active = paths.use_auto_save_temporary_files
- sub.prop(paths, "auto_save_time", text="Timer (mins)")
+ def draw_centered(self, context, layout):
+ prefs = context.preferences
+ paths = prefs.filepaths
+
+ col = layout.column()
+ col.active = paths.use_auto_save_temporary_files
+ col.prop(paths, "auto_save_time", text="Timer (mins)")
class USERPREF_PT_saveload_file_browser(SaveLoadPanel, CenterAlignMixIn, Panel):
@@ -1371,12 +1351,13 @@ class USERPREF_PT_saveload_file_browser(SaveLoadPanel, CenterAlignMixIn, Panel):
prefs = context.preferences
paths = prefs.filepaths
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
+ col = layout.column()
+ col.prop(paths, "use_filter_files")
- flow.prop(paths, "use_filter_files")
- flow.prop(paths, "show_hidden_files_datablocks")
- flow.prop(paths, "hide_recent_locations")
- flow.prop(paths, "hide_system_bookmarks")
+ col = layout.column(heading="Hide")
+ col.prop(paths, "show_hidden_files_datablocks", text="Dot File & Datablocks")
+ col.prop(paths, "hide_recent_locations", text="Recent Locations")
+ col.prop(paths, "hide_system_bookmarks", text="System Bookmarks")
# -----------------------------------------------------------------------------
@@ -1435,10 +1416,9 @@ class USERPREF_PT_input_tablet(InputPanel, CenterAlignMixIn, Panel):
layout.prop(inputs, "tablet_api")
layout.separator()
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
-
- flow.prop(inputs, "pressure_threshold_max")
- flow.prop(inputs, "pressure_softness")
+ col = layout.column()
+ col.prop(inputs, "pressure_threshold_max")
+ col.prop(inputs, "pressure_softness")
class USERPREF_PT_input_ndof(InputPanel, CenterAlignMixIn, Panel):
@@ -1485,24 +1465,27 @@ class USERPREF_PT_navigation_orbit(NavigationPanel, CenterAlignMixIn, Panel):
inputs = prefs.inputs
view = prefs.view
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
+ col = layout.column()
- flow.row().prop(inputs, "view_rotate_method", expand=True)
+ col.row().prop(inputs, "view_rotate_method", expand=True)
if inputs.view_rotate_method == 'TURNTABLE':
- flow.prop(inputs, "view_rotate_sensitivity_turntable")
+ col.prop(inputs, "view_rotate_sensitivity_turntable")
else:
- flow.prop(inputs, "view_rotate_sensitivity_trackball")
+ col.prop(inputs, "view_rotate_sensitivity_trackball")
+ col.prop(inputs, "use_rotate_around_active")
+
+ col.separator()
- flow.prop(inputs, "use_rotate_around_active")
- flow.prop(inputs, "use_auto_perspective")
- flow.prop(inputs, "use_mouse_depth_navigate")
if sys.platform == "darwin":
- flow.prop(inputs, "use_trackpad_natural", text="Natural Trackpad Direction")
+ col.prop(inputs, "use_trackpad_natural", text="Natural Trackpad Direction")
- flow.separator()
+ col = layout.column(heading="Auto")
+ col.prop(inputs, "use_auto_perspective", text="Perspective")
+ col.prop(inputs, "use_mouse_depth_navigate", text="Depth")
- flow.prop(view, "smooth_view")
- flow.prop(view, "rotation_angle")
+ col = layout.column()
+ col.prop(view, "smooth_view")
+ col.prop(view, "rotation_angle")
class USERPREF_PT_navigation_zoom(NavigationPanel, CenterAlignMixIn, Panel):
@@ -1512,16 +1495,20 @@ class USERPREF_PT_navigation_zoom(NavigationPanel, CenterAlignMixIn, Panel):
prefs = context.preferences
inputs = prefs.inputs
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
+ col = layout.column()
- flow.row().prop(inputs, "view_zoom_method", text="Zoom Method")
+ col.row().prop(inputs, "view_zoom_method", text="Zoom Method")
if inputs.view_zoom_method in {'DOLLY', 'CONTINUE'}:
- flow.row().prop(inputs, "view_zoom_axis")
- flow.prop(inputs, "invert_mouse_zoom", text="Invert Mouse Zoom Direction")
+ col.row().prop(inputs, "view_zoom_axis")
+ col.prop(inputs, "use_zoom_to_mouse")
+ col = layout.column(heading="Invert Zoom Direction", align=True)
+ col.prop(inputs, "invert_mouse_zoom", text="Mouse")
+ col.prop(inputs, "invert_zoom_wheel", text="Wheel")
+ else:
+ col.prop(inputs, "use_zoom_to_mouse")
+ col.prop(inputs, "invert_zoom_wheel", text="Invert Wheel Zoom Direction")
- flow.prop(inputs, "invert_zoom_wheel", text="Invert Wheel Zoom Direction")
# sub.prop(view, "wheel_scroll_lines", text="Scroll Lines")
- flow.prop(inputs, "use_zoom_to_mouse")
class USERPREF_PT_navigation_fly_walk(NavigationPanel, CenterAlignMixIn, Panel):
@@ -1552,15 +1539,14 @@ class USERPREF_PT_navigation_fly_walk_navigation(NavigationPanel, CenterAlignMix
inputs = prefs.inputs
walk = inputs.walk_navigation
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
-
- flow.prop(walk, "use_mouse_reverse")
- flow.prop(walk, "mouse_speed")
- flow.prop(walk, "teleport_time")
+ col = layout.column()
+ col.prop(walk, "use_mouse_reverse")
+ col.prop(walk, "mouse_speed")
+ col.prop(walk, "teleport_time")
- sub = flow.column(align=True)
- sub.prop(walk, "walk_speed")
- sub.prop(walk, "walk_speed_factor")
+ col = layout.column(align=True)
+ col.prop(walk, "walk_speed")
+ col.prop(walk, "walk_speed_factor")
class USERPREF_PT_navigation_fly_walk_gravity(NavigationPanel, CenterAlignMixIn, Panel):
@@ -1587,10 +1573,9 @@ class USERPREF_PT_navigation_fly_walk_gravity(NavigationPanel, CenterAlignMixIn,
layout.active = walk.use_gravity
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
-
- flow.prop(walk, "view_height")
- flow.prop(walk, "jump_height")
+ col = layout.column()
+ col.prop(walk, "view_height")
+ col.prop(walk, "jump_height")
# Special case, this is only exposed as a popover.
@@ -2135,7 +2120,7 @@ class ExperimentalPanel:
experimental = prefs.experimental
layout = self.layout
- layout.use_property_split = True
+ layout.use_property_split = False
layout.use_property_decorate = False
for prop_keywords, task in items:
@@ -2161,16 +2146,6 @@ class USERPREF_PT_experimental_virtual_reality(ExperimentalPanel, Panel):
)
"""
-class USERPREF_PT_experimental_ui(ExperimentalPanel, Panel):
- bl_label = "UI"
-
- def draw(self, context):
- self._draw_items(
- context, (
- ({"property": "use_menu_search"}, "T74157"),
- ),
- )
-
class USERPREF_PT_experimental_system(ExperimentalPanel, Panel):
bl_label = "System"
@@ -2223,7 +2198,6 @@ classes = (
USERPREF_PT_animation_timeline,
USERPREF_PT_animation_keyframes,
- USERPREF_PT_animation_autokey,
USERPREF_PT_animation_fcurves,
USERPREF_PT_system_cycles_devices,
@@ -2274,7 +2248,6 @@ classes = (
# Popovers.
USERPREF_PT_ndof_settings,
- USERPREF_PT_experimental_ui,
USERPREF_PT_experimental_system,
# Add dynamically generated editor theme panels last,
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index f38bbb46f85..9a46d7a6e82 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -5300,6 +5300,7 @@ class VIEW3D_MT_sculpt_mask_edit_pie(Menu):
op.auto_iteration_count = False
class VIEW3D_MT_sculpt_face_sets_edit_pie(Menu):
+
bl_label = "Face Sets Edit"
def draw(self, _context):
@@ -5395,8 +5396,8 @@ class VIEW3D_PT_view3d_properties(Panel):
layout.use_property_split = True
layout.use_property_decorate = False # No animation.
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=False, even_rows=False, align=True)
- col = flow.column()
+
+ col = layout.column()
subcol = col.column()
subcol.active = bool(view.region_3d.view_perspective != 'CAMERA' or view.region_quadviews)
@@ -5406,20 +5407,22 @@ class VIEW3D_PT_view3d_properties(Panel):
subcol.prop(view, "clip_start", text="Clip Start")
subcol.prop(view, "clip_end", text="End")
- subcol.separator()
-
- col = flow.column()
+ layout.separator()
- subcol = col.column()
- subcol.prop(view, "use_local_camera")
+ col = layout.column(align=False, heading="Local Camera")
+ col.use_property_decorate = False
+ row = col.row(align=True)
+ sub = row.row(align=True)
+ sub.prop(view, "use_local_camera", text="")
+ sub = sub.row(align=True)
+ sub.enabled = view.use_local_camera
+ sub.prop(view, "camera", text="")
- subcol = col.column()
- subcol.enabled = view.use_local_camera
- subcol.prop(view, "camera", text="Local Camera")
+ layout.separator()
- subcol = col.column(align=True)
- subcol.prop(view, "use_render_border")
- subcol.active = view.region_3d.view_perspective != 'CAMERA'
+ col = layout.column(align=True)
+ col.prop(view, "use_render_border")
+ col.active = view.region_3d.view_perspective != 'CAMERA'
class VIEW3D_PT_view3d_lock(Panel):
@@ -5438,23 +5441,24 @@ class VIEW3D_PT_view3d_lock(Panel):
view = context.space_data
col = layout.column(align=True)
- subcol = col.column()
- subcol.active = bool(view.region_3d.view_perspective != 'CAMERA' or view.region_quadviews)
+ sub = col.column()
+ sub.active = bool(view.region_3d.view_perspective != 'CAMERA' or view.region_quadviews)
- subcol.prop(view, "lock_object")
+ sub.prop(view, "lock_object")
lock_object = view.lock_object
if lock_object:
if lock_object.type == 'ARMATURE':
- subcol.prop_search(
+ sub.prop_search(
view, "lock_bone", lock_object.data,
"edit_bones" if lock_object.mode == 'EDIT'
else "bones",
text="",
)
else:
- subcol.prop(view, "lock_cursor", text="Lock to 3D Cursor")
+ subcol = sub.column(heading="Lock")
+ subcol.prop(view, "lock_cursor", text="To 3D Cursor")
- col.prop(view, "lock_camera")
+ col.prop(view, "lock_camera", text="Camera to View")
class VIEW3D_PT_view3d_cursor(Panel):
diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
index 6aaeec3f3cf..04a3e6f62ea 100644
--- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
@@ -125,21 +125,15 @@ class View3DPanel:
# Used by vertex & weight paint
def draw_vpaint_symmetry(layout, vpaint):
- split = layout.split()
-
- col = split.column()
- col.alignment = 'RIGHT'
- col.label(text="Mirror")
+ col = layout.column()
+ col.use_property_split = True
+ col.use_property_decorate = False
- col = split.column()
- row = col.row(align=True)
+ row = col.row(heading="Mirror", align=True)
row.prop(vpaint, "use_symmetry_x", text="X", toggle=True)
row.prop(vpaint, "use_symmetry_y", text="Y", toggle=True)
row.prop(vpaint, "use_symmetry_z", text="Z", toggle=True)
- col = layout.column()
- col.use_property_split = True
- col.use_property_decorate = False
col.prop(vpaint, "radial_symmetry", text="Radial")
@@ -179,10 +173,10 @@ class VIEW3D_PT_tools_object_options_transform(View3DPanel, Panel):
tool_settings = context.tool_settings
- layout.label(text="Affect Only")
- layout.prop(tool_settings, "use_transform_data_origin", text="Origins")
- layout.prop(tool_settings, "use_transform_pivot_point_align", text="Locations")
- layout.prop(tool_settings, "use_transform_skip_children", text="Parents")
+ col = layout.column(heading="Affect Only", align=True)
+ col.prop(tool_settings, "use_transform_data_origin", text="Origins")
+ col.prop(tool_settings, "use_transform_pivot_point_align", text="Locations")
+ col.prop(tool_settings, "use_transform_skip_children", text="Parents")
# ********** default tools for editmode_mesh ****************
@@ -209,16 +203,11 @@ class VIEW3D_PT_tools_meshedit_options(View3DPanel, Panel):
split = layout.split()
- col = split.column()
- col.alignment = 'RIGHT'
- col.label(text="Mirror")
-
- col = split.column()
-
- row = col.row(align=True)
- row.prop(mesh, "use_mirror_x", text="X", toggle=True)
- row.prop(mesh, "use_mirror_y", text="Y", toggle=True)
- row.prop(mesh, "use_mirror_z", text="Z", toggle=True)
+ row = layout.row(heading="Mirror")
+ sub = row.row(align=True)
+ sub.prop(mesh, "use_mirror_x", text="X", toggle=True)
+ sub.prop(mesh, "use_mirror_y", text="Y", toggle=True)
+ sub.prop(mesh, "use_mirror_z", text="Z", toggle=True)
row = layout.row(align=True)
row.active = ob.data.use_mirror_x or ob.data.use_mirror_y or ob.data.use_mirror_z
@@ -872,10 +861,13 @@ class VIEW3D_PT_sculpt_voxel_remesh(Panel, View3DPaintPanel):
col.prop(mesh, "remesh_voxel_adaptivity")
col.prop(mesh, "use_remesh_fix_poles")
col.prop(mesh, "use_remesh_smooth_normals")
- col.prop(mesh, "use_remesh_preserve_volume")
- col.prop(mesh, "use_remesh_preserve_paint_mask")
- col.prop(mesh, "use_remesh_preserve_sculpt_face_sets")
- col.operator("object.voxel_remesh", text="Remesh")
+
+ col = layout.column(heading="Preserve", align=True)
+ col.prop(mesh, "use_remesh_preserve_volume", text="Volume")
+ col.prop(mesh, "use_remesh_preserve_paint_mask", text="Paint Mask")
+ col.prop(mesh, "use_remesh_preserve_sculpt_face_sets", text="Face Sets")
+
+ layout.operator("object.voxel_remesh", text="Remesh")
# TODO, move to space_view3d.py
@@ -896,23 +888,19 @@ class VIEW3D_PT_sculpt_options(Panel, View3DPaintPanel):
tool_settings = context.tool_settings
sculpt = tool_settings.sculpt
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
-
- col = flow.column()
+ col = layout.column(heading="Display", align=True)
col.prop(sculpt, "use_threaded", text="Threaded Sculpt")
- col = flow.column()
col.prop(sculpt, "show_low_resolution")
- col = flow.column()
col.prop(sculpt, "use_sculpt_delay_updates")
- col = flow.column()
col.prop(sculpt, "use_deform_only")
- col = flow.column()
col.separator()
- col.prop(sculpt, "use_automasking_topology")
- col.prop(sculpt, "use_automasking_face_sets")
- col.prop(sculpt, "use_automasking_boundary_edges")
- col.prop(sculpt, "use_automasking_boundary_face_sets")
+
+ col = layout.column(heading="Auto-Masking", align=True)
+ col.prop(sculpt, "use_automasking_topology", text="Topology")
+ col.prop(sculpt, "use_automasking_face_sets", text="Face Sets")
+ col.prop(sculpt, "use_automasking_boundary_edges", text="Boundary Edges")
+ col.prop(sculpt, "use_automasking_boundary_face_sets", text="Boundary Face Sets")
class VIEW3D_PT_sculpt_options_gravity(Panel, View3DPaintPanel):
@@ -955,61 +943,34 @@ class VIEW3D_PT_sculpt_symmetry(Panel, View3DPaintPanel):
def draw(self, context):
layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
sculpt = context.tool_settings.sculpt
- split = layout.split()
-
- col = split.column()
- col.alignment = 'RIGHT'
- col.label(text="Mirror")
-
- col = split.column()
-
- row = col.row(align=True)
+ row = layout.row(align=True, heading="Mirror")
row.prop(sculpt, "use_symmetry_x", text="X", toggle=True)
row.prop(sculpt, "use_symmetry_y", text="Y", toggle=True)
row.prop(sculpt, "use_symmetry_z", text="Z", toggle=True)
- split = layout.split()
-
- col = split.column()
- col.alignment = 'RIGHT'
- col.label(text="Lock")
-
- col = split.column()
-
- row = col.row(align=True)
+ row = layout.row(align=True, heading="Lock")
row.prop(sculpt, "lock_x", text="X", toggle=True)
row.prop(sculpt, "lock_y", text="Y", toggle=True)
row.prop(sculpt, "lock_z", text="Z", toggle=True)
- split = layout.split()
-
- col = split.column()
- col.alignment = 'RIGHT'
- col.label(text="Tiling")
-
- col = split.column()
-
- row = col.row(align=True)
+ row = layout.row(align=True, heading="Tiling")
row.prop(sculpt, "tile_x", text="X", toggle=True)
row.prop(sculpt, "tile_y", text="Y", toggle=True)
row.prop(sculpt, "tile_z", text="Z", toggle=True)
- layout.use_property_split = True
- layout.use_property_decorate = False
-
layout.prop(sculpt, "use_symmetry_feather", text="Feather")
- layout.column().prop(sculpt, "radial_symmetry", text="Radial")
- layout.column().prop(sculpt, "tile_offset", text="Tile Offset")
+ layout.prop(sculpt, "radial_symmetry", text="Radial")
+ layout.prop(sculpt, "tile_offset", text="Tile Offset")
layout.separator()
- col = layout.column()
-
- col.prop(sculpt, "symmetrize_direction")
- col.operator("sculpt.symmetrize")
+ layout.prop(sculpt, "symmetrize_direction")
+ layout.operator("sculpt.symmetrize")
class VIEW3D_PT_sculpt_symmetry_for_topbar(Panel):
@@ -1212,12 +1173,8 @@ class VIEW3D_PT_tools_imagepaint_options(View3DPaintPanel, Panel):
layout.prop(ipaint, "seam_bleed")
layout.prop(ipaint, "dither", slider=True)
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
-
- col = flow.column()
+ col = layout.column()
col.prop(ipaint, "use_occlude")
-
- col = flow.column()
col.prop(ipaint, "use_backface_culling", text="Backface Culling")
diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py
index 969a1ca1bd7..fd169027c76 100644
--- a/release/scripts/startup/nodeitems_builtins.py
+++ b/release/scripts/startup/nodeitems_builtins.py
@@ -58,6 +58,13 @@ class TextureNodeCategory(SortedNodeCategory):
context.space_data.tree_type == 'TextureNodeTree')
+class SimulationNodeCategory(SortedNodeCategory):
+ @classmethod
+ def poll(cls, context):
+ return (context.space_data.type == 'NODE_EDITOR' and
+ context.space_data.tree_type == 'SimulationNodeTree')
+
+
# menu entry for node group tools
def group_tools_draw(self, layout, context):
layout.operator("node.group_make")
@@ -70,6 +77,7 @@ node_tree_group_type = {
'CompositorNodeTree': 'CompositorNodeGroup',
'ShaderNodeTree': 'ShaderNodeGroup',
'TextureNodeTree': 'TextureNodeGroup',
+ 'SimulationNodeTree': 'SimulationNodeGroup',
}
@@ -467,17 +475,79 @@ texture_node_categories = [
]),
]
+simulation_node_categories = [
+ # Simulation Nodes
+ SimulationNodeCategory("SIM_OUTPUT", "Output", items=[
+ NodeItem("SimulationNodeParticleSimulation"),
+ ]),
+ SimulationNodeCategory("SIM_INPUTS", "Input", items=[
+ NodeItem("SimulationNodeTime"),
+ NodeItem("SimulationNodeParticleAttribute"),
+ ]),
+ SimulationNodeCategory("SIM_EMITTERS", "Emitters", items=[
+ NodeItem("SimulationNodeParticleMeshEmitter"),
+ NodeItem("SimulationNodeEmitParticles"),
+ ]),
+ SimulationNodeCategory("SIM_EVENTS", "Events", items=[
+ NodeItem("SimulationNodeParticleBirthEvent"),
+ NodeItem("SimulationNodeParticleTimeStepEvent"),
+ NodeItem("SimulationNodeParticleMeshCollisionEvent"),
+ ]),
+ SimulationNodeCategory("SIM_FORCES", "Forces", items=[
+ NodeItem("SimulationNodeForce"),
+ ]),
+ SimulationNodeCategory("SIM_EXECUTE", "Execute", items=[
+ NodeItem("SimulationNodeSetParticleAttribute"),
+ NodeItem("SimulationNodeExecuteCondition"),
+ NodeItem("SimulationNodeMultiExecute"),
+ ]),
+ SimulationNodeCategory("SIM_NOISE", "Noise", items=[
+ NodeItem("ShaderNodeTexNoise"),
+ NodeItem("ShaderNodeTexWhiteNoise"),
+ ]),
+ SimulationNodeCategory("SIM_COLOR", "Color", items=[
+ NodeItem("ShaderNodeMixRGB"),
+ NodeItem("ShaderNodeInvert"),
+ NodeItem("ShaderNodeHueSaturation"),
+ NodeItem("ShaderNodeGamma"),
+ NodeItem("ShaderNodeBrightContrast"),
+ ]),
+ SimulationNodeCategory("SIM_CONVERTER", "Converter", items=[
+ NodeItem("ShaderNodeMapRange"),
+ NodeItem("ShaderNodeClamp"),
+ NodeItem("ShaderNodeMath"),
+ NodeItem("ShaderNodeValToRGB"),
+ NodeItem("ShaderNodeVectorMath"),
+ NodeItem("ShaderNodeSeparateRGB"),
+ NodeItem("ShaderNodeCombineRGB"),
+ NodeItem("ShaderNodeSeparateXYZ"),
+ NodeItem("ShaderNodeCombineXYZ"),
+ NodeItem("ShaderNodeSeparateHSV"),
+ NodeItem("ShaderNodeCombineHSV"),
+ NodeItem("FunctionNodeBooleanMath"),
+ NodeItem("FunctionNodeFloatCompare"),
+ NodeItem("FunctionNodeSwitch"),
+ ]),
+ SimulationNodeCategory("SIM_GROUP", "Group", items=node_group_items),
+ SimulationNodeCategory("SIM_LAYOUT", "Layout", items=[
+ NodeItem("NodeFrame"),
+ NodeItem("NodeReroute"),
+ ]),
+]
+
def register():
nodeitems_utils.register_node_categories('SHADER', shader_node_categories)
nodeitems_utils.register_node_categories('COMPOSITING', compositor_node_categories)
nodeitems_utils.register_node_categories('TEXTURE', texture_node_categories)
+ nodeitems_utils.register_node_categories('SIMULATION', simulation_node_categories)
def unregister():
nodeitems_utils.unregister_node_categories('SHADER')
nodeitems_utils.unregister_node_categories('COMPOSITING')
nodeitems_utils.unregister_node_categories('TEXTURE')
+ nodeitems_utils.unregister_node_categories('SIMULATION')
if __name__ == "__main__":
diff --git a/source/blender/blenkernel/BKE_animsys.h b/source/blender/blenkernel/BKE_animsys.h
index a8915c178d4..4076bca3b19 100644
--- a/source/blender/blenkernel/BKE_animsys.h
+++ b/source/blender/blenkernel/BKE_animsys.h
@@ -207,17 +207,15 @@ bool BKE_animsys_read_rna_setting(struct PathResolvedRNA *anim_rna, float *r_val
bool BKE_animsys_write_rna_setting(struct PathResolvedRNA *anim_rna, const float value);
/* Evaluation loop for evaluating animation data */
-void BKE_animsys_evaluate_animdata(struct Scene *scene,
- struct ID *id,
+void BKE_animsys_evaluate_animdata(struct ID *id,
struct AnimData *adt,
float ctime,
- short recalc,
+ eAnimData_Recalc recalc,
const bool flush_to_original);
/* Evaluation of all ID-blocks with Animation Data blocks - Animation Data Only */
void BKE_animsys_evaluate_all_animation(struct Main *main,
struct Depsgraph *depsgraph,
- struct Scene *scene,
float ctime);
/* ------------ Specialized API --------------- */
diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h
index 6c383ae5011..e59d5728350 100644
--- a/source/blender/blenkernel/BKE_armature.h
+++ b/source/blender/blenkernel/BKE_armature.h
@@ -27,6 +27,8 @@
extern "C" {
#endif
+#include "BLI_listbase.h"
+
struct Bone;
struct Depsgraph;
struct ListBase;
diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h
index c9a4d81604b..bc64f78ffae 100644
--- a/source/blender/blenkernel/BKE_blender_version.h
+++ b/source/blender/blenkernel/BKE_blender_version.h
@@ -26,8 +26,8 @@
*
* \note Use #STRINGIFY() rather than defining with quotes.
*/
-#define BLENDER_VERSION 283
-#define BLENDER_SUBVERSION 13
+#define BLENDER_VERSION 290
+#define BLENDER_SUBVERSION 0
/** Several breakages with 280, e.g. collections vs layers. */
#define BLENDER_MINVERSION 280
#define BLENDER_MINSUBVERSION 0
@@ -36,7 +36,7 @@
/** Can be left blank, otherwise a,b,c... etc with no quotes. */
#define BLENDER_VERSION_CHAR
/** alpha/beta/rc/release, docs use this. */
-#define BLENDER_VERSION_CYCLE beta
+#define BLENDER_VERSION_CYCLE alpha
/** Optionally set to 1,2,... for example to get alpha1 or rc2. */
#define BLENDER_VERSION_CYCLE_NUMBER
diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h
index 164867b228b..adc94a833c3 100644
--- a/source/blender/blenkernel/BKE_curve.h
+++ b/source/blender/blenkernel/BKE_curve.h
@@ -111,6 +111,8 @@ void BKE_curve_material_index_clear(struct Curve *cu);
bool BKE_curve_material_index_validate(struct Curve *cu);
void BKE_curve_material_remap(struct Curve *cu, const unsigned int *remap, unsigned int remap_len);
+void BKE_curve_smooth_flag_set(struct Curve *cu, bool set);
+
ListBase *BKE_curve_nurbs_get(struct Curve *cu);
int BKE_curve_nurb_vert_index_get(const struct Nurb *nu, const void *vert);
diff --git a/source/blender/blenkernel/BKE_fluid.h b/source/blender/blenkernel/BKE_fluid.h
index e8b4c819c62..e06a1a9fb92 100644
--- a/source/blender/blenkernel/BKE_fluid.h
+++ b/source/blender/blenkernel/BKE_fluid.h
@@ -61,6 +61,7 @@ void BKE_fluid_reallocate_copy_fluid(struct FluidDomainSettings *mds,
int o_max[3],
int o_shift[3],
int n_shift[3]);
+void BKE_fluid_cache_free_all(struct FluidDomainSettings *mds, struct Object *ob);
void BKE_fluid_cache_free(struct FluidDomainSettings *mds, struct Object *ob, int cache_map);
void BKE_fluid_cache_new_name_for_current_session(int maxlen, char *r_name);
diff --git a/source/blender/blenkernel/BKE_idtype.h b/source/blender/blenkernel/BKE_idtype.h
index 05545216217..6dc504c2007 100644
--- a/source/blender/blenkernel/BKE_idtype.h
+++ b/source/blender/blenkernel/BKE_idtype.h
@@ -165,6 +165,7 @@ extern IDTypeInfo IDType_ID_LP;
extern IDTypeInfo IDType_ID_HA;
extern IDTypeInfo IDType_ID_PT;
extern IDTypeInfo IDType_ID_VO;
+extern IDTypeInfo IDType_ID_SIM;
extern IDTypeInfo IDType_ID_LINK_PLACEHOLDER;
diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h
index ed1f67350c3..b2472e862ec 100644
--- a/source/blender/blenkernel/BKE_main.h
+++ b/source/blender/blenkernel/BKE_main.h
@@ -147,6 +147,7 @@ typedef struct Main {
ListBase hairs;
ListBase pointclouds;
ListBase volumes;
+ ListBase simulations;
/**
* Must be generated, used and freed by same code - never assume this is valid data unless you
@@ -220,7 +221,7 @@ const char *BKE_main_blendfile_path_from_global(void);
struct ListBase *which_libbase(struct Main *mainlib, short type);
-#define MAX_LIBARRAY 40
+#define MAX_LIBARRAY 41
int set_listbasepointers(struct Main *main, struct ListBase *lb[MAX_LIBARRAY]);
#define MAIN_VERSION_ATLEAST(main, ver, subver) \
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index 38fe974c228..10175a2c45f 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -385,8 +385,8 @@ struct bNodeTree *ntreeAddTree(struct Main *bmain, const char *name, const char
/* copy/free funcs, need to manage ID users */
void ntreeFreeTree(struct bNodeTree *ntree);
-/* Free tree which is owned byt another datablock. */
-void ntreeFreeNestedTree(struct bNodeTree *ntree);
+/* Free tree which is embedded into another datablock. */
+void ntreeFreeEmbeddedTree(struct bNodeTree *ntree);
struct bNodeTree *ntreeCopyTree_ex(const struct bNodeTree *ntree,
struct Main *bmain,
const bool do_id_user);
@@ -852,6 +852,7 @@ struct NodeTreeIterStore {
struct Light *light;
struct World *world;
struct FreestyleLineStyle *linestyle;
+ struct Simulation *simulation;
};
void BKE_node_tree_iter_init(struct NodeTreeIterStore *ntreeiter, struct Main *bmain);
@@ -1282,6 +1283,35 @@ int ntreeTexExecTree(struct bNodeTree *ntree,
struct MTex *mtex);
/** \} */
+/* -------------------------------------------------------------------- */
+/** \name Simulation Nodes
+ * \{ */
+
+#define SIM_NODE_PARTICLE_SIMULATION 1000
+#define SIM_NODE_FORCE 1001
+#define SIM_NODE_SET_PARTICLE_ATTRIBUTE 1002
+#define SIM_NODE_PARTICLE_BIRTH_EVENT 1003
+#define SIM_NODE_PARTICLE_TIME_STEP_EVENT 1004
+#define SIM_NODE_EXECUTE_CONDITION 1005
+#define SIM_NODE_MULTI_EXECUTE 1006
+#define SIM_NODE_PARTICLE_MESH_EMITTER 1007
+#define SIM_NODE_PARTICLE_MESH_COLLISION_EVENT 1008
+#define SIM_NODE_EMIT_PARTICLES 1009
+#define SIM_NODE_TIME 1010
+#define SIM_NODE_PARTICLE_ATTRIBUTE 1011
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Function Nodes
+ * \{ */
+
+#define FN_NODE_BOOLEAN_MATH 1200
+#define FN_NODE_SWITCH 1201
+#define FN_NODE_FLOAT_COMPARE 1202
+
+/** \} */
+
void init_nodesystem(void);
void free_nodesystem(void);
diff --git a/source/blender/blenkernel/BKE_simulation.h b/source/blender/blenkernel/BKE_simulation.h
new file mode 100644
index 00000000000..aad0ada75a9
--- /dev/null
+++ b/source/blender/blenkernel/BKE_simulation.h
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+#ifndef __BKE_SIMULATION_H__
+#define __BKE_SIMULATION_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct Main;
+struct Simulation;
+
+void *BKE_simulation_add(struct Main *bmain, const char *name);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __BKE_SIMULATION_H__ */
diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h
index 20236745438..bb88fbf863b 100644
--- a/source/blender/blenkernel/BKE_tracking.h
+++ b/source/blender/blenkernel/BKE_tracking.h
@@ -261,8 +261,16 @@ void BKE_tracking_distortion_undistort_v2(struct MovieDistortion *distortion,
float r_co[2]);
void BKE_tracking_distortion_free(struct MovieDistortion *distortion);
-void BKE_tracking_distort_v2(struct MovieTracking *tracking, const float co[2], float r_co[2]);
-void BKE_tracking_undistort_v2(struct MovieTracking *tracking, const float co[2], float r_co[2]);
+void BKE_tracking_distort_v2(struct MovieTracking *tracking,
+ int image_width,
+ int image_height,
+ const float co[2],
+ float r_co[2]);
+void BKE_tracking_undistort_v2(struct MovieTracking *tracking,
+ int image_width,
+ int image_height,
+ const float co[2],
+ float r_co[2]);
struct ImBuf *BKE_tracking_undistort_frame(struct MovieTracking *tracking,
struct ImBuf *ibuf,
@@ -276,6 +284,8 @@ struct ImBuf *BKE_tracking_distort_frame(struct MovieTracking *tracking,
float overscan);
void BKE_tracking_max_distortion_delta_across_bound(struct MovieTracking *tracking,
+ int image_width,
+ int image_height,
struct rcti *rect,
bool undistort,
float delta[2]);
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 6e612df33d5..bdf8778651d 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -211,6 +211,7 @@ set(SRC
intern/sequencer.c
intern/shader_fx.c
intern/shrinkwrap.c
+ intern/simulation.cc
intern/softbody.c
intern/sound.c
intern/speaker.c
@@ -362,6 +363,7 @@ set(SRC
BKE_sequencer.h
BKE_shader_fx.h
BKE_shrinkwrap.h
+ BKE_simulation.h
BKE_softbody.h
BKE_sound.h
BKE_speaker.h
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index ba77538bfb6..4f51e23496c 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -1665,6 +1665,6 @@ void what_does_obaction(
adt.action = act;
/* execute effects of Action on to workob (or it's PoseChannels) */
- BKE_animsys_evaluate_animdata(NULL, &workob->id, &adt, cframe, ADT_RECALC_ANIM, false);
+ BKE_animsys_evaluate_animdata(&workob->id, &adt, cframe, ADT_RECALC_ANIM, false);
}
}
diff --git a/source/blender/blenkernel/intern/anim_data.c b/source/blender/blenkernel/intern/anim_data.c
index 41bfc5b59e4..f77e2ea1e0d 100644
--- a/source/blender/blenkernel/intern/anim_data.c
+++ b/source/blender/blenkernel/intern/anim_data.c
@@ -95,6 +95,7 @@ bool id_type_can_have_animdata(const short id_type)
case ID_HA:
case ID_PT:
case ID_VO:
+ case ID_SIM:
return true;
/* no AnimData */
@@ -1321,6 +1322,9 @@ void BKE_animdata_main_cb(Main *bmain, ID_AnimData_Edit_Callback func, void *use
/* volumes */
ANIMDATA_IDS_CB(bmain->volumes.first);
+
+ /* simulations */
+ ANIMDATA_IDS_CB(bmain->simulations.first);
}
/* Fix all RNA-Paths throughout the database (directly access the Global.main version)
@@ -1430,6 +1434,9 @@ void BKE_animdata_fix_paths_rename_all(ID *ref_id,
/* volumes */
RENAMEFIX_ANIM_IDS(bmain->volumes.first);
+ /* simulations */
+ RENAMEFIX_ANIM_IDS(bmain->simulations.first);
+
/* scenes */
RENAMEFIX_ANIM_NODETREE_IDS(bmain->scenes.first, Scene);
}
diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c
index 18320ef0f8d..5e4b280d0d0 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -2500,7 +2500,7 @@ static void animsys_evaluate_overrides(PointerRNA *ptr, AnimData *adt)
* have been set already by the depsgraph. Now, we use the recalc
*/
void BKE_animsys_evaluate_animdata(
- Scene *scene, ID *id, AnimData *adt, float ctime, short recalc, const bool flush_to_original)
+ ID *id, AnimData *adt, float ctime, eAnimData_Recalc recalc, const bool flush_to_original)
{
PointerRNA id_ptr;
@@ -2547,13 +2547,6 @@ void BKE_animsys_evaluate_animdata(
* - It is best that we execute this every time, so that no errors are likely to occur.
*/
animsys_evaluate_overrides(&id_ptr, adt);
-
- /* execute and clear all cached property update functions */
- if (scene) {
- Main *bmain = G.main; // xxx - to get passed in!
- RNA_property_update_cache_flush(bmain, scene);
- RNA_property_update_cache_free();
- }
}
/* Evaluation of all ID-blocks with Animation Data blocks - Animation Data Only
@@ -2563,10 +2556,7 @@ void BKE_animsys_evaluate_animdata(
* 'local' (i.e. belonging in the nearest ID-block that setting is related to, not a
* standard 'root') block are overridden by a larger 'user'
*/
-void BKE_animsys_evaluate_all_animation(Main *main,
- Depsgraph *depsgraph,
- Scene *scene,
- float ctime)
+void BKE_animsys_evaluate_all_animation(Main *main, Depsgraph *depsgraph, float ctime)
{
ID *id;
@@ -2585,7 +2575,7 @@ void BKE_animsys_evaluate_all_animation(Main *main,
for (id = first; id; id = id->next) { \
if (ID_REAL_USERS(id) > 0) { \
AnimData *adt = BKE_animdata_from_id(id); \
- BKE_animsys_evaluate_animdata(scene, id, adt, ctime, aflag, flush_to_original); \
+ BKE_animsys_evaluate_animdata(id, adt, ctime, aflag, flush_to_original); \
} \
} \
(void)0
@@ -2604,9 +2594,9 @@ void BKE_animsys_evaluate_all_animation(Main *main,
if (ntp->nodetree) { \
AnimData *adt2 = BKE_animdata_from_id((ID *)ntp->nodetree); \
BKE_animsys_evaluate_animdata( \
- scene, (ID *)ntp->nodetree, adt2, ctime, ADT_RECALC_ANIM, flush_to_original); \
+ &ntp->nodetree->id, adt2, ctime, ADT_RECALC_ANIM, flush_to_original); \
} \
- BKE_animsys_evaluate_animdata(scene, id, adt, ctime, aflag, flush_to_original); \
+ BKE_animsys_evaluate_animdata(id, adt, ctime, aflag, flush_to_original); \
} \
} \
(void)0
@@ -2690,6 +2680,9 @@ void BKE_animsys_evaluate_all_animation(Main *main,
/* volumes */
EVAL_ANIM_IDS(main->volumes.first, ADT_RECALC_ANIM);
+ /* simulations */
+ EVAL_ANIM_IDS(main->simulations.first, ADT_RECALC_ANIM);
+
/* objects */
/* ADT_RECALC_ANIM doesn't need to be supplied here, since object AnimData gets
* this tagged by Depsgraph on framechange. This optimization means that objects
@@ -2718,10 +2711,9 @@ void BKE_animsys_eval_animdata(Depsgraph *depsgraph, ID *id)
AnimData *adt = BKE_animdata_from_id(id);
/* XXX: this is only needed for flushing RNA updates,
* which should get handled as part of the dependency graph instead. */
- Scene *scene = NULL;
DEG_debug_print_eval_time(depsgraph, __func__, id->name, id, ctime);
const bool flush_to_original = DEG_is_active(depsgraph);
- BKE_animsys_evaluate_animdata(scene, id, adt, ctime, ADT_RECALC_ANIM, flush_to_original);
+ BKE_animsys_evaluate_animdata(id, adt, ctime, ADT_RECALC_ANIM, flush_to_original);
}
void BKE_animsys_update_driver_array(ID *id)
diff --git a/source/blender/blenkernel/intern/blendfile.c b/source/blender/blenkernel/intern/blendfile.c
index 5c000fbcb36..13dcc7b06f6 100644
--- a/source/blender/blenkernel/intern/blendfile.c
+++ b/source/blender/blenkernel/intern/blendfile.c
@@ -279,9 +279,6 @@ static void setup_app_data(bContext *C,
// CTX_wm_manager_set(C, NULL);
BKE_blender_globals_clear();
- /* clear old property update cache, in case some old references are left dangling */
- RNA_property_update_cache_free();
-
bmain = G_MAIN = bfd->main;
bfd->main = NULL;
diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c
index f82b8b6675c..3da384a2745 100644
--- a/source/blender/blenkernel/intern/colortools.c
+++ b/source/blender/blenkernel/intern/colortools.c
@@ -1383,8 +1383,6 @@ typedef struct ScopesUpdateData {
struct ColormanageProcessor *cm_processor;
const unsigned char *display_buffer;
const int ycc_mode;
-
- unsigned int *bin_lum, *bin_r, *bin_g, *bin_b, *bin_a;
} ScopesUpdateData;
typedef struct ScopesUpdateDataChunk {
@@ -1495,23 +1493,24 @@ static void scopes_update_cb(void *__restrict userdata,
}
}
-static void scopes_update_finalize(void *__restrict userdata, void *__restrict userdata_chunk)
+static void scopes_update_reduce(const void *__restrict UNUSED(userdata),
+ void *__restrict chunk_join,
+ void *__restrict chunk)
{
- const ScopesUpdateData *data = userdata;
- const ScopesUpdateDataChunk *data_chunk = userdata_chunk;
-
- unsigned int *bin_lum = data->bin_lum;
- unsigned int *bin_r = data->bin_r;
- unsigned int *bin_g = data->bin_g;
- unsigned int *bin_b = data->bin_b;
- unsigned int *bin_a = data->bin_a;
+ ScopesUpdateDataChunk *join_chunk = chunk_join;
+ const ScopesUpdateDataChunk *data_chunk = chunk;
+
+ unsigned int *bin_lum = join_chunk->bin_lum;
+ unsigned int *bin_r = join_chunk->bin_r;
+ unsigned int *bin_g = join_chunk->bin_g;
+ unsigned int *bin_b = join_chunk->bin_b;
+ unsigned int *bin_a = join_chunk->bin_a;
const unsigned int *bin_lum_c = data_chunk->bin_lum;
const unsigned int *bin_r_c = data_chunk->bin_r;
const unsigned int *bin_g_c = data_chunk->bin_g;
const unsigned int *bin_b_c = data_chunk->bin_b;
const unsigned int *bin_a_c = data_chunk->bin_a;
- float(*minmax)[2] = data->scopes->minmax;
const float *min = data_chunk->min;
const float *max = data_chunk->max;
@@ -1524,11 +1523,11 @@ static void scopes_update_finalize(void *__restrict userdata, void *__restrict u
}
for (int c = 3; c--;) {
- if (min[c] < minmax[c][0]) {
- minmax[c][0] = min[c];
+ if (min[c] < join_chunk->min[c]) {
+ join_chunk->min[c] = min[c];
}
- if (max[c] > minmax[c][1]) {
- minmax[c][1] = max[c];
+ if (max[c] > join_chunk->max[c]) {
+ join_chunk->max[c] = max[c];
}
}
}
@@ -1542,7 +1541,6 @@ void BKE_scopes_update(Scopes *scopes,
unsigned int nl, na, nr, ng, nb;
double divl, diva, divr, divg, divb;
const unsigned char *display_buffer = NULL;
- uint bin_lum[256] = {0}, bin_r[256] = {0}, bin_g[256] = {0}, bin_b[256] = {0}, bin_a[256] = {0};
int ycc_mode = -1;
void *cache_handle = NULL;
struct ColormanageProcessor *cm_processor = NULL;
@@ -1638,11 +1636,6 @@ void BKE_scopes_update(Scopes *scopes,
.cm_processor = cm_processor,
.display_buffer = display_buffer,
.ycc_mode = ycc_mode,
- .bin_lum = bin_lum,
- .bin_r = bin_r,
- .bin_g = bin_g,
- .bin_b = bin_b,
- .bin_a = bin_a,
};
ScopesUpdateDataChunk data_chunk = {{0}};
INIT_MINMAX(data_chunk.min, data_chunk.max);
@@ -1652,26 +1645,26 @@ void BKE_scopes_update(Scopes *scopes,
settings.use_threading = (ibuf->y > 256);
settings.userdata_chunk = &data_chunk;
settings.userdata_chunk_size = sizeof(data_chunk);
- settings.func_finalize = scopes_update_finalize;
+ settings.func_reduce = scopes_update_reduce;
BLI_task_parallel_range(0, ibuf->y, &data, scopes_update_cb, &settings);
/* convert hist data to float (proportional to max count) */
nl = na = nr = nb = ng = 0;
for (a = 0; a < 256; a++) {
- if (bin_lum[a] > nl) {
- nl = bin_lum[a];
+ if (data_chunk.bin_lum[a] > nl) {
+ nl = data_chunk.bin_lum[a];
}
- if (bin_r[a] > nr) {
- nr = bin_r[a];
+ if (data_chunk.bin_r[a] > nr) {
+ nr = data_chunk.bin_r[a];
}
- if (bin_g[a] > ng) {
- ng = bin_g[a];
+ if (data_chunk.bin_g[a] > ng) {
+ ng = data_chunk.bin_g[a];
}
- if (bin_b[a] > nb) {
- nb = bin_b[a];
+ if (data_chunk.bin_b[a] > nb) {
+ nb = data_chunk.bin_b[a];
}
- if (bin_a[a] > na) {
- na = bin_a[a];
+ if (data_chunk.bin_a[a] > na) {
+ na = data_chunk.bin_a[a];
}
}
divl = nl ? 1.0 / (double)nl : 1.0;
@@ -1681,11 +1674,11 @@ void BKE_scopes_update(Scopes *scopes,
divb = nb ? 1.0 / (double)nb : 1.0;
for (a = 0; a < 256; a++) {
- scopes->hist.data_luma[a] = bin_lum[a] * divl;
- scopes->hist.data_r[a] = bin_r[a] * divr;
- scopes->hist.data_g[a] = bin_g[a] * divg;
- scopes->hist.data_b[a] = bin_b[a] * divb;
- scopes->hist.data_a[a] = bin_a[a] * diva;
+ scopes->hist.data_luma[a] = data_chunk.bin_lum[a] * divl;
+ scopes->hist.data_r[a] = data_chunk.bin_r[a] * divr;
+ scopes->hist.data_g[a] = data_chunk.bin_g[a] * divg;
+ scopes->hist.data_b[a] = data_chunk.bin_b[a] * divb;
+ scopes->hist.data_a[a] = data_chunk.bin_a[a] * diva;
}
if (cm_processor) {
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index 099fdacf401..bf100b2e949 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -4694,7 +4694,7 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase
pos[0] *= width;
pos[1] *= height;
- BKE_tracking_undistort_v2(tracking, pos, pos);
+ BKE_tracking_undistort_v2(tracking, width, height, pos, pos);
/* Normalize pixel coordinates back. */
pos[0] /= width;
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c
index b4a8625c0bb..76dec63903b 100644
--- a/source/blender/blenkernel/intern/curve.c
+++ b/source/blender/blenkernel/intern/curve.c
@@ -5506,6 +5506,20 @@ void BKE_curve_material_remap(Curve *cu, const unsigned int *remap, unsigned int
#undef MAT_NR_REMAP
}
+void BKE_curve_smooth_flag_set(Curve *cu, const bool use_smooth)
+{
+ if (use_smooth) {
+ for (Nurb *nu = cu->nurb.first; nu; nu = nu->next) {
+ nu->flag |= CU_SMOOTH;
+ }
+ }
+ else {
+ for (Nurb *nu = cu->nurb.first; nu; nu = nu->next) {
+ nu->flag &= ~CU_SMOOTH;
+ }
+ }
+}
+
void BKE_curve_rect_from_textbox(const struct Curve *cu,
const struct TextBox *tb,
struct rctf *r_rect)
diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c
index 4c78c88d168..3a8b846a41d 100644
--- a/source/blender/blenkernel/intern/dynamicpaint.c
+++ b/source/blender/blenkernel/intern/dynamicpaint.c
@@ -653,15 +653,15 @@ static void grid_bound_insert_cb_ex(void *__restrict userdata,
boundInsert(grid_bound, bData->realCoord[bData->s_pos[i]].v);
}
-static void grid_bound_insert_finalize(void *__restrict userdata, void *__restrict userdata_chunk)
+static void grid_bound_insert_reduce(const void *__restrict UNUSED(userdata),
+ void *__restrict chunk_join,
+ void *__restrict chunk)
{
- PaintBakeData *bData = userdata;
- VolumeGrid *grid = bData->grid;
-
- Bounds3D *grid_bound = userdata_chunk;
+ Bounds3D *join = chunk_join;
+ Bounds3D *grid_bound = chunk;
- boundInsert(&grid->grid_bounds, grid_bound->min);
- boundInsert(&grid->grid_bounds, grid_bound->max);
+ boundInsert(join, grid_bound->min);
+ boundInsert(join, grid_bound->max);
}
static void grid_cell_points_cb_ex(void *__restrict userdata,
@@ -685,17 +685,20 @@ static void grid_cell_points_cb_ex(void *__restrict userdata,
s_num[temp_t_index[i]]++;
}
-static void grid_cell_points_finalize(void *__restrict userdata, void *__restrict userdata_chunk)
+static void grid_cell_points_reduce(const void *__restrict userdata,
+ void *__restrict chunk_join,
+ void *__restrict chunk)
{
- PaintBakeData *bData = userdata;
- VolumeGrid *grid = bData->grid;
+ const PaintBakeData *bData = userdata;
+ const VolumeGrid *grid = bData->grid;
const int grid_cells = grid->dim[0] * grid->dim[1] * grid->dim[2];
- int *s_num = userdata_chunk;
+ int *join_s_num = chunk_join;
+ int *s_num = chunk;
/* calculate grid indexes */
for (int i = 0; i < grid_cells; i++) {
- grid->s_num[i] += s_num[i];
+ join_s_num[i] += s_num[i];
}
}
@@ -753,7 +756,7 @@ static void surfaceGenerateGrid(struct DynamicPaintSurface *surface)
settings.use_threading = (sData->total_points > 1000);
settings.userdata_chunk = &grid->grid_bounds;
settings.userdata_chunk_size = sizeof(grid->grid_bounds);
- settings.func_finalize = grid_bound_insert_finalize;
+ settings.func_reduce = grid_bound_insert_reduce;
BLI_task_parallel_range(0, sData->total_points, bData, grid_bound_insert_cb_ex, &settings);
}
/* get dimensions */
@@ -814,7 +817,7 @@ static void surfaceGenerateGrid(struct DynamicPaintSurface *surface)
settings.use_threading = (sData->total_points > 1000);
settings.userdata_chunk = grid->s_num;
settings.userdata_chunk_size = sizeof(*grid->s_num) * grid_cells;
- settings.func_finalize = grid_cell_points_finalize;
+ settings.func_reduce = grid_cell_points_reduce;
BLI_task_parallel_range(0, sData->total_points, bData, grid_cell_points_cb_ex, &settings);
}
@@ -4880,7 +4883,7 @@ static void dynamicPaint_prepareAdjacencyData(DynamicPaintSurface *surface, cons
0, sData->total_points, sData, dynamic_paint_prepare_adjacency_cb, &settings);
/* calculate average values (single thread).
- * Note: tried to put this in threaded callback (using _finalize feature),
+ * Note: tried to put this in threaded callback (using _reduce feature),
* but gave ~30% slower result! */
bData->average_dist = 0.0;
for (index = 0; index < sData->total_points; index++) {
diff --git a/source/blender/blenkernel/intern/fluid.c b/source/blender/blenkernel/intern/fluid.c
index 8697cd03827..3effb9c0bb0 100644
--- a/source/blender/blenkernel/intern/fluid.c
+++ b/source/blender/blenkernel/intern/fluid.c
@@ -334,6 +334,14 @@ void BKE_fluid_reallocate_copy_fluid(FluidDomainSettings *mds,
manta_free(fluid_old);
}
+void BKE_fluid_cache_free_all(FluidDomainSettings *mds, Object *ob)
+{
+ int cache_map = (FLUID_DOMAIN_OUTDATED_DATA | FLUID_DOMAIN_OUTDATED_NOISE |
+ FLUID_DOMAIN_OUTDATED_MESH | FLUID_DOMAIN_OUTDATED_PARTICLES |
+ FLUID_DOMAIN_OUTDATED_GUIDE);
+ BKE_fluid_cache_free(mds, ob, cache_map);
+}
+
void BKE_fluid_cache_free(FluidDomainSettings *mds, Object *ob, int cache_map)
{
char temp_dir[FILE_MAX];
@@ -1130,7 +1138,18 @@ static void obstacles_from_mesh(Object *coll_ob,
}
}
+static void ensure_obstaclefields(FluidDomainSettings *mds)
+{
+ if (mds->active_fields & FLUID_DOMAIN_ACTIVE_OBSTACLE) {
+ manta_ensure_obstacle(mds->fluid, mds->mmd);
+ }
+ if (mds->active_fields & FLUID_DOMAIN_ACTIVE_GUIDE) {
+ manta_ensure_guiding(mds->fluid, mds->mmd);
+ }
+}
+
static void update_obstacleflags(FluidDomainSettings *mds,
+ Object *domain,
Object **coll_ob_array,
int coll_ob_array_len)
{
@@ -1157,6 +1176,11 @@ static void update_obstacleflags(FluidDomainSettings *mds,
if (!mes) {
break;
}
+ if (mes->flags & FLUID_EFFECTOR_NEEDS_UPDATE) {
+ mes->flags &= ~FLUID_EFFECTOR_NEEDS_UPDATE;
+ BKE_fluid_cache_free_all(mds, domain);
+ mds->cache_flag |= FLUID_DOMAIN_OUTDATED_DATA;
+ }
if (mes->type == FLUID_EFFECTOR_TYPE_COLLISION) {
active_fields |= FLUID_DOMAIN_ACTIVE_OBSTACLE;
}
@@ -1165,41 +1189,53 @@ static void update_obstacleflags(FluidDomainSettings *mds,
}
}
}
- /* Finally, initialize new data fields if any */
- if (active_fields & FLUID_DOMAIN_ACTIVE_OBSTACLE) {
- manta_ensure_obstacle(mds->fluid, mds->mmd);
- }
- if (active_fields & FLUID_DOMAIN_ACTIVE_GUIDE) {
- manta_ensure_guiding(mds->fluid, mds->mmd);
- }
mds->active_fields = active_fields;
}
-static void update_obstacles(Depsgraph *depsgraph,
- Scene *scene,
- Object *ob,
- FluidDomainSettings *mds,
- float time_per_frame,
- float frame_length,
- int frame,
- float dt)
+static bool escape_effectorobject(Object *flowobj,
+ FluidDomainSettings *mds,
+ FluidEffectorSettings *mes,
+ int frame)
{
- FluidObjectBB *bb_maps = NULL;
- Object **effecobjs = NULL;
- uint numeffecobjs = 0, effec_index = 0;
- bool is_first_frame = (frame == mds->cache_frame_start);
+ bool is_static = is_static_object(flowobj);
- effecobjs = BKE_collision_objects_create(
- depsgraph, ob, mds->effector_group, &numeffecobjs, eModifierType_Fluid);
+ bool use_effector = (mes->flags & FLUID_EFFECTOR_USE_EFFEC);
- /* Update all effector related flags and ensure that corresponding grids get initialized. */
- update_obstacleflags(mds, effecobjs, numeffecobjs);
+ bool is_resume = (mds->cache_frame_pause_data == frame);
+ bool is_adaptive = (mds->flags & FLUID_DOMAIN_USE_ADAPTIVE_DOMAIN);
+ bool is_first_frame = (frame == mds->cache_frame_start);
- /* Initialize effector maps for each flow. */
- bb_maps = MEM_callocN(sizeof(struct FluidObjectBB) * numeffecobjs, "fluid_effector_bb_maps");
+ /* Cannot use static mode with adaptive domain.
+ * The adaptive domain might expand and only later discover the static object. */
+ if (is_adaptive) {
+ is_static = false;
+ }
+ /* Skip flow objects with disabled inflow flag. */
+ if (!use_effector) {
+ return true;
+ }
+ /* Skip static effector objects after initial frame. */
+ if (is_static && !is_first_frame && !is_resume) {
+ return true;
+ }
+ return false;
+}
+
+static void compute_obstaclesemission(Scene *scene,
+ FluidObjectBB *bb_maps,
+ struct Depsgraph *depsgraph,
+ float dt,
+ Object **effecobjs,
+ int frame,
+ float frame_length,
+ FluidDomainSettings *mds,
+ uint numeffecobjs,
+ float time_per_frame)
+{
+ bool is_first_frame = (frame == mds->cache_frame_start);
/* Prepare effector maps. */
- for (effec_index = 0; effec_index < numeffecobjs; effec_index++) {
+ for (int effec_index = 0; effec_index < numeffecobjs; effec_index++) {
Object *effecobj = effecobjs[effec_index];
FluidModifierData *mmd2 = (FluidModifierData *)modifiers_findByType(effecobj,
eModifierType_Fluid);
@@ -1215,20 +1251,8 @@ static void update_obstacles(Depsgraph *depsgraph,
int subframes = mes->subframes;
FluidObjectBB *bb = &bb_maps[effec_index];
- bool is_static = is_static_object(effecobj);
- /* Cannot use static mode with adaptive domain.
- * The adaptive domain might expand and only later in the simulations discover the static
- * object. */
- if (mds->flags & FLUID_DOMAIN_USE_ADAPTIVE_DOMAIN) {
- is_static = false;
- }
-
- /* Optimization: Static objects don't need emission computation after first frame. */
- if (is_static && !is_first_frame) {
- continue;
- }
- /* Optimization: Skip effector objects with disabled effec flag. */
- if ((mes->flags & FLUID_EFFECTOR_USE_EFFEC) == 0) {
+ /* Optimization: Skip this object under certain conditions. */
+ if (escape_effectorobject(effecobj, mds, mes, frame)) {
continue;
}
@@ -1296,6 +1320,44 @@ static void update_obstacles(Depsgraph *depsgraph,
}
}
}
+}
+
+static void update_obstacles(Depsgraph *depsgraph,
+ Scene *scene,
+ Object *ob,
+ FluidDomainSettings *mds,
+ float time_per_frame,
+ float frame_length,
+ int frame,
+ float dt)
+{
+ FluidObjectBB *bb_maps = NULL;
+ Object **effecobjs = NULL;
+ uint numeffecobjs = 0;
+ bool is_resume = (mds->cache_frame_pause_data == frame);
+ bool is_first_frame = (frame == mds->cache_frame_start);
+
+ effecobjs = BKE_collision_objects_create(
+ depsgraph, ob, mds->effector_group, &numeffecobjs, eModifierType_Fluid);
+
+ /* Update all effector related flags and ensure that corresponding grids get initialized. */
+ update_obstacleflags(mds, ob, effecobjs, numeffecobjs);
+ ensure_obstaclefields(mds);
+
+ /* Allocate effector map for each effector object. */
+ bb_maps = MEM_callocN(sizeof(struct FluidObjectBB) * numeffecobjs, "fluid_effector_bb_maps");
+
+ /* Initialize effector map for each effector object. */
+ compute_obstaclesemission(scene,
+ bb_maps,
+ depsgraph,
+ dt,
+ effecobjs,
+ frame,
+ frame_length,
+ mds,
+ numeffecobjs,
+ time_per_frame);
float *vel_x = manta_get_ob_velocity_x(mds->fluid);
float *vel_y = manta_get_ob_velocity_y(mds->fluid);
@@ -1346,7 +1408,7 @@ static void update_obstacles(Depsgraph *depsgraph,
}
/* Prepare grids from effector objects. */
- for (effec_index = 0; effec_index < numeffecobjs; effec_index++) {
+ for (int effec_index = 0; effec_index < numeffecobjs; effec_index++) {
Object *effecobj = effecobjs[effec_index];
FluidModifierData *mmd2 = (FluidModifierData *)modifiers_findByType(effecobj,
eModifierType_Fluid);
@@ -1356,18 +1418,11 @@ static void update_obstacles(Depsgraph *depsgraph,
continue;
}
- bool is_static = is_static_object(effecobj);
/* Cannot use static mode with adaptive domain.
* The adaptive domain might expand and only later in the simulations discover the static
* object. */
- if (mds->flags & FLUID_DOMAIN_USE_ADAPTIVE_DOMAIN) {
- is_static = false;
- }
-
- /* Optimization: Static objects don't need emission application after first frame. */
- if (is_static && !is_first_frame) {
- continue;
- }
+ bool is_static = is_static_object(effecobj) &&
+ ((mds->flags & FLUID_DOMAIN_USE_ADAPTIVE_DOMAIN) == 0);
/* Check for initialized effector object. */
if ((mmd2->type & MOD_FLUID_TYPE_EFFEC) && mmd2->effector) {
@@ -1407,53 +1462,35 @@ static void update_obstacles(Depsgraph *depsgraph,
continue;
}
- /* Apply static effectors to obstacle grid. */
- if (is_static && is_first_frame) {
- if (mes->type == FLUID_EFFECTOR_TYPE_COLLISION) {
- apply_effector_fields(mes,
- d_index,
- distance_map[e_index],
- phi_obsstatic_in,
- numobjs_map[e_index],
- num_obstacles,
- 0.0f,
- NULL,
- 0.0f,
- NULL,
- 0.0f,
- NULL);
- }
+ if (mes->type == FLUID_EFFECTOR_TYPE_COLLISION) {
+ float *levelset = ((is_first_frame || is_resume) && is_static) ? phi_obsstatic_in :
+ phi_obs_in;
+ apply_effector_fields(mes,
+ d_index,
+ distance_map[e_index],
+ levelset,
+ numobjs_map[e_index],
+ num_obstacles,
+ velocity_map[e_index * 3],
+ vel_x,
+ velocity_map[e_index * 3 + 1],
+ vel_y,
+ velocity_map[e_index * 3 + 2],
+ vel_z);
}
- /* Apply moving effectors to obstacle grid. */
- else if (!is_static) {
- if (mes->type == FLUID_EFFECTOR_TYPE_COLLISION) {
- apply_effector_fields(mes,
- d_index,
- distance_map[e_index],
- phi_obs_in,
- numobjs_map[e_index],
- num_obstacles,
- velocity_map[e_index * 3],
- vel_x,
- velocity_map[e_index * 3 + 1],
- vel_y,
- velocity_map[e_index * 3 + 2],
- vel_z);
- }
- if (mes->type == FLUID_EFFECTOR_TYPE_GUIDE) {
- apply_effector_fields(mes,
- d_index,
- distance_map[e_index],
- phi_guide_in,
- numobjs_map[e_index],
- num_guides,
- velocity_map[e_index * 3],
- vel_x_guide,
- velocity_map[e_index * 3 + 1],
- vel_y_guide,
- velocity_map[e_index * 3 + 2],
- vel_z_guide);
- }
+ if (mes->type == FLUID_EFFECTOR_TYPE_GUIDE) {
+ apply_effector_fields(mes,
+ d_index,
+ distance_map[e_index],
+ phi_guide_in,
+ numobjs_map[e_index],
+ num_guides,
+ velocity_map[e_index * 3],
+ vel_x_guide,
+ velocity_map[e_index * 3 + 1],
+ vel_y_guide,
+ velocity_map[e_index * 3 + 2],
+ vel_z_guide);
}
}
}
@@ -2450,12 +2487,13 @@ BLI_INLINE void apply_outflow_fields(int index,
float *color_b,
float *phiout)
{
- /* determine outflow cells - phiout used in smoke and liquids */
+ /* Set levelset value for liquid inflow.
+ * Ensure that distance value is "joined" into the levelset. */
if (phiout) {
- phiout[index] = distance_value;
+ phiout[index] = MIN2(distance_value, phiout[index]);
}
- /* set smoke outflow */
+ /* Set smoke outflow, i.e. reset cell to zero. */
if (density) {
density[index] = 0.0f;
}
@@ -2573,21 +2611,49 @@ BLI_INLINE void apply_inflow_fields(FluidFlowSettings *mfs,
}
}
-static void update_flowsflags(FluidDomainSettings *mds, Object **flowobjs, int numflowobj)
+static void ensure_flowsfields(FluidDomainSettings *mds)
+{
+ if (mds->active_fields & FLUID_DOMAIN_ACTIVE_INVEL) {
+ manta_ensure_invelocity(mds->fluid, mds->mmd);
+ }
+ if (mds->active_fields & FLUID_DOMAIN_ACTIVE_OUTFLOW) {
+ manta_ensure_outflow(mds->fluid, mds->mmd);
+ }
+ if (mds->active_fields & FLUID_DOMAIN_ACTIVE_HEAT) {
+ manta_smoke_ensure_heat(mds->fluid, mds->mmd);
+ }
+ if (mds->active_fields & FLUID_DOMAIN_ACTIVE_FIRE) {
+ manta_smoke_ensure_fire(mds->fluid, mds->mmd);
+ }
+ if (mds->active_fields & FLUID_DOMAIN_ACTIVE_COLORS) {
+ /* initialize all smoke with "active_color" */
+ manta_smoke_ensure_colors(mds->fluid, mds->mmd);
+ }
+ if (mds->type == FLUID_DOMAIN_TYPE_LIQUID &&
+ (mds->particle_type & FLUID_DOMAIN_PARTICLE_SPRAY ||
+ mds->particle_type & FLUID_DOMAIN_PARTICLE_FOAM ||
+ mds->particle_type & FLUID_DOMAIN_PARTICLE_TRACER)) {
+ manta_liquid_ensure_sndparts(mds->fluid, mds->mmd);
+ }
+}
+
+static void update_flowsflags(FluidDomainSettings *mds,
+ Object *domain,
+ Object **flowobjs,
+ int numflowobj)
{
int active_fields = mds->active_fields;
uint flow_index;
/* First, remove all flags that we want to update. */
int prev_flags = (FLUID_DOMAIN_ACTIVE_INVEL | FLUID_DOMAIN_ACTIVE_OUTFLOW |
- FLUID_DOMAIN_ACTIVE_HEAT | FLUID_DOMAIN_ACTIVE_FIRE |
- FLUID_DOMAIN_ACTIVE_COLOR_SET | FLUID_DOMAIN_ACTIVE_COLORS);
+ FLUID_DOMAIN_ACTIVE_HEAT | FLUID_DOMAIN_ACTIVE_FIRE);
active_fields &= ~prev_flags;
/* Monitor active fields based on flow settings */
for (flow_index = 0; flow_index < numflowobj; flow_index++) {
- Object *coll_ob = flowobjs[flow_index];
- FluidModifierData *mmd2 = (FluidModifierData *)modifiers_findByType(coll_ob,
+ Object *flow_ob = flowobjs[flow_index];
+ FluidModifierData *mmd2 = (FluidModifierData *)modifiers_findByType(flow_ob,
eModifierType_Fluid);
/* Sanity check. */
@@ -2600,6 +2666,11 @@ static void update_flowsflags(FluidDomainSettings *mds, Object **flowobjs, int n
if (!mfs) {
break;
}
+ if (mfs->flags & FLUID_FLOW_NEEDS_UPDATE) {
+ mfs->flags &= ~FLUID_FLOW_NEEDS_UPDATE;
+ BKE_fluid_cache_free_all(mds, domain);
+ mds->cache_flag |= FLUID_DOMAIN_OUTDATED_DATA;
+ }
if (mfs->flags & FLUID_FLOW_INITVELOCITY) {
active_fields |= FLUID_DOMAIN_ACTIVE_INVEL;
}
@@ -2648,57 +2719,71 @@ static void update_flowsflags(FluidDomainSettings *mds, Object **flowobjs, int n
active_fields |= FLUID_DOMAIN_ACTIVE_COLORS;
}
}
- /* Finally, initialize new data fields if any */
- if (active_fields & FLUID_DOMAIN_ACTIVE_INVEL) {
- manta_ensure_invelocity(mds->fluid, mds->mmd);
- }
- if (active_fields & FLUID_DOMAIN_ACTIVE_OUTFLOW) {
- manta_ensure_outflow(mds->fluid, mds->mmd);
- }
- if (active_fields & FLUID_DOMAIN_ACTIVE_HEAT) {
- manta_smoke_ensure_heat(mds->fluid, mds->mmd);
+ mds->active_fields = active_fields;
+}
+
+static bool escape_flowsobject(Object *flowobj,
+ FluidDomainSettings *mds,
+ FluidFlowSettings *mfs,
+ int frame)
+{
+ bool use_velocity = (mfs->flags & FLUID_FLOW_INITVELOCITY);
+ bool is_static = is_static_object(flowobj);
+
+ bool liquid_flow = mfs->type == FLUID_FLOW_TYPE_LIQUID;
+ bool gas_flow = (mfs->type == FLUID_FLOW_TYPE_SMOKE || mfs->type == FLUID_FLOW_TYPE_FIRE ||
+ mfs->type == FLUID_FLOW_TYPE_SMOKEFIRE);
+ bool is_geometry = (mfs->behavior == FLUID_FLOW_BEHAVIOR_GEOMETRY);
+ bool is_inflow = (mfs->behavior == FLUID_FLOW_BEHAVIOR_INFLOW);
+ bool is_outflow = (mfs->behavior == FLUID_FLOW_BEHAVIOR_OUTFLOW);
+ bool use_flow = (mfs->flags & FLUID_FLOW_USE_INFLOW);
+
+ bool liquid_domain = mds->type == FLUID_DOMAIN_TYPE_LIQUID;
+ bool gas_domain = mds->type == FLUID_DOMAIN_TYPE_GAS;
+ bool is_adaptive = (mds->flags & FLUID_DOMAIN_USE_ADAPTIVE_DOMAIN);
+ bool is_resume = (mds->cache_frame_pause_data == frame);
+ bool is_first_frame = (mds->cache_frame_start == frame);
+
+ /* Cannot use static mode with adaptive domain.
+ * The adaptive domain might expand and only later discover the static object. */
+ if (is_adaptive) {
+ is_static = false;
+ }
+ /* Skip flow objects with disabled inflow flag. */
+ if ((is_inflow || is_outflow) && !use_flow) {
+ return true;
}
- if (active_fields & FLUID_DOMAIN_ACTIVE_FIRE) {
- manta_smoke_ensure_fire(mds->fluid, mds->mmd);
+ /* No need to compute emission value if it won't be applied. */
+ if (liquid_flow && is_geometry && !is_first_frame) {
+ return true;
}
- if (active_fields & FLUID_DOMAIN_ACTIVE_COLORS) {
- /* initialize all smoke with "active_color" */
- manta_smoke_ensure_colors(mds->fluid, mds->mmd);
+ /* Skip flow object if it does not "belong" to this domain type. */
+ if ((liquid_flow && gas_domain) || (gas_flow && liquid_domain)) {
+ return true;
}
- if (mds->type == FLUID_DOMAIN_TYPE_LIQUID &&
- (mds->particle_type & FLUID_DOMAIN_PARTICLE_SPRAY ||
- mds->particle_type & FLUID_DOMAIN_PARTICLE_FOAM ||
- mds->particle_type & FLUID_DOMAIN_PARTICLE_TRACER)) {
- manta_liquid_ensure_sndparts(mds->fluid, mds->mmd);
+ /* Optimization: Static liquid flow objects don't need emission after first frame.
+ * TODO (sebbas): Also do not use static mode if initial velocities are enabled. */
+ if (liquid_flow && is_static && !is_first_frame && !is_resume && !use_velocity) {
+ return true;
}
- mds->active_fields = active_fields;
+ return false;
}
-static void update_flowsfluids(struct Depsgraph *depsgraph,
- Scene *scene,
- Object *ob,
- FluidDomainSettings *mds,
- float time_per_frame,
- float frame_length,
- int frame,
- float dt)
+static void compute_flowsemission(Scene *scene,
+ FluidObjectBB *bb_maps,
+ struct Depsgraph *depsgraph,
+ float dt,
+ Object **flowobjs,
+ int frame,
+ float frame_length,
+ FluidDomainSettings *mds,
+ uint numflowobjs,
+ float time_per_frame)
{
- FluidObjectBB *bb_maps = NULL;
- Object **flowobjs = NULL;
- uint numflowobj = 0, flow_index = 0;
bool is_first_frame = (frame == mds->cache_frame_start);
- flowobjs = BKE_collision_objects_create(
- depsgraph, ob, mds->fluid_group, &numflowobj, eModifierType_Fluid);
-
- /* Update all flow related flags and ensure that corresponding grids get initialized. */
- update_flowsflags(mds, flowobjs, numflowobj);
-
- /* Initialize emission maps for each flow. */
- bb_maps = MEM_callocN(sizeof(struct FluidObjectBB) * numflowobj, "fluid_flow_bb_maps");
-
/* Prepare flow emission maps. */
- for (flow_index = 0; flow_index < numflowobj; flow_index++) {
+ for (int flow_index = 0; flow_index < numflowobjs; flow_index++) {
Object *flowobj = flowobjs[flow_index];
FluidModifierData *mmd2 = (FluidModifierData *)modifiers_findByType(flowobj,
eModifierType_Fluid);
@@ -2714,37 +2799,8 @@ static void update_flowsfluids(struct Depsgraph *depsgraph,
int subframes = mfs->subframes;
FluidObjectBB *bb = &bb_maps[flow_index];
- bool use_velocity = mfs->flags & FLUID_FLOW_INITVELOCITY;
- bool is_static = is_static_object(flowobj);
- /* Cannot use static mode with adaptive domain.
- * The adaptive domain might expand and only later in the simulations discover the static
- * object. */
- if (mds->flags & FLUID_DOMAIN_USE_ADAPTIVE_DOMAIN) {
- is_static = false;
- }
-
- /* Optimization: Skip flow objects with disabled inflow flag. */
- if (mfs->behavior == FLUID_FLOW_BEHAVIOR_INFLOW &&
- (mfs->flags & FLUID_FLOW_USE_INFLOW) == 0) {
- continue;
- }
- /* Optimization: No need to compute emission value if it won't be applied. */
- if (mfs->behavior == FLUID_FLOW_BEHAVIOR_GEOMETRY && !is_first_frame) {
- continue;
- }
- /* Optimization: Skip flow object if it does not "belong" to this domain type. */
- if (mfs->type == FLUID_FLOW_TYPE_LIQUID && mds->type == FLUID_DOMAIN_TYPE_GAS) {
- continue;
- }
- if ((mfs->type == FLUID_FLOW_TYPE_SMOKE || mfs->type == FLUID_FLOW_TYPE_FIRE ||
- mfs->type == FLUID_FLOW_TYPE_SMOKEFIRE) &&
- mds->type == FLUID_DOMAIN_TYPE_LIQUID) {
- continue;
- }
- /* Optimization: Static liquid flow objects don't need emission computation after first
- * frame.
- * TODO (sebbas): Also do not use static mode if initial velocities are enabled. */
- if (mfs->type == FLUID_FLOW_TYPE_LIQUID && is_static && !is_first_frame && !use_velocity) {
+ /* Optimization: Skip this object under certain conditions. */
+ if (escape_flowsobject(flowobj, mds, mfs, frame)) {
continue;
}
@@ -2833,15 +2889,55 @@ static void update_flowsfluids(struct Depsgraph *depsgraph,
frame_length,
dt);
# endif
+}
+
+static void update_flowsfluids(struct Depsgraph *depsgraph,
+ Scene *scene,
+ Object *ob,
+ FluidDomainSettings *mds,
+ float time_per_frame,
+ float frame_length,
+ int frame,
+ float dt)
+{
+ FluidObjectBB *bb_maps = NULL;
+ Object **flowobjs = NULL;
+ uint numflowobjs = 0;
+ bool is_resume = (mds->cache_frame_pause_data == frame);
+ bool is_first_frame = (mds->cache_frame_start == frame);
+
+ flowobjs = BKE_collision_objects_create(
+ depsgraph, ob, mds->fluid_group, &numflowobjs, eModifierType_Fluid);
+
+ /* Update all flow related flags and ensure that corresponding grids get initialized. */
+ update_flowsflags(mds, ob, flowobjs, numflowobjs);
+ ensure_flowsfields(mds);
+
+ /* Allocate emission map for each flow object. */
+ bb_maps = MEM_callocN(sizeof(struct FluidObjectBB) * numflowobjs, "fluid_flow_bb_maps");
+
+ /* Initialize emission map for each flow object. */
+ compute_flowsemission(scene,
+ bb_maps,
+ depsgraph,
+ dt,
+ flowobjs,
+ frame,
+ frame_length,
+ mds,
+ numflowobjs,
+ time_per_frame);
/* Adjust domain size if needed. Only do this once for every frame. */
if (mds->type == FLUID_DOMAIN_TYPE_GAS && mds->flags & FLUID_DOMAIN_USE_ADAPTIVE_DOMAIN) {
- adaptive_domain_adjust(mds, ob, bb_maps, numflowobj, dt);
+ adaptive_domain_adjust(mds, ob, bb_maps, numflowobjs, dt);
}
float *phi_in = manta_get_phi_in(mds->fluid);
float *phistatic_in = manta_get_phistatic_in(mds->fluid);
float *phiout_in = manta_get_phiout_in(mds->fluid);
+ float *phioutstatic_in = manta_get_phioutstatic_in(mds->fluid);
+
float *density = manta_smoke_get_density(mds->fluid);
float *color_r = manta_smoke_get_color_r(mds->fluid);
float *color_g = manta_smoke_get_color_g(mds->fluid);
@@ -2864,16 +2960,18 @@ static void update_flowsfluids(struct Depsgraph *depsgraph,
float *velz_initial = manta_get_in_velocity_z(mds->fluid);
uint z;
- bool use_adaptivedomain = (mds->flags & FLUID_DOMAIN_USE_ADAPTIVE_DOMAIN);
-
/* Grid reset before writing again. */
for (z = 0; z < mds->res[0] * mds->res[1] * mds->res[2]; z++) {
+ /* Only reset static phi on first frame, dynamic phi gets reset every time. */
+ if (phistatic_in && is_first_frame) {
+ phistatic_in[z] = PHI_MAX;
+ }
if (phi_in) {
phi_in[z] = PHI_MAX;
}
- /* Only reset static inflow on first frame. Only use static inflow without adaptive domains. */
- if (phistatic_in && (is_first_frame || use_adaptivedomain)) {
- phistatic_in[z] = PHI_MAX;
+ /* Only reset static phi on first frame, dynamic phi gets reset every time. */
+ if (phioutstatic_in && is_first_frame) {
+ phioutstatic_in[z] = PHI_MAX;
}
if (phiout_in) {
phiout_in[z] = PHI_MAX;
@@ -2905,7 +3003,7 @@ static void update_flowsfluids(struct Depsgraph *depsgraph,
}
/* Apply emission data for every flow object. */
- for (flow_index = 0; flow_index < numflowobj; flow_index++) {
+ for (int flow_index = 0; flow_index < numflowobjs; flow_index++) {
Object *flowobj = flowobjs[flow_index];
FluidModifierData *mmd2 = (FluidModifierData *)modifiers_findByType(flowobj,
eModifierType_Fluid);
@@ -2919,38 +3017,11 @@ static void update_flowsfluids(struct Depsgraph *depsgraph,
if ((mmd2->type & MOD_FLUID_TYPE_FLOW) && mmd2->flow) {
FluidFlowSettings *mfs = mmd2->flow;
- bool use_velocity = mfs->flags & FLUID_FLOW_INITVELOCITY;
- bool use_inflow = (mfs->flags & FLUID_FLOW_USE_INFLOW);
- bool is_liquid = (mfs->type == FLUID_FLOW_TYPE_LIQUID);
bool is_inflow = (mfs->behavior == FLUID_FLOW_BEHAVIOR_INFLOW);
bool is_geometry = (mfs->behavior == FLUID_FLOW_BEHAVIOR_GEOMETRY);
bool is_outflow = (mfs->behavior == FLUID_FLOW_BEHAVIOR_OUTFLOW);
-
- bool is_static = is_static_object(flowobj);
- /* Cannot use static mode with adaptive domain.
- * The adaptive domain might expand and only later in the simulations discover the static
- * object. */
- if (mds->flags & FLUID_DOMAIN_USE_ADAPTIVE_DOMAIN) {
- is_static = false;
- }
-
- /* Optimization: Skip flow objects with disabled flow flag. */
- if (is_inflow && !use_inflow) {
- continue;
- }
- /* Optimization: Liquid objects don't always need emission application after first frame. */
- if (is_liquid && !is_first_frame) {
-
- /* Skip static liquid objects that are not on the first frame.
- * TODO (sebbas): Also do not use static mode if initial velocities are enabled. */
- if (is_static && !use_velocity) {
- continue;
- }
- /* Liquid geometry objects don't need emission application after first frame. */
- if (is_geometry) {
- continue;
- }
- }
+ bool is_static = is_static_object(flowobj) &&
+ ((mds->flags & FLUID_DOMAIN_USE_ADAPTIVE_DOMAIN) == 0);
FluidObjectBB *bb = &bb_maps[flow_index];
float *velocity_map = bb->velocity;
@@ -2983,6 +3054,8 @@ static void update_flowsfluids(struct Depsgraph *depsgraph,
/* Delete fluid in outflow regions. */
if (is_outflow) {
+ float *levelset = ((is_first_frame || is_resume) && is_static) ? phioutstatic_in :
+ phiout_in;
apply_outflow_fields(d_index,
distance_map[e_index],
density_in,
@@ -2992,7 +3065,7 @@ static void update_flowsfluids(struct Depsgraph *depsgraph,
color_r_in,
color_g_in,
color_b_in,
- phiout_in);
+ levelset);
}
/* Do not apply inflow after the first frame when in geometry mode. */
else if (is_geometry && !is_first_frame) {
@@ -3017,31 +3090,10 @@ static void update_flowsfluids(struct Depsgraph *depsgraph,
phi_in,
emission_in);
}
- /* Static liquid objects need inflow application onto static phi grid. */
- else if (is_inflow && is_liquid && is_static && is_first_frame) {
- apply_inflow_fields(mfs,
- 0.0f,
- distance_map[e_index],
- d_index,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- phistatic_in,
- NULL);
- }
/* Main inflow application. */
else if (is_geometry || is_inflow) {
+ float *levelset = ((is_first_frame || is_resume) && is_static) ? phistatic_in :
+ phi_in;
apply_inflow_fields(mfs,
emission_map[e_index],
distance_map[e_index],
@@ -3060,7 +3112,7 @@ static void update_flowsfluids(struct Depsgraph *depsgraph,
color_g,
color_b_in,
color_b,
- phi_in,
+ levelset,
emission_in);
if (mfs->flags & FLUID_FLOW_INITVELOCITY) {
velx_initial[d_index] = velocity_map[e_index * 3];
@@ -3566,6 +3618,7 @@ static int manta_step(
break;
}
+ /* Only bake if the domain is bigger than one cell (important for adaptive domain). */
if (mds->total_cells > 1) {
update_effectors(depsgraph, scene, ob, mds, dt);
manta_bake_data(mds->fluid, mmd, frame);
@@ -3577,15 +3630,9 @@ static int manta_step(
mds->time_per_frame = time_per_frame;
mds->time_total = time_total;
-
- /* If user requested stop, quit baking */
- if (G.is_break && !mode_replay) {
- result = 0;
- break;
- }
}
- if (mds->type == FLUID_DOMAIN_TYPE_GAS) {
+ if (mds->type == FLUID_DOMAIN_TYPE_GAS && result) {
manta_smoke_calc_transparency(mds, DEG_get_evaluated_view_layer(depsgraph));
}
BLI_mutex_unlock(&object_update_lock);
@@ -3684,14 +3731,41 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd,
return;
}
+ bool bake_outdated = mds->cache_flag &
+ (FLUID_DOMAIN_OUTDATED_DATA | FLUID_DOMAIN_OUTDATED_NOISE |
+ FLUID_DOMAIN_OUTDATED_MESH | FLUID_DOMAIN_OUTDATED_PARTICLES |
+ FLUID_DOMAIN_OUTDATED_GUIDE);
+
+ /* Exit early if cache is outdated. */
+ if (bake_outdated) {
+ return;
+ }
+
/* Reset fluid if no fluid present. */
- if (!mds->fluid) {
+ if (!mds->fluid || mds->cache_flag & FLUID_DOMAIN_OUTDATED_DATA) {
BKE_fluid_modifier_reset_ex(mmd, false);
+ }
- /* Fluid domain init must not fail in order to continue modifier evaluation. */
- if (!BKE_fluid_modifier_init(mmd, depsgraph, ob, scene, me)) {
- return;
- }
+ /* Ensure cache directory is not relative. */
+ const char *relbase = modifier_path_relbase_from_global(ob);
+ BLI_path_abs(mds->cache_directory, relbase);
+
+ objs = BKE_collision_objects_create(
+ depsgraph, ob, mds->fluid_group, &numobj, eModifierType_Fluid);
+ update_flowsflags(mds, ob, objs, numobj);
+ if (objs) {
+ MEM_freeN(objs);
+ }
+ objs = BKE_collision_objects_create(
+ depsgraph, ob, mds->effector_group, &numobj, eModifierType_Fluid);
+ update_obstacleflags(mds, ob, objs, numobj);
+ if (objs) {
+ MEM_freeN(objs);
+ }
+
+ /* Fluid domain init must not fail in order to continue modifier evaluation. */
+ if (!mds->fluid && !BKE_fluid_modifier_init(mmd, depsgraph, ob, scene, me)) {
+ return;
}
BLI_assert(mds->fluid);
@@ -3712,23 +3786,10 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd,
/* Get distance between cache start and current frame for total time. */
mds->time_total = abs(scene_framenr - mds->cache_frame_start) * mds->frame_length;
- objs = BKE_collision_objects_create(
- depsgraph, ob, mds->fluid_group, &numobj, eModifierType_Fluid);
- update_flowsflags(mds, objs, numobj);
- if (objs) {
- MEM_freeN(objs);
- }
-
- objs = BKE_collision_objects_create(
- depsgraph, ob, mds->effector_group, &numobj, eModifierType_Fluid);
- update_obstacleflags(mds, objs, numobj);
- if (objs) {
- MEM_freeN(objs);
- }
-
- /* Ensure cache directory is not relative. */
- const char *relbase = modifier_path_relbase_from_global(ob);
- BLI_path_abs(mds->cache_directory, relbase);
+ int next_frame = scene_framenr + 1;
+ int prev_frame = scene_framenr - 1;
+ /* Ensure positivity of previous frame. */
+ CLAMP(prev_frame, mds->cache_frame_start, prev_frame);
int data_frame = scene_framenr, noise_frame = scene_framenr;
int mesh_frame = scene_framenr, particles_frame = scene_framenr, guide_frame = scene_framenr;
@@ -3751,17 +3812,18 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd,
with_particles = drops || bubble || floater;
bool has_data, has_noise, has_mesh, has_particles, has_guide;
- has_data = has_noise = has_mesh = has_particles = has_guide = false;
+ has_data = manta_has_data(mds->fluid, mmd, scene_framenr);
+ has_noise = manta_has_noise(mds->fluid, mmd, scene_framenr);
+ has_mesh = manta_has_mesh(mds->fluid, mmd, scene_framenr);
+ has_particles = manta_has_particles(mds->fluid, mmd, scene_framenr);
+ has_guide = manta_has_guiding(mds->fluid, mmd, scene_framenr, guide_parent);
- bool baking_data, baking_noise, baking_mesh, baking_particles, baking_guide, bake_outdated;
+ bool baking_data, baking_noise, baking_mesh, baking_particles, baking_guide;
baking_data = mds->cache_flag & FLUID_DOMAIN_BAKING_DATA;
baking_noise = mds->cache_flag & FLUID_DOMAIN_BAKING_NOISE;
baking_mesh = mds->cache_flag & FLUID_DOMAIN_BAKING_MESH;
baking_particles = mds->cache_flag & FLUID_DOMAIN_BAKING_PARTICLES;
baking_guide = mds->cache_flag & FLUID_DOMAIN_BAKING_GUIDE;
- bake_outdated = mds->cache_flag & (FLUID_DOMAIN_OUTDATED_DATA | FLUID_DOMAIN_OUTDATED_NOISE |
- FLUID_DOMAIN_OUTDATED_MESH | FLUID_DOMAIN_OUTDATED_PARTICLES |
- FLUID_DOMAIN_OUTDATED_GUIDE);
bool resume_data, resume_noise, resume_mesh, resume_particles, resume_guide;
resume_data = (!is_startframe) && (mds->cache_frame_pause_data == scene_framenr);
@@ -3775,35 +3837,27 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd,
bake_cache = baking_data || baking_noise || baking_mesh || baking_particles || baking_guide;
bool next_data, next_noise, next_mesh, next_particles, next_guide;
- next_data = manta_has_data(mds->fluid, mmd, scene_framenr + 1);
- next_noise = manta_has_noise(mds->fluid, mmd, scene_framenr + 1);
- next_mesh = manta_has_mesh(mds->fluid, mmd, scene_framenr + 1);
- next_particles = manta_has_particles(mds->fluid, mmd, scene_framenr + 1);
- next_guide = manta_has_guiding(mds->fluid, mmd, scene_framenr + 1, guide_parent);
+ next_data = manta_has_data(mds->fluid, mmd, next_frame);
+ next_noise = manta_has_noise(mds->fluid, mmd, next_frame);
+ next_mesh = manta_has_mesh(mds->fluid, mmd, next_frame);
+ next_particles = manta_has_particles(mds->fluid, mmd, next_frame);
+ next_guide = manta_has_guiding(mds->fluid, mmd, next_frame, guide_parent);
bool prev_data, prev_noise, prev_mesh, prev_particles, prev_guide;
- prev_data = manta_has_data(mds->fluid, mmd, scene_framenr - 1);
- prev_noise = manta_has_noise(mds->fluid, mmd, scene_framenr - 1);
- prev_mesh = manta_has_mesh(mds->fluid, mmd, scene_framenr - 1);
- prev_particles = manta_has_particles(mds->fluid, mmd, scene_framenr - 1);
- prev_guide = manta_has_guiding(mds->fluid, mmd, scene_framenr - 1, guide_parent);
-
- /* Unused for now, but needed for proper caching. */
- UNUSED_VARS(prev_guide);
- UNUSED_VARS(next_noise);
- UNUSED_VARS(next_mesh);
- UNUSED_VARS(next_particles);
- UNUSED_VARS(next_guide);
+ prev_data = manta_has_data(mds->fluid, mmd, prev_frame);
+ prev_noise = manta_has_noise(mds->fluid, mmd, prev_frame);
+ prev_mesh = manta_has_mesh(mds->fluid, mmd, prev_frame);
+ prev_particles = manta_has_particles(mds->fluid, mmd, prev_frame);
+ prev_guide = manta_has_guiding(mds->fluid, mmd, prev_frame, guide_parent);
+
+ /* Unused for now. */
+ UNUSED_VARS(has_guide, prev_guide, next_mesh, next_guide);
bool with_gdomain;
with_gdomain = (mds->guide_source == FLUID_DOMAIN_GUIDE_SRC_DOMAIN);
int o_res[3], o_min[3], o_max[3], o_shift[3];
int mode = mds->cache_type;
- int prev_frame = scene_framenr - 1;
-
- /* Ensure positivity of previous frame. */
- CLAMP(prev_frame, 1, prev_frame);
/* Cache mode specific settings. */
switch (mode) {
@@ -3851,21 +3905,23 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd,
break;
case FLUID_DOMAIN_CACHE_REPLAY:
default:
+ baking_data = !has_data && (is_startframe || prev_data);
+ if (with_smoke && with_noise) {
+ baking_noise = !has_noise && (is_startframe || prev_noise);
+ }
+ if (with_liquid && with_mesh) {
+ baking_mesh = !has_mesh && (is_startframe || prev_mesh);
+ }
+ if (with_liquid && with_particles) {
+ baking_particles = !has_particles && (is_startframe || prev_particles);
+ }
+
/* Always trying to read the cache in replay mode. */
read_cache = true;
bake_cache = false;
break;
}
- /* Cache outdated? If so reset, don't read, and then just rebake.
- * Note: Only do this in replay mode! */
- bool mode_replay = (mode == FLUID_DOMAIN_CACHE_REPLAY);
- if (bake_outdated && mode_replay) {
- read_cache = false;
- bake_cache = true;
- BKE_fluid_cache_free(mds, ob, mds->cache_flag);
- }
-
/* Try to read from cache and keep track of read success. */
if (read_cache) {
@@ -3877,7 +3933,7 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd,
/* Read particles cache. */
if (with_liquid && with_particles) {
- if (!baking_data && !baking_particles && !mode_replay) {
+ if (!baking_data && !baking_particles && next_particles) {
/* Update particle data from file is faster than via Python (manta_read_particles()). */
has_particles = manta_update_particle_structures(mds->fluid, mmd, particles_frame);
}
@@ -3901,8 +3957,8 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd,
manta_needs_realloc(mds->fluid, mmd)) {
BKE_fluid_reallocate_fluid(mds, mds->res, 1);
}
- if (!baking_data && !baking_noise && !mode_replay) {
- has_data = manta_update_noise_structures(mds->fluid, mmd, noise_frame);
+ if (!baking_data && !baking_noise && next_noise) {
+ has_noise = manta_update_noise_structures(mds->fluid, mmd, noise_frame);
}
else {
has_noise = manta_read_noise(mds->fluid, mmd, noise_frame);
@@ -3921,8 +3977,9 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd,
mds, o_res, mds->res, o_min, mds->res_min, o_max, o_shift, mds->shift);
}
}
- if (!baking_data && !baking_noise && !mode_replay) {
- /* TODO (sebbas): Confirm if this read call is really needed or not. */
+ if (!baking_data && !baking_noise && next_data && next_noise) {
+ /* TODO (sebbas): Confirm if this read call is really needed or not.
+ * Currently only important to load the shadow grid. */
has_data = manta_update_smoke_structures(mds->fluid, mmd, data_frame);
}
else {
@@ -3946,7 +4003,7 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd,
}
}
if (with_liquid) {
- if (!baking_data && !baking_particles && !baking_mesh && !mode_replay) {
+ if (!baking_data && !baking_particles && !baking_mesh && next_data) {
has_data = manta_update_liquid_structures(mds->fluid, mmd, data_frame);
}
else {
@@ -3960,6 +4017,9 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd,
switch (mode) {
case FLUID_DOMAIN_CACHE_FINAL:
case FLUID_DOMAIN_CACHE_MODULAR:
+ if (!baking_data && !baking_noise && !baking_mesh && !baking_particles && !baking_guide) {
+ bake_cache = false;
+ }
break;
case FLUID_DOMAIN_CACHE_REPLAY:
default:
@@ -4103,6 +4163,12 @@ struct Mesh *BKE_fluid_modifier_do(
mmd->domain->cache_flag &= ~FLUID_DOMAIN_OUTDATED_PARTICLES;
mmd->domain->cache_flag &= ~FLUID_DOMAIN_OUTDATED_GUIDE;
}
+ else if (mmd->type & MOD_FLUID_TYPE_FLOW && mmd->flow) {
+ mmd->flow->flags &= ~FLUID_FLOW_NEEDS_UPDATE;
+ }
+ else if (mmd->type & MOD_FLUID_TYPE_EFFEC && mmd->effector) {
+ mmd->effector->flags &= ~FLUID_EFFECTOR_NEEDS_UPDATE;
+ }
if (!result) {
result = BKE_mesh_copy_for_eval(me, false);
}
diff --git a/source/blender/blenkernel/intern/idtype.c b/source/blender/blenkernel/intern/idtype.c
index 5a6e8f532c9..fafd223a0e5 100644
--- a/source/blender/blenkernel/intern/idtype.c
+++ b/source/blender/blenkernel/intern/idtype.c
@@ -92,6 +92,7 @@ static void id_type_init(void)
INIT_TYPE(ID_HA);
INIT_TYPE(ID_PT);
INIT_TYPE(ID_VO);
+ INIT_TYPE(ID_SIM);
/* Special naughty boy... */
BLI_assert(IDType_ID_LINK_PLACEHOLDER.main_listbase_index == INDEX_ID_NULL);
@@ -251,6 +252,7 @@ uint64_t BKE_idtype_idcode_to_idfilter(const short idcode)
CASE_IDFILTER(PT);
CASE_IDFILTER(LP);
CASE_IDFILTER(SCE);
+ CASE_IDFILTER(SIM);
CASE_IDFILTER(SPK);
CASE_IDFILTER(SO);
CASE_IDFILTER(TE);
@@ -302,6 +304,7 @@ short BKE_idtype_idcode_from_idfilter(const uint64_t idfilter)
CASE_IDFILTER(PT);
CASE_IDFILTER(LP);
CASE_IDFILTER(SCE);
+ CASE_IDFILTER(SIM);
CASE_IDFILTER(SPK);
CASE_IDFILTER(SO);
CASE_IDFILTER(TE);
@@ -356,6 +359,7 @@ int BKE_idtype_idcode_to_index(const short idcode)
CASE_IDINDEX(LP);
CASE_IDINDEX(SCE);
CASE_IDINDEX(SCR);
+ CASE_IDINDEX(SIM);
CASE_IDINDEX(SPK);
CASE_IDINDEX(SO);
CASE_IDINDEX(TE);
@@ -417,6 +421,7 @@ short BKE_idtype_idcode_from_index(const int index)
CASE_IDCODE(LP);
CASE_IDCODE(SCE);
CASE_IDCODE(SCR);
+ CASE_IDCODE(SIM);
CASE_IDCODE(SPK);
CASE_IDCODE(SO);
CASE_IDCODE(TE);
diff --git a/source/blender/blenkernel/intern/lib_id.c b/source/blender/blenkernel/intern/lib_id.c
index d1337620de8..fe25016344e 100644
--- a/source/blender/blenkernel/intern/lib_id.c
+++ b/source/blender/blenkernel/intern/lib_id.c
@@ -36,38 +36,12 @@
#include "MEM_guardedalloc.h"
/* all types are needed here, in order to do memory operations */
+#include "DNA_ID.h"
#include "DNA_anim_types.h"
-#include "DNA_armature_types.h"
-#include "DNA_brush_types.h"
-#include "DNA_cachefile_types.h"
-#include "DNA_camera_types.h"
-#include "DNA_collection_types.h"
#include "DNA_gpencil_types.h"
-#include "DNA_hair_types.h"
-#include "DNA_ipo_types.h"
#include "DNA_key_types.h"
-#include "DNA_lattice_types.h"
-#include "DNA_light_types.h"
-#include "DNA_lightprobe_types.h"
-#include "DNA_linestyle_types.h"
-#include "DNA_mask_types.h"
-#include "DNA_material_types.h"
-#include "DNA_mesh_types.h"
-#include "DNA_meta_types.h"
-#include "DNA_movieclip_types.h"
#include "DNA_node_types.h"
-#include "DNA_object_types.h"
-#include "DNA_pointcloud_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_screen_types.h"
-#include "DNA_sound_types.h"
-#include "DNA_speaker_types.h"
-#include "DNA_text_types.h"
-#include "DNA_vfont_types.h"
-#include "DNA_volume_types.h"
-#include "DNA_windowmanager_types.h"
#include "DNA_workspace_types.h"
-#include "DNA_world_types.h"
#include "BLI_utildefines.h"
@@ -80,50 +54,21 @@
#include "BLT_translation.h"
-#include "BKE_action.h"
#include "BKE_anim_data.h"
#include "BKE_armature.h"
#include "BKE_bpath.h"
-#include "BKE_brush.h"
-#include "BKE_cachefile.h"
-#include "BKE_camera.h"
-#include "BKE_collection.h"
#include "BKE_context.h"
-#include "BKE_curve.h"
-#include "BKE_font.h"
#include "BKE_global.h"
#include "BKE_gpencil.h"
-#include "BKE_hair.h"
#include "BKE_idprop.h"
#include "BKE_idtype.h"
-#include "BKE_image.h"
#include "BKE_key.h"
-#include "BKE_lattice.h"
#include "BKE_lib_id.h"
#include "BKE_lib_query.h"
#include "BKE_lib_remap.h"
-#include "BKE_light.h"
-#include "BKE_lightprobe.h"
-#include "BKE_linestyle.h"
#include "BKE_main.h"
-#include "BKE_mask.h"
-#include "BKE_material.h"
-#include "BKE_mball.h"
-#include "BKE_mesh.h"
-#include "BKE_movieclip.h"
#include "BKE_node.h"
-#include "BKE_object.h"
-#include "BKE_paint.h"
-#include "BKE_particle.h"
-#include "BKE_pointcloud.h"
#include "BKE_rigidbody.h"
-#include "BKE_scene.h"
-#include "BKE_sound.h"
-#include "BKE_speaker.h"
-#include "BKE_text.h"
-#include "BKE_texture.h"
-#include "BKE_volume.h"
-#include "BKE_world.h"
#include "DEG_depsgraph.h"
@@ -663,7 +608,7 @@ static void id_swap(Main *bmain, ID *id_a, ID *id_b, const bool do_full_id)
* Does a mere memory swap over the whole IDs data (including type-specific memory).
* \note Most internal ID data itself is not swapped (only IDProperties are).
*
- * \param bmain May be NULL, in which case there will be no remapping of internal pointers to
+ * \param bmain: May be NULL, in which case there will be no remapping of internal pointers to
* itself.
*/
void BKE_lib_id_swap(Main *bmain, ID *id_a, ID *id_b)
@@ -675,7 +620,7 @@ void BKE_lib_id_swap(Main *bmain, ID *id_a, ID *id_b)
* Does a mere memory swap over the whole IDs data (including type-specific memory).
* \note All internal ID data itself is also swapped.
*
- * \param bmain May be NULL, in which case there will be no remapping of internal pointers to
+ * \param bmain: May be NULL, in which case there will be no remapping of internal pointers to
* itself.
*/
void BKE_lib_id_swap_full(Main *bmain, ID *id_a, ID *id_b)
@@ -1260,7 +1205,7 @@ ID *BKE_libblock_find_name(struct Main *bmain, const short type, const char *nam
*
* \note All other IDs beside given one are assumed already properly sorted in the list.
*
- * \param id_sorting_hint Ignored if NULL. Otherwise, used to check if we can insert \a id
+ * \param id_sorting_hint: Ignored if NULL. Otherwise, used to check if we can insert \a id
* immediately before or after that pointer. It must always be into given \a lb list.
*/
void id_sort_by_name(ListBase *lb, ID *id, ID *id_sorting_hint)
diff --git a/source/blender/blenkernel/intern/lib_id_delete.c b/source/blender/blenkernel/intern/lib_id_delete.c
index 245e4f43452..fdee5500fbd 100644
--- a/source/blender/blenkernel/intern/lib_id_delete.c
+++ b/source/blender/blenkernel/intern/lib_id_delete.c
@@ -23,80 +23,20 @@
#include "MEM_guardedalloc.h"
/* all types are needed here, in order to do memory operations */
-#include "DNA_armature_types.h"
-#include "DNA_brush_types.h"
-#include "DNA_cachefile_types.h"
-#include "DNA_camera_types.h"
-#include "DNA_collection_types.h"
-#include "DNA_gpencil_types.h"
-#include "DNA_ipo_types.h"
-#include "DNA_key_types.h"
-#include "DNA_lattice_types.h"
-#include "DNA_light_types.h"
-#include "DNA_lightprobe_types.h"
-#include "DNA_linestyle_types.h"
-#include "DNA_mask_types.h"
-#include "DNA_material_types.h"
-#include "DNA_mesh_types.h"
-#include "DNA_meta_types.h"
-#include "DNA_movieclip_types.h"
-#include "DNA_node_types.h"
-#include "DNA_object_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_screen_types.h"
-#include "DNA_sound_types.h"
-#include "DNA_speaker_types.h"
-#include "DNA_text_types.h"
-#include "DNA_vfont_types.h"
-#include "DNA_windowmanager_types.h"
-#include "DNA_workspace_types.h"
-#include "DNA_world_types.h"
+#include "DNA_ID.h"
#include "BLI_utildefines.h"
#include "BLI_listbase.h"
-#include "BKE_action.h"
#include "BKE_anim_data.h"
-#include "BKE_armature.h"
-#include "BKE_brush.h"
-#include "BKE_cachefile.h"
-#include "BKE_camera.h"
-#include "BKE_collection.h"
-#include "BKE_curve.h"
-#include "BKE_font.h"
-#include "BKE_gpencil.h"
#include "BKE_idprop.h"
#include "BKE_idtype.h"
-#include "BKE_image.h"
-#include "BKE_ipo.h"
-#include "BKE_key.h"
-#include "BKE_lattice.h"
#include "BKE_lib_id.h"
#include "BKE_lib_override.h"
#include "BKE_lib_remap.h"
#include "BKE_library.h"
-#include "BKE_light.h"
-#include "BKE_lightprobe.h"
-#include "BKE_linestyle.h"
#include "BKE_main.h"
-#include "BKE_mask.h"
-#include "BKE_material.h"
-#include "BKE_mball.h"
-#include "BKE_mesh.h"
-#include "BKE_movieclip.h"
-#include "BKE_node.h"
-#include "BKE_object.h"
-#include "BKE_paint.h"
-#include "BKE_particle.h"
-#include "BKE_scene.h"
-#include "BKE_screen.h"
-#include "BKE_sound.h"
-#include "BKE_speaker.h"
-#include "BKE_text.h"
-#include "BKE_texture.h"
-#include "BKE_workspace.h"
-#include "BKE_world.h"
#include "lib_intern.h"
diff --git a/source/blender/blenkernel/intern/lib_query.c b/source/blender/blenkernel/intern/lib_query.c
index 4ffdcf14fa7..bddf8c0f819 100644
--- a/source/blender/blenkernel/intern/lib_query.c
+++ b/source/blender/blenkernel/intern/lib_query.c
@@ -49,6 +49,7 @@
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_sequence_types.h"
+#include "DNA_simulation_types.h"
#include "DNA_sound_types.h"
#include "DNA_space_types.h"
#include "DNA_speaker_types.h"
@@ -204,6 +205,40 @@ static void library_foreach_idproperty_ID_link(LibraryForeachIDData *data,
FOREACH_FINALIZE_VOID;
}
+static void library_foreach_node_socket(LibraryForeachIDData *data, bNodeSocket *sock)
+{
+ library_foreach_idproperty_ID_link(data, sock->prop, IDWALK_CB_USER);
+
+ switch ((eNodeSocketDatatype)sock->type) {
+ case SOCK_OBJECT: {
+ bNodeSocketValueObject *default_value = sock->default_value;
+ FOREACH_CALLBACK_INVOKE_ID_PP(data, (ID **)&default_value->value, IDWALK_CB_USER);
+ break;
+ }
+ case SOCK_IMAGE: {
+ bNodeSocketValueImage *default_value = sock->default_value;
+ FOREACH_CALLBACK_INVOKE_ID_PP(data, (ID **)&default_value->value, IDWALK_CB_USER);
+ break;
+ }
+ case SOCK_FLOAT:
+ case SOCK_VECTOR:
+ case SOCK_RGBA:
+ case SOCK_BOOLEAN:
+ case SOCK_INT:
+ case SOCK_STRING:
+ case __SOCK_MESH:
+ case SOCK_CUSTOM:
+ case SOCK_SHADER:
+ case SOCK_EMITTERS:
+ case SOCK_EVENTS:
+ case SOCK_FORCES:
+ case SOCK_CONTROL_FLOW:
+ break;
+ }
+
+ FOREACH_FINALIZE_VOID;
+}
+
static void library_foreach_rigidbodyworldSceneLooper(struct RigidBodyWorld *UNUSED(rbw),
ID **id_pointer,
void *user_data,
@@ -1017,7 +1052,6 @@ static void library_foreach_ID_link(Main *bmain,
case ID_NT: {
bNodeTree *ntree = (bNodeTree *)id;
bNode *node;
- bNodeSocket *sock;
CALLBACK_INVOKE(ntree->gpd, IDWALK_CB_USER);
@@ -1025,19 +1059,19 @@ static void library_foreach_ID_link(Main *bmain,
CALLBACK_INVOKE_ID(node->id, IDWALK_CB_USER);
library_foreach_idproperty_ID_link(&data, node->prop, IDWALK_CB_USER);
- for (sock = node->inputs.first; sock; sock = sock->next) {
- library_foreach_idproperty_ID_link(&data, sock->prop, IDWALK_CB_USER);
+ LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
+ library_foreach_node_socket(&data, sock);
}
- for (sock = node->outputs.first; sock; sock = sock->next) {
- library_foreach_idproperty_ID_link(&data, sock->prop, IDWALK_CB_USER);
+ LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) {
+ library_foreach_node_socket(&data, sock);
}
}
- for (sock = ntree->inputs.first; sock; sock = sock->next) {
- library_foreach_idproperty_ID_link(&data, sock->prop, IDWALK_CB_USER);
+ LISTBASE_FOREACH (bNodeSocket *, sock, &ntree->inputs) {
+ library_foreach_node_socket(&data, sock);
}
- for (sock = ntree->outputs.first; sock; sock = sock->next) {
- library_foreach_idproperty_ID_link(&data, sock->prop, IDWALK_CB_USER);
+ LISTBASE_FOREACH (bNodeSocket *, sock, &ntree->outputs) {
+ library_foreach_node_socket(&data, sock);
}
break;
}
@@ -1285,6 +1319,15 @@ static void library_foreach_ID_link(Main *bmain,
}
break;
}
+ case ID_SIM: {
+ Simulation *simulation = (Simulation *)id;
+ if (simulation->nodetree) {
+ /* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */
+ library_foreach_ID_as_subdata_link(
+ (ID **)&simulation->nodetree, callback, user_data, flag, &data);
+ }
+ break;
+ }
/* Nothing needed for those... */
case ID_IM:
@@ -1456,6 +1499,7 @@ bool BKE_library_id_can_use_idtype(ID *id_owner, const short id_type_used)
case ID_PAL:
case ID_PC:
case ID_CF:
+ case ID_SIM:
/* Those types never use/reference other IDs... */
return false;
case ID_IP:
diff --git a/source/blender/blenkernel/intern/light.c b/source/blender/blenkernel/intern/light.c
index 3d0503b2e70..13f4815124b 100644
--- a/source/blender/blenkernel/intern/light.c
+++ b/source/blender/blenkernel/intern/light.c
@@ -97,7 +97,7 @@ static void light_free_data(ID *id)
/* is no lib link block, but light extension */
if (la->nodetree) {
- ntreeFreeNestedTree(la->nodetree);
+ ntreeFreeEmbeddedTree(la->nodetree);
MEM_freeN(la->nodetree);
la->nodetree = NULL;
}
diff --git a/source/blender/blenkernel/intern/linestyle.c b/source/blender/blenkernel/intern/linestyle.c
index 42506e0d7c8..0401ae48b5c 100644
--- a/source/blender/blenkernel/intern/linestyle.c
+++ b/source/blender/blenkernel/intern/linestyle.c
@@ -125,7 +125,7 @@ static void linestyle_free_data(ID *id)
/* is no lib link block, but linestyle extension */
if (linestyle->nodetree) {
- ntreeFreeNestedTree(linestyle->nodetree);
+ ntreeFreeEmbeddedTree(linestyle->nodetree);
MEM_freeN(linestyle->nodetree);
linestyle->nodetree = NULL;
}
diff --git a/source/blender/blenkernel/intern/main.c b/source/blender/blenkernel/intern/main.c
index caa29f7817a..ea3bee8b2f6 100644
--- a/source/blender/blenkernel/intern/main.c
+++ b/source/blender/blenkernel/intern/main.c
@@ -479,6 +479,8 @@ ListBase *which_libbase(Main *bmain, short type)
return &(bmain->pointclouds);
case ID_VO:
return &(bmain->volumes);
+ case ID_SIM:
+ return &(bmain->simulations);
}
return NULL;
}
@@ -554,6 +556,7 @@ int set_listbasepointers(Main *bmain, ListBase **lb)
lb[INDEX_ID_WS] = &(bmain->workspaces); /* before wm, so it's freed after it! */
lb[INDEX_ID_WM] = &(bmain->wm);
lb[INDEX_ID_MSK] = &(bmain->masks);
+ lb[INDEX_ID_SIM] = &(bmain->simulations);
lb[INDEX_ID_NULL] = NULL;
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index 5516e877b10..b3fb9681918 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -130,7 +130,7 @@ static void material_free_data(ID *id)
/* is no lib link block, but material extension */
if (material->nodetree) {
- ntreeFreeNestedTree(material->nodetree);
+ ntreeFreeEmbeddedTree(material->nodetree);
MEM_freeN(material->nodetree);
material->nodetree = NULL;
}
@@ -1599,7 +1599,7 @@ void BKE_material_copybuf_paste(Main *bmain, Material *ma)
GPU_material_free(&ma->gpumaterial);
if (ma->nodetree) {
- ntreeFreeNestedTree(ma->nodetree);
+ ntreeFreeEmbeddedTree(ma->nodetree);
MEM_freeN(ma->nodetree);
}
diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c
index e5be85b5ec7..78991ad063d 100644
--- a/source/blender/blenkernel/intern/mesh_evaluate.c
+++ b/source/blender/blenkernel/intern/mesh_evaluate.c
@@ -1302,7 +1302,7 @@ static void loop_split_worker_do(LoopSplitTaskDataCommon *common_data,
static void loop_split_worker(TaskPool *__restrict pool, void *taskdata, int UNUSED(threadid))
{
- LoopSplitTaskDataCommon *common_data = BLI_task_pool_userdata(pool);
+ LoopSplitTaskDataCommon *common_data = BLI_task_pool_user_data(pool);
LoopSplitTaskData *data = taskdata;
/* Temp edge vectors stack, only used when computing lnor spacearr. */
diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c
index 193fe859def..7991559d1ce 100644
--- a/source/blender/blenkernel/intern/movieclip.c
+++ b/source/blender/blenkernel/intern/movieclip.c
@@ -1512,7 +1512,8 @@ void BKE_movieclip_update_scopes(MovieClip *clip, MovieClipUser *user, MovieClip
undist_marker.pos[0] *= width;
undist_marker.pos[1] *= height * aspy;
- BKE_tracking_undistort_v2(&clip->tracking, undist_marker.pos, undist_marker.pos);
+ BKE_tracking_undistort_v2(
+ &clip->tracking, width, height, undist_marker.pos, undist_marker.pos);
undist_marker.pos[0] /= width;
undist_marker.pos[1] /= height * aspy;
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index c3c538f3424..f9477339b9b 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -37,6 +37,7 @@
#include "DNA_material_types.h"
#include "DNA_node_types.h"
#include "DNA_scene_types.h"
+#include "DNA_simulation_types.h"
#include "DNA_texture_types.h"
#include "DNA_world_types.h"
@@ -66,7 +67,9 @@
#include "NOD_common.h"
#include "NOD_composite.h"
+#include "NOD_function.h"
#include "NOD_shader.h"
+#include "NOD_simulation.h"
#include "NOD_socket.h"
#include "NOD_texture.h"
@@ -86,7 +89,9 @@ static void ntree_set_typeinfo(bNodeTree *ntree, bNodeTreeType *typeinfo);
static void node_socket_copy(bNodeSocket *sock_dst, const bNodeSocket *sock_src, const int flag);
static void free_localized_node_groups(bNodeTree *ntree);
static void node_free_node(bNodeTree *ntree, bNode *node);
-static void node_socket_interface_free(bNodeTree *UNUSED(ntree), bNodeSocket *sock);
+static void node_socket_interface_free(bNodeTree *UNUSED(ntree),
+ bNodeSocket *sock,
+ const bool do_id_user);
static void ntree_init_data(ID *id)
{
@@ -229,12 +234,12 @@ static void ntree_free_data(ID *id)
/* free interface sockets */
for (sock = ntree->inputs.first; sock; sock = nextsock) {
nextsock = sock->next;
- node_socket_interface_free(ntree, sock);
+ node_socket_interface_free(ntree, sock, false);
MEM_freeN(sock);
}
for (sock = ntree->outputs.first; sock; sock = nextsock) {
nextsock = sock->next;
- node_socket_interface_free(ntree, sock);
+ node_socket_interface_free(ntree, sock, false);
MEM_freeN(sock);
}
@@ -744,6 +749,66 @@ static bNodeSocket *make_socket(bNodeTree *ntree,
return sock;
}
+static void socket_id_user_increment(bNodeSocket *sock)
+{
+ switch ((eNodeSocketDatatype)sock->type) {
+ case SOCK_OBJECT: {
+ bNodeSocketValueObject *default_value = sock->default_value;
+ id_us_plus(&default_value->value->id);
+ break;
+ }
+ case SOCK_IMAGE: {
+ bNodeSocketValueImage *default_value = sock->default_value;
+ id_us_plus(&default_value->value->id);
+ break;
+ }
+ case SOCK_FLOAT:
+ case SOCK_VECTOR:
+ case SOCK_RGBA:
+ case SOCK_BOOLEAN:
+ case SOCK_INT:
+ case SOCK_STRING:
+ case __SOCK_MESH:
+ case SOCK_CUSTOM:
+ case SOCK_SHADER:
+ case SOCK_EMITTERS:
+ case SOCK_EVENTS:
+ case SOCK_FORCES:
+ case SOCK_CONTROL_FLOW:
+ break;
+ }
+}
+
+static void socket_id_user_decrement(bNodeSocket *sock)
+{
+ switch ((eNodeSocketDatatype)sock->type) {
+ case SOCK_OBJECT: {
+ bNodeSocketValueObject *default_value = sock->default_value;
+ id_us_min(&default_value->value->id);
+ break;
+ }
+ case SOCK_IMAGE: {
+ bNodeSocketValueImage *default_value = sock->default_value;
+ id_us_min(&default_value->value->id);
+ break;
+ }
+ case SOCK_FLOAT:
+ case SOCK_VECTOR:
+ case SOCK_RGBA:
+ case SOCK_BOOLEAN:
+ case SOCK_INT:
+ case SOCK_STRING:
+ case __SOCK_MESH:
+ case SOCK_CUSTOM:
+ case SOCK_SHADER:
+ case SOCK_EMITTERS:
+ case SOCK_EVENTS:
+ case SOCK_FORCES:
+ case SOCK_CONTROL_FLOW:
+ break;
+ }
+}
+
void nodeModifySocketType(
bNodeTree *ntree, bNode *UNUSED(node), bNodeSocket *sock, int type, int subtype)
{
@@ -755,6 +820,7 @@ void nodeModifySocketType(
}
if (sock->default_value) {
+ socket_id_user_decrement(sock);
MEM_freeN(sock->default_value);
sock->default_value = NULL;
}
@@ -858,6 +924,18 @@ const char *nodeStaticSocketType(int type, int subtype)
return "NodeSocketString";
case SOCK_SHADER:
return "NodeSocketShader";
+ case SOCK_OBJECT:
+ return "NodeSocketObject";
+ case SOCK_IMAGE:
+ return "NodeSocketImage";
+ case SOCK_EMITTERS:
+ return "NodeSocketEmitters";
+ case SOCK_EVENTS:
+ return "NodeSocketEvents";
+ case SOCK_FORCES:
+ return "NodeSocketForces";
+ case SOCK_CONTROL_FLOW:
+ return "NodeSocketControlFlow";
}
return NULL;
}
@@ -919,6 +997,18 @@ const char *nodeStaticSocketInterfaceType(int type, int subtype)
return "NodeSocketInterfaceString";
case SOCK_SHADER:
return "NodeSocketInterfaceShader";
+ case SOCK_OBJECT:
+ return "NodeSocketInterfaceObject";
+ case SOCK_IMAGE:
+ return "NodeSocketInterfaceImage";
+ case SOCK_EMITTERS:
+ return "NodeSocketInterfaceEmitters";
+ case SOCK_EVENTS:
+ return "NodeSocketInterfaceEvents";
+ case SOCK_FORCES:
+ return "NodeSocketInterfaceForces";
+ case SOCK_CONTROL_FLOW:
+ return "NodeSocketInterfaceControlFlow";
}
return NULL;
}
@@ -977,6 +1067,9 @@ static void node_socket_free(bNodeTree *UNUSED(ntree),
}
if (sock->default_value) {
+ if (do_id_user) {
+ socket_id_user_decrement(sock);
+ }
MEM_freeN(sock->default_value);
}
}
@@ -1263,6 +1356,10 @@ static void node_socket_copy(bNodeSocket *sock_dst, const bNodeSocket *sock_src,
if (sock_src->default_value) {
sock_dst->default_value = MEM_dupallocN(sock_src->default_value);
+
+ if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
+ socket_id_user_increment(sock_dst);
+ }
}
sock_dst->stack_index = 0;
@@ -2083,6 +2180,13 @@ void nodeRemoveNode(Main *bmain, bNodeTree *ntree, bNode *node, bool do_id_user)
if (node->id) {
id_us_min(node->id);
}
+
+ LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
+ socket_id_user_decrement(sock);
+ }
+ LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) {
+ socket_id_user_decrement(sock);
+ }
}
/* Remove animation data. */
@@ -2102,13 +2206,18 @@ void nodeRemoveNode(Main *bmain, bNodeTree *ntree, bNode *node, bool do_id_user)
node_free_node(ntree, node);
}
-static void node_socket_interface_free(bNodeTree *UNUSED(ntree), bNodeSocket *sock)
+static void node_socket_interface_free(bNodeTree *UNUSED(ntree),
+ bNodeSocket *sock,
+ const bool do_id_user)
{
if (sock->prop) {
- IDP_FreeProperty(sock->prop);
+ IDP_FreeProperty_ex(sock->prop, do_id_user);
}
if (sock->default_value) {
+ if (do_id_user) {
+ socket_id_user_decrement(sock);
+ }
MEM_freeN(sock->default_value);
}
}
@@ -2143,7 +2252,7 @@ void ntreeFreeTree(bNodeTree *ntree)
BKE_animdata_free(&ntree->id, false);
}
-void ntreeFreeNestedTree(bNodeTree *ntree)
+void ntreeFreeEmbeddedTree(bNodeTree *ntree)
{
ntreeFreeTree(ntree);
BKE_libblock_free_data(&ntree->id, true);
@@ -2266,6 +2375,8 @@ bNodeTree **BKE_ntree_ptr_from_id(ID *id)
return &((Scene *)id)->nodetree;
case ID_LS:
return &((FreestyleLineStyle *)id)->nodetree;
+ case ID_SIM:
+ return &((Simulation *)id)->nodetree;
default:
return NULL;
}
@@ -2529,7 +2640,7 @@ void ntreeRemoveSocketInterface(bNodeTree *ntree, bNodeSocket *sock)
BLI_remlink(&ntree->inputs, sock);
BLI_remlink(&ntree->outputs, sock);
- node_socket_interface_free(ntree, sock);
+ node_socket_interface_free(ntree, sock, true);
MEM_freeN(sock);
ntree->update |= NTREE_UPDATE_GROUP;
@@ -4114,6 +4225,31 @@ static void registerTextureNodes(void)
register_node_type_tex_proc_distnoise();
}
+static void registerSimulationNodes(void)
+{
+ register_node_type_sim_group();
+
+ register_node_type_sim_particle_simulation();
+ register_node_type_sim_force();
+ register_node_type_sim_set_particle_attribute();
+ register_node_type_sim_particle_birth_event();
+ register_node_type_sim_particle_time_step_event();
+ register_node_type_sim_execute_condition();
+ register_node_type_sim_multi_execute();
+ register_node_type_sim_particle_mesh_emitter();
+ register_node_type_sim_particle_mesh_collision_event();
+ register_node_type_sim_emit_particles();
+ register_node_type_sim_time();
+ register_node_type_sim_particle_attribute();
+}
+
+static void registerFunctionNodes(void)
+{
+ register_node_type_fn_boolean_math();
+ register_node_type_fn_float_compare();
+ register_node_type_fn_switch();
+}
+
void init_nodesystem(void)
{
nodetreetypes_hash = BLI_ghash_str_new("nodetreetypes_hash gh");
@@ -4127,6 +4263,7 @@ void init_nodesystem(void)
register_node_tree_type_cmp();
register_node_tree_type_sh();
register_node_tree_type_tex();
+ register_node_tree_type_sim();
register_node_type_frame();
register_node_type_reroute();
@@ -4136,6 +4273,8 @@ void init_nodesystem(void)
registerCompositNodes();
registerShaderNodes();
registerTextureNodes();
+ registerSimulationNodes();
+ registerFunctionNodes();
}
void free_nodesystem(void)
@@ -4192,6 +4331,7 @@ void BKE_node_tree_iter_init(struct NodeTreeIterStore *ntreeiter, struct Main *b
ntreeiter->light = bmain->lights.first;
ntreeiter->world = bmain->worlds.first;
ntreeiter->linestyle = bmain->linestyles.first;
+ ntreeiter->simulation = bmain->simulations.first;
}
bool BKE_node_tree_iter_step(struct NodeTreeIterStore *ntreeiter,
bNodeTree **r_nodetree,
@@ -4232,6 +4372,11 @@ bool BKE_node_tree_iter_step(struct NodeTreeIterStore *ntreeiter,
*r_id = (ID *)ntreeiter->linestyle;
ntreeiter->linestyle = ntreeiter->linestyle->id.next;
}
+ else if (ntreeiter->simulation) {
+ *r_nodetree = ntreeiter->simulation->nodetree;
+ *r_id = (ID *)ntreeiter->simulation;
+ ntreeiter->simulation = ntreeiter->simulation->id.next;
+ }
else {
return false;
}
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index f68b1a4d314..2f281a29211 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -2677,7 +2677,7 @@ void BKE_object_where_is_calc_time(Depsgraph *depsgraph, Scene *scene, Object *o
{
/* Execute drivers and animation. */
const bool flush_to_original = DEG_is_active(depsgraph);
- BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, ctime, ADT_RECALC_ALL, flush_to_original);
+ BKE_animsys_evaluate_animdata(&ob->id, ob->adt, ctime, ADT_RECALC_ALL, flush_to_original);
object_where_is_calc_ex(depsgraph, scene, ob, ctime, NULL, NULL);
}
@@ -4567,8 +4567,7 @@ bool BKE_object_modifier_update_subframe(Depsgraph *depsgraph,
/* TODO(sergey): What about animation? */
ob->id.recalc |= ID_RECALC_ALL;
if (update_mesh) {
- BKE_animsys_evaluate_animdata(
- scene, &ob->id, ob->adt, frame, ADT_RECALC_ANIM, flush_to_original);
+ BKE_animsys_evaluate_animdata(&ob->id, ob->adt, frame, ADT_RECALC_ANIM, flush_to_original);
/* ignore cache clear during subframe updates
* to not mess up cache validity */
object_cacheIgnoreClear(ob, 1);
@@ -4582,14 +4581,12 @@ bool BKE_object_modifier_update_subframe(Depsgraph *depsgraph,
/* for curve following objects, parented curve has to be updated too */
if (ob->type == OB_CURVE) {
Curve *cu = ob->data;
- BKE_animsys_evaluate_animdata(
- scene, &cu->id, cu->adt, frame, ADT_RECALC_ANIM, flush_to_original);
+ BKE_animsys_evaluate_animdata(&cu->id, cu->adt, frame, ADT_RECALC_ANIM, flush_to_original);
}
/* and armatures... */
if (ob->type == OB_ARMATURE) {
bArmature *arm = ob->data;
- BKE_animsys_evaluate_animdata(
- scene, &arm->id, arm->adt, frame, ADT_RECALC_ANIM, flush_to_original);
+ BKE_animsys_evaluate_animdata(&arm->id, arm->adt, frame, ADT_RECALC_ANIM, flush_to_original);
BKE_pose_where_is(depsgraph, scene, ob);
}
diff --git a/source/blender/blenkernel/intern/ocean.c b/source/blender/blenkernel/intern/ocean.c
index 2683d384bc7..4835a4c6a62 100644
--- a/source/blender/blenkernel/intern/ocean.c
+++ b/source/blender/blenkernel/intern/ocean.c
@@ -457,7 +457,7 @@ static void ocean_compute_displacement_y(TaskPool *__restrict pool,
void *UNUSED(taskdata),
int UNUSED(threadid))
{
- OceanSimulateData *osd = BLI_task_pool_userdata(pool);
+ OceanSimulateData *osd = BLI_task_pool_user_data(pool);
const Ocean *o = osd->o;
fftw_execute(o->_disp_y_plan);
@@ -467,7 +467,7 @@ static void ocean_compute_displacement_x(TaskPool *__restrict pool,
void *UNUSED(taskdata),
int UNUSED(threadid))
{
- OceanSimulateData *osd = BLI_task_pool_userdata(pool);
+ OceanSimulateData *osd = BLI_task_pool_user_data(pool);
const Ocean *o = osd->o;
const float scale = osd->scale;
const float chop_amount = osd->chop_amount;
@@ -498,7 +498,7 @@ static void ocean_compute_displacement_z(TaskPool *__restrict pool,
void *UNUSED(taskdata),
int UNUSED(threadid))
{
- OceanSimulateData *osd = BLI_task_pool_userdata(pool);
+ OceanSimulateData *osd = BLI_task_pool_user_data(pool);
const Ocean *o = osd->o;
const float scale = osd->scale;
const float chop_amount = osd->chop_amount;
@@ -529,7 +529,7 @@ static void ocean_compute_jacobian_jxx(TaskPool *__restrict pool,
void *UNUSED(taskdata),
int UNUSED(threadid))
{
- OceanSimulateData *osd = BLI_task_pool_userdata(pool);
+ OceanSimulateData *osd = BLI_task_pool_user_data(pool);
const Ocean *o = osd->o;
const float chop_amount = osd->chop_amount;
int i, j;
@@ -564,7 +564,7 @@ static void ocean_compute_jacobian_jzz(TaskPool *__restrict pool,
void *UNUSED(taskdata),
int UNUSED(threadid))
{
- OceanSimulateData *osd = BLI_task_pool_userdata(pool);
+ OceanSimulateData *osd = BLI_task_pool_user_data(pool);
const Ocean *o = osd->o;
const float chop_amount = osd->chop_amount;
int i, j;
@@ -599,7 +599,7 @@ static void ocean_compute_jacobian_jxz(TaskPool *__restrict pool,
void *UNUSED(taskdata),
int UNUSED(threadid))
{
- OceanSimulateData *osd = BLI_task_pool_userdata(pool);
+ OceanSimulateData *osd = BLI_task_pool_user_data(pool);
const Ocean *o = osd->o;
const float chop_amount = osd->chop_amount;
int i, j;
@@ -628,7 +628,7 @@ static void ocean_compute_normal_x(TaskPool *__restrict pool,
void *UNUSED(taskdata),
int UNUSED(threadid))
{
- OceanSimulateData *osd = BLI_task_pool_userdata(pool);
+ OceanSimulateData *osd = BLI_task_pool_user_data(pool);
const Ocean *o = osd->o;
int i, j;
@@ -649,7 +649,7 @@ static void ocean_compute_normal_z(TaskPool *__restrict pool,
void *UNUSED(taskdata),
int UNUSED(threadid))
{
- OceanSimulateData *osd = BLI_task_pool_userdata(pool);
+ OceanSimulateData *osd = BLI_task_pool_user_data(pool);
const Ocean *o = osd->o;
int i, j;
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index cc49f500a5f..14b1ef7b87f 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -3692,10 +3692,11 @@ typedef struct DynamicStepSolverTaskData {
SpinLock spin;
} DynamicStepSolverTaskData;
-static void dynamics_step_finalize_sphdata(void *__restrict UNUSED(userdata),
- void *__restrict tls_userdata_chunk)
+static void dynamics_step_sphdata_reduce(const void *__restrict UNUSED(userdata),
+ void *__restrict UNUSED(join_v),
+ void *__restrict chunk_v)
{
- SPHData *sphdata = tls_userdata_chunk;
+ SPHData *sphdata = chunk_v;
psys_sph_flush_springs(sphdata);
}
@@ -3986,7 +3987,7 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra)
settings.use_threading = (psys->totpart > 100);
settings.userdata_chunk = &sphdata;
settings.userdata_chunk_size = sizeof(sphdata);
- settings.func_finalize = dynamics_step_finalize_sphdata;
+ settings.func_reduce = dynamics_step_sphdata_reduce;
BLI_task_parallel_range(
0, psys->totpart, &task_data, dynamics_step_sph_ddr_task_cb_ex, &settings);
@@ -4018,7 +4019,7 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra)
settings.use_threading = (psys->totpart > 100);
settings.userdata_chunk = &sphdata;
settings.userdata_chunk_size = sizeof(sphdata);
- settings.func_finalize = dynamics_step_finalize_sphdata;
+ settings.func_reduce = dynamics_step_sphdata_reduce;
BLI_task_parallel_range(0,
psys->totpart,
&task_data,
@@ -4033,7 +4034,7 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra)
settings.use_threading = (psys->totpart > 100);
settings.userdata_chunk = &sphdata;
settings.userdata_chunk_size = sizeof(sphdata);
- settings.func_finalize = dynamics_step_finalize_sphdata;
+ settings.func_reduce = dynamics_step_sphdata_reduce;
BLI_task_parallel_range(0,
psys->totpart,
&task_data,
@@ -4189,7 +4190,7 @@ static void particles_fluid_step(ParticleSimulationData *sim,
ParticleSettings *part = psys->part;
ParticleData *pa = NULL;
- int p, totpart, tottypepart = 0;
+ int p, totpart = 0, tottypepart = 0;
int flagActivePart, activeParts = 0;
float posX, posY, posZ, velX, velY, velZ;
float resX, resY, resZ;
@@ -4847,7 +4848,7 @@ void particle_system_update(struct Depsgraph *depsgraph,
hcfra = 100.0f * (float)i / (float)psys->part->hair_step;
if ((part->flag & PART_HAIR_REGROW) == 0) {
BKE_animsys_evaluate_animdata(
- scene, &part_local->id, part_local->adt, hcfra, ADT_RECALC_ANIM, false);
+ &part_local->id, part_local->adt, hcfra, ADT_RECALC_ANIM, false);
}
system_step(&sim, hcfra, use_render_params);
psys->cfra = hcfra;
diff --git a/source/blender/blenkernel/intern/pointcloud.c b/source/blender/blenkernel/intern/pointcloud.c
index 31b8de53291..717d84c1c1e 100644
--- a/source/blender/blenkernel/intern/pointcloud.c
+++ b/source/blender/blenkernel/intern/pointcloud.c
@@ -184,7 +184,7 @@ void BKE_pointcloud_update_customdata_pointers(PointCloud *pointcloud)
PointCloud *BKE_pointcloud_new_for_eval(const PointCloud *pointcloud_src, int totpoint)
{
- PointCloud *pointcloud_dst = BKE_id_new_nomain(ID_HA, NULL);
+ PointCloud *pointcloud_dst = BKE_id_new_nomain(ID_PT, NULL);
STRNCPY(pointcloud_dst->id.name, pointcloud_src->id.name);
pointcloud_dst->mat = MEM_dupallocN(pointcloud_src->mat);
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index f7c018edbd8..5a6d729568a 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -340,7 +340,7 @@ static void scene_free_data(ID *id)
/* is no lib link block, but scene extension */
if (scene->nodetree) {
- ntreeFreeNestedTree(scene->nodetree);
+ ntreeFreeEmbeddedTree(scene->nodetree);
MEM_freeN(scene->nodetree);
scene->nodetree = NULL;
}
diff --git a/source/blender/blenkernel/intern/seqprefetch.c b/source/blender/blenkernel/intern/seqprefetch.c
index 1bd02212908..4f57776f2ad 100644
--- a/source/blender/blenkernel/intern/seqprefetch.c
+++ b/source/blender/blenkernel/intern/seqprefetch.c
@@ -332,8 +332,7 @@ static void *seq_prefetch_frames(void *job)
pfjob->scene_eval->ed->prefetch_job = NULL;
AnimData *adt = BKE_animdata_from_id(&pfjob->context_cpy.scene->id);
- BKE_animsys_evaluate_animdata(pfjob->context_cpy.scene,
- &pfjob->context_cpy.scene->id,
+ BKE_animsys_evaluate_animdata(&pfjob->context_cpy.scene->id,
adt,
pfjob->cfra + pfjob->num_frames_prefetched,
ADT_RECALC_ALL,
diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c
index 93e5a3bbd74..c0ab5cf5816 100644
--- a/source/blender/blenkernel/intern/sequencer.c
+++ b/source/blender/blenkernel/intern/sequencer.c
@@ -3330,8 +3330,7 @@ static ImBuf *seq_render_mask(const SeqRenderData *context, Mask *mask, float nr
/* anim-data */
adt = BKE_animdata_from_id(&mask->id);
- BKE_animsys_evaluate_animdata(
- context->scene, &mask_temp->id, adt, mask->sfra + nr, ADT_RECALC_ANIM, false);
+ BKE_animsys_evaluate_animdata(&mask_temp->id, adt, mask->sfra + nr, ADT_RECALC_ANIM, false);
maskbuf = MEM_mallocN(sizeof(float) * context->rectx * context->recty, __func__);
@@ -3660,8 +3659,7 @@ static ImBuf *do_render_strip_seqbase(const SeqRenderData *context,
if (seqbase && !BLI_listbase_is_empty(seqbase)) {
if (seq->flag & SEQ_SCENE_STRIPS && seq->scene) {
- BKE_animsys_evaluate_all_animation(
- context->bmain, context->depsgraph, seq->scene, nr + offset);
+ BKE_animsys_evaluate_all_animation(context->bmain, context->depsgraph, nr + offset);
}
ibuf = seq_render_strip_stack(context,
diff --git a/source/blender/blenkernel/intern/simulation.cc b/source/blender/blenkernel/intern/simulation.cc
new file mode 100644
index 00000000000..ace91424764
--- /dev/null
+++ b/source/blender/blenkernel/intern/simulation.cc
@@ -0,0 +1,110 @@
+/*
+ * 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.
+ */
+
+/** \file
+ * \ingroup bke
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_ID.h"
+#include "DNA_defaults.h"
+#include "DNA_simulation_types.h"
+
+#include "BLI_compiler_compat.h"
+#include "BLI_listbase.h"
+#include "BLI_math.h"
+#include "BLI_string.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_anim_data.h"
+#include "BKE_animsys.h"
+#include "BKE_idtype.h"
+#include "BKE_lib_id.h"
+#include "BKE_lib_query.h"
+#include "BKE_lib_remap.h"
+#include "BKE_main.h"
+#include "BKE_node.h"
+#include "BKE_simulation.h"
+
+#include "NOD_simulation.h"
+
+#include "BLT_translation.h"
+
+static void simulation_init_data(ID *id)
+{
+ Simulation *simulation = (Simulation *)id;
+ BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(simulation, id));
+
+ MEMCPY_STRUCT_AFTER(simulation, DNA_struct_default_get(Simulation), id);
+
+ bNodeTree *ntree = ntreeAddTree(nullptr, "Simulation Nodetree", ntreeType_Simulation->idname);
+ simulation->nodetree = ntree;
+}
+
+static void simulation_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int flag)
+{
+ Simulation *simulation_dst = (Simulation *)id_dst;
+ Simulation *simulation_src = (Simulation *)id_src;
+
+ /* We always need allocation of our private ID data. */
+ const int flag_private_id_data = flag & ~LIB_ID_CREATE_NO_ALLOCATE;
+
+ if (simulation_src->nodetree) {
+ BKE_id_copy_ex(bmain,
+ (ID *)simulation_src->nodetree,
+ (ID **)&simulation_dst->nodetree,
+ flag_private_id_data);
+ }
+}
+
+static void simulation_free_data(ID *id)
+{
+ Simulation *simulation = (Simulation *)id;
+
+ BKE_animdata_free(&simulation->id, false);
+
+ if (simulation->nodetree) {
+ ntreeFreeEmbeddedTree(simulation->nodetree);
+ MEM_freeN(simulation->nodetree);
+ simulation->nodetree = nullptr;
+ }
+}
+
+void *BKE_simulation_add(Main *bmain, const char *name)
+{
+ Simulation *simulation = (Simulation *)BKE_libblock_alloc(bmain, ID_SIM, name, 0);
+
+ simulation_init_data(&simulation->id);
+
+ return simulation;
+}
+
+IDTypeInfo IDType_ID_SIM = {
+ /* id_code */ ID_SIM,
+ /* id_filter */ FILTER_ID_SIM,
+ /* main_listbase_index */ INDEX_ID_SIM,
+ /* struct_size */ sizeof(Simulation),
+ /* name */ "Simulation",
+ /* name_plural */ "simulations",
+ /* translation_context */ BLT_I18NCONTEXT_ID_SIMULATION,
+ /* flags */ 0,
+
+ /* init_data */ simulation_init_data,
+ /* copy_data */ simulation_copy_data,
+ /* free_data */ simulation_free_data,
+ /* make_local */ nullptr,
+};
diff --git a/source/blender/blenkernel/intern/subdiv_ccg.c b/source/blender/blenkernel/intern/subdiv_ccg.c
index 521aeb60e66..d99c41eaa3e 100644
--- a/source/blender/blenkernel/intern/subdiv_ccg.c
+++ b/source/blender/blenkernel/intern/subdiv_ccg.c
@@ -770,8 +770,8 @@ static void subdiv_ccg_recalc_inner_normal_task(void *__restrict userdata_v,
subdiv_ccg_average_inner_face_normals(data->subdiv_ccg, data->key, tls, grid_index);
}
-static void subdiv_ccg_recalc_inner_normal_finalize(void *__restrict UNUSED(userdata),
- void *__restrict tls_v)
+static void subdiv_ccg_recalc_inner_normal_free(const void *__restrict UNUSED(userdata),
+ void *__restrict tls_v)
{
RecalcInnerNormalsTLSData *tls = tls_v;
MEM_SAFE_FREE(tls->face_normals);
@@ -791,7 +791,7 @@ static void subdiv_ccg_recalc_inner_grid_normals(SubdivCCG *subdiv_ccg)
BLI_parallel_range_settings_defaults(&parallel_range_settings);
parallel_range_settings.userdata_chunk = &tls_data;
parallel_range_settings.userdata_chunk_size = sizeof(tls_data);
- parallel_range_settings.func_finalize = subdiv_ccg_recalc_inner_normal_finalize;
+ parallel_range_settings.func_free = subdiv_ccg_recalc_inner_normal_free;
BLI_task_parallel_range(0,
subdiv_ccg->num_grids,
&data,
@@ -834,8 +834,8 @@ static void subdiv_ccg_recalc_modified_inner_normal_task(void *__restrict userda
subdiv_ccg_average_inner_face_grids(subdiv_ccg, key, face);
}
-static void subdiv_ccg_recalc_modified_inner_normal_finalize(void *__restrict UNUSED(userdata),
- void *__restrict tls_v)
+static void subdiv_ccg_recalc_modified_inner_normal_free(const void *__restrict UNUSED(userdata),
+ void *__restrict tls_v)
{
RecalcInnerNormalsTLSData *tls = tls_v;
MEM_SAFE_FREE(tls->face_normals);
@@ -857,7 +857,7 @@ static void subdiv_ccg_recalc_modified_inner_grid_normals(SubdivCCG *subdiv_ccg,
BLI_parallel_range_settings_defaults(&parallel_range_settings);
parallel_range_settings.userdata_chunk = &tls_data;
parallel_range_settings.userdata_chunk_size = sizeof(tls_data);
- parallel_range_settings.func_finalize = subdiv_ccg_recalc_modified_inner_normal_finalize;
+ parallel_range_settings.func_free = subdiv_ccg_recalc_modified_inner_normal_free;
BLI_task_parallel_range(0,
num_effected_faces,
&data,
@@ -1077,8 +1077,8 @@ static void subdiv_ccg_average_grids_boundaries_task(void *__restrict userdata_v
subdiv_ccg_average_grids_boundary(subdiv_ccg, key, adjacent_edge, tls);
}
-static void subdiv_ccg_average_grids_boundaries_finalize(void *__restrict UNUSED(userdata),
- void *__restrict tls_v)
+static void subdiv_ccg_average_grids_boundaries_free(const void *__restrict UNUSED(userdata),
+ void *__restrict tls_v)
{
AverageGridsBoundariesTLSData *tls = tls_v;
MEM_SAFE_FREE(tls->accumulators);
@@ -1136,7 +1136,7 @@ static void subdiv_ccg_average_all_boundaries(SubdivCCG *subdiv_ccg, CCGKey *key
AverageGridsBoundariesTLSData tls_data = {NULL};
parallel_range_settings.userdata_chunk = &tls_data;
parallel_range_settings.userdata_chunk_size = sizeof(tls_data);
- parallel_range_settings.func_finalize = subdiv_ccg_average_grids_boundaries_finalize;
+ parallel_range_settings.func_free = subdiv_ccg_average_grids_boundaries_free;
BLI_task_parallel_range(0,
subdiv_ccg->num_adjacent_edges,
&boundaries_data,
diff --git a/source/blender/blenkernel/intern/subdiv_foreach.c b/source/blender/blenkernel/intern/subdiv_foreach.c
index b31fb2c9312..0884f40952f 100644
--- a/source/blender/blenkernel/intern/subdiv_foreach.c
+++ b/source/blender/blenkernel/intern/subdiv_foreach.c
@@ -1838,9 +1838,9 @@ static void subdiv_foreach_boundary_edges_task(void *__restrict userdata,
subdiv_foreach_boundary_edges(ctx, tls->userdata_chunk, edge_index);
}
-static void subdiv_foreach_finalize(void *__restrict userdata, void *__restrict userdata_chunk)
+static void subdiv_foreach_free(const void *__restrict userdata, void *__restrict userdata_chunk)
{
- SubdivForeachTaskContext *ctx = userdata;
+ const SubdivForeachTaskContext *ctx = userdata;
ctx->foreach_context->user_data_tls_free(userdata_chunk);
}
@@ -1873,7 +1873,7 @@ bool BKE_subdiv_foreach_subdiv_geometry(Subdiv *subdiv,
parallel_range_settings.userdata_chunk_size = context->user_data_tls_size;
parallel_range_settings.min_iter_per_thread = 1;
if (context->user_data_tls_free != NULL) {
- parallel_range_settings.func_finalize = subdiv_foreach_finalize;
+ parallel_range_settings.func_free = subdiv_foreach_free;
}
/* TODO(sergey): Possible optimization is to have a single pool and push all
diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c
index fe10861f96e..0abee335036 100644
--- a/source/blender/blenkernel/intern/texture.c
+++ b/source/blender/blenkernel/intern/texture.c
@@ -112,7 +112,7 @@ static void texture_free_data(ID *id)
/* is no lib link block, but texture extension */
if (texture->nodetree) {
- ntreeFreeNestedTree(texture->nodetree);
+ ntreeFreeEmbeddedTree(texture->nodetree);
MEM_freeN(texture->nodetree);
texture->nodetree = NULL;
}
diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c
index 0204667b3bd..97d95cb7e46 100644
--- a/source/blender/blenkernel/intern/tracking.c
+++ b/source/blender/blenkernel/intern/tracking.c
@@ -2288,13 +2288,15 @@ void BKE_tracking_distortion_free(MovieDistortion *distortion)
MEM_freeN(distortion);
}
-void BKE_tracking_distort_v2(MovieTracking *tracking, const float co[2], float r_co[2])
+void BKE_tracking_distort_v2(
+ MovieTracking *tracking, int image_width, int image_height, const float co[2], float r_co[2])
{
const MovieTrackingCamera *camera = &tracking->camera;
const float aspy = 1.0f / tracking->camera.pixel_aspect;
libmv_CameraIntrinsicsOptions camera_intrinsics_options;
- tracking_cameraIntrinscisOptionsFromTracking(tracking, 0, 0, &camera_intrinsics_options);
+ tracking_cameraIntrinscisOptionsFromTracking(
+ tracking, image_width, image_height, &camera_intrinsics_options);
libmv_CameraIntrinsics *intrinsics = libmv_cameraIntrinsicsNew(&camera_intrinsics_options);
/* Normalize coordinates. */
@@ -2309,13 +2311,15 @@ void BKE_tracking_distort_v2(MovieTracking *tracking, const float co[2], float r
r_co[1] = y;
}
-void BKE_tracking_undistort_v2(MovieTracking *tracking, const float co[2], float r_co[2])
+void BKE_tracking_undistort_v2(
+ MovieTracking *tracking, int image_width, int image_height, const float co[2], float r_co[2])
{
const MovieTrackingCamera *camera = &tracking->camera;
const float aspy = 1.0f / tracking->camera.pixel_aspect;
libmv_CameraIntrinsicsOptions camera_intrinsics_options;
- tracking_cameraIntrinscisOptionsFromTracking(tracking, 0, 0, &camera_intrinsics_options);
+ tracking_cameraIntrinscisOptionsFromTracking(
+ tracking, image_width, image_height, &camera_intrinsics_options);
libmv_CameraIntrinsics *intrinsics = libmv_cameraIntrinsicsNew(&camera_intrinsics_options);
double x = co[0], y = co[1];
@@ -2361,13 +2365,19 @@ ImBuf *BKE_tracking_distort_frame(MovieTracking *tracking,
}
void BKE_tracking_max_distortion_delta_across_bound(MovieTracking *tracking,
+ int image_width,
+ int image_height,
rcti *rect,
bool undistort,
float delta[2])
{
float pos[2], warped_pos[2];
const int coord_delta = 5;
- void (*apply_distortion)(MovieTracking * tracking, const float pos[2], float out[2]);
+ void (*apply_distortion)(MovieTracking * tracking,
+ int image_width,
+ int image_height,
+ const float pos[2],
+ float out[2]);
if (undistort) {
apply_distortion = BKE_tracking_undistort_v2;
@@ -2387,7 +2397,7 @@ void BKE_tracking_max_distortion_delta_across_bound(MovieTracking *tracking,
pos[0] = a;
pos[1] = rect->ymin;
- apply_distortion(tracking, pos, warped_pos);
+ apply_distortion(tracking, image_width, image_height, pos, warped_pos);
delta[0] = max_ff(delta[0], fabsf(pos[0] - warped_pos[0]));
delta[1] = max_ff(delta[1], fabsf(pos[1] - warped_pos[1]));
@@ -2396,7 +2406,7 @@ void BKE_tracking_max_distortion_delta_across_bound(MovieTracking *tracking,
pos[0] = a;
pos[1] = rect->ymax;
- apply_distortion(tracking, pos, warped_pos);
+ apply_distortion(tracking, image_width, image_height, pos, warped_pos);
delta[0] = max_ff(delta[0], fabsf(pos[0] - warped_pos[0]));
delta[1] = max_ff(delta[1], fabsf(pos[1] - warped_pos[1]));
@@ -2415,7 +2425,7 @@ void BKE_tracking_max_distortion_delta_across_bound(MovieTracking *tracking,
pos[0] = rect->xmin;
pos[1] = a;
- apply_distortion(tracking, pos, warped_pos);
+ apply_distortion(tracking, image_width, image_height, pos, warped_pos);
delta[0] = max_ff(delta[0], fabsf(pos[0] - warped_pos[0]));
delta[1] = max_ff(delta[1], fabsf(pos[1] - warped_pos[1]));
@@ -2424,7 +2434,7 @@ void BKE_tracking_max_distortion_delta_across_bound(MovieTracking *tracking,
pos[0] = rect->xmax;
pos[1] = a;
- apply_distortion(tracking, pos, warped_pos);
+ apply_distortion(tracking, image_width, image_height, pos, warped_pos);
delta[0] = max_ff(delta[0], fabsf(pos[0] - warped_pos[0]));
delta[1] = max_ff(delta[1], fabsf(pos[1] - warped_pos[1]));
diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c
index f2219ad1cf8..3be62750673 100644
--- a/source/blender/blenkernel/intern/world.c
+++ b/source/blender/blenkernel/intern/world.c
@@ -59,7 +59,7 @@ static void world_free_data(ID *id)
/* is no lib link block, but world extension */
if (wrld->nodetree) {
- ntreeFreeNestedTree(wrld->nodetree);
+ ntreeFreeEmbeddedTree(wrld->nodetree);
MEM_freeN(wrld->nodetree);
wrld->nodetree = NULL;
}
diff --git a/source/blender/blenlib/BLI_allocator.h b/source/blender/blenlib/BLI_allocator.hh
index e2d39c4e897..c52db4aab53 100644
--- a/source/blender/blenlib/BLI_allocator.h
+++ b/source/blender/blenlib/BLI_allocator.hh
@@ -13,8 +13,8 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#ifndef __BLI_ALLOCATOR_H__
-#define __BLI_ALLOCATOR_H__
+#ifndef __BLI_ALLOCATOR_HH__
+#define __BLI_ALLOCATOR_HH__
/** \file
* \ingroup bli
@@ -102,4 +102,4 @@ class RawAllocator {
} // namespace BLI
-#endif /* __BLI_ALLOCATOR_H__ */
+#endif /* __BLI_ALLOCATOR_HH__ */
diff --git a/source/blender/blenlib/BLI_array_cxx.h b/source/blender/blenlib/BLI_array.hh
index 8fc2aec6698..c6536f6c1ed 100644
--- a/source/blender/blenlib/BLI_array_cxx.h
+++ b/source/blender/blenlib/BLI_array.hh
@@ -13,8 +13,8 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#ifndef __BLI_ARRAY_CXX_H__
-#define __BLI_ARRAY_CXX_H__
+#ifndef __BLI_ARRAY_HH__
+#define __BLI_ARRAY_HH__
/** \file
* \ingroup bli
@@ -23,10 +23,10 @@
* a template argument. Instead it can be specified at the construction time.
*/
-#include "BLI_allocator.h"
-#include "BLI_array_ref.h"
-#include "BLI_index_range.h"
-#include "BLI_memory_utils_cxx.h"
+#include "BLI_allocator.hh"
+#include "BLI_array_ref.hh"
+#include "BLI_index_range.hh"
+#include "BLI_memory_utils.hh"
#include "BLI_utildefines.h"
namespace BLI {
@@ -231,4 +231,4 @@ template<typename T, uint N = 4, typename Allocator = GuardedAllocator> class Ar
} // namespace BLI
-#endif /* __BLI_ARRAY_CXX_H__ */
+#endif /* __BLI_ARRAY_HH__ */
diff --git a/source/blender/blenlib/BLI_array_ref.h b/source/blender/blenlib/BLI_array_ref.hh
index 2c2e441a47d..dd9421d289c 100644
--- a/source/blender/blenlib/BLI_array_ref.h
+++ b/source/blender/blenlib/BLI_array_ref.hh
@@ -14,8 +14,8 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#ifndef __BLI_ARRAY_REF_H__
-#define __BLI_ARRAY_REF_H__
+#ifndef __BLI_ARRAY_REF_HH__
+#define __BLI_ARRAY_REF_HH__
/** \file
* \ingroup bli
@@ -41,8 +41,8 @@
#include <string>
#include <vector>
-#include "BLI_index_range.h"
-#include "BLI_memory_utils_cxx.h"
+#include "BLI_index_range.hh"
+#include "BLI_memory_utils.hh"
#include "BLI_utildefines.h"
namespace BLI {
@@ -542,4 +542,4 @@ void assert_same_size(const T1 &v1, const T2 &v2, const T3 &v3)
} /* namespace BLI */
-#endif /* __BLI_ARRAY_REF_H__ */
+#endif /* __BLI_ARRAY_REF_HH__ */
diff --git a/source/blender/blenlib/BLI_color.hh b/source/blender/blenlib/BLI_color.hh
new file mode 100644
index 00000000000..ff28ae2c076
--- /dev/null
+++ b/source/blender/blenlib/BLI_color.hh
@@ -0,0 +1,92 @@
+/*
+ * 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.
+ */
+
+#ifndef __BLI_COLOR_HH__
+#define __BLI_COLOR_HH__
+
+#include <iostream>
+
+#include "BLI_math_color.h"
+
+namespace BLI {
+
+struct Color4f {
+ float r, g, b, a;
+
+ Color4f() = default;
+
+ Color4f(float r, float g, float b, float a) : r(r), g(g), b(b), a(a)
+ {
+ }
+
+ operator float *()
+ {
+ return &r;
+ }
+
+ operator const float *() const
+ {
+ return &r;
+ }
+
+ friend std::ostream &operator<<(std::ostream &stream, Color4f c)
+ {
+ stream << "(" << c.r << ", " << c.g << ", " << c.b << ", " << c.a << ")";
+ return stream;
+ }
+};
+
+struct Color4b {
+ uint8_t r, g, b, a;
+
+ Color4b() = default;
+
+ Color4b(uint8_t r, uint8_t g, uint8_t b, uint8_t a) : r(r), g(g), b(b), a(a)
+ {
+ }
+
+ Color4b(Color4f other)
+ {
+ rgba_float_to_uchar(*this, other);
+ }
+
+ operator Color4f() const
+ {
+ Color4f result;
+ rgba_uchar_to_float(result, *this);
+ return result;
+ }
+
+ operator uint8_t *()
+ {
+ return &r;
+ }
+
+ operator const uint8_t *() const
+ {
+ return &r;
+ }
+
+ friend std::ostream &operator<<(std::ostream &stream, Color4b c)
+ {
+ stream << "(" << c.r << ", " << c.g << ", " << c.b << ", " << c.a << ")";
+ return stream;
+ }
+};
+
+} // namespace BLI
+
+#endif /* __BLI_COLOR_HH__ */
diff --git a/source/blender/blenlib/BLI_float2.hh b/source/blender/blenlib/BLI_float2.hh
new file mode 100644
index 00000000000..da12dd7d206
--- /dev/null
+++ b/source/blender/blenlib/BLI_float2.hh
@@ -0,0 +1,86 @@
+/*
+ * 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.
+ */
+
+#ifndef __BLI_FLOAT2_HH__
+#define __BLI_FLOAT2_HH__
+
+#include "BLI_float3.hh"
+
+namespace BLI {
+
+struct float2 {
+ float x, y;
+
+ float2() = default;
+
+ float2(const float *ptr) : x{ptr[0]}, y{ptr[1]}
+ {
+ }
+
+ float2(float x, float y) : x(x), y(y)
+ {
+ }
+
+ float2(const float3 &other) : x(other.x), y(other.y)
+ {
+ }
+
+ operator float *()
+ {
+ return &x;
+ }
+
+ operator const float *() const
+ {
+ return &x;
+ }
+
+ friend float2 operator+(const float2 &a, const float2 &b)
+ {
+ return {a.x + b.x, a.y + b.y};
+ }
+
+ friend float2 operator-(const float2 &a, const float2 &b)
+ {
+ return {a.x - b.x, a.y - b.y};
+ }
+
+ friend float2 operator*(const float2 &a, float b)
+ {
+ return {a.x * b, a.y * b};
+ }
+
+ friend float2 operator/(const float2 &a, float b)
+ {
+ BLI_assert(b != 0.0f);
+ return {a.x / b, a.y / b};
+ }
+
+ friend float2 operator*(float a, const float2 &b)
+ {
+ return b * a;
+ }
+
+ friend std::ostream &operator<<(std::ostream &stream, const float2 &v)
+ {
+ stream << "(" << v.x << ", " << v.y << ")";
+ return stream;
+ }
+};
+
+} // namespace BLI
+
+#endif /* __BLI_FLOAT2_HH__ */
diff --git a/source/blender/blenlib/BLI_float3.hh b/source/blender/blenlib/BLI_float3.hh
new file mode 100644
index 00000000000..9678fa4b2d3
--- /dev/null
+++ b/source/blender/blenlib/BLI_float3.hh
@@ -0,0 +1,218 @@
+/*
+ * 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.
+ */
+
+#ifndef __BLI_FLOAT3_HH__
+#define __BLI_FLOAT3_HH__
+
+#include <iostream>
+
+#include "BLI_math_vector.h"
+
+namespace BLI {
+
+struct float3 {
+ float x, y, z;
+
+ float3() = default;
+
+ float3(const float *ptr) : x{ptr[0]}, y{ptr[1]}, z{ptr[2]}
+ {
+ }
+
+ float3(const float (*ptr)[3]) : float3((const float *)ptr)
+ {
+ }
+
+ explicit float3(float value) : x(value), y(value), z(value)
+ {
+ }
+
+ explicit float3(int value) : x(value), y(value), z(value)
+ {
+ }
+
+ float3(float x, float y, float z) : x{x}, y{y}, z{z}
+ {
+ }
+
+ operator const float *() const
+ {
+ return &x;
+ }
+
+ operator float *()
+ {
+ return &x;
+ }
+
+ float normalize_and_get_length()
+ {
+ return normalize_v3(*this);
+ }
+
+ float3 normalized() const
+ {
+ float3 result;
+ normalize_v3_v3(result, *this);
+ return result;
+ }
+
+ float length() const
+ {
+ return len_v3(*this);
+ }
+
+ float length_squared() const
+ {
+ return len_squared_v3(*this);
+ }
+
+ void reflect(const float3 &normal)
+ {
+ *this = this->reflected(normal);
+ }
+
+ float3 reflected(const float3 &normal) const
+ {
+ float3 result;
+ reflect_v3_v3v3(result, *this, normal);
+ return result;
+ }
+
+ static float3 safe_divide(const float3 &a, const float3 &b)
+ {
+ float3 result;
+ result.x = (b.x == 0.0f) ? 0.0f : a.x / b.x;
+ result.y = (b.y == 0.0f) ? 0.0f : a.y / b.y;
+ result.z = (b.z == 0.0f) ? 0.0f : a.z / b.z;
+ return result;
+ }
+
+ void invert()
+ {
+ x = -x;
+ y = -y;
+ z = -z;
+ }
+
+ friend float3 operator+(const float3 &a, const float3 &b)
+ {
+ return {a.x + b.x, a.y + b.y, a.z + b.z};
+ }
+
+ void operator+=(const float3 &b)
+ {
+ this->x += b.x;
+ this->y += b.y;
+ this->z += b.z;
+ }
+
+ friend float3 operator-(const float3 &a, const float3 &b)
+ {
+ return {a.x - b.x, a.y - b.y, a.z - b.z};
+ }
+
+ friend float3 operator-(const float3 &a)
+ {
+ return {-a.x, -a.y, -a.z};
+ }
+
+ void operator-=(const float3 &b)
+ {
+ this->x -= b.x;
+ this->y -= b.y;
+ this->z -= b.z;
+ }
+
+ void operator*=(float scalar)
+ {
+ this->x *= scalar;
+ this->y *= scalar;
+ this->z *= scalar;
+ }
+
+ void operator*=(const float3 &other)
+ {
+ this->x *= other.x;
+ this->y *= other.y;
+ this->z *= other.z;
+ }
+
+ friend float3 operator*(const float3 &a, const float3 &b)
+ {
+ return {a.x * b.x, a.y * b.y, a.z * b.z};
+ }
+
+ friend float3 operator*(const float3 &a, float b)
+ {
+ return {a.x * b, a.y * b, a.z * b};
+ }
+
+ friend float3 operator*(float a, const float3 &b)
+ {
+ return b * a;
+ }
+
+ friend float3 operator/(const float3 &a, float b)
+ {
+ BLI_assert(b != 0.0f);
+ return {a.x / b, a.y / b, a.z / b};
+ }
+
+ friend std::ostream &operator<<(std::ostream &stream, const float3 &v)
+ {
+ stream << "(" << v.x << ", " << v.y << ", " << v.z << ")";
+ return stream;
+ }
+
+ static float dot(const float3 &a, const float3 &b)
+ {
+ return a.x * b.x + a.y * b.y + a.z * b.z;
+ }
+
+ static float3 cross_high_precision(const float3 &a, const float3 &b)
+ {
+ float3 result;
+ cross_v3_v3v3_hi_prec(result, a, b);
+ return result;
+ }
+
+ static float3 project(const float3 &a, const float3 &b)
+ {
+ float3 result;
+ project_v3_v3v3(result, a, b);
+ return result;
+ }
+
+ static float distance(const float3 &a, const float3 &b)
+ {
+ return (a - b).length();
+ }
+
+ static float distance_squared(const float3 &a, const float3 &b)
+ {
+ return float3::dot(a, b);
+ }
+
+ static float3 interpolate(const float3 &a, const float3 &b, float t)
+ {
+ return a * (1 - t) + b * t;
+ }
+};
+
+} // namespace BLI
+
+#endif /* __BLI_FLOAT3_HH__ */
diff --git a/source/blender/blenlib/BLI_float4x4.hh b/source/blender/blenlib/BLI_float4x4.hh
new file mode 100644
index 00000000000..36186d319c9
--- /dev/null
+++ b/source/blender/blenlib/BLI_float4x4.hh
@@ -0,0 +1,115 @@
+/*
+ * 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.
+ */
+
+#ifndef __BLI_FLOAT4X4_HH__
+#define __BLI_FLOAT4X4_HH__
+
+#include "BLI_float3.hh"
+#include "BLI_math_matrix.h"
+
+namespace BLI {
+
+struct float4x4 {
+ float values[4][4];
+
+ float4x4() = default;
+
+ float4x4(const float *matrix)
+ {
+ memcpy(values, matrix, sizeof(float) * 16);
+ }
+
+ float4x4(const float matrix[4][4]) : float4x4((float *)matrix)
+ {
+ }
+
+ operator float *()
+ {
+ return (float *)this;
+ }
+
+ operator const float *() const
+ {
+ return (const float *)this;
+ }
+
+ float4x4 inverted() const
+ {
+ float result[4][4];
+ invert_m4_m4(result, values);
+ return result;
+ }
+
+ /**
+ * Matrix inversion can be implemented more efficiently for affine matrices.
+ */
+ float4x4 inverted_affine() const
+ {
+ BLI_assert(values[0][3] == 0.0f && values[1][3] == 0.0f && values[2][3] == 0.0f &&
+ values[3][3] == 1.0f);
+ return this->inverted();
+ }
+
+ friend float4x4 operator*(const float4x4 &a, const float4x4 &b)
+ {
+ float4x4 result;
+ mul_m4_m4m4(result.values, a.values, b.values);
+ return result;
+ }
+
+ /**
+ * This also applies the translation on the vector. Use `m.ref_3x3() * v` if that is not
+ * intended.
+ */
+ friend float3 operator*(const float4x4 &m, const float3 &v)
+ {
+ float3 result;
+ mul_v3_m4v3(result, m.values, v);
+ return result;
+ }
+
+ friend float3 operator*(const float4x4 &m, const float (*v)[3])
+ {
+ return m * float3(v);
+ }
+
+ struct float3x3_ref {
+ const float4x4 &data;
+
+ friend float3 operator*(const float3x3_ref &m, const float3 &v)
+ {
+ float3 result;
+ mul_v3_mat3_m4v3(result, m.data.values, v);
+ return result;
+ }
+ };
+
+ float3x3_ref ref_3x3() const
+ {
+ return {*this};
+ }
+
+ static float4x4 interpolate(const float4x4 &a, const float4x4 &b, float t)
+ {
+ float result[4][4];
+ interp_m4_m4m4(result, a.values, b.values, t);
+ return result;
+ }
+};
+
+} // namespace BLI
+
+#endif /* __BLI_FLOAT4X4_HH__ */
diff --git a/source/blender/blenlib/BLI_hash.h b/source/blender/blenlib/BLI_hash.h
index d09291b64be..3871ddf956a 100644
--- a/source/blender/blenlib/BLI_hash.h
+++ b/source/blender/blenlib/BLI_hash.h
@@ -81,7 +81,7 @@ BLI_INLINE void BLI_hash_pointer_to_color(const void *ptr, int *r, int *g, int *
{
size_t val = (size_t)ptr;
const size_t hash_a = BLI_hash_int(val & 0x0000ffff);
- const size_t hash_b = BLI_hash_int((uint)((val & 0xffff0000) >> 32));
+ const size_t hash_b = BLI_hash_int((uint)((val & 0xffff0000) >> 16));
const size_t hash = hash_a ^ (hash_b + 0x9e3779b9 + (hash_a << 6) + (hash_a >> 2));
*r = (hash & 0xff0000) >> 16;
*g = (hash & 0x00ff00) >> 8;
diff --git a/source/blender/blenlib/BLI_hash_cxx.h b/source/blender/blenlib/BLI_hash.hh
index 22941a792ba..b5041012189 100644
--- a/source/blender/blenlib/BLI_hash_cxx.h
+++ b/source/blender/blenlib/BLI_hash.hh
@@ -14,8 +14,8 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#ifndef __BLI_HASH_CXX_H__
-#define __BLI_HASH_CXX_H__
+#ifndef __BLI_HASH_HH__
+#define __BLI_HASH_HH__
/** \file
* \ingroup bli
@@ -109,4 +109,4 @@ template<typename T1, typename T2> struct DefaultHash<std::pair<T1, T2>> {
} // namespace BLI
-#endif /* __BLI_HASH_CXX_H__ */
+#endif /* __BLI_HASH_HH__ */
diff --git a/source/blender/blenlib/BLI_index_range.h b/source/blender/blenlib/BLI_index_range.hh
index 4553c996454..e24fd567810 100644
--- a/source/blender/blenlib/BLI_index_range.h
+++ b/source/blender/blenlib/BLI_index_range.hh
@@ -14,8 +14,8 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#ifndef __BLI_INDEX_RANGE_H__
-#define __BLI_INDEX_RANGE_H__
+#ifndef __BLI_INDEX_RANGE_HH__
+#define __BLI_INDEX_RANGE_HH__
/** \file
* \ingroup bli
@@ -208,4 +208,4 @@ class IndexRange {
} // namespace BLI
-#endif /* __BLI_INDEX_RANGE_H__ */
+#endif /* __BLI_INDEX_RANGE_HH__ */
diff --git a/source/blender/blenlib/BLI_listbase_wrapper.h b/source/blender/blenlib/BLI_listbase_wrapper.hh
index d6832166e35..02313d9d22d 100644
--- a/source/blender/blenlib/BLI_listbase_wrapper.h
+++ b/source/blender/blenlib/BLI_listbase_wrapper.hh
@@ -14,8 +14,8 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#ifndef __BLI_LISTBASE_WRAPPER_H__
-#define __BLI_LISTBASE_WRAPPER_H__
+#ifndef __BLI_LISTBASE_WRAPPER_HH__
+#define __BLI_LISTBASE_WRAPPER_HH__
/** \file
* \ingroup bli
@@ -29,17 +29,17 @@
namespace BLI {
-template<typename T> class IntrusiveListBaseWrapper {
+template<typename T> class ListBaseWrapper {
private:
ListBase *m_listbase;
public:
- IntrusiveListBaseWrapper(ListBase *listbase) : m_listbase(listbase)
+ ListBaseWrapper(ListBase *listbase) : m_listbase(listbase)
{
BLI_assert(listbase);
}
- IntrusiveListBaseWrapper(ListBase &listbase) : IntrusiveListBaseWrapper(&listbase)
+ ListBaseWrapper(ListBase &listbase) : ListBaseWrapper(&listbase)
{
}
@@ -110,4 +110,4 @@ template<typename T> class IntrusiveListBaseWrapper {
} /* namespace BLI */
-#endif /* __BLI_LISTBASE_WRAPPER_H__ */
+#endif /* __BLI_LISTBASE_WRAPPER_HH__ */
diff --git a/source/blender/blenlib/BLI_map.h b/source/blender/blenlib/BLI_map.hh
index 4b7ac0791d9..626c971c959 100644
--- a/source/blender/blenlib/BLI_map.h
+++ b/source/blender/blenlib/BLI_map.hh
@@ -14,8 +14,8 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#ifndef __BLI_MAP_H__
-#define __BLI_MAP_H__
+#ifndef __BLI_MAP_HH__
+#define __BLI_MAP_HH__
/** \file
* \ingroup bli
@@ -26,9 +26,9 @@
* lookups. Keys and values are stored in groups of four to avoid wasting memory due to padding.
*/
-#include "BLI_array_ref.h"
-#include "BLI_hash_cxx.h"
-#include "BLI_open_addressing.h"
+#include "BLI_array_ref.hh"
+#include "BLI_hash.hh"
+#include "BLI_open_addressing.hh"
namespace BLI {
@@ -733,4 +733,4 @@ template<typename KeyT, typename ValueT, typename Allocator = GuardedAllocator>
} // namespace BLI
-#endif /* __BLI_MAP_H__ */
+#endif /* __BLI_MAP_HH__ */
diff --git a/source/blender/blenlib/BLI_memory_utils_cxx.h b/source/blender/blenlib/BLI_memory_utils.hh
index 6534138315d..d9acf08a43f 100644
--- a/source/blender/blenlib/BLI_memory_utils_cxx.h
+++ b/source/blender/blenlib/BLI_memory_utils.hh
@@ -14,8 +14,8 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#ifndef __BLI_MEMORY_UTILS_CXX_H__
-#define __BLI_MEMORY_UTILS_CXX_H__
+#ifndef __BLI_MEMORY_UTILS_HH__
+#define __BLI_MEMORY_UTILS_HH__
/** \file
* \ingroup bli
@@ -120,4 +120,4 @@ template<uint Size, uint Alignment> class alignas(Alignment) AlignedBuffer {
} // namespace BLI
-#endif /* __BLI_MEMORY_UTILS_CXX_H__ */
+#endif /* __BLI_MEMORY_UTILS_HH__ */
diff --git a/source/blender/blenlib/BLI_open_addressing.h b/source/blender/blenlib/BLI_open_addressing.hh
index 6a0acd418eb..fa2ea6d8f94 100644
--- a/source/blender/blenlib/BLI_open_addressing.h
+++ b/source/blender/blenlib/BLI_open_addressing.hh
@@ -14,8 +14,8 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#ifndef __BLI_OPEN_ADDRESSING_H__
-#define __BLI_OPEN_ADDRESSING_H__
+#ifndef __BLI_OPEN_ADDRESSING_HH__
+#define __BLI_OPEN_ADDRESSING_HH__
/** \file
* \ingroup bli
@@ -33,9 +33,9 @@
#include <cmath>
-#include "BLI_allocator.h"
+#include "BLI_allocator.hh"
#include "BLI_math_base.h"
-#include "BLI_memory_utils_cxx.h"
+#include "BLI_memory_utils.hh"
#include "BLI_utildefines.h"
namespace BLI {
@@ -302,4 +302,4 @@ class OpenAddressingArray {
} // namespace BLI
-#endif /* __BLI_OPEN_ADDRESSING_H__ */
+#endif /* __BLI_OPEN_ADDRESSING_HH__ */
diff --git a/source/blender/blenlib/BLI_optional.h b/source/blender/blenlib/BLI_optional.hh
index 267c858e0f2..eac11293781 100644
--- a/source/blender/blenlib/BLI_optional.h
+++ b/source/blender/blenlib/BLI_optional.hh
@@ -20,10 +20,10 @@
* Simple version of std::optional, which is only available since C++17.
*/
-#ifndef __BLI_OPTIONAL_H__
-#define __BLI_OPTIONAL_H__
+#ifndef __BLI_OPTIONAL_HH__
+#define __BLI_OPTIONAL_HH__
-#include "BLI_memory_utils_cxx.h"
+#include "BLI_memory_utils.hh"
#include "BLI_utildefines.h"
#include <algorithm>
@@ -196,4 +196,4 @@ template<typename T> class Optional {
} /* namespace BLI */
-#endif /* __BLI_OPTIONAL_H__ */
+#endif /* __BLI_OPTIONAL_HH__ */
diff --git a/source/blender/blenlib/BLI_set.h b/source/blender/blenlib/BLI_set.hh
index dc101add1a7..2ef92bf1c48 100644
--- a/source/blender/blenlib/BLI_set.h
+++ b/source/blender/blenlib/BLI_set.hh
@@ -14,8 +14,8 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#ifndef __BLI_SET_H__
-#define __BLI_SET_H__
+#ifndef __BLI_SET_HH__
+#define __BLI_SET_HH__
/** \file
* \ingroup bli
@@ -23,9 +23,9 @@
* This file provides a set implementation that uses open addressing with probing.
*/
-#include "BLI_hash_cxx.h"
-#include "BLI_open_addressing.h"
-#include "BLI_vector.h"
+#include "BLI_hash.hh"
+#include "BLI_open_addressing.hh"
+#include "BLI_vector.hh"
namespace BLI {
@@ -480,4 +480,4 @@ template<typename T, typename Allocator = GuardedAllocator> class Set {
} // namespace BLI
-#endif /* __BLI_SET_H__ */
+#endif /* __BLI_SET_HH__ */
diff --git a/source/blender/blenlib/BLI_stack_cxx.h b/source/blender/blenlib/BLI_stack.hh
index a26318a3dcb..a0e8cec3b6f 100644
--- a/source/blender/blenlib/BLI_stack_cxx.h
+++ b/source/blender/blenlib/BLI_stack.hh
@@ -14,8 +14,8 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#ifndef __BLI_STACK_CXX_H__
-#define __BLI_STACK_CXX_H__
+#ifndef __BLI_STACK_HH__
+#define __BLI_STACK_HH__
/** \file
* \ingroup bli
@@ -23,7 +23,7 @@
* Basic stack implementation with support for small object optimization.
*/
-#include "BLI_vector.h"
+#include "BLI_vector.hh"
namespace BLI {
@@ -147,4 +147,4 @@ template<typename T, uint N = 4, typename Allocator = GuardedAllocator> class St
} /* namespace BLI */
-#endif /* __BLI_STACK_CXX_H__ */
+#endif /* __BLI_STACK_HH__ */
diff --git a/source/blender/blenlib/BLI_string_map.h b/source/blender/blenlib/BLI_string_map.hh
index f304b140bcc..d47f57c8bcc 100644
--- a/source/blender/blenlib/BLI_string_map.h
+++ b/source/blender/blenlib/BLI_string_map.hh
@@ -14,8 +14,8 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#ifndef __BLI_STRING_MAP_H__
-#define __BLI_STRING_MAP_H__
+#ifndef __BLI_STRING_MAP_HH__
+#define __BLI_STRING_MAP_HH__
/** \file
* \ingroup bli
@@ -27,10 +27,10 @@
* make it more efficient later on. Also, even if we will never implement this optimization, having
* a special map with string keys can be quite handy. */
-#include "BLI_map.h"
-#include "BLI_optional.h"
-#include "BLI_string_ref.h"
-#include "BLI_vector.h"
+#include "BLI_map.hh"
+#include "BLI_optional.hh"
+#include "BLI_string_ref.hh"
+#include "BLI_vector.hh"
namespace BLI {
@@ -457,4 +457,4 @@ template<typename T, typename Allocator = GuardedAllocator> class StringMap {
} // namespace BLI
-#endif /* __BLI_STRING_MAP_H__ */
+#endif /* __BLI_STRING_MAP_HH__ */
diff --git a/source/blender/blenlib/BLI_string_ref.h b/source/blender/blenlib/BLI_string_ref.hh
index 2389542bcea..6c750a81e06 100644
--- a/source/blender/blenlib/BLI_string_ref.h
+++ b/source/blender/blenlib/BLI_string_ref.hh
@@ -14,8 +14,8 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#ifndef __BLI_STRING_REF_H__
-#define __BLI_STRING_REF_H__
+#ifndef __BLI_STRING_REF_HH__
+#define __BLI_STRING_REF_HH__
/** \file
* \ingroup bli
@@ -32,7 +32,7 @@
#include <sstream>
#include <string>
-#include "BLI_array_ref.h"
+#include "BLI_array_ref.hh"
#include "BLI_utildefines.h"
namespace BLI {
@@ -252,4 +252,4 @@ inline StringRef StringRefBase::substr(uint start, uint size) const
} // namespace BLI
-#endif /* __BLI_STRING_REF_H__ */
+#endif /* __BLI_STRING_REF_HH__ */
diff --git a/source/blender/blenlib/BLI_task.h b/source/blender/blenlib/BLI_task.h
index 898e4be5f92..2b5964d091c 100644
--- a/source/blender/blenlib/BLI_task.h
+++ b/source/blender/blenlib/BLI_task.h
@@ -71,7 +71,7 @@ typedef enum TaskPriority {
typedef struct TaskPool TaskPool;
typedef void (*TaskRunFunction)(TaskPool *__restrict pool, void *taskdata, int threadid);
-typedef void (*TaskFreeFunction)(TaskPool *__restrict pool, void *taskdata, int threadid);
+typedef void (*TaskFreeFunction)(TaskPool *__restrict pool, void *taskdata);
TaskPool *BLI_task_pool_create(TaskScheduler *scheduler, void *userdata, TaskPriority priority);
TaskPool *BLI_task_pool_create_background(TaskScheduler *scheduler,
@@ -105,7 +105,7 @@ void BLI_task_pool_cancel(TaskPool *pool);
bool BLI_task_pool_canceled(TaskPool *pool);
/* optional userdata pointer to pass along to run function */
-void *BLI_task_pool_userdata(TaskPool *pool);
+void *BLI_task_pool_user_data(TaskPool *pool);
/* optional mutex to use from run function */
ThreadMutex *BLI_task_pool_user_mutex(TaskPool *pool);
@@ -146,12 +146,14 @@ typedef struct TaskParallelTLS {
void *userdata_chunk;
} TaskParallelTLS;
-typedef void (*TaskParallelFinalizeFunc)(void *__restrict userdata,
- void *__restrict userdata_chunk);
-
typedef void (*TaskParallelRangeFunc)(void *__restrict userdata,
const int iter,
const TaskParallelTLS *__restrict tls);
+typedef void (*TaskParallelReduceFunc)(const void *__restrict userdata,
+ void *__restrict chunk_join,
+ void *__restrict chunk);
+
+typedef void (*TaskParallelFreeFunc)(const void *__restrict userdata, void *__restrict chunk);
typedef struct TaskParallelSettings {
/* Whether caller allows to do threading of the particular range.
@@ -171,7 +173,13 @@ typedef struct TaskParallelSettings {
/* Function called from calling thread once whole range have been
* processed.
*/
- TaskParallelFinalizeFunc func_finalize;
+ /* Function called to join user data chunk into another, to reduce
+ * the result to the original userdata_chunk memory.
+ * The reduce functions should have no side effects, so that they
+ * can be run on any thread. */
+ TaskParallelReduceFunc func_reduce;
+ /* Function called to free data created by TaskParallelRangeFunc. */
+ TaskParallelFreeFunc func_free;
/* Minimum allowed number of range iterators to be handled by a single
* thread. This allows to achieve following:
* - Reduce amount of threading overhead.
diff --git a/source/blender/blenlib/BLI_utility_mixins.h b/source/blender/blenlib/BLI_utility_mixins.hh
index ce7a4ce094a..441575f9111 100644
--- a/source/blender/blenlib/BLI_utility_mixins.h
+++ b/source/blender/blenlib/BLI_utility_mixins.hh
@@ -18,8 +18,8 @@
* \ingroup bli
*/
-#ifndef __BLI_UTILITY_MIXINS_H__
-#define __BLI_UTILITY_MIXINS_H__
+#ifndef __BLI_UTILITY_MIXINS_HH__
+#define __BLI_UTILITY_MIXINS_HH__
namespace BLI {
@@ -49,4 +49,4 @@ class NonMovable {
} // namespace BLI
-#endif /* __BLI_UTILITY_MIXINS_H__ */
+#endif /* __BLI_UTILITY_MIXINS_HH__ */
diff --git a/source/blender/blenlib/BLI_vector.h b/source/blender/blenlib/BLI_vector.hh
index 6a708759d0e..a44962e50cc 100644
--- a/source/blender/blenlib/BLI_vector.h
+++ b/source/blender/blenlib/BLI_vector.hh
@@ -14,8 +14,8 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#ifndef __BLI_VECTOR_H__
-#define __BLI_VECTOR_H__
+#ifndef __BLI_VECTOR_HH__
+#define __BLI_VECTOR_HH__
/** \file
* \ingroup bli
@@ -31,12 +31,12 @@
#include <iostream>
#include <memory>
-#include "BLI_allocator.h"
-#include "BLI_array_ref.h"
-#include "BLI_index_range.h"
-#include "BLI_listbase_wrapper.h"
+#include "BLI_allocator.hh"
+#include "BLI_array_ref.hh"
+#include "BLI_index_range.hh"
+#include "BLI_listbase_wrapper.hh"
#include "BLI_math_base.h"
-#include "BLI_memory_utils_cxx.h"
+#include "BLI_memory_utils.hh"
#include "BLI_utildefines.h"
#include "MEM_guardedalloc.h"
@@ -130,13 +130,10 @@ template<typename T, uint N = 4, typename Allocator = GuardedAllocator> class Ve
/**
* Create a vector from a ListBase.
*/
- Vector(ListBase &values, bool intrusive_next_and_prev_pointers) : Vector()
+ Vector(ListBase &values) : Vector()
{
- BLI_assert(intrusive_next_and_prev_pointers);
- if (intrusive_next_and_prev_pointers) {
- for (T value : IntrusiveListBaseWrapper<typename std::remove_pointer<T>::type>(values)) {
- this->append(value);
- }
+ for (T value : ListBaseWrapper<typename std::remove_pointer<T>::type>(values)) {
+ this->append(value);
}
}
@@ -665,4 +662,4 @@ template<typename T, uint N = 20> using ScopedVector = Vector<T, N, GuardedAlloc
} /* namespace BLI */
-#endif /* __BLI_VECTOR_H__ */
+#endif /* __BLI_VECTOR_HH__ */
diff --git a/source/blender/blenlib/BLI_vector_set.h b/source/blender/blenlib/BLI_vector_set.hh
index 99d955c60d8..c3cecfc0acf 100644
--- a/source/blender/blenlib/BLI_vector_set.h
+++ b/source/blender/blenlib/BLI_vector_set.hh
@@ -14,8 +14,8 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#ifndef __BLI_VECTOR_SET_H__
-#define __BLI_VECTOR_SET_H__
+#ifndef __BLI_VECTOR_SET_HH__
+#define __BLI_VECTOR_SET_HH__
/** \file
* \ingroup bli
@@ -25,9 +25,9 @@
* no deletes. The expected time to check if a value is in the VectorSet is O(1).
*/
-#include "BLI_hash_cxx.h"
-#include "BLI_open_addressing.h"
-#include "BLI_vector.h"
+#include "BLI_hash.hh"
+#include "BLI_open_addressing.hh"
+#include "BLI_vector.hh"
namespace BLI {
@@ -422,4 +422,4 @@ template<typename T, typename Allocator = GuardedAllocator> class VectorSet {
} // namespace BLI
-#endif /* __BLI_VECTOR_SET_H__ */
+#endif /* __BLI_VECTOR_SET_HH__ */
diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt
index bdfe3dd4747..0835f09fa5d 100644
--- a/source/blender/blenlib/CMakeLists.txt
+++ b/source/blender/blenlib/CMakeLists.txt
@@ -136,11 +136,11 @@ set(SRC
BLI_alloca.h
- BLI_allocator.h
+ BLI_allocator.hh
BLI_args.h
BLI_array.h
- BLI_array_cxx.h
- BLI_array_ref.h
+ BLI_array.hh
+ BLI_array_ref.hh
BLI_array_store.h
BLI_array_store_utils.h
BLI_array_utils.h
@@ -151,6 +151,7 @@ set(SRC
BLI_blenlib.h
BLI_boxpack_2d.h
BLI_buffer.h
+ BLI_color.hh
BLI_compiler_attrs.h
BLI_compiler_compat.h
BLI_compiler_typecheck.h
@@ -168,17 +169,20 @@ set(SRC
BLI_expr_pylike_eval.h
BLI_fileops.h
BLI_fileops_types.h
+ BLI_float2.hh
+ BLI_float3.hh
+ BLI_float4x4.hh
BLI_fnmatch.h
BLI_ghash.h
BLI_gsqueue.h
BLI_hash.h
- BLI_hash_cxx.h
+ BLI_hash.hh
BLI_hash_md5.h
BLI_hash_mm2a.h
BLI_hash_mm3.h
BLI_heap.h
BLI_heap_simple.h
- BLI_index_range.h
+ BLI_index_range.hh
BLI_iterator.h
BLI_jitter_2d.h
BLI_kdopbvh.h
@@ -190,8 +194,8 @@ set(SRC
BLI_linklist_lockfree.h
BLI_linklist_stack.h
BLI_listbase.h
- BLI_listbase_wrapper.h
- BLI_map.h
+ BLI_listbase_wrapper.hh
+ BLI_map.hh
BLI_math.h
BLI_math_base.h
BLI_math_bits.h
@@ -209,11 +213,11 @@ set(SRC
BLI_memblock.h
BLI_memiter.h
BLI_memory_utils.h
- BLI_memory_utils_cxx.h
+ BLI_memory_utils.hh
BLI_mempool.h
BLI_noise.h
- BLI_open_addressing.h
- BLI_optional.h
+ BLI_open_addressing.hh
+ BLI_optional.hh
BLI_path_util.h
BLI_polyfill_2d.h
BLI_polyfill_2d_beautify.h
@@ -221,17 +225,17 @@ set(SRC
BLI_rand.h
BLI_rect.h
BLI_scanfill.h
- BLI_set.h
+ BLI_set.hh
BLI_smallhash.h
BLI_sort.h
BLI_sort_utils.h
BLI_stack.h
- BLI_stack_cxx.h
+ BLI_stack.hh
BLI_strict_flags.h
BLI_string.h
BLI_string_cursor_utf8.h
- BLI_string_map.h
- BLI_string_ref.h
+ BLI_string_map.hh
+ BLI_string_ref.hh
BLI_string_utf8.h
BLI_string_utils.h
BLI_sys_types.h
@@ -244,10 +248,10 @@ set(SRC
BLI_utildefines_iter.h
BLI_utildefines_stack.h
BLI_utildefines_variadic.h
- BLI_utility_mixins.h
+ BLI_utility_mixins.hh
BLI_uvproject.h
- BLI_vector.h
- BLI_vector_set.h
+ BLI_vector.hh
+ BLI_vector_set.hh
BLI_vfontdata.h
BLI_voronoi_2d.h
BLI_voxel.h
diff --git a/source/blender/blenlib/intern/BLI_index_range.cc b/source/blender/blenlib/intern/BLI_index_range.cc
index 90eb4e4a89c..fefb6e6598e 100644
--- a/source/blender/blenlib/intern/BLI_index_range.cc
+++ b/source/blender/blenlib/intern/BLI_index_range.cc
@@ -17,10 +17,10 @@
#include <atomic>
#include <mutex>
-#include "BLI_array_cxx.h"
-#include "BLI_array_ref.h"
-#include "BLI_index_range.h"
-#include "BLI_vector.h"
+#include "BLI_array.hh"
+#include "BLI_array_ref.hh"
+#include "BLI_index_range.hh"
+#include "BLI_vector.hh"
namespace BLI {
diff --git a/source/blender/blenlib/intern/task_iterator.c b/source/blender/blenlib/intern/task_iterator.c
index 4ac012fa578..8a596879b2c 100644
--- a/source/blender/blenlib/intern/task_iterator.c
+++ b/source/blender/blenlib/intern/task_iterator.c
@@ -78,8 +78,13 @@ typedef struct TaskParallelRangeState {
/* Number of 'tls' copies in the array, i.e. number of worker threads. */
size_t num_elements_in_tls_storage;
- /* Function called from calling thread once whole range have been processed. */
- TaskParallelFinalizeFunc func_finalize;
+ /* Function called to join user data chunk into another, to reduce
+ * the result to the original userdata_chunk memory.
+ * The reduce functions should have no side effects, so that they
+ * can be run on any thread. */
+ TaskParallelReduceFunc func_reduce;
+ /* Function called to free data created by TaskParallelRangeFunc. */
+ TaskParallelFreeFunc func_free;
/* Current value of the iterator, shared between all threads (atomically updated). */
int iter_value;
@@ -229,7 +234,7 @@ BLI_INLINE bool parallel_range_next_iter_get(TaskParallelRangePool *__restrict r
static void parallel_range_func(TaskPool *__restrict pool, void *tls_data_idx, int thread_id)
{
- TaskParallelRangePool *__restrict range_pool = BLI_task_pool_userdata(pool);
+ TaskParallelRangePool *__restrict range_pool = BLI_task_pool_user_data(pool);
TaskParallelTLS tls = {
.thread_id = thread_id,
.userdata_chunk = NULL,
@@ -256,23 +261,18 @@ static void parallel_range_single_thread(TaskParallelRangePool *range_pool)
void *initial_tls_memory = state->initial_tls_memory;
const size_t tls_data_size = state->tls_data_size;
- void *flatten_tls_storage = NULL;
const bool use_tls_data = (tls_data_size != 0) && (initial_tls_memory != NULL);
- if (use_tls_data) {
- flatten_tls_storage = MALLOCA(tls_data_size);
- memcpy(flatten_tls_storage, initial_tls_memory, tls_data_size);
- }
TaskParallelTLS tls = {
.thread_id = 0,
- .userdata_chunk = flatten_tls_storage,
+ .userdata_chunk = initial_tls_memory,
};
for (int i = start; i < stop; i++) {
func(userdata, i, &tls);
}
- if (state->func_finalize != NULL) {
- state->func_finalize(userdata, flatten_tls_storage);
+ if (use_tls_data && state->func_free != NULL) {
+ /* `func_free` should only free data that was created during execution of `func`. */
+ state->func_free(userdata, initial_tls_memory);
}
- MALLOCA_FREE(flatten_tls_storage, tls_data_size);
}
}
@@ -303,7 +303,7 @@ void BLI_task_parallel_range(const int start,
.iter_value = start,
.initial_tls_memory = settings->userdata_chunk,
.tls_data_size = settings->userdata_chunk_size,
- .func_finalize = settings->func_finalize,
+ .func_free = settings->func_free,
};
TaskParallelRangePool range_pool = {
.pool = NULL, .parallel_range_states = &state, .current_state = NULL, .settings = settings};
@@ -367,11 +367,15 @@ void BLI_task_parallel_range(const int start,
BLI_task_pool_work_and_wait(task_pool);
BLI_task_pool_free(task_pool);
- if (use_tls_data) {
- if (settings->func_finalize != NULL) {
- for (i = 0; i < num_tasks; i++) {
- void *userdata_chunk_local = (char *)flatten_tls_storage + (tls_data_size * (size_t)i);
- settings->func_finalize(userdata, userdata_chunk_local);
+ if (use_tls_data && (settings->func_free != NULL || settings->func_reduce != NULL)) {
+ for (i = 0; i < num_tasks; i++) {
+ void *userdata_chunk_local = (char *)flatten_tls_storage + (tls_data_size * (size_t)i);
+ if (settings->func_reduce) {
+ settings->func_reduce(userdata, tls_data, userdata_chunk_local);
+ }
+ if (settings->func_free) {
+ /* `func_free` should only free data that was created during execution of `func`. */
+ settings->func_free(userdata, userdata_chunk_local);
}
}
MALLOCA_FREE(flatten_tls_storage, tls_data_size * (size_t)num_tasks);
@@ -382,16 +386,17 @@ void BLI_task_parallel_range(const int start,
* Initialize a task pool to parallelize several for loops at the same time.
*
* See public API doc of ParallelRangeSettings for description of all settings.
- * Note that loop-specific settings (like 'tls' data or finalize function) must be left NULL here.
- * Only settings controlling how iteration is parallelized must be defined, as those will affect
- * all loops added to that pool.
+ * Note that loop-specific settings (like 'tls' data or reduce/free functions) must be left NULL
+ * here. Only settings controlling how iteration is parallelized must be defined, as those will
+ * affect all loops added to that pool.
*/
TaskParallelRangePool *BLI_task_parallel_range_pool_init(const TaskParallelSettings *settings)
{
TaskParallelRangePool *range_pool = MEM_callocN(sizeof(*range_pool), __func__);
BLI_assert(settings->userdata_chunk == NULL);
- BLI_assert(settings->func_finalize == NULL);
+ BLI_assert(settings->func_reduce == NULL);
+ BLI_assert(settings->func_free == NULL);
range_pool->settings = MEM_mallocN(sizeof(*range_pool->settings), __func__);
*range_pool->settings = *settings;
@@ -430,7 +435,8 @@ void BLI_task_parallel_range_pool_push(TaskParallelRangePool *range_pool,
state->iter_value = start;
state->initial_tls_memory = settings->userdata_chunk;
state->tls_data_size = settings->userdata_chunk_size;
- state->func_finalize = settings->func_finalize;
+ state->func_reduce = settings->func_reduce;
+ state->func_free = settings->func_free;
state->next = range_pool->parallel_range_states;
range_pool->parallel_range_states = state;
@@ -440,12 +446,18 @@ static void parallel_range_func_finalize(TaskPool *__restrict pool,
void *v_state,
int UNUSED(thread_id))
{
- TaskParallelRangePool *__restrict range_pool = BLI_task_pool_userdata(pool);
+ TaskParallelRangePool *__restrict range_pool = BLI_task_pool_user_data(pool);
TaskParallelRangeState *state = v_state;
for (int i = 0; i < range_pool->num_tasks; i++) {
void *tls_data = (char *)state->flatten_tls_storage + (state->tls_data_size * (size_t)i);
- state->func_finalize(state->userdata_shared, tls_data);
+ if (state->func_reduce != NULL) {
+ state->func_reduce(state->userdata_shared, state->initial_tls_memory, tls_data);
+ }
+ if (state->func_free != NULL) {
+ /* `func_free` should only free data that was created during execution of `func`. */
+ state->func_free(state->userdata_shared, tls_data);
+ }
}
}
@@ -531,7 +543,7 @@ void BLI_task_parallel_range_pool_work_and_wait(TaskParallelRangePool *range_poo
continue;
}
- if (state->func_finalize != NULL) {
+ if (state->func_reduce != NULL || state->func_free != NULL) {
BLI_task_pool_push_from_thread(
task_pool, parallel_range_func_finalize, state, false, NULL, thread_id);
}
@@ -654,7 +666,7 @@ static void parallel_iterator_func_do(TaskParallelIteratorState *__restrict stat
static void parallel_iterator_func(TaskPool *__restrict pool, void *userdata_chunk, int threadid)
{
- TaskParallelIteratorState *__restrict state = BLI_task_pool_userdata(pool);
+ TaskParallelIteratorState *__restrict state = BLI_task_pool_user_data(pool);
parallel_iterator_func_do(state, userdata_chunk, threadid);
}
@@ -677,11 +689,9 @@ static void task_parallel_iterator_no_threads(const TaskParallelSettings *settin
parallel_iterator_func_do(state, userdata_chunk, 0);
- if (use_userdata_chunk) {
- if (settings->func_finalize != NULL) {
- settings->func_finalize(state->userdata, userdata_chunk_local);
- }
- MALLOCA_FREE(userdata_chunk_local, userdata_chunk_size);
+ if (use_userdata_chunk && settings->func_free != NULL) {
+ /* `func_free` should only free data that was created during execution of `func`. */
+ settings->func_free(state->userdata, userdata_chunk_local);
}
}
@@ -740,11 +750,14 @@ static void task_parallel_iterator_do(const TaskParallelSettings *settings,
BLI_task_pool_work_and_wait(task_pool);
BLI_task_pool_free(task_pool);
- if (use_userdata_chunk) {
- if (settings->func_finalize != NULL) {
- for (size_t i = 0; i < num_tasks; i++) {
- userdata_chunk_local = (char *)userdata_chunk_array + (userdata_chunk_size * i);
- settings->func_finalize(state->userdata, userdata_chunk_local);
+ if (use_userdata_chunk && (settings->func_reduce != NULL || settings->func_free != NULL)) {
+ for (size_t i = 0; i < num_tasks; i++) {
+ userdata_chunk_local = (char *)userdata_chunk_array + (userdata_chunk_size * i);
+ if (settings->func_reduce != NULL) {
+ settings->func_reduce(state->userdata, userdata_chunk, userdata_chunk_local);
+ }
+ if (settings->func_free != NULL) {
+ settings->func_free(state->userdata, userdata_chunk_local);
}
}
MALLOCA_FREE(userdata_chunk_array, userdata_chunk_size * num_tasks);
@@ -849,7 +862,7 @@ typedef struct ParallelMempoolState {
static void parallel_mempool_func(TaskPool *__restrict pool, void *taskdata, int UNUSED(threadid))
{
- ParallelMempoolState *__restrict state = BLI_task_pool_userdata(pool);
+ ParallelMempoolState *__restrict state = BLI_task_pool_user_data(pool);
BLI_mempool_iter *iter = taskdata;
MempoolIterData *item;
diff --git a/source/blender/blenlib/intern/task_pool.cc b/source/blender/blenlib/intern/task_pool.cc
index 8085d495248..60ed156105c 100644
--- a/source/blender/blenlib/intern/task_pool.cc
+++ b/source/blender/blenlib/intern/task_pool.cc
@@ -230,11 +230,11 @@ typedef struct TaskThread {
} TaskThread;
/* Helper */
-BLI_INLINE void task_data_free(Task *task, const int thread_id)
+BLI_INLINE void task_data_free(Task *task, const int UNUSED(thread_id))
{
if (task->free_taskdata) {
if (task->freedata) {
- task->freedata(task->pool, task->taskdata, thread_id);
+ task->freedata(task->pool, task->taskdata);
}
else {
MEM_freeN(task->taskdata);
@@ -992,7 +992,7 @@ bool BLI_task_pool_canceled(TaskPool *pool)
return pool->do_cancel;
}
-void *BLI_task_pool_userdata(TaskPool *pool)
+void *BLI_task_pool_user_data(TaskPool *pool)
{
return pool->userdata;
}
diff --git a/source/blender/blenloader/CMakeLists.txt b/source/blender/blenloader/CMakeLists.txt
index 450d3fc2371..1555b9231ed 100644
--- a/source/blender/blenloader/CMakeLists.txt
+++ b/source/blender/blenloader/CMakeLists.txt
@@ -53,6 +53,7 @@ set(SRC
intern/versioning_260.c
intern/versioning_270.c
intern/versioning_280.c
+ intern/versioning_290.c
intern/versioning_cycles.c
intern/versioning_defaults.c
intern/versioning_dna.c
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index f64a0e48855..6b59dfbd10b 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -86,6 +86,7 @@
#include "DNA_sdna_types.h"
#include "DNA_sequence_types.h"
#include "DNA_shader_fx_types.h"
+#include "DNA_simulation_types.h"
#include "DNA_sound_types.h"
#include "DNA_space_types.h"
#include "DNA_speaker_types.h"
@@ -146,6 +147,7 @@
#include "BKE_screen.h"
#include "BKE_sequencer.h"
#include "BKE_shader_fx.h"
+#include "BKE_simulation.h"
#include "BKE_sound.h"
#include "BKE_volume.h"
#include "BKE_workspace.h"
@@ -3600,6 +3602,45 @@ static void lib_link_workspace_instance_hook(FileData *fd, WorkSpaceInstanceHook
/** \name Read ID: Node Tree
* \{ */
+static void lib_link_node_socket(FileData *fd, Library *lib, bNodeSocket *sock)
+{
+ IDP_LibLinkProperty(sock->prop, fd);
+
+ switch ((eNodeSocketDatatype)sock->type) {
+ case SOCK_OBJECT: {
+ bNodeSocketValueObject *default_value = sock->default_value;
+ default_value->value = newlibadr(fd, lib, default_value->value);
+ break;
+ }
+ case SOCK_IMAGE: {
+ bNodeSocketValueImage *default_value = sock->default_value;
+ default_value->value = newlibadr(fd, lib, default_value->value);
+ break;
+ }
+ case SOCK_FLOAT:
+ case SOCK_VECTOR:
+ case SOCK_RGBA:
+ case SOCK_BOOLEAN:
+ case SOCK_INT:
+ case SOCK_STRING:
+ case __SOCK_MESH:
+ case SOCK_CUSTOM:
+ case SOCK_SHADER:
+ case SOCK_EMITTERS:
+ case SOCK_EVENTS:
+ case SOCK_FORCES:
+ case SOCK_CONTROL_FLOW:
+ break;
+ }
+}
+
+static void lib_link_node_sockets(FileData *fd, Library *lib, ListBase *sockets)
+{
+ LISTBASE_FOREACH (bNodeSocket *, sock, sockets) {
+ lib_link_node_socket(fd, lib, sock);
+ }
+}
+
/* Single node tree (also used for material/scene trees), ntree is not NULL */
static void lib_link_ntree(FileData *fd, Library *lib, bNodeTree *ntree)
{
@@ -3614,20 +3655,12 @@ static void lib_link_ntree(FileData *fd, Library *lib, bNodeTree *ntree)
node->id = newlibadr(fd, lib, node->id);
- LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
- IDP_LibLinkProperty(sock->prop, fd);
- }
- LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) {
- IDP_LibLinkProperty(sock->prop, fd);
- }
+ lib_link_node_sockets(fd, lib, &node->inputs);
+ lib_link_node_sockets(fd, lib, &node->outputs);
}
- LISTBASE_FOREACH (bNodeSocket *, sock, &ntree->inputs) {
- IDP_LibLinkProperty(sock->prop, fd);
- }
- LISTBASE_FOREACH (bNodeSocket *, sock, &ntree->outputs) {
- IDP_LibLinkProperty(sock->prop, fd);
- }
+ lib_link_node_sockets(fd, lib, &ntree->inputs);
+ lib_link_node_sockets(fd, lib, &ntree->outputs);
/* Set node->typeinfo pointers. This is done in lib linking, after the
* first versioning that can change types still without functions that
@@ -9141,6 +9174,24 @@ static void direct_link_volume(FileData *fd, Volume *volume)
/** \} */
/* -------------------------------------------------------------------- */
+/** \name Read ID: Simulation
+ * \{ */
+
+static void lib_link_simulation(FileData *UNUSED(fd),
+ Main *UNUSED(main),
+ Simulation *UNUSED(simulation))
+{
+}
+
+static void direct_link_simulation(FileData *fd, Simulation *simulation)
+{
+ simulation->adt = newdataadr(fd, simulation->adt);
+ direct_link_animdata(fd, simulation->adt);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Read Library Data Block
* \{ */
@@ -9258,6 +9309,8 @@ static const char *dataname(short id_code)
return "Data from PT";
case ID_VO:
return "Data from VO";
+ case ID_SIM:
+ return "Data from SIM";
}
return "Data from Lib Block";
}
@@ -9409,6 +9462,9 @@ static bool direct_link_id(FileData *fd, Main *main, const int tag, ID *id, ID *
case ID_VO:
direct_link_volume(fd, (Volume *)id);
break;
+ case ID_SIM:
+ direct_link_simulation(fd, (Simulation *)id);
+ break;
}
return success;
@@ -9925,6 +9981,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
blo_do_versions_260(fd, lib, main);
blo_do_versions_270(fd, lib, main);
blo_do_versions_280(fd, lib, main);
+ blo_do_versions_290(fd, lib, main);
blo_do_versions_cycles(fd, lib, main);
/* WATCH IT!!!: pointers from libdata have not been converted yet here! */
@@ -10097,6 +10154,9 @@ static void lib_link_all(FileData *fd, Main *bmain)
case ID_AC:
lib_link_action(fd, bmain, (bAction *)id);
break;
+ case ID_SIM:
+ lib_link_simulation(fd, bmain, (Simulation *)id);
+ break;
case ID_IP:
/* XXX deprecated... still needs to be maintained for version patches still. */
lib_link_ipo(fd, bmain, (Ipo *)id);
@@ -10939,10 +10999,51 @@ static void expand_key(FileData *fd, Main *mainvar, Key *key)
expand_doit(fd, mainvar, key->ipo); // XXX deprecated - old animation system
}
+static void expand_node_socket(FileData *fd, Main *mainvar, bNodeSocket *sock)
+{
+ expand_idprops(fd, mainvar, sock->prop);
+
+ if (sock->default_value != NULL) {
+
+ switch ((eNodeSocketDatatype)sock->type) {
+ case SOCK_OBJECT: {
+ bNodeSocketValueObject *default_value = sock->default_value;
+ expand_doit(fd, mainvar, default_value->value);
+ break;
+ }
+ case SOCK_IMAGE: {
+ bNodeSocketValueImage *default_value = sock->default_value;
+ expand_doit(fd, mainvar, default_value->value);
+ break;
+ }
+ case SOCK_FLOAT:
+ case SOCK_VECTOR:
+ case SOCK_RGBA:
+ case SOCK_BOOLEAN:
+ case SOCK_INT:
+ case SOCK_STRING:
+ case __SOCK_MESH:
+ case SOCK_CUSTOM:
+ case SOCK_SHADER:
+ case SOCK_EMITTERS:
+ case SOCK_EVENTS:
+ case SOCK_FORCES:
+ case SOCK_CONTROL_FLOW:
+ break;
+ }
+ }
+}
+
+static void expand_node_sockets(FileData *fd, Main *mainvar, ListBase *sockets)
+{
+ LISTBASE_FOREACH (bNodeSocket *, sock, sockets) {
+ expand_node_socket(fd, mainvar, sock);
+ }
+}
+
static void expand_nodetree(FileData *fd, Main *mainvar, bNodeTree *ntree)
{
bNode *node;
- bNodeSocket *sock;
if (ntree->gpd) {
expand_doit(fd, mainvar, ntree->gpd);
@@ -10955,20 +11056,12 @@ static void expand_nodetree(FileData *fd, Main *mainvar, bNodeTree *ntree)
expand_idprops(fd, mainvar, node->prop);
- for (sock = node->inputs.first; sock; sock = sock->next) {
- expand_idprops(fd, mainvar, sock->prop);
- }
- for (sock = node->outputs.first; sock; sock = sock->next) {
- expand_idprops(fd, mainvar, sock->prop);
- }
+ expand_node_sockets(fd, mainvar, &node->inputs);
+ expand_node_sockets(fd, mainvar, &node->outputs);
}
- for (sock = ntree->inputs.first; sock; sock = sock->next) {
- expand_idprops(fd, mainvar, sock->prop);
- }
- for (sock = ntree->outputs.first; sock; sock = sock->next) {
- expand_idprops(fd, mainvar, sock->prop);
- }
+ expand_node_sockets(fd, mainvar, &ntree->inputs);
+ expand_node_sockets(fd, mainvar, &ntree->outputs);
}
static void expand_texture(FileData *fd, Main *mainvar, Tex *tex)
@@ -11519,6 +11612,13 @@ static void expand_volume(FileData *fd, Main *mainvar, Volume *volume)
}
}
+static void expand_simulation(FileData *fd, Main *mainvar, Simulation *simulation)
+{
+ if (simulation->adt) {
+ expand_animdata(fd, mainvar, simulation->adt);
+ }
+}
+
/**
* Set the callback func used over all ID data found by \a BLO_expand_main func.
*
@@ -11648,6 +11748,9 @@ void BLO_expand_main(void *fdhandle, Main *mainvar)
case ID_VO:
expand_volume(fd, mainvar, (Volume *)id);
break;
+ case ID_SIM:
+ expand_simulation(fd, mainvar, (Simulation *)id);
+ break;
default:
break;
}
diff --git a/source/blender/blenloader/intern/readfile.h b/source/blender/blenloader/intern/readfile.h
index 80f8bfc3f07..55abbe703de 100644
--- a/source/blender/blenloader/intern/readfile.h
+++ b/source/blender/blenloader/intern/readfile.h
@@ -199,6 +199,7 @@ void blo_do_versions_250(struct FileData *fd, struct Library *lib, struct Main *
void blo_do_versions_260(struct FileData *fd, struct Library *lib, struct Main *bmain);
void blo_do_versions_270(struct FileData *fd, struct Library *lib, struct Main *bmain);
void blo_do_versions_280(struct FileData *fd, struct Library *lib, struct Main *bmain);
+void blo_do_versions_290(struct FileData *fd, struct Library *lib, struct Main *bmain);
void blo_do_versions_cycles(struct FileData *fd, struct Library *lib, struct Main *bmain);
void do_versions_after_linking_250(struct Main *bmain);
diff --git a/source/blender/blenloader/intern/versioning_290.c b/source/blender/blenloader/intern/versioning_290.c
new file mode 100644
index 00000000000..0ce3cf405cd
--- /dev/null
+++ b/source/blender/blenloader/intern/versioning_290.c
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+/** \file
+ * \ingroup blenloader
+ */
+/* allow readfile to use deprecated functionality */
+#define DNA_DEPRECATED_ALLOW
+
+#include "BLI_listbase.h"
+#include "BLI_utildefines.h"
+
+#include "DNA_genfile.h"
+#include "DNA_screen_types.h"
+
+#include "BKE_collection.h"
+#include "BKE_main.h"
+
+#include "BLO_readfile.h"
+#include "readfile.h"
+
+/* Make preferences read-only, use versioning_userdef.c. */
+#define U (*((const UserDef *)&U))
+
+void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain)
+{
+ UNUSED_VARS(fd);
+ /**
+ * Versioning code until next subversion bump goes here.
+ *
+ * \note Be sure to check when bumping the version:
+ * - "versioning_userdef.c", #BLO_version_defaults_userpref_blend
+ * - "versioning_userdef.c", #do_versions_theme
+ *
+ * \note Keep this message at the bottom of the function.
+ */
+ {
+ /* Keep this block, even when empty. */
+
+ if (!DNA_struct_elem_find(fd->filesdna, "SpaceImage", "float", "uv_opacity")) {
+ for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) {
+ LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
+ LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
+ if (sl->spacetype == SPACE_IMAGE) {
+ SpaceImage *sima = (SpaceImage *)sl;
+ sima->uv_opacity = 1.0f;
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c
index 19606b92479..aa34bfd0de1 100644
--- a/source/blender/blenloader/intern/versioning_defaults.c
+++ b/source/blender/blenloader/intern/versioning_defaults.c
@@ -297,7 +297,7 @@ static void blo_update_defaults_scene(Main *bmain, Scene *scene)
/* Don't enable compositing nodes. */
if (scene->nodetree) {
- ntreeFreeNestedTree(scene->nodetree);
+ ntreeFreeEmbeddedTree(scene->nodetree);
MEM_freeN(scene->nodetree);
scene->nodetree = NULL;
scene->use_nodes = false;
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index ee5e6f4610a..a613603fff9 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -133,6 +133,7 @@
#include "DNA_sdna_types.h"
#include "DNA_sequence_types.h"
#include "DNA_shader_fx_types.h"
+#include "DNA_simulation_types.h"
#include "DNA_sound_types.h"
#include "DNA_space_types.h"
#include "DNA_speaker_types.h"
@@ -990,9 +991,19 @@ static void write_node_socket_default_value(WriteData *wd, bNodeSocket *sock)
case SOCK_STRING:
writestruct(wd, DATA, bNodeSocketValueString, 1, sock->default_value);
break;
+ case SOCK_OBJECT:
+ writestruct(wd, DATA, bNodeSocketValueObject, 1, sock->default_value);
+ break;
+ case SOCK_IMAGE:
+ writestruct(wd, DATA, bNodeSocketValueImage, 1, sock->default_value);
+ break;
case __SOCK_MESH:
case SOCK_CUSTOM:
case SOCK_SHADER:
+ case SOCK_EMITTERS:
+ case SOCK_EVENTS:
+ case SOCK_FORCES:
+ case SOCK_CONTROL_FLOW:
BLI_assert(false);
break;
}
@@ -3848,6 +3859,24 @@ static void write_volume(WriteData *wd, Volume *volume, const void *id_address)
}
}
+static void write_simulation(WriteData *wd, Simulation *simulation)
+{
+ if (simulation->id.us > 0 || wd->use_memfile) {
+ writestruct(wd, ID_SIM, Simulation, 1, simulation);
+ write_iddata(wd, &simulation->id);
+
+ if (simulation->adt) {
+ write_animdata(wd, simulation->adt);
+ }
+
+ /* nodetree is integral part of simulation, no libdata */
+ if (simulation->nodetree) {
+ writestruct(wd, DATA, bNodeTree, 1, simulation->nodetree);
+ write_nodetree_nolib(wd, simulation->nodetree);
+ }
+ }
+}
+
/* Keep it last of write_foodata functions. */
static void write_libraries(WriteData *wd, Main *main)
{
@@ -4197,6 +4226,9 @@ static bool write_file_handle(Main *mainvar,
case ID_VO:
write_volume(wd, (Volume *)id_buffer, id);
break;
+ case ID_SIM:
+ write_simulation(wd, (Simulation *)id);
+ break;
case ID_LI:
/* Do nothing, handled below - and should never be reached. */
BLI_assert(0);
diff --git a/source/blender/blentranslation/BLT_translation.h b/source/blender/blentranslation/BLT_translation.h
index 74c46b1cf3e..5f6ae0a86e9 100644
--- a/source/blender/blentranslation/BLT_translation.h
+++ b/source/blender/blentranslation/BLT_translation.h
@@ -122,6 +122,7 @@ bool BLT_lang_is_ime_supported(void);
#define BLT_I18NCONTEXT_ID_IMAGE "Image"
/*#define BLT_I18NCONTEXT_ID_IPO "Ipo"*/ /* Deprecated */
#define BLT_I18NCONTEXT_ID_SHAPEKEY "Key"
+#define BLT_I18NCONTEXT_ID_SIMULATION "Simulation"
#define BLT_I18NCONTEXT_ID_LIGHT "Light"
#define BLT_I18NCONTEXT_ID_LIBRARY "Library"
#define BLT_I18NCONTEXT_ID_LATTICE "Lattice"
@@ -202,6 +203,7 @@ typedef struct {
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_SCENE, "id_scene"), \
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_SCREEN, "id_screen"), \
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_SEQUENCE, "id_sequence"), \
+ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_SIMULATION, "id_simulation"), \
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_SPEAKER, "id_speaker"), \
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_SOUND, "id_sound"), \
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_TEXTURE, "id_texture"), \
diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c
index 4fa7bf64834..45666a21a2c 100644
--- a/source/blender/bmesh/intern/bmesh_opdefines.c
+++ b/source/blender/bmesh/intern/bmesh_opdefines.c
@@ -1046,6 +1046,7 @@ static BMOpDefine bmo_extrude_face_region_def = {
{"use_keep_orig", BMO_OP_SLOT_BOOL}, /* keep original geometry (requires ``geom`` to include edges). */
{"use_normal_flip", BMO_OP_SLOT_BOOL}, /* Create faces with reversed direction. */
{"use_normal_from_adjacent", BMO_OP_SLOT_BOOL}, /* Use winding from surrounding faces instead of this region. */
+ {"use_dissolve_ortho_edges", BMO_OP_SLOT_BOOL}, /* Dissolve edges whose faces form a flat surface. */
{"use_select_history", BMO_OP_SLOT_BOOL}, /* pass to duplicate */
{{'\0'}},
},
diff --git a/source/blender/bmesh/operators/bmo_extrude.c b/source/blender/bmesh/operators/bmo_extrude.c
index 7a7f4a14db3..3c63f4a60d6 100644
--- a/source/blender/bmesh/operators/bmo_extrude.c
+++ b/source/blender/bmesh/operators/bmo_extrude.c
@@ -39,6 +39,7 @@ enum {
EXT_INPUT = 1,
EXT_KEEP = 2,
EXT_DEL = 4,
+ EXT_TAG = 8,
};
#define VERT_MARK 1
@@ -335,6 +336,8 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op)
const bool use_normal_flip = BMO_slot_bool_get(op->slots_in, "use_normal_flip");
const bool use_normal_from_adjacent = BMO_slot_bool_get(op->slots_in,
"use_normal_from_adjacent");
+ const bool use_dissolve_ortho_edges = BMO_slot_bool_get(op->slots_in,
+ "use_dissolve_ortho_edges");
/* initialize our sub-operators */
BMO_op_initf(bm,
@@ -442,6 +445,24 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op)
}
}
+ BMVert **dissolve_verts = NULL;
+ int dissolve_verts_len = 0;
+ float average_normal[3];
+ if (use_dissolve_ortho_edges) {
+ /* Calc average normal. */
+ zero_v3(average_normal);
+ BMO_ITER (f, &siter, dupeop.slots_out, "geom.out", BM_FACE) {
+ add_v3_v3(average_normal, f->no);
+ }
+ if (normalize_v3(average_normal) == 0.0f) {
+ average_normal[2] = 1.0f;
+ }
+
+ /* Allocate array to store possible vertices that will be dissolved. */
+ int boundary_verts_len = BMO_slot_map_count(dupeop.slots_out, "boundary_map.out");
+ dissolve_verts = MEM_mallocN((size_t)boundary_verts_len * sizeof(*dissolve_verts), __func__);
+ }
+
BMO_slot_copy(&dupeop, slots_out, "geom.out", op, slots_out, "geom.out");
slot_edges_exclude = BMO_slot_get(op->slots_in, "edges_exclude");
@@ -483,6 +504,16 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op)
continue;
}
+ BMFace *join_face = NULL;
+ if (use_dissolve_ortho_edges) {
+ if (BM_edge_is_boundary(e)) {
+ join_face = e->l->f;
+ if (fabs(dot_v3v3(average_normal, join_face->no)) > 0.0001f) {
+ join_face = NULL;
+ }
+ }
+ }
+
bool edge_normal_flip;
if (use_normal_from_adjacent == false) {
/* Orient loop to give same normal as a loop of 'e_new'
@@ -541,7 +572,22 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op)
f = BM_face_create_verts(bm, f_verts, 4, NULL, BM_CREATE_NOP, true);
#endif
- bm_extrude_copy_face_loop_attributes(bm, f);
+ if (join_face) {
+ BMVert *v1 = e->v1;
+ BMVert *v2 = e->v2;
+ if (!BMO_elem_flag_test(bm, v1, EXT_TAG)) {
+ BMO_elem_flag_enable(bm, v1, EXT_TAG);
+ dissolve_verts[dissolve_verts_len++] = v1;
+ }
+ if (!BMO_elem_flag_test(bm, v2, EXT_TAG)) {
+ BMO_elem_flag_enable(bm, v2, EXT_TAG);
+ dissolve_verts[dissolve_verts_len++] = v2;
+ }
+ bmesh_kernel_join_face_kill_edge(bm, join_face, f, e);
+ }
+ else {
+ bm_extrude_copy_face_loop_attributes(bm, f);
+ }
}
/* link isolated vert */
@@ -559,6 +605,23 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op)
BM_edge_create(bm, v, v2, NULL, BM_CREATE_NO_DOUBLE);
}
+ if (dissolve_verts) {
+ BMVert **v_iter = &dissolve_verts[0];
+ for (int i = dissolve_verts_len; i--; v_iter++) {
+ v = *v_iter;
+ e = v->e;
+ BMEdge *e_other = BM_DISK_EDGE_NEXT(e, v);
+ if ((e_other == e) || (BM_DISK_EDGE_NEXT(e_other, v) == e)) {
+ /* Lose edge or BMVert is edge pair. */
+ BM_edge_collapse(bm, e, v, true, false);
+ }
+ else {
+ BLI_assert(!BM_vert_is_edge_pair(v));
+ }
+ }
+ MEM_freeN(dissolve_verts);
+ }
+
/* cleanup */
if (delorig) {
BMO_op_finish(bm, &delop);
diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c
index bc127243836..d1ddceb00b0 100644
--- a/source/blender/bmesh/tools/bmesh_bevel.c
+++ b/source/blender/bmesh/tools/bmesh_bevel.c
@@ -997,10 +997,10 @@ static bool point_between_edges(float co[3], BMVert *v, BMFace *f, EdgeHalf *e1,
* record the change in offset_l (or offset_r); later we can tell that a change has happened
* because the offset will differ from its original value in offset_l_spec (or offset_r_spec).
*
- * \param edges_between If this is true, there are edges between e1 and e2 in CCW order so they
+ * \param edges_between: If this is true, there are edges between e1 and e2 in CCW order so they
* don't share a common face. We want the meeting point to be on an existing face so it
* should be dropped onto one of the intermediate faces, if possible.
- * \param e_in_plane If we need to drop from the calculated offset lines to one of the faces,
+ * \param e_in_plane: If we need to drop from the calculated offset lines to one of the faces,
* we don't want to drop onto the 'in plane' face, so if this is not null skip this edge's faces.
*/
static void offset_meet(EdgeHalf *e1,
@@ -2601,13 +2601,13 @@ static void adjust_miter_inner_coords(BevelParams *bp, BevVert *bv, EdgeHalf *em
* to be a subsequent pass to make the widths as consistent as possible.
* Doesn't make the actual BMVerts.
*
- * For a width consistency pass, we just recalculate the coordinates of the BoundVerts. If the
+ * For a width consistency pass, we just recalculate the coordinates of the #BoundVerts. If the
* other ends have been (re)built already, then we copy the offsets from there to match, else we
* use the ideal (user-specified) widths.
*
- * \param construct The first time through, construct will be true and we are making the BoundVerts
- * and setting up the BoundVert and EdgeHalf pointers appropriately. Also, if construct, decide on
- * the mesh pattern that will be used inside the boundary.
+ * \param construct: The first time through, construct will be true and we are making the
+ * #BoundVerts and setting up the #BoundVert and #EdgeHalf pointers appropriately.
+ * Also, if construct, decide on the mesh pattern that will be used inside the boundary.
*/
static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
{
diff --git a/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp b/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp
index ec858ee2c19..fe2943419c5 100644
--- a/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp
+++ b/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp
@@ -50,7 +50,8 @@ void MovieDistortionOperation::initExecution()
full_frame.xmin = full_frame.ymin = 0;
full_frame.xmax = this->m_width;
full_frame.ymax = this->m_height;
- BKE_tracking_max_distortion_delta_across_bound(tracking, &full_frame, !this->m_apply, delta);
+ BKE_tracking_max_distortion_delta_across_bound(
+ tracking, this->m_width, this->m_height, &full_frame, !this->m_apply, delta);
/* 5 is just in case we didn't hit real max of distortion in
* BKE_tracking_max_undistortion_delta_across_bound
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
index 0adea027ecc..0c0cc8ebc97 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
@@ -60,6 +60,7 @@ extern "C" {
#include "DNA_rigidbody_types.h"
#include "DNA_scene_types.h"
#include "DNA_sequence_types.h"
+#include "DNA_simulation_types.h"
#include "DNA_sound_types.h"
#include "DNA_speaker_types.h"
#include "DNA_texture_types.h"
@@ -481,6 +482,9 @@ void DepsgraphNodeBuilder::build_id(ID *id)
case ID_SCE:
build_scene_parameters((Scene *)id);
break;
+ case ID_SIM:
+ build_simulation((Simulation *)id);
+ break;
default:
fprintf(stderr, "Unhandled ID %s\n", id->name);
BLI_assert(!"Should never happen");
@@ -506,8 +510,7 @@ void DepsgraphNodeBuilder::build_collection(LayerCollection *from_layer_collecti
}
else if (from_layer_collection == nullptr && !id_node->is_collection_fully_expanded) {
/* Initially collection was built from layer now, and was requested
- * to not recurs into object. But nw it's asked to recurs into all
- * objects. */
+ * to not recurs into object. But now it's asked to recurs into all objects. */
}
else {
return;
@@ -1699,6 +1702,16 @@ void DepsgraphNodeBuilder::build_sound(bSound *sound)
build_parameters(&sound->id);
}
+void DepsgraphNodeBuilder::build_simulation(Simulation *simulation)
+{
+ if (built_map_.checkIsBuiltAndTag(simulation)) {
+ return;
+ }
+ add_id_node(&simulation->id);
+ build_animdata(&simulation->id);
+ build_parameters(&simulation->id);
+}
+
void DepsgraphNodeBuilder::build_scene_sequencer(Scene *scene)
{
if (scene->ed == nullptr) {
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
index 7fcc8b431e7..15c1a42574f 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
@@ -52,6 +52,7 @@ struct MovieClip;
struct Object;
struct ParticleSettings;
struct Scene;
+struct Simulation;
struct Speaker;
struct Tex;
struct World;
@@ -217,6 +218,7 @@ class DepsgraphNodeBuilder : public DepsgraphBuilder {
virtual void build_lightprobe(LightProbe *probe);
virtual void build_speaker(Speaker *speaker);
virtual void build_sound(bSound *sound);
+ virtual void build_simulation(Simulation *simulation);
virtual void build_scene_sequencer(Scene *scene);
virtual void build_scene_audio(Scene *scene);
virtual void build_scene_speakers(Scene *scene, ViewLayer *view_layer);
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
index e968ad1ea5d..d5a3d5ee121 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
@@ -62,6 +62,7 @@ extern "C" {
#include "DNA_rigidbody_types.h"
#include "DNA_scene_types.h"
#include "DNA_sequence_types.h"
+#include "DNA_simulation_types.h"
#include "DNA_sound_types.h"
#include "DNA_speaker_types.h"
#include "DNA_texture_types.h"
@@ -558,6 +559,9 @@ void DepsgraphRelationBuilder::build_id(ID *id)
case ID_SCE:
build_scene_parameters((Scene *)id);
break;
+ case ID_SIM:
+ build_simulation((Simulation *)id);
+ break;
default:
fprintf(stderr, "Unhandled ID %s\n", id->name);
BLI_assert(!"Should never happen");
@@ -2345,21 +2349,27 @@ void DepsgraphRelationBuilder::build_texture(Tex *texture)
return;
}
/* texture itself */
+ ComponentKey texture_key(&texture->id, NodeType::GENERIC_DATABLOCK);
build_animdata(&texture->id);
build_parameters(&texture->id);
+
/* texture's nodetree */
build_nodetree(texture->nodetree);
+ build_nested_nodetree(&texture->id, texture->nodetree);
+
/* Special cases for different IDs which texture uses. */
if (texture->type == TEX_IMAGE) {
if (texture->ima != nullptr) {
build_image(texture->ima);
+
+ ComponentKey image_key(&texture->ima->id, NodeType::GENERIC_DATABLOCK);
+ add_relation(image_key, texture_key, "Texture Image");
}
}
- build_nested_nodetree(&texture->id, texture->nodetree);
+
if (check_id_has_anim_component(&texture->id)) {
ComponentKey animation_key(&texture->id, NodeType::ANIMATION);
- ComponentKey datablock_key(&texture->id, NodeType::GENERIC_DATABLOCK);
- add_relation(animation_key, datablock_key, "Datablock Animation");
+ add_relation(animation_key, texture_key, "Datablock Animation");
}
}
@@ -2502,6 +2512,15 @@ void DepsgraphRelationBuilder::build_sound(bSound *sound)
build_parameters(&sound->id);
}
+void DepsgraphRelationBuilder::build_simulation(Simulation *simulation)
+{
+ if (built_map_.checkIsBuiltAndTag(simulation)) {
+ return;
+ }
+ build_animdata(&simulation->id);
+ build_parameters(&simulation->id);
+}
+
void DepsgraphRelationBuilder::build_scene_sequencer(Scene *scene)
{
if (scene->ed == nullptr) {
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.h b/source/blender/depsgraph/intern/builder/deg_builder_relations.h
index 099a00d66a6..caec7cc1496 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.h
@@ -68,6 +68,7 @@ struct Object;
struct ParticleSettings;
struct ParticleSystem;
struct Scene;
+struct Simulation;
struct Speaker;
struct Tex;
struct ViewLayer;
@@ -282,6 +283,7 @@ class DepsgraphRelationBuilder : public DepsgraphBuilder {
virtual void build_lightprobe(LightProbe *probe);
virtual void build_speaker(Speaker *speaker);
virtual void build_sound(bSound *sound);
+ virtual void build_simulation(Simulation *simulation);
virtual void build_scene_sequencer(Scene *scene);
virtual void build_scene_audio(Scene *scene);
virtual void build_scene_speakers(Scene *scene, ViewLayer *view_layer);
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc
index d05385a7d7c..7fe7695f195 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc
@@ -69,7 +69,7 @@ void DepsgraphRelationBuilder::build_ik_pose(Object *object,
RootPChanMap *root_map)
{
if ((con->flag & CONSTRAINT_DISABLE) != 0) {
- /* Do not add disabled IK constraints to the relations. If these needs to be temporarly
+ /* Do not add disabled IK constraints to the relations. If these needs to be temporarily
* enabled, they will be added as temporary constraints during transform. */
return;
}
diff --git a/source/blender/depsgraph/intern/eval/deg_eval.cc b/source/blender/depsgraph/intern/eval/deg_eval.cc
index c7f3c5cb2b6..e61bcb961ae 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval.cc
@@ -118,7 +118,7 @@ void evaluate_node(const DepsgraphEvalState *state, OperationNode *operation_nod
void deg_task_run_func(TaskPool *pool, void *taskdata, int thread_id)
{
- void *userdata_v = BLI_task_pool_userdata(pool);
+ void *userdata_v = BLI_task_pool_user_data(pool);
DepsgraphEvalState *state = (DepsgraphEvalState *)userdata_v;
/* Evaluate node. */
diff --git a/source/blender/draw/engines/eevee/eevee_motion_blur.c b/source/blender/draw/engines/eevee/eevee_motion_blur.c
index 13927cd5124..a6e6b30a6b1 100644
--- a/source/blender/draw/engines/eevee/eevee_motion_blur.c
+++ b/source/blender/draw/engines/eevee/eevee_motion_blur.c
@@ -73,8 +73,7 @@ static void eevee_motion_blur_camera_get_matrix_at_time(Scene *scene,
/* Past matrix */
/* FIXME : This is a temporal solution that does not take care of parent animations */
/* Recalc Anim manually */
- BKE_animsys_evaluate_animdata(
- scene, &camdata_cpy.id, camdata_cpy.adt, time, ADT_RECALC_ALL, false);
+ BKE_animsys_evaluate_animdata(&camdata_cpy.id, camdata_cpy.adt, time, ADT_RECALC_ALL, false);
BKE_object_where_is_calc_time(draw_ctx->depsgraph, scene, &cam_cpy, time);
/* Compute winmat */
diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c
index b569f909d7a..0e00e48267b 100644
--- a/source/blender/editors/animation/anim_channels_defines.c
+++ b/source/blender/editors/animation/anim_channels_defines.c
@@ -51,6 +51,7 @@
#include "DNA_pointcloud_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
+#include "DNA_simulation_types.h"
#include "DNA_space_types.h"
#include "DNA_speaker_types.h"
#include "DNA_volume_types.h"
@@ -3033,6 +3034,83 @@ static bAnimChannelType ACF_DSVOLUME = {
acf_dsvolume_setting_ptr /* pointer for setting */
};
+/* Simulation Expander ----------------------------------------- */
+
+static int acf_dssimulation_icon(bAnimListElem *UNUSED(ale))
+{
+ /* TODO: Use correct icon. */
+ return ICON_PHYSICS;
+}
+
+static int acf_dssimulation_setting_flag(bAnimContext *UNUSED(ac),
+ eAnimChannel_Settings setting,
+ bool *neg)
+{
+ /* clear extra return data first */
+ *neg = false;
+
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return SIM_DS_EXPAND;
+
+ case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
+ return ADT_NLA_EVAL_OFF;
+
+ case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
+ *neg = true;
+ return ADT_CURVES_NOT_VISIBLE;
+
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ return ADT_UI_SELECTED;
+
+ default: /* unsupported */
+ return 0;
+ }
+}
+
+static void *acf_dssimulation_setting_ptr(bAnimListElem *ale,
+ eAnimChannel_Settings setting,
+ short *type)
+{
+ Simulation *simulation = (Simulation *)ale->data;
+
+ /* clear extra return data first */
+ *type = 0;
+
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return GET_ACF_FLAG_PTR(simulation->flag, type);
+
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
+ case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
+ if (simulation->adt)
+ return GET_ACF_FLAG_PTR(simulation->adt->flag, type);
+ return NULL;
+
+ default: /* unsupported */
+ return NULL;
+ }
+}
+
+static bAnimChannelType ACF_DSSIMULATION = {
+ "Simulation Expander", /* type name */
+ ACHANNEL_ROLE_EXPANDER, /* role */
+
+ acf_generic_dataexpand_color, /* backdrop color */
+ acf_generic_dataexpand_backdrop, /* backdrop */
+ acf_generic_indention_1, /* indent level */
+ acf_generic_basic_offset, /* offset */
+
+ acf_generic_idblock_name, /* name */
+ acf_generic_idblock_name_prop, /* name prop */
+ acf_dssimulation_icon, /* icon */
+
+ acf_generic_dataexpand_setting_valid, /* has setting */
+ acf_dssimulation_setting_flag, /* flag for setting */
+ acf_dssimulation_setting_ptr /* pointer for setting */
+};
+
/* GPencil Expander ------------------------------------------- */
// TODO: just get this from RNA?
@@ -4049,6 +4127,7 @@ static void ANIM_init_channel_typeinfo_data(void)
animchannelTypeInfo[type++] = &ACF_DSHAIR; /* Hair Channel */
animchannelTypeInfo[type++] = &ACF_DSPOINTCLOUD; /* PointCloud Channel */
animchannelTypeInfo[type++] = &ACF_DSVOLUME; /* Volume Channel */
+ animchannelTypeInfo[type++] = &ACF_DSSIMULATION; /* Simulation Channel */
animchannelTypeInfo[type++] = &ACF_SHAPEKEY; /* ShapeKey */
diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c
index 4e3dc3cb220..a7ca84eb6c6 100644
--- a/source/blender/editors/animation/anim_channels_edit.c
+++ b/source/blender/editors/animation/anim_channels_edit.c
@@ -138,7 +138,8 @@ void ANIM_set_active_channel(bAnimContext *ac,
case ANIMTYPE_DSMCLIP:
case ANIMTYPE_DSHAIR:
case ANIMTYPE_DSPOINTCLOUD:
- case ANIMTYPE_DSVOLUME: {
+ case ANIMTYPE_DSVOLUME:
+ case ANIMTYPE_DSSIMULATION: {
/* need to verify that this data is valid for now */
if (ale->adt) {
ACHANNEL_SET_FLAG(ale->adt, ACHANNEL_SETFLAG_CLEAR, ADT_UI_ACTIVE);
@@ -194,7 +195,8 @@ void ANIM_set_active_channel(bAnimContext *ac,
case ANIMTYPE_DSMCLIP:
case ANIMTYPE_DSHAIR:
case ANIMTYPE_DSPOINTCLOUD:
- case ANIMTYPE_DSVOLUME: {
+ case ANIMTYPE_DSVOLUME:
+ case ANIMTYPE_DSSIMULATION: {
/* need to verify that this data is valid for now */
if (ale && ale->adt) {
ale->adt->flag |= ADT_UI_ACTIVE;
@@ -332,7 +334,8 @@ void ANIM_deselect_anim_channels(
case ANIMTYPE_DSMCLIP:
case ANIMTYPE_DSHAIR:
case ANIMTYPE_DSPOINTCLOUD:
- case ANIMTYPE_DSVOLUME: {
+ case ANIMTYPE_DSVOLUME:
+ case ANIMTYPE_DSSIMULATION: {
if ((ale->adt) && (ale->adt->flag & ADT_UI_SELECTED)) {
sel = ACHANNEL_SETFLAG_CLEAR;
}
@@ -428,7 +431,8 @@ void ANIM_deselect_anim_channels(
case ANIMTYPE_DSMCLIP:
case ANIMTYPE_DSHAIR:
case ANIMTYPE_DSPOINTCLOUD:
- case ANIMTYPE_DSVOLUME: {
+ case ANIMTYPE_DSVOLUME:
+ case ANIMTYPE_DSSIMULATION: {
/* need to verify that this data is valid for now */
if (ale->adt) {
ACHANNEL_SET_FLAG(ale->adt, sel, ADT_UI_SELECTED);
@@ -2965,7 +2969,8 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index,
case ANIMTYPE_DSMCLIP:
case ANIMTYPE_DSHAIR:
case ANIMTYPE_DSPOINTCLOUD:
- case ANIMTYPE_DSVOLUME: {
+ case ANIMTYPE_DSVOLUME:
+ case ANIMTYPE_DSSIMULATION: {
/* sanity checking... */
if (ale->adt) {
/* select/deselect */
diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c
index 4dc0bef3a1b..e4da4e66e21 100644
--- a/source/blender/editors/animation/anim_filter.c
+++ b/source/blender/editors/animation/anim_filter.c
@@ -67,6 +67,7 @@
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_sequence_types.h"
+#include "DNA_simulation_types.h"
#include "DNA_space_types.h"
#include "DNA_speaker_types.h"
#include "DNA_userdef_types.h"
@@ -826,6 +827,18 @@ static bAnimListElem *make_new_animlistelem(void *data,
ale->adt = BKE_animdata_from_id(data);
break;
}
+ case ANIMTYPE_DSSIMULATION: {
+ Simulation *simulation = (Simulation *)data;
+ AnimData *adt = simulation->adt;
+
+ ale->flag = FILTER_SIMULATION_OBJD(simulation);
+
+ ale->key_data = (adt) ? adt->action : NULL;
+ ale->datatype = ALE_ACT;
+
+ ale->adt = BKE_animdata_from_id(data);
+ break;
+ }
case ANIMTYPE_DSSKEY: {
Key *key = (Key *)data;
AnimData *adt = key->adt;
diff --git a/source/blender/editors/armature/pose_transform.c b/source/blender/editors/armature/pose_transform.c
index 31c89ca9f43..1d2bf152777 100644
--- a/source/blender/editors/armature/pose_transform.c
+++ b/source/blender/editors/armature/pose_transform.c
@@ -1240,7 +1240,7 @@ static int pose_clear_user_transforms_exec(bContext *C, wmOperator *op)
workob.adt = ob->adt;
workob.pose = dummyPose;
- BKE_animsys_evaluate_animdata(scene, &workob.id, workob.adt, cframe, ADT_RECALC_ANIM, false);
+ BKE_animsys_evaluate_animdata(&workob.id, workob.adt, cframe, ADT_RECALC_ANIM, false);
/* copy back values, but on selected bones only */
for (pchan = dummyPose->chanbase.first; pchan; pchan = pchan->next) {
diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h
index a9b34e3c735..7d38792f332 100644
--- a/source/blender/editors/include/ED_anim_api.h
+++ b/source/blender/editors/include/ED_anim_api.h
@@ -229,6 +229,7 @@ typedef enum eAnim_ChannelType {
ANIMTYPE_DSHAIR,
ANIMTYPE_DSPOINTCLOUD,
ANIMTYPE_DSVOLUME,
+ ANIMTYPE_DSSIMULATION,
ANIMTYPE_SHAPEKEY,
@@ -356,6 +357,8 @@ typedef enum eAnimFilter_Flags {
#define FILTER_HAIR_OBJD(ha) (CHECK_TYPE_INLINE(ha, Hair *), ((ha->flag & HA_DS_EXPAND)))
#define FILTER_POINTS_OBJD(pt) (CHECK_TYPE_INLINE(pt, PointCloud *), ((pt->flag & PT_DS_EXPAND)))
#define FILTER_VOLUME_OBJD(vo) (CHECK_TYPE_INLINE(vo, Volume *), ((vo->flag & VO_DS_EXPAND)))
+#define FILTER_SIMULATION_OBJD(sim) \
+ (CHECK_TYPE_INLINE(sim, Simulation *), ((sim->flag & SIM_DS_EXPAND)))
/* Variable use expanders */
#define FILTER_NTREE_DATA(ntree) \
(CHECK_TYPE_INLINE(ntree, bNodeTree *), (((ntree)->flag & NTREE_DS_EXPAND)))
diff --git a/source/blender/editors/include/ED_node.h b/source/blender/editors/include/ED_node.h
index 7a1f64b61d4..1dc98cfee2f 100644
--- a/source/blender/editors/include/ED_node.h
+++ b/source/blender/editors/include/ED_node.h
@@ -37,6 +37,7 @@ struct Tex;
struct View2D;
struct bContext;
struct bNode;
+struct bNodeSocket;
struct bNodeSocketType;
struct bNodeTree;
struct bNodeTree;
@@ -79,6 +80,10 @@ void ED_node_draw_snap(
struct View2D *v2d, const float cent[2], float size, NodeBorder border, unsigned int pos);
/* node_draw.c */
+void ED_node_socket_draw(struct bNodeSocket *sock,
+ const struct rcti *rect,
+ const float color[4],
+ float scale);
void ED_node_tree_update(const struct bContext *C);
void ED_node_tag_update_id(struct ID *id);
void ED_node_tag_update_nodetree(struct Main *bmain, struct bNodeTree *ntree, struct bNode *node);
@@ -94,6 +99,7 @@ void ED_node_set_tree_type(struct SpaceNode *snode, struct bNodeTreeType *typein
bool ED_node_is_compositor(struct SpaceNode *snode);
bool ED_node_is_shader(struct SpaceNode *snode);
bool ED_node_is_texture(struct SpaceNode *snode);
+bool ED_node_is_simulation(struct SpaceNode *snode);
void ED_node_shader_default(const struct bContext *C, struct ID *id);
void ED_node_composit_default(const struct bContext *C, struct Scene *scene);
diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h
index beba4a7199b..27b7511c8a2 100644
--- a/source/blender/editors/include/ED_transform.h
+++ b/source/blender/editors/include/ED_transform.h
@@ -157,6 +157,8 @@ int BIF_countTransformOrientation(const struct bContext *C);
#define P_GPENCIL_EDIT (1 << 13)
#define P_CURSOR_EDIT (1 << 14)
#define P_CLNOR_INVALIDATE (1 << 15)
+/* For properties performed when confirming the transformation. */
+#define P_POST_TRANSFORM (1 << 16)
void Transform_Properties(struct wmOperatorType *ot, int flags);
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 774cf8c509f..cd2e2794192 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -250,6 +250,8 @@ enum {
UI_BUT_TEXT_RIGHT = 1 << 3,
/** Prevent the button to show any tooltip. */
UI_BUT_NO_TOOLTIP = 1 << 4,
+ /** Do not add the usual horizontal padding for text drawing. */
+ UI_BUT_NO_TEXT_PADDING = 1 << 5,
/* Button align flag, for drawing groups together.
* Used in 'uiBlock.flag', take care! */
@@ -1585,6 +1587,8 @@ int UI_searchbox_size_x(void);
/* check if a string is in an existing search box */
int UI_search_items_find_index(uiSearchItems *items, const char *name);
+void UI_but_node_link_set(uiBut *but, struct bNodeSocket *socket, const float draw_color[4]);
+
void UI_block_func_handle_set(uiBlock *block, uiBlockHandleFunc func, void *arg);
void UI_block_func_butmenu_set(uiBlock *block, uiMenuHandleFunc func, void *arg);
void UI_block_func_set(uiBlock *block, uiButHandleFunc func, void *arg1, void *arg2);
@@ -1772,6 +1776,8 @@ enum {
UI_ITEM_O_DEPRESS = 1 << 10,
UI_ITEM_R_COMPACT = 1 << 11,
UI_ITEM_R_CHECKBOX_INVERT = 1 << 12,
+ /** Don't add a real decorator item, just blank space. */
+ UI_ITEM_R_FORCE_BLANK_DECORATE = 1 << 13,
};
#define UI_HEADER_OFFSET ((void)0, 0.4f * UI_UNIT_X)
@@ -1782,6 +1788,9 @@ enum {
UI_TEMPLATE_OP_PROPS_SHOW_EMPTY = 1 << 1,
UI_TEMPLATE_OP_PROPS_COMPACT = 1 << 2,
UI_TEMPLATE_OP_PROPS_HIDE_ADVANCED = 1 << 3,
+ /* Disable property split for the default layout (custom ui callbacks still have full control
+ * over the layout and can enable it). */
+ UI_TEMPLATE_OP_PROPS_NO_SPLIT_LAYOUT = 1 << 4,
};
/* used for transp checkers */
@@ -1869,7 +1878,9 @@ bool uiLayoutGetPropDecorate(uiLayout *layout);
/* layout specifiers */
uiLayout *uiLayoutRow(uiLayout *layout, bool align);
+uiLayout *uiLayoutRowWithHeading(uiLayout *layout, bool align, const char *heading);
uiLayout *uiLayoutColumn(uiLayout *layout, bool align);
+uiLayout *uiLayoutColumnWithHeading(uiLayout *layout, bool align, const char *heading);
uiLayout *uiLayoutColumnFlow(uiLayout *layout, int number, bool align);
uiLayout *uiLayoutGridFlow(uiLayout *layout,
bool row_major,
@@ -2044,11 +2055,11 @@ void uiTemplateOperatorSearch(uiLayout *layout);
void UI_but_func_menu_search(uiBut *but);
void uiTemplateMenuSearch(uiLayout *layout);
-eAutoPropButsReturn uiTemplateOperatorPropertyButs(const struct bContext *C,
- uiLayout *layout,
- struct wmOperator *op,
- const eButLabelAlign label_align,
- const short flag);
+void uiTemplateOperatorPropertyButs(const struct bContext *C,
+ uiLayout *layout,
+ struct wmOperator *op,
+ eButLabelAlign label_align,
+ short flag);
void uiTemplateHeader3D_mode(uiLayout *layout, struct bContext *C);
void uiTemplateEditModeSelection(uiLayout *layout, struct bContext *C);
void uiTemplateReportsBanner(uiLayout *layout, struct bContext *C);
@@ -2088,6 +2099,7 @@ void uiTemplateList(uiLayout *layout,
bool sort_reverse,
bool sort_lock);
void uiTemplateNodeLink(uiLayout *layout,
+ struct bContext *C,
struct bNodeTree *ntree,
struct bNode *node,
struct bNodeSocket *input);
@@ -2308,6 +2320,9 @@ void uiItemM_ptr(uiLayout *layout, struct MenuType *mt, const char *name, int ic
void uiItemM(uiLayout *layout, const char *menuname, const char *name, int icon);
/* menu contents */
void uiItemMContents(uiLayout *layout, const char *menuname);
+/* Decorators */
+void uiItemDecoratorR_prop(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index);
+void uiItemDecoratorR(uiLayout *layout, PointerRNA *ptr, const char *propname, int index);
/* value */
void uiItemV(uiLayout *layout, const char *name, int icon, int argval);
/* separator */
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 9ec660a9714..8ff3dc11dc7 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -641,6 +641,26 @@ static int ui_but_calc_float_precision(uiBut *but, double value)
/* ************** BLOCK ENDING FUNCTION ************* */
+bool ui_but_rna_equals(const uiBut *a, const uiBut *b)
+{
+ return ui_but_rna_equals_ex(a, &b->rnapoin, b->rnaprop, b->rnaindex);
+}
+
+bool ui_but_rna_equals_ex(const uiBut *but,
+ const PointerRNA *ptr,
+ const PropertyRNA *prop,
+ int index)
+{
+ if (but->rnapoin.data != ptr->data) {
+ return false;
+ }
+ if (but->rnaprop != prop || but->rnaindex != index) {
+ return false;
+ }
+
+ return true;
+}
+
/* NOTE: if but->poin is allocated memory for every defbut, things fail... */
static bool ui_but_equals_old(const uiBut *but, const uiBut *oldbut)
{
@@ -649,10 +669,7 @@ static bool ui_but_equals_old(const uiBut *but, const uiBut *oldbut)
if (but->retval != oldbut->retval) {
return false;
}
- if (but->rnapoin.data != oldbut->rnapoin.data) {
- return false;
- }
- if (but->rnaprop != oldbut->rnaprop || but->rnaindex != oldbut->rnaindex) {
+ if (!ui_but_rna_equals(but, oldbut)) {
return false;
}
if (but->func != oldbut->func) {
@@ -979,7 +996,9 @@ static void ui_menu_block_set_keyaccels(uiBlock *block)
UI_BTYPE_BUT_MENU,
UI_BTYPE_MENU,
UI_BTYPE_BLOCK,
- UI_BTYPE_PULLDOWN) ||
+ UI_BTYPE_PULLDOWN,
+ /* For PIE-menus. */
+ UI_BTYPE_ROW) ||
(but->flag & UI_HIDDEN)) {
/* pass */
}
@@ -6486,6 +6505,13 @@ uiBut *uiDefSearchButO_ptr(uiBlock *block,
return but;
}
+void UI_but_node_link_set(uiBut *but, bNodeSocket *socket, const float draw_color[4])
+{
+ but->flag |= UI_BUT_NODE_LINK;
+ but->custom_data = socket;
+ rgba_float_to_uchar(but->col, draw_color);
+}
+
/**
* push a new event onto event queue to activate the given button
* (usually a text-field) upon entering a popup
diff --git a/source/blender/editors/interface/interface_anim.c b/source/blender/editors/interface/interface_anim.c
index 15fc23bc539..877216daacc 100644
--- a/source/blender/editors/interface/interface_anim.c
+++ b/source/blender/editors/interface/interface_anim.c
@@ -28,6 +28,7 @@
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
+#include "BLI_listbase.h"
#include "BLI_string.h"
#include "BLI_string_utf8.h"
#include "BLI_utildefines.h"
@@ -114,10 +115,38 @@ void ui_but_anim_flag(uiBut *but, float cfra)
}
}
+static uiBut *ui_but_anim_decorate_find_attached_button(uiBut *but_decorate)
+{
+ uiBut *but_iter = NULL;
+
+ BLI_assert(UI_but_is_decorator(but_decorate));
+ BLI_assert(but_decorate->rnasearchpoin.data && but_decorate->rnasearchprop);
+
+ LISTBASE_CIRCULAR_BACKWARD_BEGIN (&but_decorate->block->buttons, but_iter, but_decorate->prev) {
+ if (but_iter != but_decorate && ui_but_rna_equals_ex(but_decorate,
+ &but_iter->rnasearchpoin,
+ but_iter->rnasearchprop,
+ POINTER_AS_INT(but_iter->custom_data))) {
+ return but_iter;
+ }
+ }
+ LISTBASE_CIRCULAR_BACKWARD_END(&but_decorate->block->buttons, but_iter, but_decorate->prev);
+
+ return NULL;
+}
+
void ui_but_anim_decorate_update_from_flag(uiBut *but)
{
- BLI_assert(UI_but_is_decorator(but) && but->prev);
- int flag = but->prev->flag;
+ const uiBut *but_anim = ui_but_anim_decorate_find_attached_button(but);
+
+ if (!but_anim) {
+ printf("Could not find button with matching property to decorate (%s.%s)",
+ RNA_struct_identifier(but->rnapoin.type),
+ RNA_property_identifier(but->rnaprop));
+ }
+
+ int flag = but_anim->flag;
+
if (flag & UI_BUT_DRIVEN) {
but->icon = ICON_DECORATE_DRIVER;
}
@@ -289,22 +318,26 @@ void ui_but_anim_paste_driver(bContext *C)
void ui_but_anim_decorate_cb(bContext *C, void *arg_but, void *UNUSED(arg_dummy))
{
wmWindowManager *wm = CTX_wm_manager(C);
- uiBut *but = arg_but;
- but = but->prev;
+ uiBut *but_decorate = arg_but;
+ uiBut *but_anim = ui_but_anim_decorate_find_attached_button(but_decorate);
+
+ if (!but_anim) {
+ return;
+ }
/* FIXME(campbell), swapping active pointer is weak. */
- SWAP(struct uiHandleButtonData *, but->active, but->next->active);
+ SWAP(struct uiHandleButtonData *, but_anim->active, but_decorate->active);
wm->op_undo_depth++;
- if (but->flag & UI_BUT_DRIVEN) {
+ if (but_anim->flag & UI_BUT_DRIVEN) {
/* pass */
/* TODO: report? */
}
- else if (but->flag & UI_BUT_ANIMATED_KEY) {
+ else if (but_anim->flag & UI_BUT_ANIMATED_KEY) {
PointerRNA props_ptr;
wmOperatorType *ot = WM_operatortype_find("ANIM_OT_keyframe_delete_button", false);
WM_operator_properties_create_ptr(&props_ptr, ot);
- RNA_boolean_set(&props_ptr, "all", but->rnaindex == -1);
+ RNA_boolean_set(&props_ptr, "all", but_anim->rnaindex == -1);
WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr);
WM_operator_properties_free(&props_ptr);
}
@@ -312,11 +345,11 @@ void ui_but_anim_decorate_cb(bContext *C, void *arg_but, void *UNUSED(arg_dummy)
PointerRNA props_ptr;
wmOperatorType *ot = WM_operatortype_find("ANIM_OT_keyframe_insert_button", false);
WM_operator_properties_create_ptr(&props_ptr, ot);
- RNA_boolean_set(&props_ptr, "all", but->rnaindex == -1);
+ RNA_boolean_set(&props_ptr, "all", but_anim->rnaindex == -1);
WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr);
WM_operator_properties_free(&props_ptr);
}
- SWAP(struct uiHandleButtonData *, but->active, but->next->active);
+ SWAP(struct uiHandleButtonData *, but_anim->active, but_decorate->active);
wm->op_undo_depth--;
}
diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index 084eb943665..e3184ac413f 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -2326,6 +2326,9 @@ int UI_idcode_icon_get(const int idcode)
return ICON_WORLD_DATA;
case ID_WS:
return ICON_WORKSPACE;
+ case ID_SIM:
+ /* TODO: Use correct icon. */
+ return ICON_PHYSICS;
default:
return ICON_NONE;
}
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index 51fe990bd02..c2417c86086 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -790,6 +790,11 @@ float ui_block_calc_pie_segment(struct uiBlock *block, const float event_xy[2]);
void ui_but_add_shortcut(uiBut *but, const char *key_str, const bool do_strip);
void ui_but_clipboard_free(void);
+bool ui_but_rna_equals(const uiBut *a, const uiBut *b);
+bool ui_but_rna_equals_ex(const uiBut *but,
+ const PointerRNA *ptr,
+ const PropertyRNA *prop,
+ int index);
uiBut *ui_but_find_old(uiBlock *block_old, const uiBut *but_new);
uiBut *ui_but_find_new(uiBlock *block_old, const uiBut *but_new);
@@ -853,7 +858,7 @@ void ui_draw_menu_item(const struct uiFontStyle *fstyle,
int iconid,
int state,
bool use_sep,
- int *r_name_width);
+ int *r_xmax);
void ui_draw_preview_item(
const struct uiFontStyle *fstyle, rcti *rect, const char *name, int iconid, int state);
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index cbea32f179a..80e248650e5 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -75,7 +75,7 @@
} \
(void)0
-#define UI_ITEM_PROP_SEP_DIVIDE 0.5f
+#define UI_ITEM_PROP_SEP_DIVIDE 0.4f
/* uiLayoutRoot */
@@ -135,10 +135,11 @@ enum {
UI_ITEM_BOX_ITEM = 1 << 2, /* The item is "inside" a box item */
UI_ITEM_PROP_SEP = 1 << 3,
+ UI_ITEM_INSIDE_PROP_SEP = 1 << 4,
/* Show an icon button next to each property (to set keyframes, show status).
* Enabled by default, depends on 'UI_ITEM_PROP_SEP'. */
- UI_ITEM_PROP_DECORATE = 1 << 4,
- UI_ITEM_PROP_DECORATE_NO_PAD = 1 << 5,
+ UI_ITEM_PROP_DECORATE = 1 << 5,
+ UI_ITEM_PROP_DECORATE_NO_PAD = 1 << 6,
};
typedef struct uiButtonItem {
@@ -151,8 +152,11 @@ struct uiLayout {
uiLayoutRoot *root;
bContextStore *context;
+ uiLayout *parent;
ListBase items;
+ char heading[UI_MAX_NAME_STR];
+
/** Sub layout to add child items, if not the layout itself. */
uiLayout *child_items_layout;
@@ -1780,6 +1784,7 @@ static void ui_item_rna_size(uiLayout *layout,
PropertyType type;
PropertySubType subtype;
int len, w = 0, h;
+ bool is_checkbox_only = false;
/* arbitrary extended width by type */
type = RNA_property_type(prop);
@@ -1791,6 +1796,10 @@ static void ui_item_rna_size(uiLayout *layout,
name = "non-empty text";
}
else if (type == PROP_BOOLEAN) {
+ if (icon == ICON_NONE) {
+ /* Exception for checkboxes, they need a little less space to align nicely. */
+ is_checkbox_only = true;
+ }
icon = ICON_DOT;
}
else if (type == PROP_ENUM) {
@@ -1850,6 +1859,9 @@ static void ui_item_rna_size(uiLayout *layout,
if (type == PROP_BOOLEAN && name[0]) {
w += UI_UNIT_X / 5;
}
+ else if (is_checkbox_only) {
+ w -= UI_UNIT_X / 4;
+ }
else if (type == PROP_ENUM && !icon_only) {
w += UI_UNIT_X / 4;
}
@@ -1863,13 +1875,62 @@ static void ui_item_rna_size(uiLayout *layout,
}
/**
+ * Find first layout ancestor (or self) with a heading set.
+ *
+ * \returns the layout to add the heading to as fallback (i.e. if it can't be placed in a split
+ * layout). Its #uiLayout.heading member can be cleared to mark the heading as added (so
+ * it's not added multiple times). Returns a pointer to the heading
+ */
+static uiLayout *ui_layout_heading_find(uiLayout *cur_layout)
+{
+ for (uiLayout *parent = cur_layout; parent; parent = parent->parent) {
+ if (parent->heading[0]) {
+ return parent;
+ }
+ }
+
+ return NULL;
+}
+
+static void ui_layout_heading_label_add(uiLayout *layout,
+ uiLayout *heading_layout,
+ bool right_align,
+ bool respect_prop_split)
+{
+ const int prev_alignment = layout->alignment;
+
+ if (right_align) {
+ uiLayoutSetAlignment(layout, UI_LAYOUT_ALIGN_RIGHT);
+ }
+
+ if (respect_prop_split) {
+ uiItemL_respect_property_split(layout, heading_layout->heading, ICON_NONE);
+ }
+ else {
+ uiItemL(layout, heading_layout->heading, ICON_NONE);
+ }
+ /* After adding the heading label, we have to mark it somehow as added, so it's not added again
+ * for other items in this layout. For now just clear it. */
+ heading_layout->heading[0] = '\0';
+
+ layout->alignment = prev_alignment;
+}
+
+/**
* Hack to add further items in a row into the second part of the split layout, so the label part
* keeps a fixed size.
* \return The layout to place further items in for the split layout.
*/
static uiLayout *ui_item_prop_split_layout_hack(uiLayout *layout_parent, uiLayout *layout_split)
{
+ /* Tag item as using property split layout, this is inherited to children so they can get special
+ * treatment if needed. */
+ layout_parent->item.flag |= UI_ITEM_INSIDE_PROP_SEP;
+
if (layout_parent->item.type == ITEM_LAYOUT_ROW) {
+ /* Prevent further splits within the row. */
+ uiLayoutSetPropSep(layout_parent, false);
+
layout_parent->child_items_layout = uiLayoutRow(layout_split, true);
return layout_parent->child_items_layout;
}
@@ -1888,13 +1949,18 @@ void uiItemFullR(uiLayout *layout,
uiBlock *block = layout->root->block;
char namestr[UI_MAX_NAME_STR];
const bool use_prop_sep = ((layout->item.flag & UI_ITEM_PROP_SEP) != 0);
-
- /* By default 'use_prop_sep' uses a separate column for labels.
- * This is an exception for check-boxes otherwise only the small checkbox region is clickable.
+ const bool inside_prop_sep = ((layout->item.flag & UI_ITEM_INSIDE_PROP_SEP) != 0);
+ /* Columns can define a heading to insert. If the first item added to a split layout doesn't have
+ * a label to display in the first column, the heading is inserted there. Otherwise it's inserted
+ * as a new row before the first item. */
+ uiLayout *heading_layout = ui_layout_heading_find(layout);
+ /* Although checkboxes use the split layout, they are an exception and should only place their
+ * label in the second column, to not make that almost empty.
*
* Keep using 'use_prop_sep' instead of disabling it entirely because
* we need the ability to have decorators still. */
bool use_prop_sep_split_label = use_prop_sep;
+ bool forbid_single_col = false;
#ifdef UI_PROP_DECORATE
struct {
@@ -2005,6 +2071,9 @@ void uiItemFullR(uiLayout *layout,
if (use_prop_sep) {
if (type == PROP_BOOLEAN && (icon == ICON_NONE) && !icon_only) {
use_prop_sep_split_label = false;
+ /* For checkboxes we make an expection: We allow showing them in a split row even without
+ * label. It typically relates to its neighbor items, so no need for an extra label. */
+ forbid_single_col = true;
}
}
#endif
@@ -2031,6 +2100,7 @@ void uiItemFullR(uiLayout *layout,
/* Split the label / property. */
uiLayout *layout_parent = layout;
+
if (use_prop_sep) {
uiLayout *layout_row = NULL;
#ifdef UI_PROP_DECORATE
@@ -2041,21 +2111,28 @@ void uiItemFullR(uiLayout *layout,
}
#endif /* UI_PROP_DECORATE */
- if ((name[0] == '\0') || (use_prop_sep_split_label == false)) {
+ if ((name[0] == '\0') && !forbid_single_col) {
/* Ensure we get a column when text is not set. */
layout = uiLayoutColumn(layout_row ? layout_row : layout, true);
layout->space = 0;
+ if (heading_layout) {
+ ui_layout_heading_label_add(layout, heading_layout, false, false);
+ }
}
else {
const PropertySubType subtype = RNA_property_subtype(prop);
uiLayout *layout_split = uiLayoutSplit(
layout_row ? layout_row : layout, UI_ITEM_PROP_SEP_DIVIDE, true);
+ bool label_added = false;
layout_split->space = 0;
uiLayout *layout_sub = uiLayoutColumn(layout_split, true);
layout_sub->space = 0;
- if ((index == RNA_NO_INDEX && is_array) &&
- ((!expand && ELEM(subtype, PROP_COLOR, PROP_COLOR_GAMMA, PROP_DIRECTION)) == 0)) {
+ if (!use_prop_sep_split_label) {
+ /* Pass */
+ }
+ else if ((index == RNA_NO_INDEX && is_array) &&
+ ((!expand && ELEM(subtype, PROP_COLOR, PROP_COLOR_GAMMA, PROP_DIRECTION)) == 0)) {
char name_with_suffix[UI_MAX_DRAW_STR + 2];
char str[2] = {'\0'};
for (int a = 0; a < len; a++) {
@@ -2084,6 +2161,8 @@ void uiItemFullR(uiLayout *layout,
"");
but->drawflag |= UI_BUT_TEXT_RIGHT;
but->drawflag &= ~UI_BUT_TEXT_LEFT;
+
+ label_added = true;
}
}
else {
@@ -2092,13 +2171,17 @@ void uiItemFullR(uiLayout *layout,
block, UI_BTYPE_LABEL, 0, name, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
but->drawflag |= UI_BUT_TEXT_RIGHT;
but->drawflag &= ~UI_BUT_TEXT_LEFT;
+
+ label_added = true;
}
}
- if (layout_parent) {
- layout_split = ui_item_prop_split_layout_hack(layout_parent, layout_split);
+ if (!label_added && heading_layout) {
+ ui_layout_heading_label_add(layout_sub, heading_layout, true, false);
}
+ layout_split = ui_item_prop_split_layout_hack(layout_parent, layout_split);
+
/* Watch out! We can only write into the new layout now. */
if ((type == PROP_ENUM) && (flag & UI_ITEM_R_EXPAND)) {
/* Expanded enums each have their own name. */
@@ -2113,7 +2196,9 @@ void uiItemFullR(uiLayout *layout,
}
}
else {
- name = "";
+ if (use_prop_sep_split_label) {
+ name = "";
+ }
layout = uiLayoutColumn(layout_split, true);
}
layout->space = 0;
@@ -2132,9 +2217,20 @@ void uiItemFullR(uiLayout *layout,
#endif /* UI_PROP_DECORATE */
}
/* End split. */
+ else if (heading_layout) {
+ /* Could not add heading to split layout, fallback to inserting it to the layout with the
+ * heading itself. */
+ ui_layout_heading_label_add(heading_layout, heading_layout, false, false);
+ }
/* array property */
if (index == RNA_NO_INDEX && is_array) {
+ if (inside_prop_sep) {
+ /* Within a split row, add array items to a column so they match the column layout of
+ * previous items (e.g. transform vector with lock icon for each item). */
+ layout = uiLayoutColumn(layout, true);
+ }
+
ui_item_array(layout,
block,
name,
@@ -2214,12 +2310,6 @@ void uiItemFullR(uiLayout *layout,
if (layout->activate_init) {
UI_but_flag_enable(but, UI_BUT_ACTIVATE_ON_INIT);
}
-
- if (use_prop_sep && (use_prop_sep_split_label == false)) {
- /* When the button uses it's own text right align it. */
- but->drawflag |= UI_BUT_TEXT_RIGHT;
- but->drawflag &= ~UI_BUT_TEXT_LEFT;
- }
}
/* The resulting button may have the icon set since boolean button drawing
@@ -2242,50 +2332,21 @@ void uiItemFullR(uiLayout *layout,
#ifdef UI_PROP_DECORATE
if (ui_decorate.use_prop_decorate) {
- const bool is_anim = RNA_property_animateable(ptr, prop);
uiBut *but_decorate = ui_decorate.but ? ui_decorate.but->next : block->buttons.first;
+ const bool use_blank_decorator = (flag & UI_ITEM_R_FORCE_BLANK_DECORATE);
uiLayout *layout_col = uiLayoutColumn(ui_decorate.layout, false);
layout_col->space = 0;
layout_col->emboss = UI_EMBOSS_NONE;
+
int i;
for (i = 0; i < ui_decorate.len && but_decorate; i++) {
+ PointerRNA *ptr_dec = use_blank_decorator ? NULL : &but_decorate->rnapoin;
+ PropertyRNA *prop_dec = use_blank_decorator ? NULL : but_decorate->rnaprop;
+
/* The icons are set in 'ui_but_anim_flag' */
- if (is_anim) {
- but = uiDefIconBut(block,
- UI_BTYPE_BUT,
- 0,
- ICON_DOT,
- 0,
- 0,
- UI_UNIT_X,
- UI_UNIT_Y,
- NULL,
- 0.0,
- 0.0,
- 0.0,
- 0.0,
- TIP_("Animate property"));
- UI_but_func_set(but, ui_but_anim_decorate_cb, but, NULL);
- but->flag |= UI_BUT_UNDO | UI_BUT_DRAG_LOCK;
- }
- else {
- /* We may show other information here in future, for now use empty space. */
- but = uiDefIconBut(block,
- UI_BTYPE_BUT,
- 0,
- ICON_BLANK1,
- 0,
- 0,
- UI_UNIT_X,
- UI_UNIT_Y,
- NULL,
- 0.0,
- 0.0,
- 0.0,
- 0.0,
- "");
- but->flag |= UI_BUT_DISABLED;
- }
+ uiItemDecoratorR_prop(layout_col, ptr_dec, prop_dec, but_decorate->rnaindex);
+ but = block->buttons.last;
+
/* Order the decorator after the button we decorate, this is used so we can always
* do a quick lookup. */
BLI_remlink(&block->buttons, but);
@@ -2759,6 +2820,7 @@ static uiBut *ui_item_menu(uiLayout *layout,
bool force_menu)
{
uiBlock *block = layout->root->block;
+ uiLayout *heading_layout = ui_layout_heading_find(layout);
uiBut *but;
int w, h;
@@ -2788,6 +2850,10 @@ static uiBut *ui_item_menu(uiLayout *layout,
}
}
+ if (heading_layout) {
+ ui_layout_heading_label_add(layout, heading_layout, true, true);
+ }
+
if (name[0] && icon) {
but = uiDefIconTextMenuBut(block, func, arg, icon, name, 0, 0, w, h, tip);
}
@@ -2861,6 +2927,79 @@ void uiItemMContents(uiLayout *layout, const char *menuname)
UI_menutype_draw(C, mt, layout);
}
+/**
+ * Insert a decorator item for a button with the same property as \a prop.
+ * To force inserting a blank dummy element, NULL can be passed for \a ptr and \a prop.
+ */
+void uiItemDecoratorR_prop(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index)
+{
+ uiBlock *block = layout->root->block;
+ const bool is_anim = ptr && prop && RNA_property_animateable(ptr, prop);
+ uiBut *but = NULL;
+ uiLayout *row;
+
+ UI_block_layout_set_current(block, layout);
+ row = uiLayoutRow(layout, false);
+ row->space = 0;
+ row->emboss = UI_EMBOSS_NONE;
+
+ if (is_anim) {
+ but = uiDefIconBut(block,
+ UI_BTYPE_BUT,
+ 0,
+ ICON_DOT,
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ TIP_("Animate property"));
+ UI_but_func_set(but, ui_but_anim_decorate_cb, but, NULL);
+ but->flag |= UI_BUT_UNDO | UI_BUT_DRAG_LOCK;
+ /* Reusing RNA search members, setting actual RNA data has many side-effects. */
+ but->rnasearchpoin = *ptr;
+ but->rnasearchprop = prop;
+ but->custom_data = POINTER_FROM_INT(index);
+ }
+ else {
+ /* We may show other information here in future, for now use empty space. */
+ but = uiDefIconBut(block,
+ UI_BTYPE_BUT,
+ 0,
+ ICON_BLANK1,
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ "");
+ but->flag |= UI_BUT_DISABLED;
+ }
+}
+
+void uiItemDecoratorR(uiLayout *layout, PointerRNA *ptr, const char *propname, int index)
+{
+ PropertyRNA *prop;
+
+ /* validate arguments */
+ prop = RNA_struct_find_property(ptr, propname);
+ if (!prop) {
+ ui_item_disabled(layout, propname);
+ RNA_warning("property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
+ return;
+ }
+
+ uiItemDecoratorR_prop(layout, ptr, prop, index);
+}
+
/* popover */
void uiItemPopoverPanel_ptr(
uiLayout *layout, bContext *C, PanelType *pt, const char *name, int icon)
@@ -3017,6 +3156,7 @@ uiLayout *uiItemL_respect_property_split(uiLayout *layout, const char *text, int
{
if (layout->item.flag & UI_ITEM_PROP_SEP) {
uiBlock *block = uiLayoutGetBlock(layout);
+
uiLayout *layout_row = uiLayoutRow(layout, true);
uiLayout *layout_split = uiLayoutSplit(layout_row, UI_ITEM_PROP_SEP_DIVIDE, true);
uiLayout *layout_sub = uiLayoutColumn(layout_split, true);
@@ -3029,8 +3169,9 @@ uiLayout *uiItemL_respect_property_split(uiLayout *layout, const char *text, int
layout_split = ui_item_prop_split_layout_hack(layout, layout_split);
UI_block_layout_set_current(block, layout_split);
- /* Give caller a new sub-row to place items in. */
- return layout_row;
+ /* The decorator layout uses the row the split layout was inserted to. */
+ uiLayout *layout_decorator = layout_row;
+ return layout_decorator;
}
else {
char namestr[UI_MAX_NAME_STR];
@@ -4471,13 +4612,24 @@ static void ui_litem_init_from_parent(uiLayout *litem, uiLayout *layout, int ali
litem->redalert = layout->redalert;
litem->w = layout->w;
litem->emboss = layout->emboss;
- litem->item.flag = (layout->item.flag & (UI_ITEM_PROP_SEP | UI_ITEM_PROP_DECORATE));
+ litem->item.flag = (layout->item.flag &
+ (UI_ITEM_PROP_SEP | UI_ITEM_PROP_DECORATE | UI_ITEM_INSIDE_PROP_SEP));
if (layout->child_items_layout) {
BLI_addtail(&layout->child_items_layout->items, litem);
+ litem->parent = layout->child_items_layout;
}
else {
BLI_addtail(&layout->items, litem);
+ litem->parent = layout;
+ }
+}
+
+static void ui_layout_heading_set(uiLayout *layout, const char *heading)
+{
+ BLI_assert(layout->heading[0] == '\0');
+ if (heading) {
+ STRNCPY(layout->heading, heading);
}
}
@@ -4497,6 +4649,16 @@ uiLayout *uiLayoutRow(uiLayout *layout, bool align)
return litem;
}
+/**
+ * See #uiLayoutColumnWithHeading().
+ */
+uiLayout *uiLayoutRowWithHeading(uiLayout *layout, bool align, const char *heading)
+{
+ uiLayout *litem = uiLayoutRow(layout, align);
+ ui_layout_heading_set(litem, heading);
+ return litem;
+}
+
uiLayout *uiLayoutColumn(uiLayout *layout, bool align)
{
uiLayout *litem;
@@ -4512,6 +4674,19 @@ uiLayout *uiLayoutColumn(uiLayout *layout, bool align)
return litem;
}
+/**
+ * Variant of #uiLayoutColumn() that sets a heading label for the layout if the first item is
+ * added through #uiItemFullR(). If split layout is used and the item has no string to add to the
+ * first split-column, the heading is added there instead. Otherwise the heading inserted with a
+ * new row.
+ */
+uiLayout *uiLayoutColumnWithHeading(uiLayout *layout, bool align, const char *heading)
+{
+ uiLayout *litem = uiLayoutColumn(layout, align);
+ ui_layout_heading_set(litem, heading);
+ return litem;
+}
+
uiLayout *uiLayoutColumnFlow(uiLayout *layout, int number, bool align)
{
uiLayoutItemFlow *flow;
diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c
index 2ad1c25305c..f824670cc57 100644
--- a/source/blender/editors/interface/interface_panel.c
+++ b/source/blender/editors/interface/interface_panel.c
@@ -743,7 +743,7 @@ void ui_draw_aligned_panel(uiStyle *style,
/* an open panel */
else {
/* in some occasions, draw a border */
- if (panel->flag & PNL_SELECT) {
+ if (panel->flag & PNL_SELECT && !is_subpanel) {
if (panel->control & UI_PNL_SOLID) {
UI_draw_roundbox_corner_set(UI_CNR_ALL);
}
@@ -2458,6 +2458,24 @@ static void ui_handler_remove_panel(bContext *C, void *userdata)
panel_activate_state(C, panel, PANEL_STATE_EXIT);
}
+/**
+ * Set selection state for a panel and its subpanels. The subpanels need to know they are selected
+ * too so they can be drawn above their parent when it is dragged.
+ */
+static void set_panel_selection(Panel *panel, bool value)
+{
+ if (value) {
+ panel->flag |= PNL_SELECT;
+ }
+ else {
+ panel->flag &= ~PNL_SELECT;
+ }
+
+ LISTBASE_FOREACH (Panel *, child, &panel->children) {
+ set_panel_selection(child, value);
+ }
+}
+
static void panel_activate_state(const bContext *C, Panel *panel, uiHandlePanelState state)
{
uiHandlePanelData *data = panel->activedata;
@@ -2480,10 +2498,10 @@ static void panel_activate_state(const bContext *C, Panel *panel, uiHandlePanelS
check_panel_overlap(region, NULL); /* clears */
}
- panel->flag &= ~PNL_SELECT;
+ set_panel_selection(panel, false);
}
else {
- panel->flag |= PNL_SELECT;
+ set_panel_selection(panel, true);
}
if (data && data->animtimer) {
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index ca9f12a4219..1df42659bf8 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -688,6 +688,8 @@ static const char *template_id_browse_tip(const StructRNA *type)
return N_("Browse Point Cloud Data to be linked");
case ID_VO:
return N_("Browse Volume Data to be linked");
+ case ID_SIM:
+ return N_("Browse Simulation to be linked");
}
}
return N_("Browse ID data to be linked");
@@ -753,7 +755,8 @@ static uiBut *template_id_def_new_but(uiBlock *block,
BLT_I18NCONTEXT_ID_LIGHTPROBE,
BLT_I18NCONTEXT_ID_HAIR,
BLT_I18NCONTEXT_ID_POINTCLOUD,
- BLT_I18NCONTEXT_ID_VOLUME, );
+ BLT_I18NCONTEXT_ID_VOLUME,
+ BLT_I18NCONTEXT_ID_SIMULATION, );
/* Note: BLT_I18N_MSGID_MULTI_CTXT takes a maximum number of parameters,
* check the definition to see if a new call must be added when the limit
* is exceeded. */
@@ -2432,21 +2435,196 @@ uiLayout *uiTemplateShaderFx(uiLayout *layout, bContext *UNUSED(C), PointerRNA *
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Operator Redo Buttons Template
+/** \name Operator Property Buttons Template
* \{ */
-static void template_operator_redo_property_buts_draw(
- const bContext *C, wmOperator *op, uiLayout *layout, int layout_flags, bool *r_has_advanced)
+typedef struct uiTemplateOperatorPropertyPollParam {
+ const bContext *C;
+ wmOperator *op;
+ short flag;
+} uiTemplateOperatorPropertyPollParam;
+
+#ifdef USE_OP_RESET_BUT
+static void ui_layout_operator_buts__reset_cb(bContext *UNUSED(C),
+ void *op_pt,
+ void *UNUSED(arg_dummy2))
+{
+ WM_operator_properties_reset((wmOperator *)op_pt);
+}
+#endif
+
+static bool ui_layout_operator_buts_poll_property(struct PointerRNA *UNUSED(ptr),
+ struct PropertyRNA *prop,
+ void *user_data)
+{
+ uiTemplateOperatorPropertyPollParam *params = user_data;
+
+ if ((params->flag & UI_TEMPLATE_OP_PROPS_HIDE_ADVANCED) &&
+ (RNA_property_tags(prop) & OP_PROP_TAG_ADVANCED)) {
+ return false;
+ }
+ return params->op->type->poll_property(params->C, params->op, prop);
+}
+
+static eAutoPropButsReturn template_operator_property_buts_draw_single(
+ const bContext *C,
+ wmOperator *op,
+ uiLayout *layout,
+ const eButLabelAlign label_align,
+ int layout_flags)
+{
+ uiBlock *block = uiLayoutGetBlock(layout);
+ eAutoPropButsReturn return_info = 0;
+
+ if (!op->properties) {
+ IDPropertyTemplate val = {0};
+ op->properties = IDP_New(IDP_GROUP, &val, "wmOperatorProperties");
+ }
+
+ /* poll() on this operator may still fail,
+ * at the moment there is no nice feedback when this happens just fails silently. */
+ if (!WM_operator_repeat_check(C, op)) {
+ UI_block_lock_set(block, true, "Operator can't' redo");
+ return return_info;
+ }
+ else {
+ /* useful for macros where only one of the steps can't be re-done */
+ UI_block_lock_clear(block);
+ }
+
+ if (layout_flags & UI_TEMPLATE_OP_PROPS_SHOW_TITLE) {
+ uiItemL(layout, WM_operatortype_name(op->type, op->ptr), ICON_NONE);
+ }
+
+ /* menu */
+ if (op->type->flag & OPTYPE_PRESET) {
+ /* XXX, no simple way to get WM_MT_operator_presets.bl_label
+ * from python! Label remains the same always! */
+ PointerRNA op_ptr;
+ uiLayout *row;
+
+ block->ui_operator = op;
+
+ row = uiLayoutRow(layout, true);
+ uiItemM(row, "WM_MT_operator_presets", NULL, ICON_NONE);
+
+ wmOperatorType *ot = WM_operatortype_find("WM_OT_operator_preset_add", false);
+ uiItemFullO_ptr(row, ot, "", ICON_ADD, NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr);
+ RNA_string_set(&op_ptr, "operator", op->type->idname);
+
+ uiItemFullO_ptr(row, ot, "", ICON_REMOVE, NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr);
+ RNA_string_set(&op_ptr, "operator", op->type->idname);
+ RNA_boolean_set(&op_ptr, "remove_active", true);
+ }
+
+ if (op->type->ui) {
+ op->layout = layout;
+ op->type->ui((bContext *)C, op);
+ op->layout = NULL;
+
+ /* UI_LAYOUT_OP_SHOW_EMPTY ignored. retun_info is ignored too. We could
+ * allow ot.ui callback to return this, but not needed right now. */
+ }
+ else {
+ wmWindowManager *wm = CTX_wm_manager(C);
+ PointerRNA ptr;
+ uiTemplateOperatorPropertyPollParam user_data = {.C = C, .op = op, .flag = layout_flags};
+ const bool use_prop_split = (layout_flags & UI_TEMPLATE_OP_PROPS_NO_SPLIT_LAYOUT) == 0;
+
+ RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
+
+ uiLayoutSetPropSep(layout, use_prop_split);
+ uiLayoutSetPropDecorate(layout, false);
+
+ /* main draw call */
+ return_info = uiDefAutoButsRNA(
+ layout,
+ &ptr,
+ op->type->poll_property ? ui_layout_operator_buts_poll_property : NULL,
+ op->type->poll_property ? &user_data : NULL,
+ op->type->prop,
+ label_align,
+ (layout_flags & UI_TEMPLATE_OP_PROPS_COMPACT));
+
+ if ((return_info & UI_PROP_BUTS_NONE_ADDED) &&
+ (layout_flags & UI_TEMPLATE_OP_PROPS_SHOW_EMPTY)) {
+ uiItemL(layout, IFACE_("No Properties"), ICON_NONE);
+ }
+ }
+
+#ifdef USE_OP_RESET_BUT
+ /* its possible that reset can do nothing if all have PROP_SKIP_SAVE enabled
+ * but this is not so important if this button is drawn in those cases
+ * (which isn't all that likely anyway) - campbell */
+ if (op->properties->len) {
+ uiBut *but;
+ uiLayout *col; /* needed to avoid alignment errors with previous buttons */
+
+ col = uiLayoutColumn(layout, false);
+ block = uiLayoutGetBlock(col);
+ but = uiDefIconTextBut(block,
+ UI_BTYPE_BUT,
+ 0,
+ ICON_FILE_REFRESH,
+ IFACE_("Reset"),
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ TIP_("Reset operator defaults"));
+ UI_but_func_set(but, ui_layout_operator_buts__reset_cb, op, NULL);
+ }
+#endif
+
+ /* set various special settings for buttons */
+
+ /* Only do this if we're not refreshing an existing UI. */
+ if (block->oldblock == NULL) {
+ const bool is_popup = (block->flag & UI_BLOCK_KEEP_OPEN) != 0;
+ uiBut *but;
+
+ for (but = block->buttons.first; but; but = but->next) {
+ /* no undo for buttons for operator redo panels */
+ UI_but_flag_disable(but, UI_BUT_UNDO);
+
+ /* only for popups, see [#36109] */
+
+ /* if button is operator's default property, and a text-field, enable focus for it
+ * - this is used for allowing operators with popups to rename stuff with fewer clicks
+ */
+ if (is_popup) {
+ if ((but->rnaprop == op->type->prop) && (but->type == UI_BTYPE_TEXT)) {
+ UI_but_focus_on_enter_event(CTX_wm_window(C), but);
+ }
+ }
+ }
+ }
+
+ return return_info;
+}
+
+static void template_operator_property_buts_draw_recursive(const bContext *C,
+ wmOperator *op,
+ uiLayout *layout,
+ const eButLabelAlign label_align,
+ int layout_flags,
+ bool *r_has_advanced)
{
if (op->type->flag & OPTYPE_MACRO) {
LISTBASE_FOREACH (wmOperator *, macro_op, &op->macro) {
- template_operator_redo_property_buts_draw(C, macro_op, layout, layout_flags, r_has_advanced);
+ template_operator_property_buts_draw_recursive(
+ C, macro_op, layout, label_align, layout_flags, r_has_advanced);
}
}
else {
/* Might want to make label_align adjustable somehow. */
- eAutoPropButsReturn return_info = uiTemplateOperatorPropertyButs(
- C, layout, op, UI_BUT_LABEL_ALIGN_NONE, layout_flags);
+ eAutoPropButsReturn return_info = template_operator_property_buts_draw_single(
+ C, op, layout, label_align, layout_flags);
if (return_info & UI_PROP_BUTS_ANY_FAILED_CHECK) {
if (r_has_advanced) {
*r_has_advanced = true;
@@ -2455,6 +2633,61 @@ static void template_operator_redo_property_buts_draw(
}
}
+static bool ui_layout_operator_properties_only_booleans(const bContext *C,
+ wmWindowManager *wm,
+ wmOperator *op,
+ int layout_flags)
+{
+ if (op->type->flag & OPTYPE_MACRO) {
+ LISTBASE_FOREACH (wmOperator *, macro_op, &op->macro) {
+ if (!ui_layout_operator_properties_only_booleans(C, wm, macro_op, layout_flags)) {
+ return false;
+ }
+ }
+ }
+ else {
+ uiTemplateOperatorPropertyPollParam user_data = {.C = C, .op = op, .flag = layout_flags};
+ PointerRNA ptr;
+
+ RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
+
+ RNA_STRUCT_BEGIN (&ptr, prop) {
+ if (RNA_property_flag(prop) & PROP_HIDDEN) {
+ continue;
+ }
+ if (op->type->poll_property &&
+ !ui_layout_operator_buts_poll_property(&ptr, prop, &user_data)) {
+ continue;
+ }
+ if (RNA_property_type(prop) != PROP_BOOLEAN) {
+ return false;
+ }
+ }
+ RNA_STRUCT_END;
+ }
+
+ return true;
+}
+
+/**
+ * Draw Operator property buttons for redoing execution with different settings.
+ * This function does not initialize the layout,
+ * functions can be called on the layout before and after.
+ */
+void uiTemplateOperatorPropertyButs(
+ const bContext *C, uiLayout *layout, wmOperator *op, eButLabelAlign label_align, short flag)
+{
+ wmWindowManager *wm = CTX_wm_manager(C);
+
+ /* If there are only checkbox items, don't use split layout by default. It looks weird if the
+ * checkboxes only use half the width. */
+ if (ui_layout_operator_properties_only_booleans(C, wm, op, flag)) {
+ flag |= UI_TEMPLATE_OP_PROPS_NO_SPLIT_LAYOUT;
+ }
+
+ template_operator_property_buts_draw_recursive(C, op, layout, label_align, flag, NULL);
+}
+
void uiTemplateOperatorRedoProperties(uiLayout *layout, const bContext *C)
{
wmOperator *op = WM_operator_last_redo(C);
@@ -2487,8 +2720,8 @@ void uiTemplateOperatorRedoProperties(uiLayout *layout, const bContext *C)
#endif
UI_block_func_handle_set(block, ED_undo_operator_repeat_cb_evt, op);
- template_operator_redo_property_buts_draw(
- C, op, layout, layout_flags, NULL /* &has_advanced */);
+ template_operator_property_buts_draw_recursive(
+ C, op, layout, UI_BUT_LABEL_ALIGN_NONE, layout_flags, NULL /* &has_advanced */);
/* Warning! this leaves the handle function for any other users of this block. */
#if 0
@@ -7348,187 +7581,6 @@ void uiTemplateMenuSearch(uiLayout *layout)
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Operator Redo Properties Template
- * \{ */
-
-#ifdef USE_OP_RESET_BUT
-static void ui_layout_operator_buts__reset_cb(bContext *UNUSED(C),
- void *op_pt,
- void *UNUSED(arg_dummy2))
-{
- WM_operator_properties_reset((wmOperator *)op_pt);
-}
-#endif
-
-struct uiTemplateOperatorPropertyPollParam {
- const bContext *C;
- wmOperator *op;
- short flag;
-};
-
-static bool ui_layout_operator_buts_poll_property(struct PointerRNA *UNUSED(ptr),
- struct PropertyRNA *prop,
- void *user_data)
-{
- struct uiTemplateOperatorPropertyPollParam *params = user_data;
- if ((params->flag & UI_TEMPLATE_OP_PROPS_HIDE_ADVANCED) &&
- (RNA_property_tags(prop) & OP_PROP_TAG_ADVANCED)) {
- return false;
- }
- return params->op->type->poll_property(params->C, params->op, prop);
-}
-
-/**
- * Draw Operator property buttons for redoing execution with different settings.
- * This function does not initialize the layout,
- * functions can be called on the layout before and after.
- */
-eAutoPropButsReturn uiTemplateOperatorPropertyButs(const bContext *C,
- uiLayout *layout,
- wmOperator *op,
- const eButLabelAlign label_align,
- const short flag)
-{
- uiBlock *block = uiLayoutGetBlock(layout);
- eAutoPropButsReturn return_info = 0;
-
- if (!op->properties) {
- IDPropertyTemplate val = {0};
- op->properties = IDP_New(IDP_GROUP, &val, "wmOperatorProperties");
- }
-
- /* poll() on this operator may still fail,
- * at the moment there is no nice feedback when this happens just fails silently. */
- if (!WM_operator_repeat_check(C, op)) {
- UI_block_lock_set(block, true, "Operator can't' redo");
- return return_info;
- }
- else {
- /* useful for macros where only one of the steps can't be re-done */
- UI_block_lock_clear(block);
- }
-
- if (flag & UI_TEMPLATE_OP_PROPS_SHOW_TITLE) {
- uiItemL(layout, WM_operatortype_name(op->type, op->ptr), ICON_NONE);
- }
-
- /* menu */
- if (op->type->flag & OPTYPE_PRESET) {
- /* XXX, no simple way to get WM_MT_operator_presets.bl_label
- * from python! Label remains the same always! */
- PointerRNA op_ptr;
- uiLayout *row;
-
- block->ui_operator = op;
-
- row = uiLayoutRow(layout, true);
- uiItemM(row, "WM_MT_operator_presets", NULL, ICON_NONE);
-
- wmOperatorType *ot = WM_operatortype_find("WM_OT_operator_preset_add", false);
- uiItemFullO_ptr(row, ot, "", ICON_ADD, NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr);
- RNA_string_set(&op_ptr, "operator", op->type->idname);
-
- uiItemFullO_ptr(row, ot, "", ICON_REMOVE, NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr);
- RNA_string_set(&op_ptr, "operator", op->type->idname);
- RNA_boolean_set(&op_ptr, "remove_active", true);
- }
-
- if (op->type->ui) {
- op->layout = layout;
- op->type->ui((bContext *)C, op);
- op->layout = NULL;
-
- /* UI_LAYOUT_OP_SHOW_EMPTY ignored. return_info is ignored too. We could
- * allow ot.ui callback to return this, but not needed right now. */
- }
- else {
- wmWindowManager *wm = CTX_wm_manager(C);
- PointerRNA ptr;
- struct uiTemplateOperatorPropertyPollParam user_data = {
- .C = C,
- .op = op,
- .flag = flag,
- };
-
- RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
-
- uiLayoutSetPropSep(layout, true);
- uiLayoutSetPropDecorate(layout, false);
-
- /* main draw call */
- return_info = uiDefAutoButsRNA(
- layout,
- &ptr,
- op->type->poll_property ? ui_layout_operator_buts_poll_property : NULL,
- op->type->poll_property ? &user_data : NULL,
- op->type->prop,
- label_align,
- (flag & UI_TEMPLATE_OP_PROPS_COMPACT));
-
- if ((return_info & UI_PROP_BUTS_NONE_ADDED) && (flag & UI_TEMPLATE_OP_PROPS_SHOW_EMPTY)) {
- uiItemL(layout, IFACE_("No Properties"), ICON_NONE);
- }
- }
-
-#ifdef USE_OP_RESET_BUT
- /* its possible that reset can do nothing if all have PROP_SKIP_SAVE enabled
- * but this is not so important if this button is drawn in those cases
- * (which isn't all that likely anyway) - campbell */
- if (op->properties->len) {
- uiBut *but;
- uiLayout *col; /* needed to avoid alignment errors with previous buttons */
-
- col = uiLayoutColumn(layout, false);
- block = uiLayoutGetBlock(col);
- but = uiDefIconTextBut(block,
- UI_BTYPE_BUT,
- 0,
- ICON_FILE_REFRESH,
- IFACE_("Reset"),
- 0,
- 0,
- UI_UNIT_X,
- UI_UNIT_Y,
- NULL,
- 0.0,
- 0.0,
- 0.0,
- 0.0,
- TIP_("Reset operator defaults"));
- UI_but_func_set(but, ui_layout_operator_buts__reset_cb, op, NULL);
- }
-#endif
-
- /* set various special settings for buttons */
-
- /* Only do this if we're not refreshing an existing UI. */
- if (block->oldblock == NULL) {
- const bool is_popup = (block->flag & UI_BLOCK_KEEP_OPEN) != 0;
- uiBut *but;
-
- for (but = block->buttons.first; but; but = but->next) {
- /* no undo for buttons for operator redo panels */
- UI_but_flag_disable(but, UI_BUT_UNDO);
-
- /* only for popups, see [#36109] */
-
- /* if button is operator's default property, and a text-field, enable focus for it
- * - this is used for allowing operators with popups to rename stuff with fewer clicks
- */
- if (is_popup) {
- if ((but->rnaprop == op->type->prop) && (but->type == UI_BTYPE_TEXT)) {
- UI_but_focus_on_enter_event(CTX_wm_window(C), but);
- }
- }
- }
- }
-
- return return_info;
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
/** \name Running Jobs Template
* \{ */
diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c
index 79a90d27373..d8c168a1423 100644
--- a/source/blender/editors/interface/interface_utils.c
+++ b/source/blender/editors/interface/interface_utils.c
@@ -294,7 +294,7 @@ eAutoPropButsReturn uiDefAutoButsRNA(uiLayout *layout,
const bool compact)
{
eAutoPropButsReturn return_info = UI_PROP_BUTS_NONE_ADDED;
- uiLayout *split, *col;
+ uiLayout *col;
const char *name;
RNA_STRUCT_BEGIN (ptr, prop) {
@@ -325,19 +325,11 @@ eAutoPropButsReturn uiDefAutoButsRNA(uiLayout *layout,
}
else {
BLI_assert(label_align == UI_BUT_LABEL_ALIGN_SPLIT_COLUMN);
- split = uiLayoutSplit(layout, 0.5f, false);
-
- col = uiLayoutColumn(split, false);
- uiItemL(col, (is_boolean) ? "" : name, ICON_NONE);
- col = uiLayoutColumn(split, false);
+ col = uiLayoutColumn(layout, true);
+ /* Let uiItemFullR() create the split layout. */
+ uiLayoutSetPropSep(col, true);
}
- /* May need to add more cases here.
- * don't override enum flag names */
-
- /* name is shown above, empty name for button below */
- name = (flag & PROP_ENUM_FLAG || is_boolean) ? NULL : "";
-
break;
}
case UI_BUT_LABEL_ALIGN_NONE:
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index ae40b01c77d..064fa14a75e 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -42,6 +42,8 @@
#include "BLF_api.h"
+#include "ED_node.h"
+
#include "UI_interface.h"
#include "UI_interface_icons.h"
@@ -2394,6 +2396,30 @@ static void widget_draw_extra_icons(const uiWidgetColors *wcol,
}
}
+static void widget_draw_node_link_socket(const uiWidgetColors *wcol,
+ const rcti *rect,
+ uiBut *but,
+ float alpha)
+{
+ /* Node socket pointer can be passed as custom_data, see UI_but_node_link_set(). */
+ if (but->custom_data) {
+ const float scale = 0.9f / but->block->aspect;
+
+ float col[4];
+ rgba_uchar_to_float(col, but->col);
+ col[3] *= alpha;
+
+ GPU_blend(true);
+ UI_widgetbase_draw_cache_flush();
+ GPU_blend(false);
+
+ ED_node_socket_draw(but->custom_data, rect, col, scale);
+ }
+ else {
+ widget_draw_icon(but, ICON_LAYER_USED, alpha, rect, wcol->text);
+ }
+}
+
/* draws text and icons for buttons */
static void widget_draw_text_icon(const uiFontStyle *fstyle,
const uiWidgetColors *wcol,
@@ -2403,15 +2429,27 @@ static void widget_draw_text_icon(const uiFontStyle *fstyle,
const bool show_menu_icon = ui_but_draw_menu_icon(but);
float alpha = (float)wcol->text[3] / 255.0f;
char password_str[UI_MAX_DRAW_STR];
+ bool no_text_padding = but->drawflag & UI_BUT_NO_TEXT_PADDING;
ui_but_text_password_hide(password_str, but, false);
/* check for button text label */
if (ELEM(but->type, UI_BTYPE_MENU, UI_BTYPE_POPOVER) && (but->flag & UI_BUT_NODE_LINK)) {
rcti temp = *rect;
- temp.xmin = rect->xmax - BLI_rcti_size_y(rect) - 1;
- widget_draw_icon(but, ICON_LAYER_USED, alpha, &temp, wcol->text);
- rect->xmax = temp.xmin;
+ const int size = BLI_rcti_size_y(rect) + 1; /* Not the icon size! */
+
+ if (but->drawflag & UI_BUT_ICON_LEFT) {
+ temp.xmax = rect->xmin + size;
+ rect->xmin = temp.xmax;
+ /* Further padding looks off. */
+ no_text_padding = true;
+ }
+ else {
+ temp.xmin = rect->xmax - size;
+ rect->xmax = temp.xmin;
+ }
+
+ widget_draw_node_link_socket(wcol, &temp, but, alpha);
}
/* If there's an icon too (made with uiDefIconTextBut) then draw the icon
@@ -2496,28 +2534,30 @@ static void widget_draw_text_icon(const uiFontStyle *fstyle,
rect->xmin += icon_size + icon_padding;
}
- int text_padding = (UI_TEXT_MARGIN_X * U.widget_unit) / but->block->aspect;
- if (but->editstr) {
- rect->xmin += text_padding;
- }
- else if (but->flag & UI_BUT_DRAG_MULTI) {
- bool text_is_edited = ui_but_drag_multi_edit_get(but) != NULL;
- if (text_is_edited) {
+ if (!no_text_padding) {
+ int text_padding = (UI_TEXT_MARGIN_X * U.widget_unit) / but->block->aspect;
+ if (but->editstr) {
rect->xmin += text_padding;
}
- }
- else if (but->drawflag & UI_BUT_TEXT_LEFT) {
-
- /* Reduce the left padding for labels without an icon. */
- if ((but->type == UI_BTYPE_LABEL) && !(but->flag & UI_HAS_ICON) &&
- !ui_block_is_menu(but->block)) {
- text_padding /= 2;
+ else if (but->flag & UI_BUT_DRAG_MULTI) {
+ bool text_is_edited = ui_but_drag_multi_edit_get(but) != NULL;
+ if (text_is_edited) {
+ rect->xmin += text_padding;
+ }
}
+ else if (but->drawflag & UI_BUT_TEXT_LEFT) {
- rect->xmin += text_padding;
- }
- else if (but->drawflag & UI_BUT_TEXT_RIGHT) {
- rect->xmax -= text_padding;
+ /* Reduce the left padding for labels without an icon. */
+ if ((but->type == UI_BTYPE_LABEL) && !(but->flag & UI_HAS_ICON) &&
+ !ui_block_is_menu(but->block)) {
+ text_padding /= 2;
+ }
+
+ rect->xmin += text_padding;
+ }
+ else if (but->drawflag & UI_BUT_TEXT_RIGHT) {
+ rect->xmax -= text_padding;
+ }
}
/* Menu contains sub-menu items with triangle icon on their right. Shortcut
@@ -4121,10 +4161,10 @@ static void widget_optionbut(uiWidgetColors *wcol,
/* smaller */
delta = 1 + BLI_rcti_size_y(&recttemp) / 8;
- recttemp.xmin += delta;
- recttemp.ymin += delta;
- recttemp.xmax -= delta;
- recttemp.ymax -= delta;
+ BLI_rcti_resize(
+ &recttemp, BLI_rcti_size_x(&recttemp) - delta * 2, BLI_rcti_size_y(&recttemp) - delta * 2);
+ /* Keep one edge in place. */
+ BLI_rcti_translate(&recttemp, text_before_widget ? delta : -delta, 0);
rad = wcol->roundness * BLI_rcti_size_y(&recttemp);
round_box_edges(&wtb, UI_CNR_ALL, &recttemp, rad);
@@ -4136,13 +4176,13 @@ static void widget_optionbut(uiWidgetColors *wcol,
widgetbase_draw(&wtb, wcol);
- /* text space */
- const float offset = BLI_rcti_size_y(rect) * 0.7 + delta;
+ /* Text space - factor is really just eyeballed. */
+ const float offset = delta * 0.9;
if (text_before_widget) {
- rect->xmax -= offset;
+ rect->xmax = recttemp.xmin - offset;
}
else {
- rect->xmin += offset;
+ rect->xmin = recttemp.xmax + offset;
}
}
@@ -4699,9 +4739,14 @@ void ui_draw_but(const bContext *C, ARegion *region, uiStyle *style, uiBut *but,
case UI_BTYPE_CHECKBOX_N:
if (!(but->flag & UI_HAS_ICON)) {
wt = widget_type(UI_WTYPE_CHECKBOX);
+
if ((but->drawflag & (UI_BUT_TEXT_LEFT | UI_BUT_TEXT_RIGHT)) == 0) {
but->drawflag |= UI_BUT_TEXT_LEFT;
}
+ /* widget_optionbut() carefully sets the text rectangle for fine tuned paddings. If the
+ * text drawing were to add its own padding, DPI and zoom factor would be applied twice
+ * in the final padding, so it's difficult to control it. */
+ but->drawflag |= UI_BUT_NO_TEXT_PADDING;
}
else {
wt = widget_type(UI_WTYPE_TOGGLE);
@@ -5252,15 +5297,23 @@ void ui_draw_tooltip_background(const uiStyle *UNUSED(style), uiBlock *UNUSED(bl
wt->draw(&wt->wcol, rect, 0, 0);
}
-/* helper call to draw a menu item without button */
-/* state: UI_ACTIVE or 0 */
+/**
+ * Helper call to draw a menu item without a button.
+ *
+ * \param state: The state of the button,
+ * typically #UI_ACTIVE, #UI_BUT_DISABLED, #UI_BUT_INACTIVE.
+ * \param use_sep: When true, characters after the last #UI_SEP_CHAR are right aligned,
+ * use for displaying key shortcuts.
+ * \param r_xmax: The right hand position of the text, this takes into the icon,
+ * padding and text clipping when there is not enough room to display the full text.
+ */
void ui_draw_menu_item(const uiFontStyle *fstyle,
rcti *rect,
const char *name,
int iconid,
int state,
bool use_sep,
- int *r_name_width)
+ int *r_xmax)
{
uiWidgetType *wt = widget_type(UI_WTYPE_MENU_ITEM);
rcti _rect = *rect;
@@ -5323,8 +5376,8 @@ void ui_draw_menu_item(const uiFontStyle *fstyle,
&xofs,
&yofs,
&info);
- if (r_name_width != NULL) {
- *r_name_width = xofs + info.width;
+ if (r_xmax != NULL) {
+ *r_xmax = xofs + info.width;
}
}
diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c
index c07166b9ad2..72f6535eadf 100644
--- a/source/blender/editors/interface/view2d.c
+++ b/source/blender/editors/interface/view2d.c
@@ -60,7 +60,7 @@
#include "interface_intern.h"
-static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize, bool mask_scrollers);
+static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize);
/* -------------------------------------------------------------------- */
/** \name Internal Utilities
@@ -134,7 +134,7 @@ void UI_view2d_mask_from_win(const View2D *v2d, rcti *r_mask)
*
* \param mask_scroll: Optionally clamp scrollbars by this region.
*/
-static void view2d_masks(View2D *v2d, bool check_scrollers, const rcti *mask_scroll)
+static void view2d_masks(View2D *v2d, const rcti *mask_scroll)
{
int scroll;
@@ -144,26 +144,24 @@ static void view2d_masks(View2D *v2d, bool check_scrollers, const rcti *mask_scr
mask_scroll = &v2d->mask;
}
- if (check_scrollers) {
- /* check size if hiding flag is set: */
- if (v2d->scroll & V2D_SCROLL_HORIZONTAL_HIDE) {
- if (!(v2d->scroll & V2D_SCROLL_HORIZONTAL_HANDLES)) {
- if (BLI_rctf_size_x(&v2d->tot) > BLI_rctf_size_x(&v2d->cur)) {
- v2d->scroll &= ~V2D_SCROLL_HORIZONTAL_FULLR;
- }
- else {
- v2d->scroll |= V2D_SCROLL_HORIZONTAL_FULLR;
- }
+ /* check size if hiding flag is set: */
+ if (v2d->scroll & V2D_SCROLL_HORIZONTAL_HIDE) {
+ if (!(v2d->scroll & V2D_SCROLL_HORIZONTAL_HANDLES)) {
+ if (BLI_rctf_size_x(&v2d->tot) > BLI_rctf_size_x(&v2d->cur)) {
+ v2d->scroll &= ~V2D_SCROLL_HORIZONTAL_FULLR;
+ }
+ else {
+ v2d->scroll |= V2D_SCROLL_HORIZONTAL_FULLR;
}
}
- if (v2d->scroll & V2D_SCROLL_VERTICAL_HIDE) {
- if (!(v2d->scroll & V2D_SCROLL_VERTICAL_HANDLES)) {
- if (BLI_rctf_size_y(&v2d->tot) + 0.01f > BLI_rctf_size_y(&v2d->cur)) {
- v2d->scroll &= ~V2D_SCROLL_VERTICAL_FULLR;
- }
- else {
- v2d->scroll |= V2D_SCROLL_VERTICAL_FULLR;
- }
+ }
+ if (v2d->scroll & V2D_SCROLL_VERTICAL_HIDE) {
+ if (!(v2d->scroll & V2D_SCROLL_VERTICAL_HANDLES)) {
+ if (BLI_rctf_size_y(&v2d->tot) + 0.01f > BLI_rctf_size_y(&v2d->cur)) {
+ v2d->scroll &= ~V2D_SCROLL_VERTICAL_FULLR;
+ }
+ else {
+ v2d->scroll |= V2D_SCROLL_VERTICAL_FULLR;
}
}
}
@@ -385,8 +383,7 @@ void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy)
v2d->winx = winx;
v2d->winy = winy;
- /* set masks (always do), but leave scroller scheck to totrect_set */
- view2d_masks(v2d, 0, NULL);
+ view2d_masks(v2d, NULL);
if (do_init) {
/* Visible by default. */
@@ -394,13 +391,12 @@ void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy)
}
/* set 'tot' rect before setting cur? */
- /* XXX confusing stuff here still -
- * I made this function not check scroller hide - that happens in totrect_set */
+ /* XXX confusing stuff here still */
if (tot_changed) {
UI_view2d_totRect_set_resize(v2d, winx, winy, !do_init);
}
else {
- ui_view2d_curRect_validate_resize(v2d, !do_init, 0);
+ ui_view2d_curRect_validate_resize(v2d, !do_init);
}
}
@@ -409,7 +405,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, bool resize, bool mask_scrollers)
+static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize)
{
float totwidth, totheight, curwidth, curheight, width, height;
float winx, winy;
@@ -851,12 +847,12 @@ static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize, bool mas
}
/* set masks */
- view2d_masks(v2d, mask_scrollers, NULL);
+ view2d_masks(v2d, NULL);
}
void UI_view2d_curRect_validate(View2D *v2d)
{
- ui_view2d_curRect_validate_resize(v2d, 0, 1);
+ ui_view2d_curRect_validate_resize(v2d, false);
}
/* ------------------ */
@@ -982,22 +978,10 @@ 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, bool resize)
{
- // int scroll = view2d_scroll_mapped(v2d->scroll);
-
/* don't do anything if either value is 0 */
width = abs(width);
height = abs(height);
- /* hrumf! */
- /* XXX: there are work arounds for this in the panel and file browse code. */
- /* round to int, because this is called with width + V2D_SCROLL_WIDTH */
- // if (scroll & V2D_SCROLL_HORIZONTAL) {
- // width -= (int)V2D_SCROLL_WIDTH;
- // }
- // if (scroll & V2D_SCROLL_VERTICAL) {
- // height -= (int)V2D_SCROLL_HEIGHT;
- // }
-
if (ELEM(0, width, height)) {
if (G.debug & G_DEBUG) {
printf("Error: View2D totRect set exiting: v2d=%p width=%d height=%d\n",
@@ -1047,20 +1031,12 @@ void UI_view2d_totRect_set_resize(View2D *v2d, int width, int height, bool resiz
}
/* make sure that 'cur' rect is in a valid state as a result of these changes */
- ui_view2d_curRect_validate_resize(v2d, resize, 1);
+ ui_view2d_curRect_validate_resize(v2d, resize);
}
void UI_view2d_totRect_set(View2D *v2d, int width, int height)
{
- int scroll = view2d_scroll_mapped(v2d->scroll);
-
- UI_view2d_totRect_set_resize(v2d, width, height, 0);
-
- /* solve bad recursion... if scroller state changed,
- * mask is different, so you get different rects */
- if (scroll != view2d_scroll_mapped(v2d->scroll)) {
- UI_view2d_totRect_set_resize(v2d, width, height, 0);
- }
+ UI_view2d_totRect_set_resize(v2d, width, height, false);
}
bool UI_view2d_tab_set(View2D *v2d, int tab)
@@ -1448,7 +1424,7 @@ View2DScrollers *UI_view2d_scrollers_calc(View2D *v2d, const rcti *mask_custom)
scrollers = MEM_callocN(sizeof(View2DScrollers), "View2DScrollers");
/* Always update before drawing (for dynamically sized scrollers). */
- view2d_masks(v2d, false, mask_custom);
+ view2d_masks(v2d, mask_custom);
vert = v2d->vert;
hor = v2d->hor;
diff --git a/source/blender/editors/mesh/editmesh_extrude.c b/source/blender/editors/mesh/editmesh_extrude.c
index 23f622ac359..bf6c5a2f829 100644
--- a/source/blender/editors/mesh/editmesh_extrude.c
+++ b/source/blender/editors/mesh/editmesh_extrude.c
@@ -226,6 +226,7 @@ static bool edbm_extrude_ex(Object *obedit,
char htype,
const char hflag,
const bool use_normal_flip,
+ const bool use_dissolve_ortho_edges,
const bool use_mirror,
const bool use_select_history)
{
@@ -241,6 +242,7 @@ static bool edbm_extrude_ex(Object *obedit,
BMO_op_init(bm, &extop, BMO_FLAG_DEFAULTS, "extrude_face_region");
BMO_slot_bool_set(extop.slots_in, "use_normal_flip", use_normal_flip);
+ BMO_slot_bool_set(extop.slots_in, "use_dissolve_ortho_edges", use_dissolve_ortho_edges);
BMO_slot_bool_set(extop.slots_in, "use_select_history", use_select_history);
BMO_slot_buffer_from_enabled_hflag(bm, &extop, extop.slots_in, "geom", htype, hflag);
@@ -312,7 +314,7 @@ static int edbm_extrude_repeat_exec(bContext *C, wmOperator *op)
mul_v3_m3v3(offset_local, tmat, offset);
for (int a = 0; a < steps; a++) {
- edbm_extrude_ex(obedit, em, BM_ALL_NOLOOP, BM_ELEM_SELECT, false, false, true);
+ edbm_extrude_ex(obedit, em, BM_ALL_NOLOOP, BM_ELEM_SELECT, false, false, false, true);
BMO_op_callf(
em->bm, BMO_FLAG_DEFAULTS, "translate vec=%v verts=%hv", offset_local, BM_ELEM_SELECT);
}
@@ -359,6 +361,7 @@ void MESH_OT_extrude_repeat(wmOperatorType *ot)
static bool edbm_extrude_mesh(Object *obedit, BMEditMesh *em, wmOperator *op)
{
const bool use_normal_flip = RNA_boolean_get(op->ptr, "use_normal_flip");
+ const bool use_dissolve_ortho_edges = RNA_boolean_get(op->ptr, "use_dissolve_ortho_edges");
const char htype = edbm_extrude_htype_from_em_select(em);
enum { NONE = 0, ELEM_FLAG, VERT_ONLY, EDGE_ONLY } nr;
bool changed = false;
@@ -401,7 +404,14 @@ static bool edbm_extrude_mesh(Object *obedit, BMEditMesh *em, wmOperator *op)
case NONE:
return false;
case ELEM_FLAG:
- changed = edbm_extrude_ex(obedit, em, htype, BM_ELEM_SELECT, use_normal_flip, true, true);
+ changed = edbm_extrude_ex(obedit,
+ em,
+ htype,
+ BM_ELEM_SELECT,
+ use_normal_flip,
+ use_dissolve_ortho_edges,
+ true,
+ true);
break;
case VERT_ONLY:
changed = edbm_extrude_verts_indiv(em, op, BM_ELEM_SELECT);
@@ -465,6 +475,7 @@ void MESH_OT_extrude_region(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
RNA_def_boolean(ot->srna, "use_normal_flip", false, "Flip Normals", "");
+ RNA_def_boolean(ot->srna, "use_dissolve_ortho_edges", false, "Dissolve Orthogonal Edges", "");
Transform_Properties(ot, P_NO_DEFAULTS | P_MIRROR_DUMMY);
}
@@ -519,6 +530,7 @@ void MESH_OT_extrude_context(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
RNA_def_boolean(ot->srna, "use_normal_flip", false, "Flip Normals", "");
+ RNA_def_boolean(ot->srna, "use_dissolve_ortho_edges", false, "Dissolve Orthogonal Edges", "");
Transform_Properties(ot, P_NO_DEFAULTS | P_MIRROR_DUMMY);
}
@@ -840,7 +852,7 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const w
}
}
- edbm_extrude_ex(vc.obedit, vc.em, extrude_htype, BM_ELEM_SELECT, false, true, true);
+ edbm_extrude_ex(vc.obedit, vc.em, extrude_htype, BM_ELEM_SELECT, false, false, true, true);
EDBM_op_callf(
vc.em, op, "rotate verts=%hv cent=%v matrix=%m3", BM_ELEM_SELECT, local_center, mat);
EDBM_op_callf(vc.em, op, "translate verts=%hv vec=%v", BM_ELEM_SELECT, ofs);
diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c
index 66b2c66f2aa..c52a5956ac4 100644
--- a/source/blender/editors/mesh/mesh_ops.c
+++ b/source/blender/editors/mesh/mesh_ops.c
@@ -277,6 +277,18 @@ void ED_operatormacros_mesh(void)
RNA_boolean_set(otmacro->ptr, "use_proportional_edit", false);
RNA_boolean_set(otmacro->ptr, "mirror", false);
+ ot = WM_operatortype_append_macro(
+ "MESH_OT_extrude_region_dissolve_move_intersect",
+ "Extrude, Dissolve, Move and Intersect",
+ "Extrude, dissolves edges whose faces form a flat surface and intersect new edges",
+ OPTYPE_UNDO | OPTYPE_REGISTER);
+ otmacro = WM_operatortype_macro_define(ot, "MESH_OT_extrude_region");
+ RNA_boolean_set(otmacro->ptr, "use_dissolve_ortho_edges", true);
+ otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
+ RNA_boolean_set(otmacro->ptr, "use_proportional_edit", false);
+ RNA_boolean_set(otmacro->ptr, "mirror", false);
+ RNA_boolean_set(otmacro->ptr, "use_automerge_and_split", true);
+
ot = WM_operatortype_append_macro("MESH_OT_extrude_context_move",
"Extrude Region and Move",
"Extrude region together along the average normal",
diff --git a/source/blender/editors/object/CMakeLists.txt b/source/blender/editors/object/CMakeLists.txt
index c2c25e47908..de9cc72dfa4 100644
--- a/source/blender/editors/object/CMakeLists.txt
+++ b/source/blender/editors/object/CMakeLists.txt
@@ -34,6 +34,7 @@ set(INC
../../shader_fx
../../render/extern/include
../../windowmanager
+ ../../../../intern/clog
../../../../intern/glew-mx
../../../../intern/guardedalloc
)
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index 5506895613b..d944d4c4dd3 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -100,6 +100,8 @@
#include "RNA_define.h"
#include "RNA_enum_types.h"
+#include "CLG_log.h"
+
/* for menu/popup icons etc etc*/
#include "UI_interface.h"
@@ -112,21 +114,17 @@
#include "object_intern.h" // own include
+static CLG_LogRef LOG = {"ed.object.edit"};
+
/* prototypes */
typedef struct MoveToCollectionData MoveToCollectionData;
static void move_to_collection_menus_items(struct uiLayout *layout,
struct MoveToCollectionData *menu);
static ListBase selected_objects_get(bContext *C);
-/* ************* XXX **************** */
-static void error(const char *UNUSED(arg))
-{
-}
-
-/* port over here */
-static void error_libdata(void)
-{
-}
+/* -------------------------------------------------------------------- */
+/** \name Internal Utilities
+ * \{ */
Object *ED_object_context(bContext *C)
{
@@ -147,7 +145,11 @@ Object *ED_object_active_context(bContext *C)
return ob;
}
-/* ********************** object hiding *************************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Hide Operator
+ * \{ */
static bool object_hide_poll(bContext *C)
{
@@ -401,7 +403,11 @@ void OBJECT_OT_hide_collection(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
}
-/* ******************* toggle editmode operator ***************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Toggle Edit-Mode Operator
+ * \{ */
static bool mesh_needs_keyindex(Main *bmain, const Mesh *me)
{
@@ -441,7 +447,11 @@ static bool ED_object_editmode_load_ex(Main *bmain, Object *obedit, const bool f
}
if (me->edit_mesh->bm->totvert > MESH_MAX_VERTS) {
- error("Too many vertices");
+ /* This used to be warned int the UI, we could warn again although it's quite rare. */
+ CLOG_WARN(&LOG,
+ "Too many vertices for mesh '%s' (%d)",
+ me->id.name + 2,
+ me->edit_mesh->bm->totvert);
return false;
}
@@ -600,7 +610,8 @@ bool ED_object_editmode_enter_ex(Main *bmain, Scene *scene, Object *ob, int flag
}
if (BKE_object_obdata_is_libdata(ob)) {
- error_libdata();
+ /* Ideally the caller should check this. */
+ CLOG_WARN(&LOG, "Unable to enter edit-mode on library data for object '%s'", ob->id.name + 2);
return false;
}
@@ -777,7 +788,11 @@ void OBJECT_OT_editmode_toggle(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* *************************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Toggle Pose-Mode Operator
+ * \{ */
static int posemode_exec(bContext *C, wmOperator *op)
{
@@ -861,7 +876,11 @@ void OBJECT_OT_posemode_toggle(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* ******************* force field toggle operator ***************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Force Field Toggle Operator
+ * \{ */
void ED_object_check_force_modifiers(Main *bmain, Scene *scene, Object *object)
{
@@ -924,8 +943,11 @@ void OBJECT_OT_forcefield_toggle(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* ********************************************** */
-/* Motion Paths */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Calculate Motion Paths Operator
+ * \{ */
static eAnimvizCalcRange object_path_convert_range(eObjectPathCalcRange range)
{
@@ -1019,7 +1041,7 @@ static int object_calculate_paths_invoke(bContext *C, wmOperator *op, const wmEv
}
/* show popup dialog to allow editing of range... */
- /* FIXME: hardcoded dimensions here are just arbitrary */
+ /* FIXME: hard-coded dimensions here are just arbitrary. */
return WM_operator_props_dialog_popup(C, op, 200);
}
@@ -1088,7 +1110,11 @@ void OBJECT_OT_paths_calculate(wmOperatorType *ot)
MAXFRAME / 2.0);
}
-/* --------- */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Update Motion Paths Operator
+ * \{ */
static bool object_update_paths_poll(bContext *C)
{
@@ -1132,7 +1158,11 @@ void OBJECT_OT_paths_update(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* --------- */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Clear Motion Paths Operator
+ * \{ */
/* Helper for ED_objects_clear_paths() */
static void object_clear_mpath(Object *ob)
@@ -1151,14 +1181,14 @@ static void object_clear_mpath(Object *ob)
void ED_objects_clear_paths(bContext *C, bool only_selected)
{
if (only_selected) {
- /* loop over all selected + sedtiable objects in scene */
+ /* Loop over all selected + editable objects in scene. */
CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
object_clear_mpath(ob);
}
CTX_DATA_END;
}
else {
- /* loop over all edtiable objects in scene */
+ /* Loop over all editable objects in scene. */
CTX_DATA_BEGIN (C, Object *, ob, editable_objects) {
object_clear_mpath(ob);
}
@@ -1210,13 +1240,17 @@ void OBJECT_OT_paths_clear(wmOperatorType *ot)
RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
}
-/* --------- */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Update Motion Paths Range from Scene Operator
+ * \{ */
static int object_update_paths_range_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
- /* loop over all edtiable objects in scene */
+ /* Loop over all editable objects in scene. */
CTX_DATA_BEGIN (C, Object *, ob, editable_objects) {
/* use Preview Range or Full Frame Range - whichever is in use */
ob->avs.path_sf = PSFRA;
@@ -1246,63 +1280,99 @@ void OBJECT_OT_paths_range_update(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/********************** Smooth/Flat *********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Object Shade Smooth/Flat Operator
+ * \{ */
static int shade_smooth_exec(bContext *C, wmOperator *op)
{
- ID *data;
- Curve *cu;
- Nurb *nu;
- int clear = (STREQ(op->idname, "OBJECT_OT_shade_flat"));
- bool done = false, linked_data = false;
+ const bool use_smooth = STREQ(op->idname, "OBJECT_OT_shade_smooth");
+ bool changed_multi = false;
+ bool has_linked_data = false;
- CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
- data = ob->data;
+ ListBase ctx_objects = {NULL, NULL};
+ CollectionPointerLink ctx_ob_single_active = {NULL};
+
+ /* For modes that only use an active object, don't handle the whole selection. */
+ {
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *obact = OBACT(view_layer);
+ if (obact && ((obact->mode & OB_MODE_ALL_PAINT))) {
+ ctx_ob_single_active.ptr.data = obact;
+ BLI_addtail(&ctx_objects, &ctx_ob_single_active);
+ }
+ }
+
+ if (ctx_objects.first != &ctx_ob_single_active) {
+ CTX_data_selected_editable_objects(C, &ctx_objects);
+ }
+
+ for (CollectionPointerLink *ctx_ob = ctx_objects.first; ctx_ob; ctx_ob = ctx_ob->next) {
+ Object *ob = ctx_ob->ptr.data;
+ ID *data = ob->data;
+ if (data != NULL) {
+ data->tag |= LIB_TAG_DOIT;
+ }
+ }
+
+ for (CollectionPointerLink *ctx_ob = ctx_objects.first; ctx_ob; ctx_ob = ctx_ob->next) {
+ /* Always un-tag all object data-blocks irrespective of our ability to operate on them. */
+ Object *ob = ctx_ob->ptr.data;
+ ID *data = ob->data;
+ if ((data == NULL) || ((data->tag & LIB_TAG_DOIT) == 0)) {
+ continue;
+ }
+ data->tag &= ~LIB_TAG_DOIT;
+ /* Finished un-tagging, continue with regular logic. */
if (data && ID_IS_LINKED(data)) {
- linked_data = true;
+ has_linked_data = true;
continue;
}
+ bool changed = false;
if (ob->type == OB_MESH) {
- BKE_mesh_smooth_flag_set(ob->data, !clear);
-
+ BKE_mesh_smooth_flag_set(ob->data, use_smooth);
BKE_mesh_batch_cache_dirty_tag(ob->data, BKE_MESH_BATCH_DIRTY_ALL);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
-
- done = true;
+ changed = true;
}
else if (ELEM(ob->type, OB_SURF, OB_CURVE)) {
- cu = ob->data;
+ BKE_curve_smooth_flag_set(ob->data, use_smooth);
+ changed = true;
+ }
- for (nu = cu->nurb.first; nu; nu = nu->next) {
- if (!clear) {
- nu->flag |= ME_SMOOTH;
- }
- else {
- nu->flag &= ~ME_SMOOTH;
- }
- }
+ if (changed) {
+ changed_multi = true;
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
-
- done = true;
}
}
- CTX_DATA_END;
- if (linked_data) {
+ if (ctx_objects.first != &ctx_ob_single_active) {
+ BLI_freelistN(&ctx_objects);
+ }
+
+ if (has_linked_data) {
BKE_report(op->reports, RPT_WARNING, "Can't edit linked mesh or curve data");
}
- return (done) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ return (changed_multi) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
static bool shade_poll(bContext *C)
{
- return (CTX_data_edit_object(C) == NULL);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *obact = OBACT(view_layer);
+ if (obact != NULL) {
+ /* Doesn't handle edit-data, sculpt dynamic-topology, or their undo systems. */
+ if (obact->mode & (OB_MODE_EDIT | OB_MODE_SCULPT)) {
+ return false;
+ }
+ }
+ return true;
}
void OBJECT_OT_shade_flat(wmOperatorType *ot)
@@ -1335,7 +1405,11 @@ void OBJECT_OT_shade_smooth(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* ********************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Object Mode Set Operator
+ * \{ */
static const EnumPropertyItem *object_mode_set_itemsf(bContext *C,
PointerRNA *UNUSED(ptr),
@@ -1516,6 +1590,12 @@ void OBJECT_OT_mode_set_with_submode(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Object Link/Move to Collection Operator
+ * \{ */
+
static ListBase selected_objects_get(bContext *C)
{
ListBase objects = {NULL};
@@ -1856,3 +1936,5 @@ void OBJECT_OT_link_to_collection(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
ot->prop = prop;
}
+
+/** \} */
diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c
index a24f3ba2269..1b662ccc389 100644
--- a/source/blender/editors/object/object_modifier.c
+++ b/source/blender/editors/object/object_modifier.c
@@ -142,10 +142,11 @@ static void object_force_modifier_bind_simple_options(Depsgraph *depsgraph,
md_eval->mode = mode;
}
-/** Add a modifier to given object, including relevant extra processing needed by some physics
- * types (particles, simulations...).
+/**
+ * Add a modifier to given object, including relevant extra processing needed by some physics types
+ * (particles, simulations...).
*
- * \param scene is only used to set current frame in some cases, and may be NULL.
+ * \param scene: is only used to set current frame in some cases, and may be NULL.
*/
ModifierData *ED_object_modifier_add(
ReportList *reports, Main *bmain, Scene *scene, Object *ob, const char *name, int type)
@@ -2455,7 +2456,7 @@ static int ocean_bake_exec(bContext *C, wmOperator *op)
* No drivers or other modifier parameters. */
/* TODO(sergey): This operates on an original data, so no flush is needed. However, baking
* usually should happen on an evaluated objects, so this seems to be deeper issue here. */
- BKE_animsys_evaluate_animdata(scene, (ID *)ob, ob->adt, f, ADT_RECALC_ANIM, false);
+ BKE_animsys_evaluate_animdata((ID *)ob, ob->adt, f, ADT_RECALC_ANIM, false);
och->time[i] = omd->time;
i++;
diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c
index b3d76382d26..1eede3e5197 100644
--- a/source/blender/editors/object/object_transform.c
+++ b/source/blender/editors/object/object_transform.c
@@ -1608,6 +1608,7 @@ struct XFormAxisItem {
float rot_mat[3][3];
void *obtfm;
float xform_dist;
+ bool is_z_flip;
#ifdef USE_RELATIVE_ROTATION
/* use when translating multiple */
@@ -1730,11 +1731,16 @@ static void object_apply_location(Object *ob, const float loc[3])
static void object_orient_to_location(Object *ob,
const float rot_orig[3][3],
const float axis[3],
- const float location[3])
+ const float location[3],
+ const bool z_flip)
{
float delta[3];
sub_v3_v3v3(delta, ob->obmat[3], location);
if (normalize_v3(delta) != 0.0f) {
+ if (z_flip) {
+ negate_v3(delta);
+ }
+
if (len_squared_v3v3(delta, axis) > FLT_EPSILON) {
float delta_rot[3][3];
float final_rot[3][3];
@@ -1840,6 +1846,11 @@ static int object_transform_axis_target_invoke(bContext *C, wmOperator *op, cons
for (int i = 0; i < xfd->object_data_len; i++, item++) {
item->obtfm = BKE_object_tfm_backup(item->ob);
BKE_object_rot_to_mat3(item->ob, item->rot_mat, true);
+
+ /* Detect negative scale matrix. */
+ float full_mat3[3][3];
+ BKE_object_to_mat3(item->ob, full_mat3);
+ item->is_z_flip = dot_v3v3(item->rot_mat[2], full_mat3[2]) < 0.0f;
}
}
@@ -1974,7 +1985,7 @@ static int object_transform_axis_target_modal(bContext *C, wmOperator *op, const
}
object_orient_to_location(
- item->ob, item->rot_mat, item->rot_mat[2], location_world);
+ item->ob, item->rot_mat, item->rot_mat[2], location_world, item->is_z_flip);
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, item->ob);
}
if (normal_found) {
@@ -1986,7 +1997,8 @@ static int object_transform_axis_target_modal(bContext *C, wmOperator *op, const
else {
struct XFormAxisItem *item = xfd->object_data;
for (int i = 0; i < xfd->object_data_len; i++, item++) {
- object_orient_to_location(item->ob, item->rot_mat, item->rot_mat[2], location_world);
+ object_orient_to_location(
+ item->ob, item->rot_mat, item->rot_mat[2], location_world, item->is_z_flip);
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, item->ob);
}
xfd->prev.is_normal_valid = false;
diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c
index 75ae0299318..3ce5aeedae8 100644
--- a/source/blender/editors/physics/particle_edit.c
+++ b/source/blender/editors/physics/particle_edit.c
@@ -4084,7 +4084,6 @@ typedef struct BrushAddCountIterData {
short size;
float imat[4][4];
ParticleData *add_pars;
- int num_added;
} BrushAddCountIterData;
typedef struct BrushAddCountIterTLSData {
@@ -4176,12 +4175,19 @@ static void brush_add_count_iter(void *__restrict iter_data_v,
}
}
-static void brush_add_count_iter_finalize(void *__restrict userdata_v,
- void *__restrict userdata_chunk_v)
+static void brush_add_count_iter_reduce(const void *__restrict UNUSED(userdata),
+ void *__restrict join_v,
+ void *__restrict chunk_v)
+{
+ BrushAddCountIterTLSData *join = (BrushAddCountIterTLSData *)join_v;
+ BrushAddCountIterTLSData *tls = (BrushAddCountIterTLSData *)chunk_v;
+ join->num_added += tls->num_added;
+}
+
+static void brush_add_count_iter_free(const void *__restrict UNUSED(userdata_v),
+ void *__restrict chunk_v)
{
- BrushAddCountIterData *iter_data = (BrushAddCountIterData *)userdata_v;
- BrushAddCountIterTLSData *tls = (BrushAddCountIterTLSData *)userdata_chunk_v;
- iter_data->num_added += tls->num_added;
+ BrushAddCountIterTLSData *tls = (BrushAddCountIterTLSData *)chunk_v;
if (tls->rng != NULL) {
BLI_rng_free(tls->rng);
}
@@ -4245,7 +4251,6 @@ static int brush_add(const bContext *C, PEData *data, short number)
iter_data.number = number;
iter_data.size = size;
iter_data.add_pars = add_pars;
- iter_data.num_added = 0;
copy_m4_m4(iter_data.imat, imat);
BrushAddCountIterTLSData tls = {NULL};
@@ -4255,13 +4260,14 @@ static int brush_add(const bContext *C, PEData *data, short number)
settings.scheduling_mode = TASK_SCHEDULING_DYNAMIC;
settings.userdata_chunk = &tls;
settings.userdata_chunk_size = sizeof(BrushAddCountIterTLSData);
- settings.func_finalize = brush_add_count_iter_finalize;
+ settings.func_reduce = brush_add_count_iter_reduce;
+ settings.func_free = brush_add_count_iter_free;
BLI_task_parallel_range(0, number, &iter_data, brush_add_count_iter, &settings);
/* Convert add_parse to a dense array, where all new particles are in the
* beginning of the array.
*/
- n = iter_data.num_added;
+ n = tls.num_added;
for (int current_iter = 0, new_index = 0; current_iter < number; current_iter++) {
if (add_pars[current_iter].num == DMCACHE_NOTFOUND) {
continue;
diff --git a/source/blender/editors/physics/physics_fluid.c b/source/blender/editors/physics/physics_fluid.c
index eb808398254..5550f1a63c8 100644
--- a/source/blender/editors/physics/physics_fluid.c
+++ b/source/blender/editors/physics/physics_fluid.c
@@ -361,7 +361,7 @@ static void fluid_bake_endjob(void *customdata)
RPT_INFO, "Fluid: %s complete! (%.2f)", job->name, PIL_check_seconds_timer() - job->start);
}
else {
- if (mds->error != NULL && mds->error[0] != '\0') {
+ if (mds->error[0] != '\0') {
WM_reportf(RPT_ERROR, "Fluid: %s failed: %s", job->name, mds->error);
}
else { /* User canceled the bake */
@@ -473,7 +473,7 @@ static void fluid_free_endjob(void *customdata)
RPT_INFO, "Fluid: %s complete! (%.2f)", job->name, PIL_check_seconds_timer() - job->start);
}
else {
- if (mds->error != NULL && mds->error[0] != '\0') {
+ if (mds->error[0] != '\0') {
WM_reportf(RPT_ERROR, "Fluid: %s failed: %s", job->name, mds->error);
}
else { /* User canceled the free job */
diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c
index f35f92feaec..b0444f25a8c 100644
--- a/source/blender/editors/render/render_opengl.c
+++ b/source/blender/editors/render/render_opengl.c
@@ -630,6 +630,7 @@ static int gather_frames_to_render_for_id(LibraryIDLinkCallbackData *cb_data)
case ID_HA: /* Hair */
case ID_PT: /* PointCloud */
case ID_VO: /* Volume */
+ case ID_SIM: /* Simulation */
break;
/* Blacklist: */
@@ -1034,7 +1035,7 @@ typedef struct WriteTaskData {
static void write_result_func(TaskPool *__restrict pool, void *task_data_v, int UNUSED(thread_id))
{
- OGLRender *oglrender = (OGLRender *)BLI_task_pool_userdata(pool);
+ OGLRender *oglrender = (OGLRender *)BLI_task_pool_user_data(pool);
WriteTaskData *task_data = (WriteTaskData *)task_data_v;
Scene *scene = &task_data->tmp_scene;
RenderResult *rr = task_data->rr;
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index 49838b62b71..69cfe72308f 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -2532,7 +2532,6 @@ void ED_region_panels_layout_ex(const bContext *C,
v2d->scroll |= (V2D_SCROLL_BOTTOM);
v2d->scroll &= ~(V2D_SCROLL_RIGHT);
}
- const int scroll = v2d->scroll;
/* collect categories */
if (use_category_tabs) {
@@ -2642,16 +2641,6 @@ void ED_region_panels_layout_ex(const bContext *C,
/* this also changes the 'cur' */
UI_view2d_totRect_set(v2d, x, y);
- if (scroll != v2d->scroll) {
- /* Note: this code scales fine, but because of rounding differences, positions of elements
- * flip +1 or -1 pixel compared to redoing the entire layout again.
- * Leaving in commented code for future tests */
-#if 0
- UI_panels_scale(region, BLI_rctf_size_x(&v2d->cur));
- break;
-#endif
- }
-
if (use_category_tabs) {
region->runtime.category = category;
}
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index 452984f2333..b66964d0e7f 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -3870,7 +3870,6 @@ static int region_quadview_exec(bContext *C, wmOperator *op)
rv3d->viewlock_quad = RV3D_VIEWLOCK_INIT;
rv3d->viewlock = 0;
- rv3d->rflag &= ~RV3D_CLIPPING;
/* Accumulate locks, in case they're mixed. */
for (region_iter = area->regionbase.first; region_iter; region_iter = region_iter->next) {
diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c
index a1652ca0e88..4a51b3c8b8a 100644
--- a/source/blender/editors/space_clip/clip_draw.c
+++ b/source/blender/editors/space_clip/clip_draw.c
@@ -1651,7 +1651,7 @@ static void draw_tracking_tracks(SpaceClip *sc,
pos[0] = (pos[0] / (pos[3] * 2.0f) + 0.5f) * width;
pos[1] = (pos[1] / (pos[3] * 2.0f) + 0.5f) * height * aspy;
- BKE_tracking_distort_v2(tracking, pos, npos);
+ BKE_tracking_distort_v2(tracking, width, height, pos, npos);
if (npos[0] >= 0.0f && npos[1] >= 0.0f && npos[0] <= width && npos[1] <= height * aspy) {
vec[0] = (marker->pos[0] + track->offset[0]) * width;
@@ -1777,7 +1777,7 @@ static void draw_distortion(SpaceClip *sc,
for (i = 0; i <= n; i++) {
for (j = 0; j <= n; j++) {
if (i == 0 || j == 0 || i == n || j == n) {
- BKE_tracking_distort_v2(tracking, pos, tpos);
+ BKE_tracking_distort_v2(tracking, width, height, pos, tpos);
for (a = 0; a < 4; a++) {
int ok;
@@ -1810,7 +1810,7 @@ static void draw_distortion(SpaceClip *sc,
pos[0] = idx[a][0] * dx;
pos[1] = idx[a][1] * dy;
- BKE_tracking_undistort_v2(tracking, pos, tpos);
+ BKE_tracking_undistort_v2(tracking, width, height, pos, tpos);
minmax_v2v2_v2(min, max, tpos);
}
@@ -1821,7 +1821,7 @@ static void draw_distortion(SpaceClip *sc,
for (i = 0; i <= n; i++) {
for (j = 0; j <= n; j++) {
- BKE_tracking_distort_v2(tracking, pos, grid[i][j]);
+ BKE_tracking_distort_v2(tracking, width, height, pos, grid[i][j]);
grid[i][j][0] /= width;
grid[i][j][1] /= height * aspy;
@@ -1897,8 +1897,8 @@ static void draw_distortion(SpaceClip *sc,
/* we want to distort only long straight lines */
if (stroke->totpoints == 2) {
- BKE_tracking_undistort_v2(tracking, pos, pos);
- BKE_tracking_undistort_v2(tracking, npos, npos);
+ BKE_tracking_undistort_v2(tracking, width, height, pos, pos);
+ BKE_tracking_undistort_v2(tracking, width, height, npos, npos);
}
sub_v2_v2v2(dpos, npos, pos);
@@ -1907,7 +1907,7 @@ static void draw_distortion(SpaceClip *sc,
immBegin(GPU_PRIM_LINE_STRIP, steps + 1);
for (j = 0; j <= steps; j++) {
- BKE_tracking_distort_v2(tracking, pos, tpos);
+ BKE_tracking_distort_v2(tracking, width, height, pos, tpos);
immVertex2f(position, tpos[0] / width, tpos[1] / (height * aspy));
add_v2_v2(pos, dpos);
diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c
index cce01947ab7..657635b845d 100644
--- a/source/blender/editors/space_clip/clip_editor.c
+++ b/source/blender/editors/space_clip/clip_editor.c
@@ -546,7 +546,7 @@ void ED_clip_point_undistorted_pos(SpaceClip *sc, const float co[2], float r_co[
r_co[0] *= width;
r_co[1] *= height * aspy;
- BKE_tracking_undistort_v2(&clip->tracking, r_co, r_co);
+ BKE_tracking_undistort_v2(&clip->tracking, width, height, r_co, r_co);
r_co[0] /= width;
r_co[1] /= height * aspy;
@@ -580,7 +580,7 @@ void ED_clip_point_stable_pos(
float aspy = 1.0f / tracking->camera.pixel_aspect;
float tmp[2] = {*xr * width, *yr * height * aspy};
- BKE_tracking_distort_v2(tracking, tmp, tmp);
+ BKE_tracking_distort_v2(tracking, width, height, tmp, tmp);
*xr = tmp[0] / width;
*yr = tmp[1] / (height * aspy);
@@ -887,7 +887,7 @@ static uchar *prefetch_thread_next_frame(PrefetchQueue *queue,
static void prefetch_task_func(TaskPool *__restrict pool, void *task_data, int UNUSED(threadid))
{
- PrefetchQueue *queue = (PrefetchQueue *)BLI_task_pool_userdata(pool);
+ PrefetchQueue *queue = (PrefetchQueue *)BLI_task_pool_user_data(pool);
MovieClip *clip = (MovieClip *)task_data;
uchar *mem;
size_t size;
diff --git a/source/blender/editors/space_clip/clip_ops.c b/source/blender/editors/space_clip/clip_ops.c
index 3204374b747..b849fbd9250 100644
--- a/source/blender/editors/space_clip/clip_ops.c
+++ b/source/blender/editors/space_clip/clip_ops.c
@@ -1370,7 +1370,7 @@ static uchar *proxy_thread_next_frame(ProxyQueue *queue,
static void proxy_task_func(TaskPool *__restrict pool, void *task_data, int UNUSED(threadid))
{
ProxyThread *data = (ProxyThread *)task_data;
- ProxyQueue *queue = (ProxyQueue *)BLI_task_pool_userdata(pool);
+ ProxyQueue *queue = (ProxyQueue *)BLI_task_pool_user_data(pool);
uchar *mem;
size_t size;
int cfra;
diff --git a/source/blender/editors/space_clip/clip_utils.c b/source/blender/editors/space_clip/clip_utils.c
index 4a0df454a78..03f791ad70d 100644
--- a/source/blender/editors/space_clip/clip_utils.c
+++ b/source/blender/editors/space_clip/clip_utils.c
@@ -166,7 +166,8 @@ static float calculate_reprojection_error_at_marker(MovieClip *clip,
reprojected_position[1] = (reprojected_position[1] / (reprojected_position[3] * 2.0f) + 0.5f) *
clip_height * aspy;
- BKE_tracking_distort_v2(tracking, reprojected_position, reprojected_position);
+ BKE_tracking_distort_v2(
+ tracking, clip_width, clip_height, reprojected_position, reprojected_position);
marker_position[0] = (marker->pos[0] + track->offset[0]) * clip_width;
marker_position[1] = (marker->pos[1] + track->offset[1]) * clip_height * aspy;
diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c
index ac8fa413f07..c04d08d7b78 100644
--- a/source/blender/editors/space_file/filelist.c
+++ b/source/blender/editors/space_file/filelist.c
@@ -1268,7 +1268,7 @@ static void filelist_cache_preview_runf(TaskPool *__restrict pool,
void *taskdata,
int UNUSED(threadid))
{
- FileListEntryCache *cache = BLI_task_pool_userdata(pool);
+ FileListEntryCache *cache = BLI_task_pool_user_data(pool);
FileListEntryPreviewTaskData *preview_taskdata = taskdata;
FileListEntryPreview *preview = preview_taskdata->preview;
@@ -1306,9 +1306,7 @@ static void filelist_cache_preview_runf(TaskPool *__restrict pool,
// printf("%s: End (%d)...\n", __func__, threadid);
}
-static void filelist_cache_preview_freef(TaskPool *__restrict UNUSED(pool),
- void *taskdata,
- int UNUSED(threadid))
+static void filelist_cache_preview_freef(TaskPool *__restrict UNUSED(pool), void *taskdata)
{
FileListEntryPreviewTaskData *preview_taskdata = taskdata;
FileListEntryPreview *preview = preview_taskdata->preview;
diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c
index 1e1d4373fea..d7d85112497 100644
--- a/source/blender/editors/space_image/space_image.c
+++ b/source/blender/editors/space_image/space_image.c
@@ -127,6 +127,7 @@ static SpaceLink *image_new(const ScrArea *UNUSED(area), const Scene *UNUSED(sce
simage->zoom = 1.0f;
simage->lock = true;
simage->flag = SI_SHOW_GPENCIL | SI_USE_ALPHA | SI_COORDFLOATS;
+ simage->uv_opacity = 1.0f;
BKE_imageuser_default(&simage->iuser);
simage->iuser.flag = IMA_SHOW_STEREO | IMA_ANIM_ALWAYS;
diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c
index 218e2be0362..307b6d9bc21 100644
--- a/source/blender/editors/space_nla/nla_buttons.c
+++ b/source/blender/editors/space_nla/nla_buttons.c
@@ -143,7 +143,8 @@ bool nla_panel_context(const bContext *C,
case ANIMTYPE_PALETTE:
case ANIMTYPE_DSHAIR:
case ANIMTYPE_DSPOINTCLOUD:
- case ANIMTYPE_DSVOLUME: {
+ case ANIMTYPE_DSVOLUME:
+ case ANIMTYPE_DSSIMULATION: {
/* for these channels, we only do AnimData */
if (ale->adt && adt_ptr) {
ID *id;
@@ -354,7 +355,7 @@ static void nla_panel_properties(const bContext *C, Panel *panel)
{
PointerRNA strip_ptr;
uiLayout *layout = panel->layout;
- uiLayout *column;
+ uiLayout *column, *row;
uiBlock *block;
short showEvalProps = 1;
@@ -401,20 +402,19 @@ static void nla_panel_properties(const bContext *C, Panel *panel)
uiItemR(column, &strip_ptr, "blend_in", 0, IFACE_("Blend In"), ICON_NONE);
uiItemR(column, &strip_ptr, "blend_out", 0, IFACE_("Out"), ICON_NONE);
- column = uiLayoutColumn(layout, true);
- uiLayoutSetActive(column, RNA_boolean_get(&strip_ptr, "use_animated_influence") == false);
- uiItemR(column, &strip_ptr, "use_auto_blend", 0, NULL, ICON_NONE); // XXX as toggle?
-
- uiItemS(layout);
+ row = uiLayoutRow(column, true);
+ uiLayoutSetActive(row, RNA_boolean_get(&strip_ptr, "use_animated_influence") == false);
+ uiItemR(row, &strip_ptr, "use_auto_blend", 0, NULL, ICON_NONE); // XXX as toggle?
/* settings */
- column = uiLayoutColumn(layout, true);
- uiLayoutSetActive(column,
+ column = uiLayoutColumnWithHeading(layout, true, "Playback");
+ row = uiLayoutRow(column, true);
+ uiLayoutSetActive(row,
!(RNA_boolean_get(&strip_ptr, "use_animated_influence") ||
RNA_boolean_get(&strip_ptr, "use_animated_time")));
- uiItemR(column, &strip_ptr, "use_reverse", 0, NULL, ICON_NONE);
+ uiItemR(row, &strip_ptr, "use_reverse", 0, NULL, ICON_NONE);
- uiItemR(layout, &strip_ptr, "use_animated_time_cyclic", 0, NULL, ICON_NONE);
+ uiItemR(column, &strip_ptr, "use_animated_time_cyclic", 0, NULL, ICON_NONE);
}
}
@@ -442,15 +442,12 @@ static void nla_panel_actclip(const bContext *C, Panel *panel)
uiItemR(row, &strip_ptr, "action", 0, NULL, ICON_ACTION);
/* action extents */
- // XXX custom names were used here (to avoid the prefixes)... probably not necessary in future?
column = uiLayoutColumn(layout, true);
uiItemR(column, &strip_ptr, "action_frame_start", 0, IFACE_("Frame Start"), ICON_NONE);
uiItemR(column, &strip_ptr, "action_frame_end", 0, IFACE_("End"), ICON_NONE);
- /* XXX: this layout may actually be too abstract and confusing,
- * and may be better using standard column layout. */
- row = uiLayoutRow(layout, false);
- uiItemR(row, &strip_ptr, "use_sync_length", 0, IFACE_("Sync Length"), ICON_NONE);
+ row = uiLayoutRowWithHeading(layout, false, "Sync Length");
+ uiItemR(row, &strip_ptr, "use_sync_length", 0, "", ICON_NONE);
uiItemO(row, IFACE_("Now"), ICON_FILE_REFRESH, "NLA_OT_action_sync_length");
/* action usage */
diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c
index 5adcec8a5d7..d399ea47d7e 100644
--- a/source/blender/editors/space_nla/nla_channels.c
+++ b/source/blender/editors/space_nla/nla_channels.c
@@ -193,7 +193,8 @@ static int mouse_nla_channels(
case ANIMTYPE_PALETTE:
case ANIMTYPE_DSHAIR:
case ANIMTYPE_DSPOINTCLOUD:
- case ANIMTYPE_DSVOLUME: {
+ case ANIMTYPE_DSVOLUME:
+ case ANIMTYPE_DSSIMULATION: {
/* sanity checking... */
if (ale->adt) {
/* select/deselect */
diff --git a/source/blender/editors/space_node/CMakeLists.txt b/source/blender/editors/space_node/CMakeLists.txt
index f8c30f9a688..4e21cdc9d16 100644
--- a/source/blender/editors/space_node/CMakeLists.txt
+++ b/source/blender/editors/space_node/CMakeLists.txt
@@ -75,6 +75,10 @@ if(WITH_OPENIMAGEDENOISE)
add_definitions(-DWITH_OPENIMAGEDENOISE)
endif()
+if (WITH_NEW_SIMULATION_TYPE)
+ add_definitions(-DWITH_NEW_SIMULATION_TYPE)
+endif()
+
add_definitions(${GL_DEFINITIONS})
blender_add_lib(bf_editor_space_node "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index e5ca2efb26f..70f3db1e2ab 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -69,6 +69,7 @@
#include "NOD_composite.h"
#include "NOD_shader.h"
+#include "NOD_simulation.h"
#include "NOD_texture.h"
#include "node_intern.h" /* own include */
@@ -3122,6 +3123,96 @@ static void node_texture_set_butfunc(bNodeType *ntype)
}
}
+/* ****************** BUTTON CALLBACKS FOR SIMULATION NODES ***************** */
+
+static void node_simulation_buts_particle_simulation(uiLayout *layout,
+ bContext *UNUSED(C),
+ PointerRNA *ptr)
+{
+ uiItemR(layout, ptr, "name", 0, "", ICON_NONE);
+}
+
+static void node_simulation_buts_particle_time_step_event(uiLayout *layout,
+ bContext *UNUSED(C),
+ PointerRNA *ptr)
+{
+ uiItemR(layout, ptr, "mode", 0, "", ICON_NONE);
+}
+
+static void node_simulation_buts_particle_attribute(uiLayout *layout,
+ bContext *UNUSED(C),
+ PointerRNA *ptr)
+{
+ uiItemR(layout, ptr, "data_type", 0, "", ICON_NONE);
+}
+
+static void node_simulation_buts_set_particle_attribute(uiLayout *layout,
+ bContext *UNUSED(C),
+ PointerRNA *ptr)
+{
+ uiItemR(layout, ptr, "data_type", 0, "", ICON_NONE);
+}
+
+static void node_simulation_buts_time(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+ uiItemR(layout, ptr, "mode", 0, "", ICON_NONE);
+}
+
+static void node_simulation_set_butfunc(bNodeType *ntype)
+{
+ switch (ntype->type) {
+ case SIM_NODE_PARTICLE_SIMULATION:
+ ntype->draw_buttons = node_simulation_buts_particle_simulation;
+ break;
+ case SIM_NODE_PARTICLE_TIME_STEP_EVENT:
+ ntype->draw_buttons = node_simulation_buts_particle_time_step_event;
+ break;
+ case SIM_NODE_PARTICLE_ATTRIBUTE:
+ ntype->draw_buttons = node_simulation_buts_particle_attribute;
+ break;
+ case SIM_NODE_SET_PARTICLE_ATTRIBUTE:
+ ntype->draw_buttons = node_simulation_buts_set_particle_attribute;
+ break;
+ case SIM_NODE_TIME:
+ ntype->draw_buttons = node_simulation_buts_time;
+ break;
+ }
+}
+
+/* ****************** BUTTON CALLBACKS FOR FUNCTION NODES ***************** */
+
+static void node_function_buts_boolean_math(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+ uiItemR(layout, ptr, "operation", 0, "", ICON_NONE);
+}
+
+static void node_function_buts_float_compare(uiLayout *layout,
+ bContext *UNUSED(C),
+ PointerRNA *ptr)
+{
+ uiItemR(layout, ptr, "operation", 0, "", ICON_NONE);
+}
+
+static void node_function_buts_switch(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+ uiItemR(layout, ptr, "data_type", 0, "", ICON_NONE);
+}
+
+static void node_function_set_butfunc(bNodeType *ntype)
+{
+ switch (ntype->type) {
+ case FN_NODE_BOOLEAN_MATH:
+ ntype->draw_buttons = node_function_buts_boolean_math;
+ break;
+ case FN_NODE_FLOAT_COMPARE:
+ ntype->draw_buttons = node_function_buts_float_compare;
+ break;
+ case FN_NODE_SWITCH:
+ ntype->draw_buttons = node_function_buts_switch;
+ break;
+ }
+}
+
/* ****** init draw callbacks for all tree types, only called in usiblender.c, once ************ */
static void node_property_update_default(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
@@ -3230,6 +3321,8 @@ void ED_node_init_butfuncs(void)
node_composit_set_butfunc(ntype);
node_shader_set_butfunc(ntype);
node_texture_set_butfunc(ntype);
+ node_simulation_set_butfunc(ntype);
+ node_function_set_butfunc(ntype);
/* define update callbacks for socket properties */
node_template_properties_update(ntype);
@@ -3240,6 +3333,7 @@ void ED_node_init_butfuncs(void)
ntreeType_Composite->ui_icon = ICON_NODE_COMPOSITING;
ntreeType_Shader->ui_icon = ICON_NODE_MATERIAL;
ntreeType_Texture->ui_icon = ICON_NODE_TEXTURE;
+ ntreeType_Simulation->ui_icon = ICON_PHYSICS; /* TODO: Use correct icon. */
}
void ED_init_custom_node_type(bNodeType *ntype)
@@ -3268,6 +3362,12 @@ static const float std_node_socket_colors[][4] = {
{0.0, 0.0, 0.0, 1.0}, /*__SOCK_MESH (deprecated) */
{0.06, 0.52, 0.15, 1.0}, /* SOCK_INT */
{0.39, 0.39, 0.39, 1.0}, /* SOCK_STRING */
+ {0.40, 0.10, 0.10, 1.0}, /* SOCK_OBJECT */
+ {0.10, 0.40, 0.10, 1.0}, /* SOCK_IMAGE */
+ {0.80, 0.80, 0.20, 1.0}, /* SOCK_EMITTERS */
+ {0.80, 0.20, 0.80, 1.0}, /* SOCK_EVENTS */
+ {0.20, 0.80, 0.80, 1.0}, /* SOCK_FORCES */
+ {0.30, 0.30, 0.30, 1.0}, /* SOCK_CONTROL_FLOW */
};
/* common color callbacks for standard types */
@@ -3385,6 +3485,14 @@ static void std_node_socket_draw(
uiItemR(row, ptr, "default_value", 0, "", 0);
break;
}
+ case SOCK_OBJECT: {
+ uiItemR(layout, ptr, "default_value", 0, text, 0);
+ break;
+ }
+ case SOCK_IMAGE: {
+ uiItemR(layout, ptr, "default_value", 0, text, 0);
+ break;
+ }
default:
node_socket_button_label(C, layout, ptr, node_ptr, text);
break;
diff --git a/source/blender/editors/space_node/node_buttons.c b/source/blender/editors/space_node/node_buttons.c
index 4cf67dddb57..8fc343a9ed4 100644
--- a/source/blender/editors/space_node/node_buttons.c
+++ b/source/blender/editors/space_node/node_buttons.c
@@ -84,7 +84,7 @@ static void node_sockets_panel(const bContext *C, Panel *panel)
split = uiLayoutSplit(layout, 0.35f, false);
uiItemL(split, name, ICON_NONE);
- uiTemplateNodeLink(split, ntree, node, sock);
+ uiTemplateNodeLink(split, (bContext *)C, ntree, node, sock);
}
}
diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c
index 0552660b9bf..bd8950c5085 100644
--- a/source/blender/editors/space_node/node_draw.c
+++ b/source/blender/editors/space_node/node_draw.c
@@ -94,23 +94,11 @@ void ED_node_tree_update(const bContext *C)
static bNodeTree *node_tree_from_ID(ID *id)
{
if (id) {
- short idtype = GS(id->name);
-
- switch (idtype) {
- case ID_NT:
- return (bNodeTree *)id;
- case ID_MA:
- return ((Material *)id)->nodetree;
- case ID_LA:
- return ((Light *)id)->nodetree;
- case ID_WO:
- return ((World *)id)->nodetree;
- case ID_SCE:
- return ((Scene *)id)->nodetree;
- case ID_TE:
- return ((Tex *)id)->nodetree;
- case ID_LS:
- return ((FreestyleLineStyle *)id)->nodetree;
+ if (GS(id->name) == ID_NT) {
+ return (bNodeTree *)id;
+ }
+ else {
+ return ntreeFromID(id);
}
}
@@ -719,39 +707,19 @@ static void node_draw_mute_line(View2D *v2d, SpaceNode *snode, bNode *node)
#define MARKER_SHAPE_CIRCLE 0x2
#define MARKER_SHAPE_INNER_DOT 0x10
-static void node_socket_draw(const bContext *C,
- bNodeTree *ntree,
- PointerRNA node_ptr,
- bNodeSocket *sock,
+static void node_socket_draw(const bNodeSocket *sock,
+ const float color[4],
+ const float color_outline[4],
+ float size,
+ int locx,
+ int locy,
uint pos_id,
uint col_id,
uint shape_id,
uint size_id,
- uint outline_col_id,
- float size,
- bool selected)
+ uint outline_col_id)
{
- PointerRNA ptr;
- float color[4];
- float outline_color[4];
- uint flags = 0;
-
- RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
- sock->typeinfo->draw_color((bContext *)C, &ptr, &node_ptr, color);
-
- bNode *node = node_ptr.data;
- if (node->flag & NODE_MUTED) {
- color[3] *= 0.25f;
- }
-
- if (selected) {
- UI_GetThemeColor4fv(TH_TEXT_HI, outline_color);
- outline_color[3] = 0.9f;
- }
- else {
- copy_v4_fl(outline_color, 0.0f);
- outline_color[3] = 0.6f;
- }
+ int flags;
/* sets shape flags */
switch (sock->display_shape) {
@@ -780,8 +748,120 @@ static void node_socket_draw(const bContext *C,
immAttr4fv(col_id, color);
immAttr1u(shape_id, flags);
immAttr1f(size_id, size);
- immAttr4fv(outline_col_id, outline_color);
- immVertex2f(pos_id, sock->locx, sock->locy);
+ immAttr4fv(outline_col_id, color_outline);
+ immVertex2f(pos_id, locx, locy);
+}
+
+static void node_socket_outline_color_get(bool selected, float r_outline_color[4])
+{
+ if (selected) {
+ UI_GetThemeColor4fv(TH_TEXT_HI, r_outline_color);
+ r_outline_color[3] = 0.9f;
+ }
+ else {
+ copy_v4_fl(r_outline_color, 0.0f);
+ r_outline_color[3] = 0.6f;
+ }
+}
+
+/* Usual convention here would be node_socket_get_color(), but that's already used (for setting a
+ * color property socket). */
+void node_socket_color_get(
+ bContext *C, bNodeTree *ntree, PointerRNA *node_ptr, bNodeSocket *sock, float r_color[4])
+{
+ PointerRNA ptr;
+
+ BLI_assert(RNA_struct_is_a(node_ptr->type, &RNA_Node));
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
+
+ sock->typeinfo->draw_color(C, &ptr, node_ptr, r_color);
+
+ bNode *node = node_ptr->data;
+ if (node->flag & NODE_MUTED) {
+ r_color[3] *= 0.25f;
+ }
+}
+
+static void node_socket_draw_nested(const bContext *C,
+ bNodeTree *ntree,
+ PointerRNA *node_ptr,
+ bNodeSocket *sock,
+ uint pos_id,
+ uint col_id,
+ uint shape_id,
+ uint size_id,
+ uint outline_col_id,
+ float size,
+ bool selected)
+{
+ float color[4];
+ float outline_color[4];
+
+ node_socket_color_get((bContext *)C, ntree, node_ptr, sock, color);
+ node_socket_outline_color_get(selected, outline_color);
+
+ node_socket_draw(sock,
+ color,
+ outline_color,
+ size,
+ sock->locx,
+ sock->locy,
+ pos_id,
+ col_id,
+ shape_id,
+ size_id,
+ outline_col_id);
+}
+
+/**
+ * Draw a single node socket at default size.
+ * \note this is only called from external code, internally #node_socket_draw_nested() is used for
+ * optimized drawing of multiple/all sockets of a node.
+ */
+void ED_node_socket_draw(bNodeSocket *sock, const rcti *rect, const float color[4], float scale)
+{
+ const float size = 2.25f * NODE_SOCKSIZE * scale;
+ rcti draw_rect = *rect;
+ float outline_color[4] = {0};
+
+ node_socket_outline_color_get(sock->flag & SELECT, outline_color);
+
+ BLI_rcti_resize(&draw_rect, size, size);
+
+ GPUVertFormat *format = immVertexFormat();
+ uint pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint col_id = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+ uint shape_id = GPU_vertformat_attr_add(format, "flags", GPU_COMP_U32, 1, GPU_FETCH_INT);
+ uint size_id = GPU_vertformat_attr_add(format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+ uint outline_col_id = GPU_vertformat_attr_add(
+ format, "outlineColor", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+
+ gpuPushAttr(GPU_BLEND_BIT);
+ GPU_blend(true);
+ GPU_program_point_size(true);
+
+ immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND);
+ immUniform1f("outline_scale", 0.7f);
+ immUniform2f("ViewportSize", -1.0f, -1.0f);
+
+ /* Single point */
+ immBegin(GPU_PRIM_POINTS, 1);
+ node_socket_draw(sock,
+ color,
+ outline_color,
+ BLI_rcti_size_y(&draw_rect),
+ BLI_rcti_cent_x(&draw_rect),
+ BLI_rcti_cent_y(&draw_rect),
+ pos_id,
+ col_id,
+ shape_id,
+ size_id,
+ outline_col_id);
+ immEnd();
+
+ immUnbindProgram();
+ GPU_program_point_size(false);
+ gpuPopAttr();
}
/* ************** Socket callbacks *********** */
@@ -974,17 +1054,17 @@ void node_draw_sockets(View2D *v2d,
continue;
}
- node_socket_draw(C,
- ntree,
- node_ptr,
- sock,
- pos_id,
- col_id,
- shape_id,
- size_id,
- outline_col_id,
- scale,
- selected);
+ node_socket_draw_nested(C,
+ ntree,
+ &node_ptr,
+ sock,
+ pos_id,
+ col_id,
+ shape_id,
+ size_id,
+ outline_col_id,
+ scale,
+ selected);
}
/* socket outputs */
@@ -999,17 +1079,17 @@ void node_draw_sockets(View2D *v2d,
continue;
}
- node_socket_draw(C,
- ntree,
- node_ptr,
- sock,
- pos_id,
- col_id,
- shape_id,
- size_id,
- outline_col_id,
- scale,
- selected);
+ node_socket_draw_nested(C,
+ ntree,
+ &node_ptr,
+ sock,
+ pos_id,
+ col_id,
+ shape_id,
+ size_id,
+ outline_col_id,
+ scale,
+ selected);
}
}
@@ -1032,17 +1112,17 @@ void node_draw_sockets(View2D *v2d,
continue;
}
if (select_all || (sock->flag & SELECT)) {
- node_socket_draw(C,
- ntree,
- node_ptr,
- sock,
- pos_id,
- col_id,
- shape_id,
- size_id,
- outline_col_id,
- scale,
- selected);
+ node_socket_draw_nested(C,
+ ntree,
+ &node_ptr,
+ sock,
+ pos_id,
+ col_id,
+ shape_id,
+ size_id,
+ outline_col_id,
+ scale,
+ selected);
if (--selected_input_len == 0) {
break; /* stop as soon as last one is drawn */
}
@@ -1057,17 +1137,17 @@ void node_draw_sockets(View2D *v2d,
continue;
}
if (select_all || (sock->flag & SELECT)) {
- node_socket_draw(C,
- ntree,
- node_ptr,
- sock,
- pos_id,
- col_id,
- shape_id,
- size_id,
- outline_col_id,
- scale,
- selected);
+ node_socket_draw_nested(C,
+ ntree,
+ &node_ptr,
+ sock,
+ pos_id,
+ col_id,
+ shape_id,
+ size_id,
+ outline_col_id,
+ scale,
+ selected);
if (--selected_output_len == 0) {
break; /* stop as soon as last one is drawn */
}
diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c
index a82acfc4dbe..bd5ce135f82 100644
--- a/source/blender/editors/space_node/node_edit.c
+++ b/source/blender/editors/space_node/node_edit.c
@@ -69,6 +69,7 @@
#include "NOD_composite.h"
#include "NOD_shader.h"
+#include "NOD_simulation.h"
#include "NOD_texture.h"
#include "node_intern.h" /* own include */
@@ -438,6 +439,11 @@ bool ED_node_is_texture(struct SpaceNode *snode)
return STREQ(snode->tree_idname, ntreeType_Texture->idname);
}
+bool ED_node_is_simulation(struct SpaceNode *snode)
+{
+ return STREQ(snode->tree_idname, ntreeType_Simulation->idname);
+}
+
/* assumes nothing being done in ntree yet, sets the default in/out node */
/* called from shading buttons or header */
void ED_node_shader_default(const bContext *C, ID *id)
diff --git a/source/blender/editors/space_node/node_group.c b/source/blender/editors/space_node/node_group.c
index 3a0ef45a68d..2617384d046 100644
--- a/source/blender/editors/space_node/node_group.c
+++ b/source/blender/editors/space_node/node_group.c
@@ -69,7 +69,8 @@ static bool node_group_operator_active(bContext *C)
*/
if (STREQ(snode->tree_idname, "ShaderNodeTree") ||
STREQ(snode->tree_idname, "CompositorNodeTree") ||
- STREQ(snode->tree_idname, "TextureNodeTree")) {
+ STREQ(snode->tree_idname, "TextureNodeTree") ||
+ STREQ(snode->tree_idname, "SimulationNodeTree")) {
return true;
}
}
@@ -85,7 +86,8 @@ static bool node_group_operator_editable(bContext *C)
* Disabled otherwise to allow pynodes define their own operators
* with same keymap.
*/
- if (ED_node_is_shader(snode) || ED_node_is_compositor(snode) || ED_node_is_texture(snode)) {
+ if (ED_node_is_shader(snode) || ED_node_is_compositor(snode) || ED_node_is_texture(snode) ||
+ ED_node_is_simulation(snode)) {
return true;
}
}
@@ -111,6 +113,9 @@ static const char *group_node_idname(bContext *C)
else if (ED_node_is_texture(snode)) {
return "TextureNodeGroup";
}
+ else if (ED_node_is_simulation(snode)) {
+ return "SimulationNodeGroup";
+ }
return "";
}
diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h
index 42439e88c96..04186c3a727 100644
--- a/source/blender/editors/space_node/node_intern.h
+++ b/source/blender/editors/space_node/node_intern.h
@@ -38,6 +38,7 @@ struct bContext;
struct bNode;
struct bNodeLink;
struct bNodeSocket;
+struct wmGizmoGroupType;
struct wmKeyConfig;
struct wmWindow;
@@ -77,6 +78,11 @@ void node_draw_sockets(struct View2D *v2d,
void node_update_default(const struct bContext *C, struct bNodeTree *ntree, struct bNode *node);
int node_select_area_default(struct bNode *node, int x, int y);
int node_tweak_area_default(struct bNode *node, int x, int y);
+void node_socket_color_get(struct bContext *C,
+ struct bNodeTree *ntree,
+ struct PointerRNA *node_ptr,
+ struct bNodeSocket *sock,
+ float r_color[4]);
void node_update_nodetree(const struct bContext *C, struct bNodeTree *ntree);
void node_draw_nodetree(const struct bContext *C,
struct ARegion *region,
@@ -122,7 +128,7 @@ void NODE_OT_find_node(struct wmOperatorType *ot);
/* node_view.c */
int space_node_view_flag(struct bContext *C,
- SpaceNode *snode,
+ struct SpaceNode *snode,
ARegion *region,
const int node_flag,
const int smooth_viewtx);
@@ -196,7 +202,7 @@ void NODE_OT_detach(struct wmOperatorType *ot);
void NODE_OT_link_viewer(struct wmOperatorType *ot);
-void NODE_OT_insert_offset(wmOperatorType *ot);
+void NODE_OT_insert_offset(struct wmOperatorType *ot);
/* node_edit.c */
void snode_notify(struct bContext *C, struct SpaceNode *snode);
@@ -207,8 +213,8 @@ void snode_update(struct SpaceNode *snode, struct bNode *node);
bool composite_node_active(struct bContext *C);
bool composite_node_editable(struct bContext *C);
-int node_has_hidden_sockets(bNode *node);
-void node_set_hidden_sockets(SpaceNode *snode, bNode *node, int set);
+int node_has_hidden_sockets(struct bNode *node);
+void node_set_hidden_sockets(struct SpaceNode *snode, bNode *node, int set);
int node_render_changed_exec(bContext *, struct wmOperator *);
int node_find_indicated_socket(struct SpaceNode *snode,
struct bNode **nodep,
diff --git a/source/blender/editors/space_node/node_templates.c b/source/blender/editors/space_node/node_templates.c
index 7d4095326f8..91fe6a97432 100644
--- a/source/blender/editors/space_node/node_templates.c
+++ b/source/blender/editors/space_node/node_templates.c
@@ -45,6 +45,7 @@
#include "UI_interface.h"
#include "ED_node.h" /* own include */
+#include "node_intern.h"
#include "ED_undo.h"
@@ -662,17 +663,23 @@ static void ui_template_node_link_menu(bContext *C, uiLayout *layout, void *but_
ui_node_menu_column(arg, NODE_CLASS_GROUP, N_("Group"));
}
-void uiTemplateNodeLink(uiLayout *layout, bNodeTree *ntree, bNode *node, bNodeSocket *sock)
+void uiTemplateNodeLink(
+ uiLayout *layout, bContext *C, bNodeTree *ntree, bNode *node, bNodeSocket *sock)
{
uiBlock *block = uiLayoutGetBlock(layout);
NodeLinkArg *arg;
uiBut *but;
+ float socket_col[4];
arg = MEM_callocN(sizeof(NodeLinkArg), "NodeLinkArg");
arg->ntree = ntree;
arg->node = node;
arg->sock = sock;
+ PointerRNA node_ptr;
+ RNA_pointer_create((ID *)ntree, &RNA_Node, node, &node_ptr);
+ node_socket_color_get(C, ntree, &node_ptr, sock, socket_col);
+
UI_block_layout_set_current(block, layout);
if (sock->link || sock->type == SOCK_SHADER || (sock->flag & SOCK_HIDE_VALUE)) {
@@ -687,8 +694,9 @@ void uiTemplateNodeLink(uiLayout *layout, bNodeTree *ntree, bNode *node, bNodeSo
}
UI_but_type_set_menu_from_pulldown(but);
+ UI_but_node_link_set(but, sock, socket_col);
+ UI_but_drawflag_enable(but, UI_BUT_ICON_LEFT);
- but->flag |= UI_BUT_NODE_LINK;
but->poin = (char *)but;
but->func_argN = arg;
@@ -798,7 +806,7 @@ static void ui_node_draw_input(
}
else if (lnode) {
/* input linked to a node */
- uiTemplateNodeLink(split, ntree, node, input);
+ uiTemplateNodeLink(split, C, ntree, node, input);
if (depth == 0 || !(input->flag & SOCK_COLLAPSED)) {
if (depth == 0) {
@@ -809,6 +817,10 @@ static void ui_node_draw_input(
}
}
else {
+ row = uiLayoutRow(split, true);
+
+ uiTemplateNodeLink(row, C, ntree, node, input);
+
/* input not linked, show value */
if (!(input->flag & SOCK_HIDE_VALUE)) {
switch (input->type) {
@@ -817,25 +829,15 @@ static void ui_node_draw_input(
case SOCK_BOOLEAN:
case SOCK_RGBA:
case SOCK_STRING:
- row = uiLayoutRow(split, true);
uiItemR(row, &inputptr, "default_value", 0, "", ICON_NONE);
break;
case SOCK_VECTOR:
- row = uiLayoutRow(split, false);
+ uiItemS(row);
col = uiLayoutColumn(row, false);
uiItemR(col, &inputptr, "default_value", 0, "", ICON_NONE);
break;
-
- default:
- row = uiLayoutRow(split, false);
- break;
}
}
- else {
- row = uiLayoutRow(split, false);
- }
-
- uiTemplateNodeLink(row, ntree, node, input);
}
/* clear */
diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c
index b6ee393b991..30fe9a1ed11 100644
--- a/source/blender/editors/space_node/space_node.c
+++ b/source/blender/editors/space_node/space_node.c
@@ -938,6 +938,11 @@ static void node_space_subtype_item_extend(bContext *C, EnumPropertyItem **item,
bool free;
const EnumPropertyItem *item_src = RNA_enum_node_tree_types_itemf_impl(C, &free);
for (const EnumPropertyItem *item_iter = item_src; item_iter->identifier; item_iter++) {
+#ifndef WITH_NEW_SIMULATION_TYPE
+ if (STREQ(item_iter->identifier, "SimulationNodeTree")) {
+ continue;
+ }
+#endif
RNA_enum_item_add(item, totitem, item_iter);
}
if (free) {
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index ce83cfc3c97..6eba41982a7 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -2581,6 +2581,10 @@ TreeElementIcon tree_element_get_icon(TreeStoreElem *tselem, TreeElement *te)
case ID_PC:
data.icon = ICON_CURVE_BEZCURVE;
break;
+ case ID_SIM:
+ /* TODO: Use correct icon. */
+ data.icon = ICON_PHYSICS;
+ break;
default:
break;
}
diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h
index 90092817acc..3032d38b7ac 100644
--- a/source/blender/editors/space_outliner/outliner_intern.h
+++ b/source/blender/editors/space_outliner/outliner_intern.h
@@ -108,7 +108,8 @@ typedef struct TreeElementIcon {
ID_LP, \
ID_HA, \
ID_PT, \
- ID_VO) || /* Only in 'blendfile' mode ... :/ */ \
+ ID_VO, \
+ ID_SIM) || /* Only in 'blendfile' mode ... :/ */ \
ELEM(GS((_id)->name), \
ID_SCR, \
ID_WM, \
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c
index a6c1594678b..24c0e63ee9a 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -39,6 +39,7 @@
#include "DNA_pointcloud_types.h"
#include "DNA_scene_types.h"
#include "DNA_sequence_types.h"
+#include "DNA_simulation_types.h"
#include "DNA_volume_types.h"
#include "DNA_world_types.h"
@@ -160,6 +161,7 @@ static void set_operation_types(SpaceOutliner *soops,
case ID_HA:
case ID_PT:
case ID_VO:
+ case ID_SIM:
is_standard_id = true;
break;
case ID_WM:
diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c
index b226d291188..9b06de67825 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -46,6 +46,7 @@
#include "DNA_pointcloud_types.h"
#include "DNA_scene_types.h"
#include "DNA_sequence_types.h"
+#include "DNA_simulation_types.h"
#include "DNA_speaker_types.h"
#include "DNA_volume_types.h"
#include "DNA_world_types.h"
@@ -773,6 +774,13 @@ static void outliner_add_id_contents(SpaceOutliner *soops,
outliner_add_element(soops, &te->subtree, volume, te, TSE_ANIM_DATA, 0);
break;
}
+ case ID_SIM: {
+ Simulation *simulation = (Simulation *)id;
+ if (outliner_animdata_test(simulation->adt)) {
+ outliner_add_element(soops, &te->subtree, simulation, te, TSE_ANIM_DATA, 0);
+ }
+ break;
+ }
default:
break;
}
diff --git a/source/blender/editors/space_sequencer/sequencer_scopes.c b/source/blender/editors/space_sequencer/sequencer_scopes.c
index b06bc7ad8b7..243a6e193eb 100644
--- a/source/blender/editors/space_sequencer/sequencer_scopes.c
+++ b/source/blender/editors/space_sequencer/sequencer_scopes.c
@@ -447,7 +447,6 @@ static void draw_histogram_bar(ImBuf *ibuf, int x, float val, int col)
typedef struct MakeHistogramViewData {
const ImBuf *ibuf;
- uint32_t (*bins)[HIS_STEPS];
} MakeHistogramViewData;
static void make_histogram_view_from_ibuf_byte_fn(void *__restrict userdata,
@@ -469,17 +468,16 @@ static void make_histogram_view_from_ibuf_byte_fn(void *__restrict userdata,
}
}
-static void make_histogram_view_from_ibuf_finalize(void *__restrict userdata,
- void *__restrict userdata_chunk)
+static void make_histogram_view_from_ibuf_reduce(const void *__restrict UNUSED(userdata),
+ void *__restrict chunk_join,
+ void *__restrict chunk)
{
- MakeHistogramViewData *data = userdata;
- uint32_t(*bins)[HIS_STEPS] = data->bins;
-
- uint32_t(*cur_bins)[HIS_STEPS] = userdata_chunk;
+ uint32_t(*join_bins)[HIS_STEPS] = chunk_join;
+ uint32_t(*bins)[HIS_STEPS] = chunk;
for (int j = 3; j--;) {
for (int i = 0; i < HIS_STEPS; i++) {
- bins[j][i] += cur_bins[j][i];
+ join_bins[j][i] += bins[j][i];
}
}
}
@@ -496,14 +494,13 @@ static ImBuf *make_histogram_view_from_ibuf_byte(ImBuf *ibuf)
MakeHistogramViewData data = {
.ibuf = ibuf,
- .bins = bins,
};
TaskParallelSettings settings;
BLI_parallel_range_settings_defaults(&settings);
settings.use_threading = (ibuf->y >= 256);
settings.userdata_chunk = bins;
settings.userdata_chunk_size = sizeof(bins);
- settings.func_finalize = make_histogram_view_from_ibuf_finalize;
+ settings.func_reduce = make_histogram_view_from_ibuf_reduce;
BLI_task_parallel_range(0, ibuf->y, &data, make_histogram_view_from_ibuf_byte_fn, &settings);
nr = nb = ng = 0;
@@ -582,14 +579,13 @@ static ImBuf *make_histogram_view_from_ibuf_float(ImBuf *ibuf)
MakeHistogramViewData data = {
.ibuf = ibuf,
- .bins = bins,
};
TaskParallelSettings settings;
BLI_parallel_range_settings_defaults(&settings);
settings.use_threading = (ibuf->y >= 256);
settings.userdata_chunk = bins;
settings.userdata_chunk_size = sizeof(bins);
- settings.func_finalize = make_histogram_view_from_ibuf_finalize;
+ settings.func_reduce = make_histogram_view_from_ibuf_reduce;
BLI_task_parallel_range(0, ibuf->y, &data, make_histogram_view_from_ibuf_float_fn, &settings);
nr = nb = ng = 0;
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index 701e068d3fa..f4ea0beadb6 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -677,6 +677,10 @@ enum {
T_MODAL_CURSOR_SET = 1 << 26,
T_CLNOR_REBUILD = 1 << 27,
+
+ /* Special Aftertrans. */
+ T_AUTOMERGE = 1 << 28,
+ T_AUTOSPLIT = 1 << 29,
};
/** #TransInfo.modifiers */
diff --git a/source/blender/editors/transform/transform_convert.c b/source/blender/editors/transform/transform_convert.c
index 0beacf1244a..f75c2c52756 100644
--- a/source/blender/editors/transform/transform_convert.c
+++ b/source/blender/editors/transform/transform_convert.c
@@ -1843,8 +1843,8 @@ static void special_aftertrans_update__node(bContext *C, TransInfo *t)
static void special_aftertrans_update__mesh(bContext *UNUSED(C), TransInfo *t)
{
- /* so automerge supports mirror */
- if ((t->scene->toolsettings->automerge) && ((t->flag & T_EDIT) && t->obedit_type == OB_MESH)) {
+ bool use_automerge = (t->flag & (T_AUTOMERGE | T_AUTOSPLIT)) != 0;
+ if (use_automerge && ((t->flag & T_EDIT) && t->obedit_type == OB_MESH)) {
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
@@ -1870,14 +1870,12 @@ static void special_aftertrans_update__mesh(bContext *UNUSED(C), TransInfo *t)
hflag = BM_ELEM_SELECT;
}
- if (t->scene->toolsettings->automerge & AUTO_MERGE) {
- if (t->scene->toolsettings->automerge & AUTO_MERGE_AND_SPLIT) {
- EDBM_automerge_and_split(
- tc->obedit, true, true, true, hflag, t->scene->toolsettings->doublimit);
- }
- else {
- EDBM_automerge(tc->obedit, true, hflag, t->scene->toolsettings->doublimit);
- }
+ if (t->flag & T_AUTOSPLIT) {
+ EDBM_automerge_and_split(
+ tc->obedit, true, true, true, hflag, t->scene->toolsettings->doublimit);
+ }
+ else {
+ EDBM_automerge(tc->obedit, true, hflag, t->scene->toolsettings->doublimit);
}
/* Special case, this is needed or faces won't re-select.
diff --git a/source/blender/editors/transform/transform_convert_armature.c b/source/blender/editors/transform/transform_convert_armature.c
index 91b8b1ff657..17d210f57b9 100644
--- a/source/blender/editors/transform/transform_convert_armature.c
+++ b/source/blender/editors/transform/transform_convert_armature.c
@@ -609,9 +609,9 @@ void pose_transform_mirror_update(TransInfo *t, TransDataContainer *tc, Object *
/* TODO(germano): Realitve Mirror support */
}
data->flag |= CONSTRAINT_IK_AUTO;
- /* Add a temporary auto IK constraint here, as we will only temporarly active this targetless
- * bone during transform. (Targetless IK constraints are treated as if they are disabled
- * unless they are transformed) */
+ /* Add a temporary auto IK constraint here, as we will only temporarily active this
+ * target-less bone during transform. (Target-less IK constraints are treated as if they are
+ * disabled unless they are transformed) */
add_temporary_ik_constraint(pchan, data);
Main *bmain = CTX_data_main(t->context);
update_deg_with_temporary_ik(bmain, ob);
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index 05318a5c1d3..485ceb2c209 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -1763,6 +1763,24 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
t->options |= CTX_NO_PET;
}
+ if (t->obedit_type == OB_MESH) {
+ if (op && (prop = RNA_struct_find_property(op->ptr, "use_automerge_and_split")) &&
+ RNA_property_is_set(op->ptr, prop)) {
+ if (RNA_property_boolean_get(op->ptr, prop)) {
+ t->flag |= T_AUTOMERGE | T_AUTOSPLIT;
+ }
+ }
+ else {
+ char automerge = t->scene->toolsettings->automerge;
+ if (automerge & AUTO_MERGE) {
+ t->flag |= T_AUTOMERGE;
+ if (automerge & AUTO_MERGE_AND_SPLIT) {
+ t->flag |= T_AUTOSPLIT;
+ }
+ }
+ }
+ }
+
// Mirror is not supported with PET, turn it off.
#if 0
if (t->flag & T_PROP_EDIT) {
diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c
index 36f42992573..d643244e6ca 100644
--- a/source/blender/editors/transform/transform_ops.c
+++ b/source/blender/editors/transform/transform_ops.c
@@ -716,6 +716,15 @@ void Transform_Properties(struct wmOperatorType *ot, int flags)
prop = RNA_def_boolean(ot->srna, "use_accurate", 0, "Accurate", "Use accurate transformation");
RNA_def_property_flag(prop, PROP_HIDDEN);
}
+
+ if (flags & P_POST_TRANSFORM) {
+ prop = RNA_def_boolean(ot->srna,
+ "use_automerge_and_split",
+ 0,
+ "Auto Merge & Split",
+ "Forces the use of Auto Merge & Split");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+ }
}
static void TRANSFORM_OT_translate(struct wmOperatorType *ot)
@@ -741,7 +750,7 @@ static void TRANSFORM_OT_translate(struct wmOperatorType *ot)
Transform_Properties(ot,
P_ORIENT_MATRIX | P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_ALIGN_SNAP |
- P_OPTIONS | P_GPENCIL_EDIT | P_CURSOR_EDIT);
+ P_OPTIONS | P_GPENCIL_EDIT | P_CURSOR_EDIT | P_POST_TRANSFORM);
}
static void TRANSFORM_OT_resize(struct wmOperatorType *ot)
diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c
index 6ea1bbbcc10..959ca1eeef1 100644
--- a/source/blender/editors/uvedit/uvedit_draw.c
+++ b/source/blender/editors/uvedit/uvedit_draw.c
@@ -306,6 +306,7 @@ static void draw_uvs(SpaceImage *sima,
Object *ob_eval = batch->ob_eval;
const ToolSettings *ts = scene->toolsettings;
float col1[4], col2[4], col3[4], transparent[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ const float overlay_alpha = sima->uv_opacity;
if (sima->flag & SI_DRAWSHADOW) {
bool is_cage_like_final_meshes = false;
@@ -346,7 +347,11 @@ static void draw_uvs(SpaceImage *sima,
UI_GetThemeColor4fv(TH_FACE, col1);
UI_GetThemeColor4fv(TH_FACE_SELECT, col2);
UI_GetThemeColor4fv(TH_EDITMESH_ACTIVE, col3);
- col3[3] *= 0.2; /* Simulate dithering */
+
+ col1[3] *= overlay_alpha;
+ col2[3] *= overlay_alpha;
+ col3[3] *= overlay_alpha;
+
GPU_batch_uniform_4fv(batch->faces, "faceColor", col1);
GPU_batch_uniform_4fv(batch->faces, "selectColor", col2);
GPU_batch_uniform_4fv(batch->faces, "activeColor", col3);
@@ -372,9 +377,16 @@ static void draw_uvs(SpaceImage *sima,
GPU_line_smooth(true);
GPU_blend(true);
}
+ else if (overlay_alpha < 1.0f) {
+ GPU_blend(true);
+ }
+
switch (sima->dt_uv) {
case SI_UVDT_DASH: {
- float dash_colors[2][4] = {{0.56f, 0.56f, 0.56f, 1.0f}, {0.07f, 0.07f, 0.07f, 1.0f}};
+ float dash_colors[2][4] = {
+ {0.56f, 0.56f, 0.56f, overlay_alpha},
+ {0.07f, 0.07f, 0.07f, overlay_alpha},
+ };
float viewport_size[4];
GPU_viewport_size_get_f(viewport_size);
@@ -398,7 +410,8 @@ static void draw_uvs(SpaceImage *sima,
* instead of modifying the provoking vert. */
glProvokingVertex(GL_FIRST_VERTEX_CONVENTION);
- UI_GetThemeColor4fv(TH_EDGE_SELECT, col2);
+ UI_GetThemeColor3fv(TH_EDGE_SELECT, col2);
+ col2[3] = overlay_alpha;
GPU_batch_program_set_builtin(
batch->edges, (interpedges) ? GPU_SHADER_2D_UV_EDGES_SMOOTH : GPU_SHADER_2D_UV_EDGES);
@@ -406,18 +419,19 @@ static void draw_uvs(SpaceImage *sima,
if (sima->dt_uv == SI_UVDT_OUTLINE) {
/* Black Outline. */
GPU_line_width(3.0f);
- GPU_batch_uniform_4f(batch->edges, "edgeColor", 0.0f, 0.0f, 0.0f, 1.0f);
- GPU_batch_uniform_4f(batch->edges, "selectColor", 0.0f, 0.0f, 0.0f, 1.0f);
+ GPU_batch_uniform_4f(batch->edges, "edgeColor", 0.0f, 0.0f, 0.0f, overlay_alpha);
+ GPU_batch_uniform_4f(batch->edges, "selectColor", 0.0f, 0.0f, 0.0f, overlay_alpha);
GPU_batch_draw(batch->edges);
- UI_GetThemeColor4fv(TH_WIRE_EDIT, col1);
+ UI_GetThemeColor3fv(TH_WIRE_EDIT, col1);
}
else if (sima->dt_uv == SI_UVDT_WHITE) {
- copy_v4_fl4(col1, 1.0f, 1.0f, 1.0f, 1.0f);
+ copy_v3_fl3(col1, 1.0f, 1.0f, 1.0f);
}
else {
- copy_v4_fl4(col1, 0.0f, 0.0f, 0.0f, 1.0f);
+ copy_v3_fl3(col1, 0.0f, 0.0f, 0.0f);
}
+ col1[3] = overlay_alpha;
/* Inner Line. Use depth test to insure selection is drawn on top. */
GPU_depth_test(true);
@@ -435,6 +449,9 @@ static void draw_uvs(SpaceImage *sima,
GPU_line_smooth(false);
GPU_blend(false);
}
+ else if (overlay_alpha < 1.0f) {
+ GPU_blend(false);
+ }
}
if (batch->verts || batch->facedots) {
UI_GetThemeColor4fv(TH_VERTEX_SELECT, col2);
diff --git a/source/blender/gpencil_modifiers/CMakeLists.txt b/source/blender/gpencil_modifiers/CMakeLists.txt
index 87743911add..0e8aafad7ac 100644
--- a/source/blender/gpencil_modifiers/CMakeLists.txt
+++ b/source/blender/gpencil_modifiers/CMakeLists.txt
@@ -59,6 +59,7 @@ set(SRC
intern/MOD_gpencilthick.c
intern/MOD_gpenciltime.c
intern/MOD_gpenciltint.c
+ intern/MOD_gpenciltexture.c
MOD_gpencil_modifiertypes.h
)
diff --git a/source/blender/gpencil_modifiers/MOD_gpencil_modifiertypes.h b/source/blender/gpencil_modifiers/MOD_gpencil_modifiertypes.h
index f5c064c1c07..a7a4333d82e 100644
--- a/source/blender/gpencil_modifiers/MOD_gpencil_modifiertypes.h
+++ b/source/blender/gpencil_modifiers/MOD_gpencil_modifiertypes.h
@@ -43,6 +43,7 @@ extern GpencilModifierTypeInfo modifierType_Gpencil_Offset;
extern GpencilModifierTypeInfo modifierType_Gpencil_Armature;
extern GpencilModifierTypeInfo modifierType_Gpencil_Time;
extern GpencilModifierTypeInfo modifierType_Gpencil_Multiply;
+extern GpencilModifierTypeInfo modifierType_Gpencil_Texture;
/* MOD_gpencil_util.c */
void gpencil_modifier_type_init(GpencilModifierTypeInfo *types[]);
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c
index 7df0440aa85..f7b51b08c44 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c
@@ -72,6 +72,7 @@ void gpencil_modifier_type_init(GpencilModifierTypeInfo *types[])
INIT_GP_TYPE(Armature);
INIT_GP_TYPE(Time);
INIT_GP_TYPE(Multiply);
+ INIT_GP_TYPE(Texture);
#undef INIT_GP_TYPE
}
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpenciltexture.c b/source/blender/gpencil_modifiers/intern/MOD_gpenciltexture.c
new file mode 100644
index 00000000000..d3d6fc470f7
--- /dev/null
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpenciltexture.c
@@ -0,0 +1,165 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2017, Blender Foundation
+ * This is a new part of Blender
+ */
+
+/** \file
+ * \ingroup modifiers
+ */
+
+#include <stdio.h>
+
+#include "BLI_listbase.h"
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
+
+#include "DNA_gpencil_modifier_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "BKE_colortools.h"
+#include "BKE_deform.h"
+#include "BKE_gpencil.h"
+#include "BKE_gpencil_geom.h"
+#include "BKE_gpencil_modifier.h"
+
+#include "DEG_depsgraph.h"
+
+#include "MOD_gpencil_modifiertypes.h"
+#include "MOD_gpencil_util.h"
+
+static void initData(GpencilModifierData *md)
+{
+ TextureGpencilModifierData *gpmd = (TextureGpencilModifierData *)md;
+ gpmd->fit_method = GP_TEX_CONSTANT_LENGTH;
+ gpmd->fill_rotation = 0.0f;
+ gpmd->fill_scale = 1.0f;
+ gpmd->fill_offset[0] = 0.0f;
+ gpmd->fill_offset[1] = 0.0f;
+ gpmd->uv_offset = 0.0f;
+ gpmd->uv_scale = 1.0f;
+ gpmd->pass_index = 0;
+ gpmd->layername[0] = '\0';
+ gpmd->materialname[0] = '\0';
+ gpmd->vgname[0] = '\0';
+}
+
+static void copyData(const GpencilModifierData *md, GpencilModifierData *target)
+{
+ BKE_gpencil_modifier_copyData_generic(md, target);
+}
+
+/* change stroke uv texture values */
+static void deformStroke(GpencilModifierData *md,
+ Depsgraph *UNUSED(depsgraph),
+ Object *ob,
+ bGPDlayer *gpl,
+ bGPDframe *UNUSED(gpf),
+ bGPDstroke *gps)
+{
+ TextureGpencilModifierData *mmd = (TextureGpencilModifierData *)md;
+ const int def_nr = BKE_object_defgroup_name_index(ob, mmd->vgname);
+
+ if (!is_stroke_affected_by_modifier(ob,
+ mmd->layername,
+ mmd->materialname,
+ mmd->pass_index,
+ mmd->layer_pass,
+ 1,
+ gpl,
+ gps,
+ mmd->flag & GP_TEX_INVERT_LAYER,
+ mmd->flag & GP_TEX_INVERT_PASS,
+ mmd->flag & GP_TEX_INVERT_LAYERPASS,
+ mmd->flag & GP_TEX_INVERT_MATERIAL)) {
+ return;
+ }
+ if ((mmd->mode == FILL) || (mmd->mode == STROKE_AND_FILL)) {
+ gps->uv_rotation += mmd->fill_rotation;
+ gps->uv_translation[0] += mmd->fill_offset[0];
+ gps->uv_translation[1] += mmd->fill_offset[1];
+ gps->uv_scale *= mmd->fill_scale;
+ BKE_gpencil_stroke_geometry_update(gps);
+ }
+
+ if ((mmd->mode == STROKE) || (mmd->mode == STROKE_AND_FILL)) {
+ float totlen = 1.0f;
+ if (mmd->fit_method == GP_TEX_FIT_STROKE) {
+ totlen = 0.0f;
+ for (int i = 1; i < gps->totpoints; i++) {
+ totlen += len_v3v3(&gps->points[i - 1].x, &gps->points[i].x);
+ }
+ }
+
+ for (int i = 0; i < gps->totpoints; i++) {
+ bGPDspoint *pt = &gps->points[i];
+ MDeformVert *dvert = gps->dvert != NULL ? &gps->dvert[i] : NULL;
+ /* Verify point is part of vertex group. */
+ float weight = get_modifier_point_weight(
+ dvert, (mmd->flag & GP_TEX_INVERT_VGROUP) != 0, def_nr);
+ if (weight < 0.0f) {
+ continue;
+ }
+
+ pt->uv_fac /= totlen;
+ pt->uv_fac *= mmd->uv_scale;
+ pt->uv_fac += mmd->uv_offset;
+ }
+ }
+}
+
+static void bakeModifier(struct Main *UNUSED(bmain),
+ Depsgraph *depsgraph,
+ GpencilModifierData *md,
+ Object *ob)
+{
+ bGPdata *gpd = ob->data;
+
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
+ deformStroke(md, depsgraph, ob, gpl, gpf, gps);
+ }
+ }
+ }
+}
+
+GpencilModifierTypeInfo modifierType_Gpencil_Texture = {
+ /* name */ "Texture",
+ /* structName */ "TextureGpencilModifierData",
+ /* structSize */ sizeof(TextureGpencilModifierData),
+ /* type */ eGpencilModifierTypeType_Gpencil,
+ /* flags */ eGpencilModifierTypeFlag_SupportsEditmode,
+
+ /* copyData */ copyData,
+
+ /* deformStroke */ deformStroke,
+ /* generateStrokes */ NULL,
+ /* bakeModifier */ bakeModifier,
+ /* remapTime */ NULL,
+
+ /* initData */ initData,
+ /* freeData */ NULL,
+ /* isDisabled */ NULL,
+ /* updateDepsgraph */ NULL,
+ /* dependsOnTime */ NULL,
+ /* foreachObjectLink */ NULL,
+ /* foreachIDLink */ NULL,
+ /* foreachTexLink */ NULL,
+};
diff --git a/source/blender/gpu/intern/gpu_shader_interface.c b/source/blender/gpu/intern/gpu_shader_interface.c
index cb1cd9a6f6d..1caa88d18ae 100644
--- a/source/blender/gpu/intern/gpu_shader_interface.c
+++ b/source/blender/gpu/intern/gpu_shader_interface.c
@@ -254,8 +254,12 @@ GPUShaderInterface *GPU_shaderinterface_create(int32_t program)
}
/* TODO: reject DOUBLE gl_types */
-
input->location = glGetAttribLocation(program, name);
+ /* Ignore OpenGL names like `gl_BaseInstanceARB`, `gl_InstanceID` and `gl_VertexID`. */
+ if (input->location == -1) {
+ MEM_freeN(input);
+ continue;
+ }
shaderface->enabled_attr_mask |= (1 << input->location);
diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c
index 496e8981f2b..f30270b9eed 100644
--- a/source/blender/gpu/intern/gpu_viewport.c
+++ b/source/blender/gpu/intern/gpu_viewport.c
@@ -559,10 +559,10 @@ void GPU_viewport_colorspace_set(GPUViewport *viewport,
{
/**
* HACK(fclem): We copy the settings here to avoid use after free if an update frees the scene
- * and the viewport stays cached (see T75443). But this means the OCIO curvemapping caching
- * (which is based on CurveMap pointer address) cannot operate correctly and it will create
- * a different OCIO processor for each viewport. We try to only realloc the curvemap copy if
- * needed to avoid uneeded cache invalidation.
+ * and the viewport stays cached (see T75443). But this means the OCIO curve-mapping caching
+ * (which is based on #CurveMap pointer address) cannot operate correctly and it will create
+ * a different OCIO processor for each viewport. We try to only reallocate the curve-map copy
+ * if needed to avoid unneeded cache invalidation.
*/
if (view_settings->curve_mapping) {
if (viewport->view_settings.curve_mapping) {
diff --git a/source/blender/imbuf/intern/imageprocess.c b/source/blender/imbuf/intern/imageprocess.c
index aa82487d69f..e6f0f44b2b3 100644
--- a/source/blender/imbuf/intern/imageprocess.c
+++ b/source/blender/imbuf/intern/imageprocess.c
@@ -340,7 +340,7 @@ void nearest_interpolation(ImBuf *in, ImBuf *out, float x, float y, int xout, in
static void processor_apply_func(TaskPool *__restrict pool, void *taskdata, int UNUSED(threadid))
{
- void (*do_thread)(void *) = (void (*)(void *))BLI_task_pool_userdata(pool);
+ void (*do_thread)(void *) = (void (*)(void *))BLI_task_pool_user_data(pool);
do_thread(taskdata);
}
@@ -403,7 +403,7 @@ static void processor_apply_scanline_func(TaskPool *__restrict pool,
void *taskdata,
int UNUSED(threadid))
{
- ScanlineGlobalData *data = BLI_task_pool_userdata(pool);
+ ScanlineGlobalData *data = BLI_task_pool_user_data(pool);
int start_scanline = POINTER_AS_INT(taskdata);
int num_scanlines = min_ii(data->scanlines_per_task, data->total_scanlines - start_scanline);
data->do_thread(data->custom_data, start_scanline, num_scanlines);
diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h
index d6d3628cc66..ba1485004ae 100644
--- a/source/blender/makesdna/DNA_ID.h
+++ b/source/blender/makesdna/DNA_ID.h
@@ -424,6 +424,7 @@ typedef enum ID_Type {
ID_HA = MAKE_ID2('H', 'A'), /* Hair */
ID_PT = MAKE_ID2('P', 'T'), /* PointCloud */
ID_VO = MAKE_ID2('V', 'O'), /* Volume */
+ ID_SIM = MAKE_ID2('S', 'I'), /* Simulation */
} ID_Type;
/* Only used as 'placeholder' in .blend files for directly linked data-blocks. */
@@ -552,9 +553,9 @@ enum {
/* RESET_NEVER tag data-block as needing an auto-override execution, if enabled. */
LIB_TAG_OVERRIDE_LIBRARY_AUTOREFRESH = 1 << 17,
- /* tag data-block has having an extra user. */
+ /* tag data-block as having an extra user. */
LIB_TAG_EXTRAUSER = 1 << 2,
- /* tag data-block has having actually increased usercount for the extra virtual user. */
+ /* tag data-block as having actually increased usercount for the extra virtual user. */
LIB_TAG_EXTRAUSER_SET = 1 << 7,
/* RESET_AFTER_USE tag newly duplicated/copied IDs.
@@ -723,6 +724,7 @@ typedef enum IDRecalcFlag {
#define FILTER_ID_HA (1ULL << 32)
#define FILTER_ID_PT (1ULL << 33)
#define FILTER_ID_VO (1ULL << 34)
+#define FILTER_ID_SIM (1ULL << 35)
#define FILTER_ID_ALL \
(FILTER_ID_AC | FILTER_ID_AR | FILTER_ID_BR | FILTER_ID_CA | FILTER_ID_CU | FILTER_ID_GD | \
@@ -730,7 +732,7 @@ typedef enum IDRecalcFlag {
FILTER_ID_MB | FILTER_ID_MC | FILTER_ID_ME | FILTER_ID_MSK | FILTER_ID_NT | FILTER_ID_OB | \
FILTER_ID_PA | FILTER_ID_PAL | FILTER_ID_PC | FILTER_ID_SCE | FILTER_ID_SPK | FILTER_ID_SO | \
FILTER_ID_TE | FILTER_ID_TXT | FILTER_ID_VF | FILTER_ID_WO | FILTER_ID_CF | FILTER_ID_WS | \
- FILTER_ID_LP | FILTER_ID_HA | FILTER_ID_PT | FILTER_ID_VO)
+ FILTER_ID_LP | FILTER_ID_HA | FILTER_ID_PT | FILTER_ID_VO | FILTER_ID_SIM)
/* IMPORTANT: this enum matches the order currently use in set_listbasepointers,
* keep them in sync! */
@@ -774,6 +776,7 @@ enum {
INDEX_ID_WS,
INDEX_ID_WM,
INDEX_ID_MSK,
+ INDEX_ID_SIM,
INDEX_ID_NULL,
INDEX_ID_MAX,
};
diff --git a/source/blender/makesdna/DNA_fluid_types.h b/source/blender/makesdna/DNA_fluid_types.h
index bb85d8304ec..166b3c22932 100644
--- a/source/blender/makesdna/DNA_fluid_types.h
+++ b/source/blender/makesdna/DNA_fluid_types.h
@@ -541,6 +541,8 @@ enum {
FLUID_FLOW_USE_INFLOW = (1 << 5),
/* Control how to initialize flow objects. */
FLUID_FLOW_USE_PLANE_INIT = (1 << 6),
+ /* Notify domain objects about state change (invalidate cache). */
+ FLUID_FLOW_NEEDS_UPDATE = (1 << 7),
};
typedef struct FluidFlowSettings {
@@ -614,6 +616,8 @@ enum {
FLUID_EFFECTOR_USE_EFFEC = (1 << 1),
/* Control how to initialize flow objects. */
FLUID_EFFECTOR_USE_PLANE_INIT = (1 << 2),
+ /* Notify domain objects about state change (invalidate cache). */
+ FLUID_EFFECTOR_NEEDS_UPDATE = (1 << 3),
};
/* Collision objects (filled with smoke). */
diff --git a/source/blender/makesdna/DNA_gpencil_modifier_types.h b/source/blender/makesdna/DNA_gpencil_modifier_types.h
index c3425826d36..1265ce0983c 100644
--- a/source/blender/makesdna/DNA_gpencil_modifier_types.h
+++ b/source/blender/makesdna/DNA_gpencil_modifier_types.h
@@ -47,6 +47,7 @@ typedef enum GpencilModifierType {
eGpencilModifierType_Armature = 15,
eGpencilModifierType_Time = 16,
eGpencilModifierType_Multiply = 17,
+ eGpencilModifierType_Texture = 18,
NUM_GREASEPENCIL_MODIFIER_TYPES,
} GpencilModifierType;
@@ -713,4 +714,50 @@ typedef enum eTintGpencil_Flag {
GP_TINT_CUSTOM_CURVE = (1 << 6),
} eTintGpencil_Flag;
+typedef struct TextureGpencilModifierData {
+ GpencilModifierData modifier;
+ /** Layer name. */
+ char layername[64];
+ /** Material name. */
+ char materialname[64];
+ /** Optional vertexgroup name, MAX_VGROUP_NAME. */
+ char vgname[64];
+ /** Custom index for passes. */
+ int pass_index;
+ /** Flags. */
+ int flag;
+ /** Offset value to add to uv_fac. */
+ float uv_offset;
+ float uv_scale;
+ float fill_rotation;
+ float fill_offset[2];
+ float fill_scale;
+ /** Custom index for passes. */
+ int layer_pass;
+ /** Texture fit options. */
+ short fit_method;
+ short mode;
+} TextureGpencilModifierData;
+
+typedef enum eTextureGpencil_Flag {
+ GP_TEX_INVERT_LAYER = (1 << 0),
+ GP_TEX_INVERT_PASS = (1 << 1),
+ GP_TEX_INVERT_VGROUP = (1 << 2),
+ GP_TEX_INVERT_LAYERPASS = (1 << 3),
+ GP_TEX_INVERT_MATERIAL = (1 << 4),
+} eTextureGpencil_Flag;
+
+/* Texture->fit_method */
+typedef enum eTextureGpencil_Fit {
+ GP_TEX_FIT_STROKE = 0,
+ GP_TEX_CONSTANT_LENGTH = 1,
+} eTextureGpencil_Fit;
+
+/* Texture->mode */
+typedef enum eTextureGpencil_Mode {
+ STROKE = 0,
+ FILL = 1,
+ STROKE_AND_FILL = 2,
+} eTextureGpencil_Mode;
+
#endif /* __DNA_GPENCIL_MODIFIER_TYPES_H__ */
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index 8029e8ebc13..4ff0e531168 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -154,6 +154,12 @@ typedef enum eNodeSocketDatatype {
__SOCK_MESH = 5, /* deprecated */
SOCK_INT = 6,
SOCK_STRING = 7,
+ SOCK_OBJECT = 8,
+ SOCK_IMAGE = 9,
+ SOCK_EMITTERS = 10,
+ SOCK_EVENTS = 11,
+ SOCK_FORCES = 12,
+ SOCK_CONTROL_FLOW = 13,
} eNodeSocketDatatype;
/* socket shape */
@@ -498,6 +504,7 @@ typedef struct bNodeTree {
#define NTREE_SHADER 0
#define NTREE_COMPOSIT 1
#define NTREE_TEXTURE 2
+#define NTREE_SIMULATION 3
/* ntree->init, flag */
#define NTREE_TYPE_INIT 1
@@ -565,6 +572,14 @@ typedef struct bNodeSocketValueString {
char value[1024];
} bNodeSocketValueString;
+typedef struct bNodeSocketValueObject {
+ struct Object *value;
+} bNodeSocketValueObject;
+
+typedef struct bNodeSocketValueImage {
+ struct Image *value;
+} bNodeSocketValueImage;
+
/* data structs, for node->storage */
enum {
CMP_NODE_MASKTYPE_ADD = 0,
@@ -1293,6 +1308,23 @@ enum {
NODE_VECTOR_MATH_TANGENT = 23,
};
+/* Boolean math node operations. */
+enum {
+ NODE_BOOLEAN_MATH_AND = 0,
+ NODE_BOOLEAN_MATH_OR = 1,
+ NODE_BOOLEAN_MATH_NOT = 2,
+};
+
+/* Float compare node operations. */
+enum {
+ NODE_FLOAT_COMPARE_LESS_THAN = 0,
+ NODE_FLOAT_COMPARE_LESS_EQUAL = 1,
+ NODE_FLOAT_COMPARE_GREATER_THAN = 2,
+ NODE_FLOAT_COMPARE_GREATER_EQUAL = 3,
+ NODE_FLOAT_COMPARE_EQUAL = 4,
+ NODE_FLOAT_COMPARE_NOT_EQUAL = 5,
+};
+
/* Clamp node types. */
enum {
NODE_CLAMP_MINMAX = 0,
@@ -1385,4 +1417,16 @@ typedef enum NodeShaderOutputTarget {
SHD_OUTPUT_CYCLES = 2,
} NodeShaderOutputTarget;
+/* Particle Time Step Event node */
+typedef enum NodeSimParticleTimeStepEventType {
+ NODE_PARTICLE_TIME_STEP_EVENT_BEGIN = 0,
+ NODE_PARTICLE_TIME_STEP_EVENT_END = 1,
+} NodeSimParticleTimeStepEventType;
+
+/* Simulation Time node */
+typedef enum NodeSimInputTimeType {
+ NODE_SIM_INPUT_SIMULATION_TIME = 0,
+ NODE_SIM_INPUT_SCENE_TIME = 1,
+} NodeSimInputTimeType;
+
#endif
diff --git a/source/blender/makesdna/DNA_simulation_defaults.h b/source/blender/makesdna/DNA_simulation_defaults.h
new file mode 100644
index 00000000000..b4cecd861a9
--- /dev/null
+++ b/source/blender/makesdna/DNA_simulation_defaults.h
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+/** \file
+ * \ingroup DNA
+ */
+
+#ifndef __DNA_SIMULATION_DEFAULTS_H__
+#define __DNA_SIMULATION_DEFAULTS_H__
+
+/* Struct members on own line. */
+/* clang-format off */
+
+/* -------------------------------------------------------------------- */
+/** \name Simulation Struct
+ * \{ */
+
+#define _DNA_DEFAULT_Simulation \
+ { \
+ .flag = 0, \
+ }
+
+/** \} */
+
+/* clang-format on */
+
+#endif /* __DNA_SIMULATION_DEFAULTS_H__ */
diff --git a/source/blender/makesdna/DNA_simulation_types.h b/source/blender/makesdna/DNA_simulation_types.h
new file mode 100644
index 00000000000..113c301bb9e
--- /dev/null
+++ b/source/blender/makesdna/DNA_simulation_types.h
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+/** \file
+ * \ingroup DNA
+ */
+
+#ifndef __DNA_SIMULATION_TYPES_H__
+#define __DNA_SIMULATION_TYPES_H__
+
+#include "DNA_ID.h"
+
+typedef struct Simulation {
+ ID id;
+ struct AnimData *adt; /* animation data (must be immediately after id) */
+
+ struct bNodeTree *nodetree;
+
+ int flag;
+ int _pad1[1];
+} Simulation;
+
+/* Simulation.flag */
+enum {
+ SIM_DS_EXPAND = (1 << 0),
+};
+
+#endif /* __DNA_SIMULATION_TYPES_H__ */
diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h
index 648d35c9a2d..90af60447fe 100644
--- a/source/blender/makesdna/DNA_space_types.h
+++ b/source/blender/makesdna/DNA_space_types.h
@@ -1075,7 +1075,9 @@ typedef struct SpaceImage {
int flag;
char pixel_snap_mode;
- char _pad2[3];
+ char _pad2[7];
+
+ float uv_opacity;
int tile_grid_shape[2];
diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h
index 7a09059e344..622222307c7 100644
--- a/source/blender/makesdna/DNA_userdef_types.h
+++ b/source/blender/makesdna/DNA_userdef_types.h
@@ -619,9 +619,8 @@ typedef struct UserDef_FileSpaceData {
typedef struct UserDef_Experimental {
char use_undo_legacy;
- char use_menu_search;
/** `makesdna` does not allow empty structs. */
- char _pad0[6];
+ char _pad0[7];
} UserDef_Experimental;
#define USER_EXPERIMENTAL_TEST(userdef, member) \
diff --git a/source/blender/makesdna/intern/CMakeLists.txt b/source/blender/makesdna/intern/CMakeLists.txt
index a101e96e958..1b0bf086269 100644
--- a/source/blender/makesdna/intern/CMakeLists.txt
+++ b/source/blender/makesdna/intern/CMakeLists.txt
@@ -146,6 +146,7 @@ set(SRC
../DNA_object_defaults.h
../DNA_pointcloud_defaults.h
../DNA_scene_defaults.h
+ ../DNA_simulation_defaults.h
../DNA_speaker_defaults.h
../DNA_texture_defaults.h
../DNA_vec_defaults.h
diff --git a/source/blender/makesdna/intern/dna_defaults.c b/source/blender/makesdna/intern/dna_defaults.c
index dadd2fd9d7d..2d86e97debf 100644
--- a/source/blender/makesdna/intern/dna_defaults.c
+++ b/source/blender/makesdna/intern/dna_defaults.c
@@ -71,6 +71,7 @@
#include "DNA_object_types.h"
#include "DNA_pointcloud_types.h"
#include "DNA_scene_types.h"
+#include "DNA_simulation_types.h"
#include "DNA_space_types.h"
#include "DNA_speaker_types.h"
#include "DNA_texture_types.h"
@@ -93,6 +94,7 @@
#include "DNA_object_defaults.h"
#include "DNA_pointcloud_defaults.h"
#include "DNA_scene_defaults.h"
+#include "DNA_simulation_defaults.h"
#include "DNA_speaker_defaults.h"
#include "DNA_texture_defaults.h"
#include "DNA_volume_defaults.h"
@@ -150,6 +152,9 @@ SDNA_DEFAULT_DECL_STRUCT(PointCloud);
SDNA_DEFAULT_DECL_STRUCT(Scene);
SDNA_DEFAULT_DECL_STRUCT(ToolSettings);
+/* DNA_simulation_defaults.h */
+SDNA_DEFAULT_DECL_STRUCT(Simulation);
+
/* DNA_speaker_defaults.h */
SDNA_DEFAULT_DECL_STRUCT(Speaker);
@@ -260,6 +265,9 @@ const void *DNA_default_table[SDNA_TYPE_MAX] = {
SDNA_DEFAULT_DECL_EX(GP_Sculpt_Settings, ToolSettings.gp_sculpt),
SDNA_DEFAULT_DECL_EX(GP_Sculpt_Guide, ToolSettings.gp_sculpt.guide),
+ /* DNA_simulation_defaults.h */
+ SDNA_DEFAULT_DECL(Simulation),
+
/* DNA_speaker_defaults.h */
SDNA_DEFAULT_DECL(Speaker),
diff --git a/source/blender/makesdna/intern/makesdna.c b/source/blender/makesdna/intern/makesdna.c
index 39b26fef176..49f778f2eb1 100644
--- a/source/blender/makesdna/intern/makesdna.c
+++ b/source/blender/makesdna/intern/makesdna.c
@@ -136,6 +136,7 @@ static const char *includefiles[] = {
"DNA_hair_types.h",
"DNA_pointcloud_types.h",
"DNA_volume_types.h",
+ "DNA_simulation_types.h",
/* see comment above before editing! */
@@ -1590,6 +1591,7 @@ int main(int argc, char **argv)
#include "DNA_sdna_types.h"
#include "DNA_sequence_types.h"
#include "DNA_shader_fx_types.h"
+#include "DNA_simulation_types.h"
#include "DNA_sound_types.h"
#include "DNA_space_types.h"
#include "DNA_speaker_types.h"
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index 31d1ed54fa1..d2e27bdbcad 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -259,6 +259,7 @@ extern StructRNA RNA_FreestyleLineStyle;
extern StructRNA RNA_FreestyleModuleSettings;
extern StructRNA RNA_FreestyleSettings;
extern StructRNA RNA_Function;
+extern StructRNA RNA_FunctionNode;
extern StructRNA RNA_GPencilFrame;
extern StructRNA RNA_GPencilInterpolateSettings;
extern StructRNA RNA_GPencilLayer;
@@ -548,6 +549,9 @@ extern StructRNA RNA_ShrinkwrapConstraint;
extern StructRNA RNA_ShrinkwrapModifier;
extern StructRNA RNA_SimpleDeformModifier;
extern StructRNA RNA_SimplifyGpencilModifier;
+extern StructRNA RNA_Simulation;
+extern StructRNA RNA_SimulationNode;
+extern StructRNA RNA_SimulationNodeTree;
extern StructRNA RNA_SkinModifier;
extern StructRNA RNA_SmoothGpencilModifier;
extern StructRNA RNA_SmoothModifier;
@@ -930,10 +934,6 @@ void RNA_property_update_main(struct Main *bmain,
PropertyRNA *prop);
bool RNA_property_update_check(struct PropertyRNA *prop);
-void RNA_property_update_cache_add(PointerRNA *ptr, PropertyRNA *prop);
-void RNA_property_update_cache_flush(struct Main *bmain, struct Scene *scene);
-void RNA_property_update_cache_free(void);
-
/* Property Data */
bool RNA_property_boolean_get(PointerRNA *ptr, PropertyRNA *prop);
diff --git a/source/blender/makesrna/RNA_enum_types.h b/source/blender/makesrna/RNA_enum_types.h
index fef98f9da4b..b6bae805636 100644
--- a/source/blender/makesrna/RNA_enum_types.h
+++ b/source/blender/makesrna/RNA_enum_types.h
@@ -23,6 +23,10 @@
#include "RNA_types.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct bNodeSocketType;
struct bNodeTreeType;
struct bNodeType;
@@ -191,6 +195,8 @@ extern const EnumPropertyItem rna_enum_node_socket_in_out_items[];
extern const EnumPropertyItem rna_enum_node_math_items[];
extern const EnumPropertyItem rna_enum_mapping_type_items[];
extern const EnumPropertyItem rna_enum_node_vec_math_items[];
+extern const EnumPropertyItem rna_enum_node_boolean_math_items[];
+extern const EnumPropertyItem rna_enum_node_float_compare_items[];
extern const EnumPropertyItem rna_enum_node_filter_items[];
extern const EnumPropertyItem rna_enum_node_map_range_items[];
extern const EnumPropertyItem rna_enum_node_clamp_items[];
@@ -315,4 +321,8 @@ const EnumPropertyItem *RNA_mask_local_itemf(struct bContext *C,
/* Non confirming, utility function. */
const EnumPropertyItem *RNA_enum_node_tree_types_itemf_impl(struct bContext *C, bool *r_free);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __RNA_ENUM_TYPES_H__ */
diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt
index 64b7a3e70c1..cd05aba8794 100644
--- a/source/blender/makesrna/intern/CMakeLists.txt
+++ b/source/blender/makesrna/intern/CMakeLists.txt
@@ -103,6 +103,13 @@ if(WITH_NEW_OBJECT_TYPES)
)
endif()
+if (WITH_NEW_SIMULATION_TYPE)
+ list(APPEND DEFSRC
+ rna_simulation.c
+ )
+endif()
+
+
set(APISRC
rna_action_api.c
rna_animation_api.c
@@ -342,6 +349,11 @@ if(WITH_NEW_OBJECT_TYPES)
add_definitions(-DWITH_NEW_OBJECT_TYPES)
endif()
+if (WITH_NEW_SIMULATION_TYPE)
+ add_definitions(-DWITH_NEW_SIMULATION_TYPE)
+endif()
+
+
# Build makesrna executable
blender_include_dirs(
.
diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c
index 46854bc6307..86a088f38ed 100644
--- a/source/blender/makesrna/intern/makesrna.c
+++ b/source/blender/makesrna/intern/makesrna.c
@@ -4302,6 +4302,9 @@ static RNAProcessItem PROCESS_ITEMS[] = {
{"rna_screen.c", NULL, RNA_def_screen},
{"rna_sculpt_paint.c", NULL, RNA_def_sculpt_paint},
{"rna_sequencer.c", "rna_sequencer_api.c", RNA_def_sequencer},
+#ifdef WITH_NEW_SIMULATION_TYPE
+ {"rna_simulation.c", NULL, RNA_def_simulation},
+#endif
{"rna_space.c", "rna_space_api.c", RNA_def_space},
{"rna_speaker.c", NULL, RNA_def_speaker},
{"rna_test.c", NULL, RNA_def_test},
diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c
index 699ce0f041e..891c30af466 100644
--- a/source/blender/makesrna/intern/rna_ID.c
+++ b/source/blender/makesrna/intern/rna_ID.c
@@ -71,6 +71,9 @@ const EnumPropertyItem rna_enum_id_type_items[] = {
{ID_PA, "PARTICLE", ICON_PARTICLE_DATA, "Particle", ""},
{ID_LP, "LIGHT_PROBE", ICON_LIGHTPROBE_CUBEMAP, "Light Probe", ""},
{ID_SCE, "SCENE", ICON_SCENE_DATA, "Scene", ""},
+#ifdef WITH_NEW_SIMULATION_TYPE
+ {ID_SIM, "SIMULATION", ICON_PHYSICS, "Simulation", ""}, /* TODO: Use correct icon. */
+#endif
{ID_SO, "SOUND", ICON_SOUND, "Sound", ""},
{ID_SPK, "SPEAKER", ICON_SPEAKER, "Speaker", ""},
{ID_TXT, "TEXT", ICON_TEXT, "Text", ""},
@@ -303,6 +306,11 @@ short RNA_type_to_ID_code(const StructRNA *type)
if (base_type == &RNA_Screen) {
return ID_SCR;
}
+# ifdef WITH_NEW_SIMULATION_TYPE
+ if (base_type == &RNA_Simulation) {
+ return ID_SIM;
+ }
+# endif
if (base_type == &RNA_Sound) {
return ID_SO;
}
@@ -405,6 +413,12 @@ StructRNA *ID_code_to_RNA_type(short idcode)
return &RNA_Scene;
case ID_SCR:
return &RNA_Screen;
+ case ID_SIM:
+# ifdef WITH_NEW_SIMULATION_TYPE
+ return &RNA_Simulation;
+# else
+ return &RNA_ID;
+# endif
case ID_SO:
return &RNA_Sound;
case ID_SPK:
diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c
index b56a18c18a9..85892758a88 100644
--- a/source/blender/makesrna/intern/rna_access.c
+++ b/source/blender/makesrna/intern/rna_access.c
@@ -98,8 +98,6 @@ void RNA_exit(void)
{
StructRNA *srna;
- RNA_property_update_cache_free();
-
for (srna = BLENDER_RNA.structs.first; srna; srna = srna->cont.next) {
if (srna->cont.prophash) {
BLI_ghash_free(srna->cont.prophash, NULL, NULL);
@@ -2308,115 +2306,6 @@ void RNA_property_update_main(Main *bmain, Scene *scene, PointerRNA *ptr, Proper
rna_property_update(NULL, bmain, scene, ptr, prop);
}
-/* RNA Updates Cache ------------------------ */
-/* Overview of RNA Update cache system:
- *
- * RNA Update calls need to be cached in order to maintain reasonable performance
- * of the animation system (i.e. maintaining a somewhat interactive framerate)
- * while still allowing updates to be called (necessary in particular for modifier
- * property updates to actually work).
- *
- * The cache is structured with a dual-layer structure
- * - L1 = PointerRNA used as key; owner_id is used (it should always be defined,
- * and most updates end up using just that anyways)
- * - L2 = Update functions to be called on those PointerRNA's
- */
-
-/* cache element */
-typedef struct tRnaUpdateCacheElem {
- struct tRnaUpdateCacheElem *next, *prev;
-
- PointerRNA ptr; /* L1 key - id as primary, data secondary/ignored? */
- ListBase L2Funcs; /* L2 functions (LinkData<RnaUpdateFuncRef>) */
-} tRnaUpdateCacheElem;
-
-/* cache global (tRnaUpdateCacheElem's) - only accessible using these API calls */
-static ListBase rna_updates_cache = {NULL, NULL};
-
-/* ........................... */
-
-void RNA_property_update_cache_add(PointerRNA *ptr, PropertyRNA *prop)
-{
- const bool is_rna = (prop->magic == RNA_MAGIC);
- tRnaUpdateCacheElem *uce = NULL;
- UpdateFunc fn = NULL;
- LinkData *ld;
-
- /* sanity check */
- if (NULL == ptr) {
- return;
- }
-
- prop = rna_ensure_property(prop);
-
- /* we can only handle update calls with no context args for now (makes animsys updates easier) */
- if ((is_rna == false) || (prop->update == NULL) || (prop->flag & PROP_CONTEXT_UPDATE)) {
- return;
- }
- fn = prop->update;
-
- /* find cache element for which key matches... */
- for (uce = rna_updates_cache.first; uce; uce = uce->next) {
- /* Just match by id only for now,
- * since most update calls that we'll encounter only really care about this. */
- /* TODO: later, the cache might need to have some nesting on L1 to cope better
- * with these problems + some tagging to indicate we need this */
- if (uce->ptr.owner_id == ptr->owner_id) {
- break;
- }
- }
- if (uce == NULL) {
- /* create new instance */
- uce = MEM_callocN(sizeof(tRnaUpdateCacheElem), "tRnaUpdateCacheElem");
- BLI_addtail(&rna_updates_cache, uce);
-
- /* copy pointer */
- RNA_pointer_create(ptr->owner_id, ptr->type, ptr->data, &uce->ptr);
- }
-
- /* check on the update func */
- for (ld = uce->L2Funcs.first; ld; ld = ld->next) {
- /* stop on match - function already cached */
- if (fn == ld->data) {
- return;
- }
- }
- /* else... if still here, we need to add it */
- BLI_addtail(&uce->L2Funcs, BLI_genericNodeN(fn));
-}
-
-void RNA_property_update_cache_flush(Main *bmain, Scene *scene)
-{
- tRnaUpdateCacheElem *uce;
-
- /* TODO: should we check that bmain and scene are valid? The above stuff doesn't! */
-
- /* execute the cached updates */
- for (uce = rna_updates_cache.first; uce; uce = uce->next) {
- LinkData *ld;
-
- for (ld = uce->L2Funcs.first; ld; ld = ld->next) {
- UpdateFunc fn = (UpdateFunc)ld->data;
- fn(bmain, scene, &uce->ptr);
- }
- }
-}
-
-void RNA_property_update_cache_free(void)
-{
- tRnaUpdateCacheElem *uce, *ucn;
-
- for (uce = rna_updates_cache.first; uce; uce = ucn) {
- ucn = uce->next;
-
- /* free L2 cache */
- BLI_freelistN(&uce->L2Funcs);
-
- /* remove self */
- BLI_freelinkN(&rna_updates_cache, uce);
- }
-}
-
/* ---------------------------------------------------------------------- */
/* Property Data */
@@ -5785,10 +5674,10 @@ static char *rna_idp_path(PointerRNA *ptr,
}
/**
- * Find the path from the structure referenced by the pointer to the IDProperty object.
+ * Find the path from the structure referenced by the pointer to the #IDProperty object.
*
- * \param ptr Reference to the object owning the custom property storage.
- * \param needle Custom property object to find.
+ * \param ptr: Reference to the object owning the custom property storage.
+ * \param needle: Custom property object to find.
* \return Relative path or NULL.
*/
char *RNA_path_from_struct_to_idproperty(PointerRNA *ptr, IDProperty *needle)
diff --git a/source/blender/makesrna/intern/rna_fluid.c b/source/blender/makesrna/intern/rna_fluid.c
index e087056e850..d89bdcd074f 100644
--- a/source/blender/makesrna/intern/rna_fluid.c
+++ b/source/blender/makesrna/intern/rna_fluid.c
@@ -73,44 +73,112 @@ static void rna_Fluid_dependency_update(Main *bmain, Scene *scene, PointerRNA *p
DEG_relations_tag_update(bmain);
}
-static void rna_Fluid_resetCache(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
+static void rna_Fluid_datacache_reset(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
+# ifdef WITH_FLUID
FluidDomainSettings *settings = (FluidDomainSettings *)ptr->data;
if (settings->mmd && settings->mmd->domain) {
- settings->mmd->domain->cache_flag |= (FLUID_DOMAIN_OUTDATED_DATA |
- FLUID_DOMAIN_OUTDATED_NOISE |
- FLUID_DOMAIN_OUTDATED_MESH |
- FLUID_DOMAIN_OUTDATED_PARTICLES);
+ Object *ob = (Object *)ptr->owner_id;
+ int cache_map = (FLUID_DOMAIN_OUTDATED_DATA | FLUID_DOMAIN_OUTDATED_NOISE |
+ FLUID_DOMAIN_OUTDATED_MESH | FLUID_DOMAIN_OUTDATED_PARTICLES);
+ BKE_fluid_cache_free(settings, ob, cache_map);
}
+# endif
DEG_id_tag_update(ptr->owner_id, ID_RECALC_GEOMETRY);
}
-static void rna_Fluid_reset(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_Fluid_noisecache_reset(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
+{
+# ifdef WITH_FLUID
+ FluidDomainSettings *settings = (FluidDomainSettings *)ptr->data;
+ if (settings->mmd && settings->mmd->domain) {
+ Object *ob = (Object *)ptr->owner_id;
+ int cache_map = FLUID_DOMAIN_OUTDATED_NOISE;
+ BKE_fluid_cache_free(settings, ob, cache_map);
+ }
+# endif
+ DEG_id_tag_update(ptr->owner_id, ID_RECALC_GEOMETRY);
+}
+static void rna_Fluid_meshcache_reset(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
-
# ifdef WITH_FLUID
- {
- FluidDomainSettings *settings = (FluidDomainSettings *)ptr->data;
- BKE_fluid_modifier_reset(settings->mmd);
+ FluidDomainSettings *settings = (FluidDomainSettings *)ptr->data;
+ if (settings->mmd && settings->mmd->domain) {
+ Object *ob = (Object *)ptr->owner_id;
+ int cache_map = FLUID_DOMAIN_OUTDATED_MESH;
+ BKE_fluid_cache_free(settings, ob, cache_map);
}
# endif
+ DEG_id_tag_update(ptr->owner_id, ID_RECALC_GEOMETRY);
+}
+static void rna_Fluid_particlescache_reset(Main *UNUSED(bmain),
+ Scene *UNUSED(scene),
+ PointerRNA *ptr)
+{
+# ifdef WITH_FLUID
+ FluidDomainSettings *settings = (FluidDomainSettings *)ptr->data;
+ if (settings->mmd && settings->mmd->domain) {
+ Object *ob = (Object *)ptr->owner_id;
+ int cache_map = FLUID_DOMAIN_OUTDATED_PARTICLES;
+ BKE_fluid_cache_free(settings, ob, cache_map);
+ }
+# endif
+ DEG_id_tag_update(ptr->owner_id, ID_RECALC_GEOMETRY);
+}
+static void rna_Fluid_guidingcache_reset(Main *UNUSED(bmain),
+ Scene *UNUSED(scene),
+ PointerRNA *ptr)
+{
+# ifdef WITH_FLUID
+ FluidDomainSettings *settings = (FluidDomainSettings *)ptr->data;
+ if (settings->mmd && settings->mmd->domain) {
+ Object *ob = (Object *)ptr->owner_id;
+ int cache_map = (FLUID_DOMAIN_OUTDATED_DATA | FLUID_DOMAIN_OUTDATED_NOISE |
+ FLUID_DOMAIN_OUTDATED_MESH | FLUID_DOMAIN_OUTDATED_PARTICLES |
+ FLUID_DOMAIN_OUTDATED_GUIDE);
+ BKE_fluid_cache_free(settings, ob, cache_map);
+ }
+# endif
+ DEG_id_tag_update(ptr->owner_id, ID_RECALC_GEOMETRY);
+}
+
+static void rna_Fluid_effector_reset(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+# ifdef WITH_FLUID
+ FluidEffectorSettings *settings = (FluidEffectorSettings *)ptr->data;
+ settings->flags |= FLUID_EFFECTOR_NEEDS_UPDATE;
+# endif
+
+ rna_Fluid_update(bmain, scene, ptr);
+}
- rna_Fluid_resetCache(bmain, scene, ptr);
+static void rna_Fluid_flow_reset(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+# ifdef WITH_FLUID
+ FluidFlowSettings *settings = (FluidFlowSettings *)ptr->data;
+ settings->flags |= FLUID_FLOW_NEEDS_UPDATE;
+# endif
rna_Fluid_update(bmain, scene, ptr);
}
-static void rna_Fluid_reset_dependency(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_Fluid_domain_reset(Main *bmain, Scene *scene, PointerRNA *ptr)
{
+# ifdef WITH_FLUID
FluidDomainSettings *settings = (FluidDomainSettings *)ptr->data;
+ BKE_fluid_modifier_reset(settings->mmd);
+# endif
+ rna_Fluid_datacache_reset(bmain, scene, ptr);
+ rna_Fluid_update(bmain, scene, ptr);
+}
+
+static void rna_Fluid_reset_dependency(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
# ifdef WITH_FLUID
+ FluidDomainSettings *settings = (FluidDomainSettings *)ptr->data;
BKE_fluid_modifier_reset(settings->mmd);
# endif
- if (settings->mmd && settings->mmd->domain) {
- settings->mmd->domain->point_cache[0]->flag |= PTCACHE_OUTDATED;
- }
-
rna_Fluid_dependency_update(bmain, scene, ptr);
}
@@ -161,7 +229,7 @@ static void rna_Fluid_flip_parts_update(Main *bmain, Scene *scene, PointerRNA *p
/* Only create a particle system in liquid domain mode. */
if (mmd->domain->type != FLUID_DOMAIN_TYPE_LIQUID) {
- rna_Fluid_reset(bmain, scene, ptr);
+ rna_Fluid_domain_reset(bmain, scene, ptr);
return;
}
@@ -1260,14 +1328,14 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
RNA_def_property_int_sdna(prop, NULL, "adapt_res");
RNA_def_property_range(prop, 0, 512);
RNA_def_property_ui_text(prop, "Additional", "Maximum number of additional cells");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset");
prop = RNA_def_property(srna, "adapt_margin", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "adapt_margin");
RNA_def_property_range(prop, 2, 24);
RNA_def_property_ui_text(
prop, "Margin", "Margin added around fluid to minimize boundary interference");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset");
prop = RNA_def_property(srna, "adapt_threshold", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0, 1.0);
@@ -1276,14 +1344,14 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
prop,
"Threshold",
"Minimum amount of fluid a cell can contain before it is considered empty");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset");
prop = RNA_def_property(srna, "use_adaptive_domain", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", FLUID_DOMAIN_USE_ADAPTIVE_DOMAIN);
RNA_def_property_ui_text(
prop, "Adaptive Domain", "Adapt simulation resolution and size to fluid");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_domain_reset");
/* fluid domain options */
@@ -1297,44 +1365,44 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
"Resolution used for the fluid domain. Value corresponds to the longest domain side "
"(resolution for other domain sides is calculated automatically)");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_domain_reset");
prop = RNA_def_property(srna, "use_collision_border_front", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "border_collisions", FLUID_DOMAIN_BORDER_FRONT);
RNA_def_property_ui_text(prop, "Front", "Enable collisions with front domain border");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset");
prop = RNA_def_property(srna, "use_collision_border_back", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "border_collisions", FLUID_DOMAIN_BORDER_BACK);
RNA_def_property_ui_text(prop, "Back", "Enable collisions with back domain border");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset");
prop = RNA_def_property(srna, "use_collision_border_right", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "border_collisions", FLUID_DOMAIN_BORDER_RIGHT);
RNA_def_property_ui_text(prop, "Right", "Enable collisions with right domain border");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset");
prop = RNA_def_property(srna, "use_collision_border_left", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "border_collisions", FLUID_DOMAIN_BORDER_LEFT);
RNA_def_property_ui_text(prop, "Left", "Enable collisions with left domain border");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset");
prop = RNA_def_property(srna, "use_collision_border_top", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "border_collisions", FLUID_DOMAIN_BORDER_TOP);
RNA_def_property_ui_text(prop, "Top", "Enable collisions with top domain border");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset");
prop = RNA_def_property(srna, "use_collision_border_bottom", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "border_collisions", FLUID_DOMAIN_BORDER_BOTTOM);
RNA_def_property_ui_text(prop, "Bottom", "Enable collisions with bottom domain border");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset");
prop = RNA_def_property(srna, "gravity", PROP_FLOAT, PROP_ACCELERATION);
RNA_def_property_float_sdna(prop, NULL, "gravity");
RNA_def_property_array(prop, 3);
RNA_def_property_range(prop, -1000.1, 1000.1);
RNA_def_property_ui_text(prop, "Gravity", "Gravity in X, Y and Z direction");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset");
prop = RNA_def_property(srna, "domain_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "type");
@@ -1347,7 +1415,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "delete_in_obstacle", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", FLUID_DOMAIN_DELETE_IN_OBSTACLE);
RNA_def_property_ui_text(prop, "Clear In Obstacle", "Delete fluid inside obstacles");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset");
/* smoke domain options */
@@ -1359,7 +1427,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
prop,
"Buoyancy Density",
"Buoyant force based on smoke density (higher value results in faster rising smoke)");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset");
prop = RNA_def_property(srna, "beta", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "beta");
@@ -1369,7 +1437,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
prop,
"Buoyancy Heat",
"Buoyant force based on smoke heat (higher value results in faster rising smoke)");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset");
prop = RNA_def_property(srna, "dissolve_speed", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "diss_speed");
@@ -1379,23 +1447,23 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
prop,
"Dissolve Speed",
"Determine how quickly the smoke dissolves (lower value makes smoke disappear faster)");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset");
prop = RNA_def_property(srna, "vorticity", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "vorticity");
RNA_def_property_range(prop, 0.0, 4.0);
RNA_def_property_ui_text(prop, "Vorticity", "Amount of turbulence and rotation in smoke");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset");
prop = RNA_def_property(srna, "highres_sampling", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, smoke_highres_sampling_items);
RNA_def_property_ui_text(prop, "Emitter", "Method for sampling the high resolution flow");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset");
prop = RNA_def_property(srna, "use_dissolve_smoke", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", FLUID_DOMAIN_USE_DISSOLVE);
RNA_def_property_ui_text(prop, "Dissolve Smoke", "Let smoke disappear over time");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset");
prop = RNA_def_property(srna, "use_dissolve_smoke_log", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", FLUID_DOMAIN_USE_DISSOLVE_LOG);
@@ -1403,7 +1471,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
prop,
"Logarithmic Dissolve",
"Dissolve smoke in a logarithmic fashion. Dissolves quickly at first, but lingers longer");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset");
/* flame options */
@@ -1412,19 +1480,19 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
RNA_def_property_ui_range(prop, 0.01, 2.0, 1.0, 5);
RNA_def_property_ui_text(
prop, "Speed", "Speed of the burning reaction (higher value results in smaller flames)");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset");
prop = RNA_def_property(srna, "flame_smoke", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0, 8.0);
RNA_def_property_ui_range(prop, 0.0, 4.0, 1.0, 5);
RNA_def_property_ui_text(prop, "Smoke", "Amount of smoke created by burning fuel");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset");
prop = RNA_def_property(srna, "flame_vorticity", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0, 2.0);
RNA_def_property_ui_range(prop, 0.0, 1.0, 1.0, 5);
RNA_def_property_ui_text(prop, "Vorticity", "Additional vorticity for the flames");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset");
prop = RNA_def_property(srna, "flame_ignition", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.5, 5.0);
@@ -1433,7 +1501,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
prop,
"Minimum",
"Minimum temperature of the flames (higher value results in faster rising flames)");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset");
prop = RNA_def_property(srna, "flame_max_temp", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 1.0, 10.0);
@@ -1442,12 +1510,12 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
prop,
"Maximum",
"Maximum temperature of the flames (higher value results in faster rising flames)");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset");
prop = RNA_def_property(srna, "flame_smoke_color", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_array(prop, 3);
RNA_def_property_ui_text(prop, "Smoke Color", "Color of smoke emitted from burning fuel");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset");
/* noise options */
@@ -1456,19 +1524,20 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
RNA_def_property_range(prop, 0.0, 10.0);
RNA_def_property_ui_range(prop, 0.0, 10.0, 1, 2);
RNA_def_property_ui_text(prop, "Strength", "Strength of noise");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_noisecache_reset");
prop = RNA_def_property(srna, "noise_pos_scale", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "noise_pos_scale");
RNA_def_property_range(prop, 0.0001, 10.0);
RNA_def_property_ui_text(
prop, "Scale", "Scale of noise (higher value results in larger vortices)");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_noisecache_reset");
prop = RNA_def_property(srna, "noise_time_anim", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "noise_time_anim");
RNA_def_property_range(prop, 0.0001, 10.0);
RNA_def_property_ui_text(prop, "Time", "Animation time of noise");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_noisecache_reset");
prop = RNA_def_property(srna, "noise_scale", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "noise_scale");
@@ -1479,7 +1548,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
"The noise simulation is scaled up by this factor (compared to the "
"base resolution of the domain)");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_domain_reset");
prop = RNA_def_property(srna, "noise_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "noise_type");
@@ -1487,7 +1556,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
RNA_def_property_ui_text(
prop, "Noise Method", "Noise method which is used during the high-res simulation");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_domain_reset");
prop = RNA_def_property(srna, "use_noise", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", FLUID_DOMAIN_USE_NOISE);
@@ -1501,7 +1570,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
RNA_def_property_enum_sdna(prop, NULL, "simulation_method");
RNA_def_property_enum_items(prop, simulation_methods);
RNA_def_property_ui_text(prop, "Simulation Method", "Change the underlying simulation method");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_domain_reset");
prop = RNA_def_property(srna, "flip_ratio", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0, 1.0);
@@ -1510,18 +1579,18 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
"FLIP Ratio",
"PIC/FLIP Ratio. A value of 1.0 will result in a completely FLIP based simulation. Use a "
"lower value for simulations which should produce smaller splashes");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset");
prop = RNA_def_property(srna, "particle_randomness", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0, 10.0);
RNA_def_property_ui_text(prop, "Randomness", "Randomness factor for particle sampling");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset");
prop = RNA_def_property(srna, "particle_number", PROP_INT, PROP_NONE);
RNA_def_property_range(prop, 1, 5);
RNA_def_property_ui_text(
prop, "Number", "Particle number factor (higher value results in more particles)");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset");
prop = RNA_def_property(srna, "particle_min", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "particle_minimum");
@@ -1530,7 +1599,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
"Minimum",
"Minimum number of particles per cell (ensures that each cell has at "
"least this amount of particles)");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset");
prop = RNA_def_property(srna, "particle_max", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "particle_maximum");
@@ -1539,7 +1608,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
"Maximum",
"Maximum number of particles per cell (ensures that each cell has at "
"most this amount of particles)");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset");
prop = RNA_def_property(srna, "particle_radius", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0, 10.0);
@@ -1547,7 +1616,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
"Radius",
"Particle radius factor. Increase this value if the simulation appears "
"to leak volume, decrease it if the simulation seems to gain volume");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset");
prop = RNA_def_property(srna, "particle_band_width", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0, 1000.0);
@@ -1555,7 +1624,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
prop,
"Width",
"Particle (narrow) band width (higher value results in thicker band and more particles)");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset");
prop = RNA_def_property(srna, "use_flip_particles", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "particle_type", FLUID_DOMAIN_PARTICLE_FLIP);
@@ -1569,7 +1638,8 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
prop,
"Fractional Obstacles",
"Fractional obstacles improve and smoothen the fluid-obstacle boundary");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset");
prop = RNA_def_property(srna, "fractions_threshold", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.001, 1.0);
@@ -1579,7 +1649,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
"Determines how much fluid is allowed in an obstacle cell "
"(higher values will tag a boundary cell as an obstacle easier "
"and reduce the boundary smoothening effect)");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset");
/* diffusion options */
@@ -1588,7 +1658,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
RNA_def_property_ui_text(
prop, "Use Diffusion", "Enable fluid diffusion settings (e.g. viscosity, surface tension)");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_domain_reset");
prop = RNA_def_property(srna, "surface_tension", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0, 100.0);
@@ -1596,7 +1666,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
prop,
"Tension",
"Surface tension of liquid (higher value results in greater hydrophobic behaviour)");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset");
prop = RNA_def_property(srna, "viscosity_base", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "viscosity_base");
@@ -1605,7 +1675,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
prop,
"Viscosity Base",
"Viscosity setting: value that is multiplied by 10 to the power of (exponent*-1)");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset");
prop = RNA_def_property(srna, "viscosity_exponent", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "viscosity_exponent");
@@ -1615,12 +1685,12 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
"Viscosity Exponent",
"Negative exponent for the viscosity value (to simplify entering small values "
"e.g. 5*10^-6)");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset");
prop = RNA_def_property(srna, "domain_size", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.001, 10000.0);
RNA_def_property_ui_text(prop, "Meters", "Domain size in meters (longest domain side)");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_domain_reset");
/* mesh options options */
@@ -1630,7 +1700,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
prop,
"Upper Concavity",
"Upper mesh concavity bound (high values tend to smoothen and fill out concave regions)");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_meshcache_reset");
prop = RNA_def_property(srna, "mesh_concave_lower", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0, 10.0);
@@ -1638,17 +1708,17 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
prop,
"Lower Concavity",
"Lower mesh concavity bound (high values tend to smoothen and fill out concave regions)");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_meshcache_reset");
prop = RNA_def_property(srna, "mesh_smoothen_pos", PROP_INT, PROP_NONE);
RNA_def_property_range(prop, 0, 100);
RNA_def_property_ui_text(prop, "Smoothen Pos", "Positive mesh smoothening");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_meshcache_reset");
prop = RNA_def_property(srna, "mesh_smoothen_neg", PROP_INT, PROP_NONE);
RNA_def_property_range(prop, 0, 100);
RNA_def_property_ui_text(prop, "Smoothen Neg", "Negative mesh smoothening");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_meshcache_reset");
prop = RNA_def_property(srna, "mesh_scale", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "mesh_scale");
@@ -1660,7 +1730,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
"resolution of the domain). For best meshing, it is recommended to "
"adjust the mesh particle radius alongside this value");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_domain_reset");
prop = RNA_def_property(srna, "mesh_generator", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "mesh_generator");
@@ -1689,7 +1759,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
"Caches velocities of mesh vertices. These will be used "
"(automatically) when rendering with motion blur enabled");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_domain_reset");
prop = RNA_def_property(srna, "mesh_particle_radius", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0, 10.0);
@@ -1697,7 +1767,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
"Radius",
"Particle radius factor (higher value results in larger (meshed) "
"particles). Needs to be adjusted after changing the mesh scale");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_meshcache_reset");
/* secondary particles options */
@@ -1709,7 +1779,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
"Minimum Wave Crest Potential",
"Lower clamping threshold for marking fluid cells as wave crests "
"(lower value results in more marked cells)");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_particlescache_reset");
prop = RNA_def_property(srna, "sndparticle_potential_max_wavecrest", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "sndparticle_tau_max_wc");
@@ -1719,7 +1789,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
"Maximum Wave Crest Potential",
"Upper clamping threshold for marking fluid cells as wave crests "
"(higher value results in less marked cells)");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_particlescache_reset");
prop = RNA_def_property(srna, "sndparticle_potential_min_trappedair", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "sndparticle_tau_min_ta");
@@ -1729,7 +1799,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
"Minimum Trapped Air Potential",
"Lower clamping threshold for marking fluid cells where air is trapped "
"(lower value results in more marked cells)");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_particlescache_reset");
prop = RNA_def_property(srna, "sndparticle_potential_max_trappedair", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "sndparticle_tau_max_ta");
@@ -1739,7 +1809,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
"Maximum Trapped Air Potential",
"Upper clamping threshold for marking fluid cells where air is trapped "
"(higher value results in less marked cells)");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_particlescache_reset");
prop = RNA_def_property(srna, "sndparticle_potential_min_energy", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "sndparticle_tau_min_k");
@@ -1750,7 +1820,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
"Minimum Kinetic Energy Potential",
"Lower clamping threshold that indicates the fluid speed where cells start to emit "
"particles (lower values result in generally more particles)");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_particlescache_reset");
prop = RNA_def_property(srna, "sndparticle_potential_max_energy", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "sndparticle_tau_max_k");
@@ -1761,7 +1831,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
"Maximum Kinetic Energy Potential",
"Upper clamping threshold that indicates the fluid speed where cells no longer emit more "
"particles (higher value results in generally less particles)");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_particlescache_reset");
prop = RNA_def_property(srna, "sndparticle_sampling_wavecrest", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "sndparticle_k_wc");
@@ -1770,7 +1840,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
RNA_def_property_ui_text(prop,
"Wave Crest Sampling",
"Maximum number of particles generated per wave crest cell per frame");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_particlescache_reset");
prop = RNA_def_property(srna, "sndparticle_sampling_trappedair", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "sndparticle_k_ta");
@@ -1779,7 +1849,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
RNA_def_property_ui_text(prop,
"Trapped Air Sampling",
"Maximum number of particles generated per trapped air cell per frame");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_particlescache_reset");
prop = RNA_def_property(srna, "sndparticle_bubble_buoyancy", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "sndparticle_k_b");
@@ -1789,7 +1859,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
"Bubble Buoyancy",
"Amount of buoyancy force that rises bubbles (high value results in "
"bubble movement mainly upwards)");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_particlescache_reset");
prop = RNA_def_property(srna, "sndparticle_bubble_drag", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "sndparticle_k_d");
@@ -1799,28 +1869,28 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
"Bubble Drag",
"Amount of drag force that moves bubbles along with the fluid (high "
"value results in bubble movement mainly along with the fluid)");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_particlescache_reset");
prop = RNA_def_property(srna, "sndparticle_life_min", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "sndparticle_l_min");
RNA_def_property_range(prop, 0.0, 10000.0);
RNA_def_property_ui_range(prop, 0.0, 10000.0, 100.0, 1);
RNA_def_property_ui_text(prop, "Minimum Lifetime", "Lowest possible particle lifetime");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_particlescache_reset");
prop = RNA_def_property(srna, "sndparticle_life_max", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "sndparticle_l_max");
RNA_def_property_range(prop, 0.0, 10000.0);
RNA_def_property_ui_range(prop, 0.0, 10000.0, 100.0, 1);
RNA_def_property_ui_text(prop, "Maximum Lifetime", "Highest possible particle lifetime");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_particlescache_reset");
prop = RNA_def_property(srna, "sndparticle_boundary", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "sndparticle_boundary");
RNA_def_property_enum_items(prop, sndparticle_boundary_items);
RNA_def_property_ui_text(
prop, "Particles in Boundary", "How particles that left the domain are treated");
- RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_particlescache_reset");
prop = RNA_def_property(srna, "sndparticle_combined_export", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "sndparticle_combined_export");
@@ -1839,7 +1909,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
"Potential Radius",
"Radius to compute potential for each cell (higher values are slower "
"but create smoother potential grids)");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_particlescache_reset");
prop = RNA_def_property(srna, "sndparticle_update_radius", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "sndparticle_update_radius");
@@ -1849,7 +1919,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
"Update Radius",
"Radius to compute position update for each particle (higher values "
"are slower but particles move less chaotic)");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_particlescache_reset");
prop = RNA_def_property(srna, "particle_scale", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "particle_scale");
@@ -1860,7 +1930,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
"The particle simulation is scaled up by this factor (compared to the "
"base resolution of the domain)");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_domain_reset");
prop = RNA_def_property(srna, "use_spray_particles", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "particle_type", FLUID_DOMAIN_PARTICLE_SPRAY);
@@ -1892,13 +1962,13 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "guide_alpha");
RNA_def_property_range(prop, 1.0, 100.0);
RNA_def_property_ui_text(prop, "Weight", "Guiding weight (higher value results in greater lag)");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_guidingcache_reset");
prop = RNA_def_property(srna, "guide_beta", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "guide_beta");
RNA_def_property_range(prop, 1, 50);
RNA_def_property_ui_text(prop, "Size", "Guiding size (higher value results in larger vortices)");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_guidingcache_reset");
prop = RNA_def_property(srna, "guide_vel_factor", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "guide_vel_factor");
@@ -1907,7 +1977,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
prop,
"Velocity Factor",
"Guiding velocity factor (higher value results in greater guiding velocities)");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_guidingcache_reset");
prop = RNA_def_property(srna, "guide_source", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "guide_source");
@@ -1924,13 +1994,13 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
"",
"Use velocities from this object for the guiding effect (object needs "
"to have fluid modifier and be of type domain))");
- RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Fluid_update");
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Fluid_guidingcache_reset");
prop = RNA_def_property(srna, "use_guide", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", FLUID_DOMAIN_USE_GUIDE);
RNA_def_property_ui_text(prop, "Use Guiding", "Enable fluid guiding");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_guidingcache_reset");
/* cache options */
@@ -1968,7 +2038,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
prop, NULL, "rna_Fluid_cachetype_mesh_set", "rna_Fluid_cachetype_mesh_itemf");
RNA_def_property_ui_text(
prop, "File Format", "Select the file format to be used for caching surface data");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_meshcache_reset");
prop = RNA_def_property(srna, "cache_data_format", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "cache_data_format");
@@ -1977,7 +2047,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
prop, NULL, "rna_Fluid_cachetype_data_set", "rna_Fluid_cachetype_volume_itemf");
RNA_def_property_ui_text(
prop, "File Format", "Select the file format to be used for caching volumetric data");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset");
prop = RNA_def_property(srna, "cache_particle_format", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "cache_particle_format");
@@ -1986,7 +2056,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
prop, NULL, "rna_Fluid_cachetype_particle_set", "rna_Fluid_cachetype_particle_itemf");
RNA_def_property_ui_text(
prop, "File Format", "Select the file format to be used for caching particle data");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_particlescache_reset");
prop = RNA_def_property(srna, "cache_noise_format", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "cache_noise_format");
@@ -1995,21 +2065,21 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
prop, NULL, "rna_Fluid_cachetype_noise_set", "rna_Fluid_cachetype_volume_itemf");
RNA_def_property_ui_text(
prop, "File Format", "Select the file format to be used for caching noise data");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_noisecache_reset");
prop = RNA_def_property(srna, "cache_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "cache_type");
RNA_def_property_enum_items(prop, cache_types);
RNA_def_property_enum_funcs(prop, NULL, "rna_Fluid_cachetype_set", NULL);
RNA_def_property_ui_text(prop, "Type", "Change the cache type of the simulation");
- RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Fluid_domain_reset");
prop = RNA_def_property(srna, "cache_directory", PROP_STRING, PROP_DIRPATH);
RNA_def_property_string_maxlength(prop, FILE_MAX);
RNA_def_property_string_funcs(prop, NULL, NULL, "rna_Fluid_cache_directory_set");
RNA_def_property_string_sdna(prop, NULL, "cache_directory");
RNA_def_property_ui_text(prop, "Cache directory", "Directory that contains fluid cache files");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, NULL);
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_update");
prop = RNA_def_property(srna, "is_cache_baking_data", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "cache_flag", FLUID_DOMAIN_BAKING_DATA);
@@ -2069,7 +2139,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
"only needed if you plan to analyze the cache (e.g. view grids, velocity vectors, "
"particles) in Mantaflow directly (outside of Blender) after baking the simulation");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_domain_reset");
/* time options */
@@ -2077,19 +2147,19 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "time_scale");
RNA_def_property_range(prop, 0.0001, 10.0);
RNA_def_property_ui_text(prop, "Time Scale", "Adjust simulation speed");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset");
prop = RNA_def_property(srna, "cfl_condition", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "cfl_condition");
RNA_def_property_range(prop, 0.0, 10.0);
RNA_def_property_ui_text(
prop, "CFL", "Maximal velocity per cell (higher value results in greater timesteps)");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset");
prop = RNA_def_property(srna, "use_adaptive_timesteps", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", FLUID_DOMAIN_USE_ADAPTIVE_TIME);
RNA_def_property_ui_text(prop, "Use Adaptive Time Steps", "");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset");
prop = RNA_def_property(srna, "timesteps_min", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "timesteps_minimum");
@@ -2097,7 +2167,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
RNA_def_property_ui_range(prop, 0, 100, 1, -1);
RNA_def_property_ui_text(
prop, "Minimum", "Minimum number of simulation steps to perform for one frame");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset");
prop = RNA_def_property(srna, "timesteps_max", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "timesteps_maximum");
@@ -2105,7 +2175,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
RNA_def_property_ui_range(prop, 0, 100, 1, -1);
RNA_def_property_ui_text(
prop, "Maximum", "Maximum number of simulation steps to perform for one frame");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset");
/* display settings */
@@ -2316,26 +2386,26 @@ static void rna_def_fluid_flow_settings(BlenderRNA *brna)
RNA_def_property_range(prop, 0.0, 10);
RNA_def_property_ui_range(prop, 0.0, 1.0, 1.0, 4);
RNA_def_property_ui_text(prop, "Density", "");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_flow_reset");
prop = RNA_def_property(srna, "smoke_color", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "color");
RNA_def_property_array(prop, 3);
RNA_def_property_ui_text(prop, "Smoke Color", "Color of smoke");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_flow_reset");
prop = RNA_def_property(srna, "fuel_amount", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0, 10);
RNA_def_property_ui_range(prop, 0.0, 5.0, 1.0, 4);
RNA_def_property_ui_text(prop, "Flame Rate", "");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_flow_reset");
prop = RNA_def_property(srna, "temperature", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "temperature");
RNA_def_property_range(prop, -10, 10);
RNA_def_property_ui_range(prop, -10, 10, 1, 1);
RNA_def_property_ui_text(prop, "Temp. Diff.", "Temperature difference to ambient temperature");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_flow_reset");
prop = RNA_def_property(srna, "particle_system", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "psys");
@@ -2349,13 +2419,13 @@ static void rna_def_fluid_flow_settings(BlenderRNA *brna)
RNA_def_property_enum_items(prop, flow_type_items);
RNA_def_property_enum_funcs(prop, NULL, "rna_Fluid_flowtype_set", NULL);
RNA_def_property_ui_text(prop, "Flow Type", "Change type of fluid in the simulation");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_flow_reset");
prop = RNA_def_property(srna, "flow_behavior", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "behavior");
RNA_def_property_enum_items(prop, flow_behavior_items);
RNA_def_property_ui_text(prop, "Flow Behavior", "Change flow behavior in the simulation");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_flow_reset");
prop = RNA_def_property(srna, "flow_source", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "source");
@@ -2363,20 +2433,20 @@ static void rna_def_fluid_flow_settings(BlenderRNA *brna)
RNA_def_property_enum_funcs(
prop, NULL, "rna_Fluid_flowsource_set", "rna_Fluid_flowsource_itemf");
RNA_def_property_ui_text(prop, "Source", "Change how fluid is emitted");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_flow_reset");
prop = RNA_def_property(srna, "use_absolute", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", FLUID_FLOW_ABSOLUTE);
RNA_def_property_ui_text(prop,
"Absolute Density",
"Only allow given density value in emitter area and will not add up");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_flow_reset");
prop = RNA_def_property(srna, "use_initial_velocity", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", FLUID_FLOW_INITVELOCITY);
RNA_def_property_ui_text(
prop, "Initial Velocity", "Fluid has some initial velocity when it is emitted");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_flow_reset");
prop = RNA_def_property(srna, "velocity_factor", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "vel_multi");
@@ -2386,28 +2456,28 @@ static void rna_def_fluid_flow_settings(BlenderRNA *brna)
"Source",
"Multiplier of source velocity passed to fluid (source velocity is "
"non-zero only if object is moving)");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_flow_reset");
prop = RNA_def_property(srna, "velocity_normal", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "vel_normal");
RNA_def_property_range(prop, -100.0, 100.0);
RNA_def_property_ui_range(prop, -2.0, 2.0, 0.05, 5);
RNA_def_property_ui_text(prop, "Normal", "Amount of normal directional velocity");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_flow_reset");
prop = RNA_def_property(srna, "velocity_random", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "vel_random");
RNA_def_property_range(prop, 0.0, 10.0);
RNA_def_property_ui_range(prop, 0.0, 2.0, 0.05, 5);
RNA_def_property_ui_text(prop, "Random", "Amount of random velocity");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_flow_reset");
prop = RNA_def_property(srna, "velocity_coord", PROP_FLOAT, PROP_XYZ);
RNA_def_property_float_sdna(prop, NULL, "vel_coord");
RNA_def_property_array(prop, 3);
RNA_def_property_range(prop, -1000.1, 1000.1);
RNA_def_property_ui_text(prop, "Initial", "Initial velocity in X, Y and Z direction");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_flow_reset");
prop = RNA_def_property(srna, "volume_density", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0, 1.0);
@@ -2416,7 +2486,7 @@ static void rna_def_fluid_flow_settings(BlenderRNA *brna)
"Volume Emission",
"Controls fluid emission from within the mesh (higher value results in "
"greater emissions from inside the mesh)");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_flow_reset");
prop = RNA_def_property(srna, "surface_distance", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0, 10.0);
@@ -2425,7 +2495,7 @@ static void rna_def_fluid_flow_settings(BlenderRNA *brna)
"Surface Emission",
"Controls fluid emission from the mesh surface (higher value results "
"in emission further away from the mesh surface");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_flow_reset");
prop = RNA_def_property(srna, "use_plane_init", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", FLUID_FLOW_USE_PLANE_INIT);
@@ -2434,24 +2504,24 @@ static void rna_def_fluid_flow_settings(BlenderRNA *brna)
"Is Planar",
"Treat this object as a planar and unclosed mesh. Fluid will only be emitted from the mesh "
"surface and based on the surface emission value");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_flow_reset");
prop = RNA_def_property(srna, "particle_size", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.1, 20.0);
RNA_def_property_ui_range(prop, 0.5, 5.0, 0.05, 5);
RNA_def_property_ui_text(prop, "Size", "Particle size in simulation cells");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_flow_reset");
prop = RNA_def_property(srna, "use_particle_size", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", FLUID_FLOW_USE_PART_SIZE);
RNA_def_property_ui_text(
prop, "Set Size", "Set particle size in simulation cells or use nearest cell");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_flow_reset");
prop = RNA_def_property(srna, "use_inflow", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", FLUID_FLOW_USE_INFLOW);
RNA_def_property_ui_text(prop, "Enabled", "Control when to apply inflow");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_flow_reset");
prop = RNA_def_property(srna, "subframes", PROP_INT, PROP_NONE);
RNA_def_property_range(prop, 0, 200);
@@ -2460,7 +2530,7 @@ static void rna_def_fluid_flow_settings(BlenderRNA *brna)
"Subframes",
"Number of additional samples to take between frames to improve "
"quality of fast moving flows");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_flow_reset");
prop = RNA_def_property(srna, "density_vertex_group", PROP_STRING, PROP_NONE);
RNA_def_property_string_funcs(prop,
@@ -2469,41 +2539,41 @@ static void rna_def_fluid_flow_settings(BlenderRNA *brna)
"rna_FluidFlow_density_vgroup_set");
RNA_def_property_ui_text(
prop, "Vertex Group", "Name of vertex group which determines surface emission rate");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_flow_reset");
prop = RNA_def_property(srna, "use_texture", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", FLUID_FLOW_TEXTUREEMIT);
RNA_def_property_ui_text(prop, "Use Texture", "Use a texture to control emission strength");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_flow_reset");
prop = RNA_def_property(srna, "texture_map_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "texture_type");
RNA_def_property_enum_items(prop, flow_texture_types);
RNA_def_property_ui_text(prop, "Mapping", "Texture mapping type");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_flow_reset");
prop = RNA_def_property(srna, "uv_layer", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "uvlayer_name");
RNA_def_property_ui_text(prop, "UV Map", "UV map name");
RNA_def_property_string_funcs(prop, NULL, NULL, "rna_FluidFlow_uvlayer_set");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_flow_reset");
prop = RNA_def_property(srna, "noise_texture", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Texture", "Texture that controls emission strength");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_flow_reset");
prop = RNA_def_property(srna, "texture_size", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.01, 10.0);
RNA_def_property_ui_range(prop, 0.1, 5.0, 0.05, 5);
RNA_def_property_ui_text(prop, "Size", "Size of texture mapping");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_flow_reset");
prop = RNA_def_property(srna, "texture_offset", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0, 200.0);
RNA_def_property_ui_range(prop, 0.0, 100.0, 0.05, 5);
RNA_def_property_ui_text(prop, "Offset", "Z-offset of texture mapping");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_flow_reset");
}
static void rna_def_fluid_effector_settings(BlenderRNA *brna)
@@ -2553,36 +2623,36 @@ static void rna_def_fluid_effector_settings(BlenderRNA *brna)
RNA_def_property_enum_sdna(prop, NULL, "type");
RNA_def_property_enum_items(prop, effector_type_items);
RNA_def_property_ui_text(prop, "Effector Type", "Change type of effector in the simulation");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_effector_reset");
prop = RNA_def_property(srna, "surface_distance", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0, 10.0);
RNA_def_property_ui_range(prop, 0.0, 10.0, 0.05, 5);
RNA_def_property_ui_text(
prop, "Surface", "Additional distance around mesh surface to consider as effector");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_effector_reset");
prop = RNA_def_property(srna, "use_plane_init", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", FLUID_EFFECTOR_USE_PLANE_INIT);
RNA_def_property_ui_text(prop, "Is Planar", "Treat this object as a planar, unclosed mesh");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_domain_reset");
prop = RNA_def_property(srna, "velocity_factor", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "vel_multi");
RNA_def_property_range(prop, -100.0, 100.0);
RNA_def_property_ui_text(prop, "Source", "Multiplier of obstacle velocity");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_effector_reset");
prop = RNA_def_property(srna, "guide_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "guide_mode");
RNA_def_property_enum_items(prop, fluid_guide_mode_items);
RNA_def_property_ui_text(prop, "Guiding mode", "How to create guiding velocities");
- RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Fluid_update");
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Fluid_effector_reset");
prop = RNA_def_property(srna, "use_effector", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", FLUID_EFFECTOR_USE_EFFEC);
RNA_def_property_ui_text(prop, "Enabled", "Control when to apply the effector");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_effector_reset");
prop = RNA_def_property(srna, "subframes", PROP_INT, PROP_NONE);
RNA_def_property_range(prop, 0, 200);
@@ -2591,7 +2661,7 @@ static void rna_def_fluid_effector_settings(BlenderRNA *brna)
"Subframes",
"Number of additional samples to take between frames to improve "
"quality of fast moving effector objects");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_effector_reset");
}
void RNA_def_fluid(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_gpencil.c b/source/blender/makesrna/intern/rna_gpencil.c
index d0e084dc0e7..63fe1cf05ca 100644
--- a/source/blender/makesrna/intern/rna_gpencil.c
+++ b/source/blender/makesrna/intern/rna_gpencil.c
@@ -1664,13 +1664,11 @@ static void rna_def_gpencil_layer(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_mask_layer", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_USE_MASK);
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(prop, "Mask Layer", "Mask pixels from underlying layers drawing");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
prop = RNA_def_property(srna, "use_lights", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_USE_LIGHTS);
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(
prop, "Use Lights", "Enable the use of lights on stroke and fill materials");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
diff --git a/source/blender/makesrna/intern/rna_gpencil_modifier.c b/source/blender/makesrna/intern/rna_gpencil_modifier.c
index 5475f62cb8c..cb16dae7afa 100644
--- a/source/blender/makesrna/intern/rna_gpencil_modifier.c
+++ b/source/blender/makesrna/intern/rna_gpencil_modifier.c
@@ -129,6 +129,11 @@ const EnumPropertyItem rna_enum_object_greasepencil_modifier_type_items[] = {
"Opacity",
"Opacity of the strokes"},
{eGpencilModifierType_Tint, "GP_TINT", ICON_MOD_TINT, "Tint", "Tint strokes with new color"},
+ {eGpencilModifierType_Texture,
+ "GP_TEXTURE",
+ ICON_TEXTURE,
+ "Texture",
+ "Change stroke uv texture values"},
{0, NULL, 0, NULL, NULL},
};
@@ -234,6 +239,8 @@ static StructRNA *rna_GpencilModifier_refine(struct PointerRNA *ptr)
return &RNA_ArmatureGpencilModifier;
case eGpencilModifierType_Multiply:
return &RNA_MultiplyGpencilModifier;
+ case eGpencilModifierType_Texture:
+ return &RNA_TextureGpencilModifier;
/* Default */
case eGpencilModifierType_None:
case NUM_GREASEPENCIL_MODIFIER_TYPES:
@@ -302,6 +309,7 @@ RNA_GP_MOD_VGROUP_NAME_SET(Smooth, vgname);
RNA_GP_MOD_VGROUP_NAME_SET(Hook, vgname);
RNA_GP_MOD_VGROUP_NAME_SET(Offset, vgname);
RNA_GP_MOD_VGROUP_NAME_SET(Armature, vgname);
+RNA_GP_MOD_VGROUP_NAME_SET(Texture, vgname);
# undef RNA_GP_MOD_VGROUP_NAME_SET
@@ -2138,6 +2146,140 @@ static void rna_def_modifier_gpencilmultiply(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
}
+static void rna_def_modifier_gpenciltexture(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ static const EnumPropertyItem fit_type_items[] = {
+ {GP_TEX_CONSTANT_LENGTH,
+ "CONSTANT_LENGTH",
+ 0,
+ "Keep Texture at Constant Length",
+ "Keep the texture at a constant length regardless of the length of each stroke"},
+ {GP_TEX_FIT_STROKE,
+ "FIT_STROKE",
+ 0,
+ "Fit Texture to Stroke Length",
+ "Scale the texture to fit the length of each stroke"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ static const EnumPropertyItem mode_items[] = {
+ {STROKE, "STROKE", 0, "Stroke UVs", "Manipulate only stroke UVs"},
+ {FILL, "FILL", 0, "Fill UVs", "Manipulate only fill UVs"},
+ {STROKE_AND_FILL,
+ "STROKE_AND_FILL",
+ 0,
+ "Stroke and Fill UVs",
+ "Manipulate both stroke and fill UVs"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ srna = RNA_def_struct(brna, "TextureGpencilModifier", "GpencilModifier");
+ RNA_def_struct_ui_text(srna, "Texture Modifier", "Transform stroke texture UVs Modifier");
+ RNA_def_struct_sdna(srna, "TextureGpencilModifierData");
+ RNA_def_struct_ui_icon(srna, ICON_TEXTURE);
+
+ prop = RNA_def_property(srna, "layer", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "layername");
+ RNA_def_property_ui_text(prop, "Layer", "Layer name");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "invert_layers", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_TEX_INVERT_LAYER);
+ RNA_def_property_ui_text(prop, "Inverse Layers", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "material", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "materialname");
+ RNA_def_property_ui_text(prop, "Material", "Material name");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "invert_materials", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_TEX_INVERT_MATERIAL);
+ RNA_def_property_ui_text(prop, "Inverse Materials", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "vgname");
+ RNA_def_property_ui_text(prop, "Vertex Group", "Vertex group name for modulating the deform");
+ RNA_def_property_string_funcs(prop, NULL, NULL, "rna_TextureGpencilModifier_vgname_set");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "invert_vertex", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_TEX_INVERT_VGROUP);
+ RNA_def_property_ui_text(prop, "Inverse VertexGroup", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "pass_index", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "pass_index");
+ RNA_def_property_range(prop, 0, 100);
+ RNA_def_property_ui_text(prop, "Pass", "Pass index");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "invert_material_pass", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_TEX_INVERT_PASS);
+ RNA_def_property_ui_text(prop, "Inverse Pass", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "layer_pass", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "layer_pass");
+ RNA_def_property_range(prop, 0, 100);
+ RNA_def_property_ui_text(prop, "Pass", "Layer pass index");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "invert_layer_pass", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_TEX_INVERT_LAYERPASS);
+ RNA_def_property_ui_text(prop, "Inverse Pass", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "uv_offset", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "uv_offset");
+ RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
+ RNA_def_property_ui_range(prop, -100.0, 100.0, 0.1, 3);
+ RNA_def_property_float_default(prop, 0.0f);
+ RNA_def_property_ui_text(prop, "Offset UVs", "Offset value to add to stroke UVs");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "uv_scale", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "uv_scale");
+ RNA_def_property_range(prop, 0.0, FLT_MAX);
+ RNA_def_property_ui_range(prop, 0.0, 100.0, 0.1, 3);
+ RNA_def_property_float_default(prop, 1.0f);
+ RNA_def_property_ui_text(prop, "UV Scale", "Factor to scale the UVs");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "fill_rotation", PROP_FLOAT, PROP_ANGLE);
+ RNA_def_property_float_sdna(prop, NULL, "fill_rotation");
+ RNA_def_property_ui_text(prop, "Fill Rotation", "Additional rotation of the fill UV");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "fill_offset", PROP_FLOAT, PROP_COORDS);
+ RNA_def_property_float_sdna(prop, NULL, "fill_offset");
+ RNA_def_property_array(prop, 2);
+ RNA_def_property_ui_text(prop, "Fill Offset", "Additional offset of the fill UV");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "fill_scale", PROP_FLOAT, PROP_COORDS);
+ RNA_def_property_float_sdna(prop, NULL, "fill_scale");
+ RNA_def_property_range(prop, 0.01f, 100.0f);
+ RNA_def_property_ui_text(prop, "Fill Scale", "Additional scale of the fill UV");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "fit_method", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "fit_method");
+ RNA_def_property_enum_items(prop, fit_type_items);
+ RNA_def_property_ui_text(prop, "Fit Method", "");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_dependency_update");
+
+ prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "mode");
+ RNA_def_property_enum_items(prop, mode_items);
+ RNA_def_property_ui_text(prop, "Mode", "");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_dependency_update");
+}
+
void RNA_def_greasepencil_modifier(BlenderRNA *brna)
{
StructRNA *srna;
@@ -2211,6 +2353,7 @@ void RNA_def_greasepencil_modifier(BlenderRNA *brna)
rna_def_modifier_gpencilhook(brna);
rna_def_modifier_gpencilarmature(brna);
rna_def_modifier_gpencilmultiply(brna);
+ rna_def_modifier_gpenciltexture(brna);
}
#endif
diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h
index 27097261930..cb59eee6afa 100644
--- a/source/blender/makesrna/intern/rna_internal.h
+++ b/source/blender/makesrna/intern/rna_internal.h
@@ -185,6 +185,7 @@ void RNA_def_render(struct BlenderRNA *brna);
void RNA_def_rigidbody(struct BlenderRNA *brna);
void RNA_def_rna(struct BlenderRNA *brna);
void RNA_def_scene(struct BlenderRNA *brna);
+void RNA_def_simulation(struct BlenderRNA *brna);
void RNA_def_view_layer(struct BlenderRNA *brna);
void RNA_def_screen(struct BlenderRNA *brna);
void RNA_def_sculpt_paint(struct BlenderRNA *brna);
@@ -449,6 +450,7 @@ void RNA_def_main_lightprobes(BlenderRNA *brna, PropertyRNA *cprop);
void RNA_def_main_hairs(BlenderRNA *brna, PropertyRNA *cprop);
void RNA_def_main_pointclouds(BlenderRNA *brna, PropertyRNA *cprop);
void RNA_def_main_volumes(BlenderRNA *brna, PropertyRNA *cprop);
+void RNA_def_main_simulations(BlenderRNA *brna, PropertyRNA *cprop);
/* ID Properties */
diff --git a/source/blender/makesrna/intern/rna_main.c b/source/blender/makesrna/intern/rna_main.c
index 855d5f46890..2f37e4079c7 100644
--- a/source/blender/makesrna/intern/rna_main.c
+++ b/source/blender/makesrna/intern/rna_main.c
@@ -134,6 +134,9 @@ RNA_MAIN_LISTBASE_FUNCS_DEF(pointclouds)
RNA_MAIN_LISTBASE_FUNCS_DEF(scenes)
RNA_MAIN_LISTBASE_FUNCS_DEF(screens)
RNA_MAIN_LISTBASE_FUNCS_DEF(shapekeys)
+# ifdef WITH_NEW_SIMULATION_TYPE
+RNA_MAIN_LISTBASE_FUNCS_DEF(simulations)
+# endif
RNA_MAIN_LISTBASE_FUNCS_DEF(sounds)
RNA_MAIN_LISTBASE_FUNCS_DEF(speakers)
RNA_MAIN_LISTBASE_FUNCS_DEF(texts)
@@ -402,6 +405,14 @@ void RNA_def_main(BlenderRNA *brna)
"Volumes",
"Volume data-blocks",
RNA_def_main_volumes},
+# ifdef WITH_NEW_SIMULATION_TYPE
+ {"simulations",
+ "Simulation",
+ "rna_Main_simulations_begin",
+ "Simulations",
+ "Simulation data-blocks",
+ RNA_def_main_simulations},
+# endif
{NULL, NULL, NULL, NULL, NULL, NULL},
};
diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c
index 9799054ccd2..c5781175d65 100644
--- a/source/blender/makesrna/intern/rna_main_api.c
+++ b/source/blender/makesrna/intern/rna_main_api.c
@@ -69,6 +69,7 @@
# include "BKE_particle.h"
# include "BKE_pointcloud.h"
# include "BKE_scene.h"
+# include "BKE_simulation.h"
# include "BKE_sound.h"
# include "BKE_speaker.h"
# include "BKE_text.h"
@@ -98,6 +99,7 @@
# include "DNA_node_types.h"
# include "DNA_particle_types.h"
# include "DNA_pointcloud_types.h"
+# include "DNA_simulation_types.h"
# include "DNA_sound_types.h"
# include "DNA_speaker_types.h"
# include "DNA_text_types.h"
@@ -738,6 +740,18 @@ static Volume *rna_Main_volumes_new(Main *bmain, const char *name)
return volume;
}
+# ifdef WITH_NEW_SIMULATION_TYPE
+static Simulation *rna_Main_simulations_new(Main *bmain, const char *name)
+{
+ char safe_name[MAX_ID_NAME - 2];
+ rna_idname_validate(name, safe_name);
+
+ Simulation *simulation = BKE_simulation_add(bmain, safe_name);
+ id_us_min(&simulation->id);
+ return simulation;
+}
+# endif
+
/* tag functions, all the same */
# define RNA_MAIN_ID_TAG_FUNCS_DEF(_func_name, _listbase_name, _id_type) \
static void rna_Main_##_func_name##_tag(Main *bmain, bool value) \
@@ -785,6 +799,9 @@ RNA_MAIN_ID_TAG_FUNCS_DEF(hairs, hairs, ID_HA)
RNA_MAIN_ID_TAG_FUNCS_DEF(pointclouds, pointclouds, ID_PT)
# endif
RNA_MAIN_ID_TAG_FUNCS_DEF(volumes, volumes, ID_VO)
+# ifdef WITH_NEW_SIMULATION_TYPE
+RNA_MAIN_ID_TAG_FUNCS_DEF(simulations, simulations, ID_SIM)
+# endif
# undef RNA_MAIN_ID_TAG_FUNCS_DEF
@@ -2304,4 +2321,44 @@ void RNA_def_main_volumes(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
}
+void RNA_def_main_simulations(BlenderRNA *brna, PropertyRNA *cprop)
+{
+ StructRNA *srna;
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
+ RNA_def_property_srna(cprop, "BlendDataSimulations");
+ srna = RNA_def_struct(brna, "BlendDataSimulations", NULL);
+ RNA_def_struct_sdna(srna, "Main");
+ RNA_def_struct_ui_text(srna, "Main Simulations", "Collection of simulations");
+
+ func = RNA_def_function(srna, "new", "rna_Main_simulations_new");
+ RNA_def_function_ui_description(func, "Add a new simulation to the main database");
+ parm = RNA_def_string(func, "name", "Simulation", 0, "", "New name for the data-block");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ /* return type */
+ parm = RNA_def_pointer(func, "simulation", "Simulation", "", "New simulation data-block");
+ RNA_def_function_return(func, parm);
+
+ func = RNA_def_function(srna, "remove", "rna_Main_ID_remove");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ RNA_def_function_ui_description(func, "Remove a simulation from the current blendfile");
+ parm = RNA_def_pointer(func, "simulation", "Simulation", "", "Simulation to remove");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
+ RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0);
+ RNA_def_boolean(
+ func, "do_unlink", true, "", "Unlink all usages of this simulation before deleting it");
+ RNA_def_boolean(func,
+ "do_id_user",
+ true,
+ "",
+ "Decrement user counter of all datablocks used by this simulation data");
+ RNA_def_boolean(
+ func, "do_ui_user", true, "", "Make sure interface does not reference this simulation data");
+
+ func = RNA_def_function(srna, "tag", "rna_Main_simulations_tag");
+ parm = RNA_def_boolean(func, "value", 0, "Value", "");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+}
+
#endif
diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c
index e13b9caa90c..ccc141c1bb2 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -920,7 +920,7 @@ static bool rna_HookModifier_object_override_apply(Main *UNUSED(bmain),
{
BLI_assert(len_dst == len_src && (!ptr_storage || len_dst == len_storage) && len_dst == 0);
BLI_assert(opop->operation == IDOVERRIDE_LIBRARY_OP_REPLACE &&
- "Unsupported RNA override operation on Hook modifier target objet pointer");
+ "Unsupported RNA override operation on Hook modifier target object pointer");
UNUSED_VARS_NDEBUG(ptr_storage, len_dst, len_src, len_storage, opop);
/* We need a special handling here because setting hook target resets invert parent matrix,
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index 31d6ff80f34..9242ad7237f 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -81,6 +81,35 @@ static const EnumPropertyItem node_socket_type_items[] = {
{SOCK_STRING, "STRING", 0, "String", ""},
{SOCK_RGBA, "RGBA", 0, "RGBA", ""},
{SOCK_SHADER, "SHADER", 0, "Shader", ""},
+ {SOCK_OBJECT, "OBJECT", 0, "Object", ""},
+ {SOCK_IMAGE, "IMAGE", 0, "Image", ""},
+ {SOCK_EMITTERS, "EMITTERS", 0, "Emitters", ""},
+ {SOCK_EVENTS, "EVENTS", 0, "Events", ""},
+ {SOCK_FORCES, "FORCES", 0, "Forces", ""},
+ {SOCK_CONTROL_FLOW, "CONTROL_FLOW", 0, "Control Flow", ""},
+ {0, NULL, 0, NULL, NULL},
+};
+
+static const EnumPropertyItem particle_attribute_socket_type_items[] = {
+ {SOCK_FLOAT, "FLOAT", 0, "Float", ""},
+ {SOCK_INT, "INT", 0, "Int", ""},
+ {SOCK_BOOLEAN, "BOOLEAN", 0, "Boolean", ""},
+ {SOCK_VECTOR, "VECTOR", 0, "Vector", ""},
+ {SOCK_RGBA, "RGBA", 0, "Color", ""},
+ {SOCK_OBJECT, "OBJECT", 0, "Object", ""},
+ {SOCK_IMAGE, "IMAGE", 0, "Image", ""},
+ {0, NULL, 0, NULL, NULL},
+};
+
+static const EnumPropertyItem node_socket_data_type_items[] = {
+ {SOCK_FLOAT, "FLOAT", 0, "Float", ""},
+ {SOCK_INT, "INT", 0, "Int", ""},
+ {SOCK_BOOLEAN, "BOOLEAN", 0, "Boolean", ""},
+ {SOCK_VECTOR, "VECTOR", 0, "Vector", ""},
+ {SOCK_STRING, "STRING", 0, "String", ""},
+ {SOCK_RGBA, "RGBA", 0, "Color", ""},
+ {SOCK_OBJECT, "OBJECT", 0, "Object", ""},
+ {SOCK_IMAGE, "IMAGE", 0, "Image", ""},
{0, NULL, 0, NULL, NULL},
};
@@ -244,6 +273,47 @@ const EnumPropertyItem rna_enum_node_vec_math_items[] = {
{0, NULL, 0, NULL, NULL},
};
+const EnumPropertyItem rna_enum_node_boolean_math_items[] = {
+ {NODE_BOOLEAN_MATH_AND, "AND", 0, "And", "Outputs true only when both inputs are true"},
+ {NODE_BOOLEAN_MATH_OR, "OR", 0, "Or", "Outputs or when at least one of the inputs is true"},
+ {NODE_BOOLEAN_MATH_NOT, "NOT", 0, "Not", "Outputs the opposite of the input"},
+ {0, NULL, 0, NULL, NULL},
+};
+
+const EnumPropertyItem rna_enum_node_float_compare_items[] = {
+ {NODE_FLOAT_COMPARE_LESS_THAN,
+ "LESS_THAN",
+ 0,
+ "A < B",
+ "True when the first input is smaller than second input"},
+ {NODE_FLOAT_COMPARE_LESS_EQUAL,
+ "LESS_EQUAL",
+ 0,
+ "A <= B",
+ "True when the first input is smaller than the second input or equal"},
+ {NODE_FLOAT_COMPARE_GREATER_THAN,
+ "GREATER_THAN",
+ 0,
+ "A > B",
+ "True when the first input is greater than the second input"},
+ {NODE_FLOAT_COMPARE_GREATER_EQUAL,
+ "GREATER_EQUAL",
+ 0,
+ "A >= B",
+ "True when the first input is greater than the second input or equal"},
+ {NODE_FLOAT_COMPARE_EQUAL,
+ "EQUAL",
+ 0,
+ "A = B",
+ "True when both inputs are approximately equal"},
+ {NODE_FLOAT_COMPARE_NOT_EQUAL,
+ "NOT_EQUAL",
+ 0,
+ "A != B",
+ "True when both inputs are not approximately equal"},
+ {0, NULL, 0, NULL, NULL},
+};
+
const EnumPropertyItem rna_enum_node_map_range_items[] = {
{NODE_MAP_RANGE_LINEAR,
"LINEAR",
@@ -669,6 +739,34 @@ static const EnumPropertyItem *rna_node_static_type_itemf(bContext *UNUSED(C),
# undef DefNode
}
+ if (RNA_struct_is_a(ptr->type, &RNA_SimulationNode)) {
+# define DefNode(Category, ID, DefFunc, EnumName, StructName, UIName, UIDesc) \
+ if (STREQ(#Category, "SimulationNode")) { \
+ tmp.value = ID; \
+ tmp.identifier = EnumName; \
+ tmp.name = UIName; \
+ tmp.description = UIDesc; \
+ tmp.icon = ICON_NONE; \
+ RNA_enum_item_add(&item, &totitem, &tmp); \
+ }
+# include "../../nodes/NOD_static_types.h"
+# undef DefNode
+ }
+
+ if (RNA_struct_is_a(ptr->type, &RNA_FunctionNode)) {
+# define DefNode(Category, ID, DefFunc, EnumName, StructName, UIName, UIDesc) \
+ if (STREQ(#Category, "FunctionNode")) { \
+ tmp.value = ID; \
+ tmp.identifier = EnumName; \
+ tmp.name = UIName; \
+ tmp.description = UIDesc; \
+ tmp.icon = ICON_NONE; \
+ RNA_enum_item_add(&item, &totitem, &tmp); \
+ }
+# include "../../nodes/NOD_static_types.h"
+# undef DefNode
+ }
+
RNA_enum_item_end(&item, &totitem);
*r_free = true;
@@ -1785,6 +1883,50 @@ static StructRNA *rna_TextureNode_register(Main *bmain,
return nt->rna_ext.srna;
}
+static StructRNA *rna_SimulationNode_register(Main *bmain,
+ ReportList *reports,
+ void *data,
+ const char *identifier,
+ StructValidateFunc validate,
+ StructCallbackFunc call,
+ StructFreeFunc free)
+{
+ bNodeType *nt = rna_Node_register_base(
+ bmain, reports, &RNA_SimulationNode, data, identifier, validate, call, free);
+ if (!nt) {
+ return NULL;
+ }
+
+ nodeRegisterType(nt);
+
+ /* update while blender is running */
+ WM_main_add_notifier(NC_NODE | NA_EDITED, NULL);
+
+ return nt->rna_ext.srna;
+}
+
+static StructRNA *rna_FunctionNode_register(Main *bmain,
+ ReportList *reports,
+ void *data,
+ const char *identifier,
+ StructValidateFunc validate,
+ StructCallbackFunc call,
+ StructFreeFunc free)
+{
+ bNodeType *nt = rna_Node_register_base(
+ bmain, reports, &RNA_FunctionNode, data, identifier, validate, call, free);
+ if (!nt) {
+ return NULL;
+ }
+
+ nodeRegisterType(nt);
+
+ /* update while blender is running */
+ WM_main_add_notifier(NC_NODE | NA_EDITED, NULL);
+
+ return nt->rna_ext.srna;
+}
+
static IDProperty *rna_Node_idprops(PointerRNA *ptr, bool create)
{
bNode *node = ptr->data;
@@ -3581,6 +3723,15 @@ static void rna_ShaderNode_socket_update(Main *bmain, Scene *scene, PointerRNA *
rna_Node_update(bmain, scene, ptr);
}
+static void rna_FunctionNode_socket_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ bNodeTree *ntree = (bNodeTree *)ptr->owner_id;
+ bNode *node = (bNode *)ptr->data;
+
+ nodeUpdate(ntree, node);
+ rna_Node_update(bmain, scene, ptr);
+}
+
static void rna_CompositorNodeScale_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
bNodeTree *ntree = (bNodeTree *)ptr->owner_id;
@@ -3590,6 +3741,15 @@ static void rna_CompositorNodeScale_update(Main *bmain, Scene *scene, PointerRNA
rna_Node_update(bmain, scene, ptr);
}
+static void rna_SimulationNode_socket_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ bNodeTree *ntree = (bNodeTree *)ptr->owner_id;
+ bNode *node = (bNode *)ptr->data;
+
+ nodeUpdate(ntree, node);
+ rna_Node_update(bmain, scene, ptr);
+}
+
static PointerRNA rna_ShaderNodePointDensity_psys_get(PointerRNA *ptr)
{
bNode *node = ptr->data;
@@ -4016,6 +4176,39 @@ static void def_math(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
+static void def_boolean_math(StructRNA *srna)
+{
+ PropertyRNA *prop;
+
+ prop = RNA_def_property(srna, "operation", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "custom1");
+ RNA_def_property_enum_items(prop, rna_enum_node_boolean_math_items);
+ RNA_def_property_ui_text(prop, "Operation", "");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_FunctionNode_socket_update");
+}
+
+static void def_float_compare(StructRNA *srna)
+{
+ PropertyRNA *prop;
+
+ prop = RNA_def_property(srna, "operation", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "custom1");
+ RNA_def_property_enum_items(prop, rna_enum_node_float_compare_items);
+ RNA_def_property_ui_text(prop, "Operation", "");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_FunctionNode_socket_update");
+}
+
+static void def_fn_switch(StructRNA *srna)
+{
+ PropertyRNA *prop;
+
+ prop = RNA_def_property(srna, "data_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "custom1");
+ RNA_def_property_enum_items(prop, node_socket_data_type_items);
+ RNA_def_property_ui_text(prop, "Data Type", "Data type for inputs and outputs");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_FunctionNode_socket_update");
+}
+
static void def_vector_math(StructRNA *srna)
{
PropertyRNA *prop;
@@ -7899,6 +8092,82 @@ static void def_tex_bricks(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
+/* -- Simulation Nodes --------------------------------------------------------- */
+
+static void def_sim_particle_time_step_event(StructRNA *srna)
+{
+ static const EnumPropertyItem mode_items[] = {
+ {NODE_PARTICLE_TIME_STEP_EVENT_BEGIN,
+ "BEGIN",
+ 0,
+ "Begin",
+ "Execute for every particle at the beginning of each time step"},
+ {NODE_PARTICLE_TIME_STEP_EVENT_END,
+ "END",
+ 0,
+ "End",
+ "Execute for every particle at the end of each time step"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ PropertyRNA *prop;
+
+ prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "custom1");
+ RNA_def_property_enum_items(prop, mode_items);
+ RNA_def_property_ui_text(prop, "Mode", "When in each time step is the event triggered");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+}
+
+static void def_sim_particle_attribute(StructRNA *srna)
+{
+ PropertyRNA *prop;
+
+ prop = RNA_def_property(srna, "data_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "custom1");
+ RNA_def_property_enum_items(prop, particle_attribute_socket_type_items);
+ RNA_def_property_ui_text(
+ prop,
+ "Data Type",
+ "Expected type of the attribute. A default value is returned if the type is not correct");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_SimulationNode_socket_update");
+}
+
+static void def_sim_set_particle_attribute(StructRNA *srna)
+{
+ PropertyRNA *prop;
+
+ prop = RNA_def_property(srna, "data_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "custom1");
+ RNA_def_property_enum_items(prop, particle_attribute_socket_type_items);
+ RNA_def_property_ui_text(
+ prop,
+ "Data Type",
+ "Expected type of the attribute. Nothing is done if the type is not correct");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_SimulationNode_socket_update");
+}
+
+static void def_sim_time(StructRNA *srna)
+{
+ static const EnumPropertyItem mode_items[] = {
+ {NODE_SIM_INPUT_SIMULATION_TIME,
+ "SIMULATION_TIME",
+ 0,
+ "Simulation Time",
+ "Time since start of simulation"},
+ {NODE_SIM_INPUT_SCENE_TIME, "SCENE_TIME", 0, "Scene Time", "Time shown in the timeline"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ PropertyRNA *prop;
+
+ prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "custom1");
+ RNA_def_property_enum_items(prop, mode_items);
+ RNA_def_property_ui_text(prop, "Mode", "The time to output");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_SimulationNode_socket_update");
+}
+
/* -------------------------------------------------------------------------- */
static void rna_def_shader_node(BlenderRNA *brna)
@@ -7936,6 +8205,26 @@ static void rna_def_texture_node(BlenderRNA *brna)
RNA_def_struct_register_funcs(srna, "rna_TextureNode_register", "rna_Node_unregister", NULL);
}
+static void rna_def_simulation_node(BlenderRNA *brna)
+{
+ StructRNA *srna;
+
+ srna = RNA_def_struct(brna, "SimulationNode", "NodeInternal");
+ RNA_def_struct_ui_text(srna, "Simulation Node", "");
+ RNA_def_struct_sdna(srna, "bNode");
+ RNA_def_struct_register_funcs(srna, "rna_SimulationNode_register", "rna_Node_unregister", NULL);
+}
+
+static void rna_def_function_node(BlenderRNA *brna)
+{
+ StructRNA *srna;
+
+ srna = RNA_def_struct(brna, "FunctionNode", "NodeInternal");
+ RNA_def_struct_ui_text(srna, "Function Node", "");
+ RNA_def_struct_sdna(srna, "bNode");
+ RNA_def_struct_register_funcs(srna, "rna_FunctionNode_register", "rna_Node_unregister", NULL);
+}
+
/* -------------------------------------------------------------------------- */
static void rna_def_node_socket(BlenderRNA *brna)
@@ -8492,6 +8781,104 @@ static void rna_def_node_socket_virtual(BlenderRNA *brna, const char *identifier
RNA_def_struct_sdna(srna, "bNodeSocket");
}
+static void rna_def_node_socket_object(BlenderRNA *brna,
+ const char *identifier,
+ const char *interface_idname)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, identifier, "NodeSocketStandard");
+ RNA_def_struct_ui_text(srna, "Object Node Socket", "Object socket of a node");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+
+ RNA_def_struct_sdna_from(srna, "bNodeSocketValueObject", "default_value");
+
+ prop = RNA_def_property(srna, "default_value", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "value");
+ RNA_def_property_struct_type(prop, "Object");
+ RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketStandard_value_update");
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT | PROP_CONTEXT_UPDATE);
+
+ /* socket interface */
+ srna = RNA_def_struct(brna, interface_idname, "NodeSocketInterfaceStandard");
+ RNA_def_struct_ui_text(srna, "Object Node Socket Interface", "Object socket of a node");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+
+ RNA_def_struct_sdna_from(srna, "bNodeSocketValueObject", "default_value");
+
+ prop = RNA_def_property(srna, "default_value", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "value");
+ RNA_def_property_struct_type(prop, "Object");
+ RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketInterface_update");
+}
+
+static void rna_def_node_socket_image(BlenderRNA *brna,
+ const char *identifier,
+ const char *interface_idname)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, identifier, "NodeSocketStandard");
+ RNA_def_struct_ui_text(srna, "Image Node Socket", "Image socket of a node");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+
+ RNA_def_struct_sdna_from(srna, "bNodeSocketValueImage", "default_value");
+
+ prop = RNA_def_property(srna, "default_value", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "value");
+ RNA_def_property_struct_type(prop, "Image");
+ RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketStandard_value_update");
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT | PROP_CONTEXT_UPDATE);
+
+ /* socket interface */
+ srna = RNA_def_struct(brna, interface_idname, "NodeSocketInterfaceStandard");
+ RNA_def_struct_ui_text(srna, "Image Node Socket Interface", "Image socket of a node");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+
+ RNA_def_struct_sdna_from(srna, "bNodeSocketValueImage", "default_value");
+
+ prop = RNA_def_property(srna, "default_value", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "value");
+ RNA_def_property_struct_type(prop, "Image");
+ RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketInterface_update");
+}
+
+static void rna_def_node_socket_effector(BlenderRNA *brna,
+ const char *identifier,
+ const char *interface_idname)
+{
+ StructRNA *srna;
+
+ srna = RNA_def_struct(brna, identifier, "NodeSocketStandard");
+ RNA_def_struct_ui_text(srna, "", "");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+
+ srna = RNA_def_struct(brna, interface_idname, "NodeSocketInterfaceStandard");
+ RNA_def_struct_ui_text(srna, "", "");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+}
+
+static void rna_def_node_socket_control_flow(BlenderRNA *brna,
+ const char *identifier,
+ const char *interface_idname)
+{
+ StructRNA *srna;
+
+ srna = RNA_def_struct(brna, identifier, "NodeSocketStandard");
+ RNA_def_struct_ui_text(srna, "", "");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+
+ srna = RNA_def_struct(brna, interface_idname, "NodeSocketInterfaceStandard");
+ RNA_def_struct_ui_text(srna, "", "");
+ RNA_def_struct_sdna(srna, "bNodeSocket");
+}
+
static void rna_def_node_socket_standard_types(BlenderRNA *brna)
{
/* XXX Workaround: Registered functions are not exposed in python by bpy,
@@ -8626,6 +9013,17 @@ static void rna_def_node_socket_standard_types(BlenderRNA *brna)
rna_def_node_socket_shader(brna, "NodeSocketShader", "NodeSocketInterfaceShader");
rna_def_node_socket_virtual(brna, "NodeSocketVirtual");
+
+ rna_def_node_socket_object(brna, "NodeSocketObject", "NodeSocketInterfaceObject");
+
+ rna_def_node_socket_image(brna, "NodeSocketImage", "NodeSocketInterfaceImage");
+
+ rna_def_node_socket_effector(brna, "NodeSocketEmitters", "NodeSocketInterfaceEmitters");
+ rna_def_node_socket_effector(brna, "NodeSocketEvents", "NodeSocketInterfaceEvents");
+ rna_def_node_socket_effector(brna, "NodeSocketForces", "NodeSocketInterfaceForces");
+
+ rna_def_node_socket_control_flow(
+ brna, "NodeSocketControlFlow", "NodeSocketInterfaceControlFlow");
}
static void rna_def_internal_node(BlenderRNA *brna)
@@ -9251,6 +9649,7 @@ static void rna_def_nodetree(BlenderRNA *brna)
{NTREE_SHADER, "SHADER", ICON_MATERIAL, "Shader", "Shader nodes"},
{NTREE_TEXTURE, "TEXTURE", ICON_TEXTURE, "Texture", "Texture nodes"},
{NTREE_COMPOSIT, "COMPOSITING", ICON_RENDERLAYERS, "Compositing", "Compositing nodes"},
+ {NTREE_SIMULATION, "SIMULATION", ICON_PHYSICS, "Simulation", "Simulation nodes"},
{0, NULL, 0, NULL, NULL},
};
@@ -9474,6 +9873,17 @@ static void rna_def_texture_nodetree(BlenderRNA *brna)
RNA_def_struct_ui_icon(srna, ICON_TEXTURE);
}
+static void rna_def_simulation_nodetree(BlenderRNA *brna)
+{
+ StructRNA *srna;
+
+ srna = RNA_def_struct(brna, "SimulationNodeTree", "NodeTree");
+ RNA_def_struct_ui_text(
+ srna, "Simulation Node Tree", "Node tree consisting of linked nodes used for simulations");
+ RNA_def_struct_sdna(srna, "bNodeTree");
+ RNA_def_struct_ui_icon(srna, ICON_PHYSICS); /* TODO: Use correct icon. */
+}
+
static StructRNA *define_specific_node(BlenderRNA *brna,
const char *struct_name,
const char *base_name,
@@ -9560,6 +9970,8 @@ void RNA_def_nodetree(BlenderRNA *brna)
rna_def_shader_node(brna);
rna_def_compositor_node(brna);
rna_def_texture_node(brna);
+ rna_def_simulation_node(brna);
+ rna_def_function_node(brna);
rna_def_nodetree(brna);
@@ -9568,6 +9980,7 @@ void RNA_def_nodetree(BlenderRNA *brna)
rna_def_composite_nodetree(brna);
rna_def_shader_nodetree(brna);
rna_def_texture_nodetree(brna);
+ rna_def_simulation_nodetree(brna);
# define DefNode(Category, ID, DefFunc, EnumName, StructName, UIName, UIDesc) \
{ \
@@ -9584,12 +9997,13 @@ void RNA_def_nodetree(BlenderRNA *brna)
*/
# include "../../nodes/NOD_static_types.h"
- /* Node group types need to be defined for shader, compositor, texture nodes individually.
- * Cannot use the static types header for this, since they share the same int id.
+ /* Node group types need to be defined for shader, compositor, texture, simulation nodes
+ * individually. Cannot use the static types header for this, since they share the same int id.
*/
define_specific_node(brna, "ShaderNodeGroup", "ShaderNode", "Group", "", def_group);
define_specific_node(brna, "CompositorNodeGroup", "CompositorNode", "Group", "", def_group);
define_specific_node(brna, "TextureNodeGroup", "TextureNode", "Group", "", def_group);
+ define_specific_node(brna, "SimulationNodeGroup", "SimulationNode", "Group", "", def_group);
def_custom_group(brna,
"ShaderNodeCustomGroup",
"ShaderNode",
diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c
index b108093a9dd..1ebcb1c776d 100644
--- a/source/blender/makesrna/intern/rna_object.c
+++ b/source/blender/makesrna/intern/rna_object.c
@@ -3192,7 +3192,6 @@ static void rna_def_object(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_grease_pencil_lights", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "dtx", OB_USE_GPENCIL_LIGHTS);
RNA_def_property_boolean_default(prop, true);
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(prop, "Use Lights", "Lights affect grease pencil object");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_GPencil_update");
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 27ebbe79085..6548aa01091 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -5699,6 +5699,16 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL},
};
+ static const EnumPropertyItem meta_input_items[] = {
+ {0, "SCENE", 0, "Scene", "Use metadata from the current scene"},
+ {R_STAMP_STRIPMETA,
+ "STRIPS",
+ 0,
+ "Sequencer Strips",
+ "Use metadata from the strips in the sequencer"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
rna_def_scene_ffmpeg_settings(brna);
srna = RNA_def_struct(brna, "RenderSettings", NULL);
@@ -6216,10 +6226,10 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
prop, "Stamp Labels", "Display stamp labels (\"Camera\" in front of camera name, etc.)");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
- prop = RNA_def_property(srna, "use_stamp_strip_meta", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "stamp", R_STAMP_STRIPMETA);
- RNA_def_property_ui_text(
- prop, "Strip Metadata", "Use metadata from the strips in the sequencer");
+ prop = RNA_def_property(srna, "metadata_input", PROP_ENUM, PROP_NONE); /* as an enum */
+ RNA_def_property_enum_bitflag_sdna(prop, NULL, "stamp");
+ RNA_def_property_enum_items(prop, meta_input_items);
+ RNA_def_property_ui_text(prop, "Metadata Input", "Where to take the metadata from");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "use_stamp_memory", PROP_BOOLEAN, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_simulation.c b/source/blender/makesrna/intern/rna_simulation.c
new file mode 100644
index 00000000000..789ea299feb
--- /dev/null
+++ b/source/blender/makesrna/intern/rna_simulation.c
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+/** \file
+ * \ingroup RNA
+ */
+
+#include <stdlib.h>
+
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#include "DNA_simulation_types.h"
+
+#include "rna_internal.h"
+
+#ifdef RNA_RUNTIME
+
+#else
+
+static void rna_def_simulation(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "Simulation", "ID");
+ RNA_def_struct_ui_text(srna, "Simulation", "Simulation data-block");
+ RNA_def_struct_ui_icon(srna, ICON_PHYSICS); /* TODO: Use correct icon. */
+
+ prop = RNA_def_property(srna, "node_tree", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "nodetree");
+ RNA_def_property_ui_text(prop, "Node Tree", "Node tree defining the simulation");
+
+ /* common */
+ rna_def_animdata_common(srna);
+}
+
+void RNA_def_simulation(BlenderRNA *brna)
+{
+ rna_def_simulation(brna);
+}
+
+#endif
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index 1f072d2eb26..266bf1334ba 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -45,6 +45,7 @@
#include "DNA_node_types.h"
#include "DNA_object_types.h"
#include "DNA_sequence_types.h"
+#include "DNA_simulation_types.h"
#include "DNA_space_types.h"
#include "DNA_view3d_types.h"
#include "DNA_workspace_types.h"
@@ -2166,6 +2167,40 @@ static void rna_SpaceNodeEditor_node_tree_update(const bContext *C, PointerRNA *
ED_node_tree_update(C);
}
+# ifdef WITH_NEW_SIMULATION_TYPE
+static PointerRNA rna_SpaceNodeEditor_simulation_get(PointerRNA *ptr)
+{
+ SpaceNode *snode = (SpaceNode *)ptr->data;
+ ID *id = snode->id;
+ if (id && GS(id->name) == ID_SIM) {
+ return rna_pointer_inherit_refine(ptr, &RNA_Simulation, snode->id);
+ }
+ else {
+ return PointerRNA_NULL;
+ }
+}
+
+static void rna_SpaceNodeEditor_simulation_set(PointerRNA *ptr,
+ const PointerRNA value,
+ struct ReportList *UNUSED(reports))
+{
+ SpaceNode *snode = (SpaceNode *)ptr->data;
+ if (!STREQ(snode->tree_idname, "SimulationNodeTree")) {
+ return;
+ }
+
+ Simulation *sim = (Simulation *)value.data;
+ if (sim != NULL) {
+ bNodeTree *ntree = sim->nodetree;
+ ED_node_tree_start(snode, ntree, NULL, NULL);
+ }
+ else {
+ ED_node_tree_start(snode, NULL, NULL, NULL);
+ }
+ snode->id = &sim->id;
+}
+# endif
+
static int rna_SpaceNodeEditor_tree_type_get(PointerRNA *ptr)
{
SpaceNode *snode = (SpaceNode *)ptr->data;
@@ -2935,6 +2970,12 @@ static void rna_def_space_image_uv(BlenderRNA *brna)
prop, "Tile Grid Shape", "How many tiles will be shown in the background");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, NULL);
+ prop = RNA_def_property(srna, "uv_opacity", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "uv_opacity");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "UV Opacity", "Opacity of UV overlays");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, NULL);
+
/* todo: move edge and face drawing options here from G.f */
prop = RNA_def_property(srna, "pixel_snap_mode", PROP_ENUM, PROP_NONE);
@@ -5521,6 +5562,13 @@ static void rna_def_fileselect_idfilter(BlenderRNA *brna)
"Show/hide Point Cloud data-blocks"},
# endif
{FILTER_ID_SCE, "filter_scene", ICON_SCENE_DATA, "Scenes", "Show Scene data-blocks"},
+# ifdef WITH_NEW_SIMULATION_TYPE
+ {FILTER_ID_SIM,
+ "filter_simulation",
+ ICON_PHYSICS,
+ "Simulations",
+ "Show Simulation data-blocks"}, /* TODO: Use correct icon. */
+# endif
{FILTER_ID_SPK, "filter_speaker", ICON_SPEAKER, "Speakers", "Show Speaker data-blocks"},
{FILTER_ID_SO, "filter_sound", ICON_SOUND, "Sounds", "Show Sound data-blocks"},
{FILTER_ID_TE, "filter_texture", ICON_TEXTURE_DATA, "Textures", "Show Texture data-blocks"},
@@ -6202,6 +6250,19 @@ static void rna_def_space_node(BlenderRNA *brna)
RNA_def_property_ui_text(
prop, "ID From", "Data-block from which the edited data-block is linked");
+# ifdef WITH_NEW_SIMULATION_TYPE
+ prop = RNA_def_property(srna, "simulation", PROP_POINTER, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_struct_type(prop, "Simulation");
+ RNA_def_property_ui_text(prop, "Simulation", "Simulation that is being edited");
+ RNA_def_property_pointer_funcs(prop,
+ "rna_SpaceNodeEditor_simulation_get",
+ "rna_SpaceNodeEditor_simulation_set",
+ NULL,
+ NULL);
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE, NULL);
+# endif
+
prop = RNA_def_property(srna, "path", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "treepath", NULL);
RNA_def_property_struct_type(prop, "NodeTreePath");
diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c
index a169e81237d..2a64ffa73cd 100644
--- a/source/blender/makesrna/intern/rna_ui_api.c
+++ b/source/blender/makesrna/intern/rna_ui_api.c
@@ -693,7 +693,7 @@ void RNA_api_ui_layout(StructRNA *srna)
static float node_socket_color_default[] = {0.0f, 0.0f, 0.0f, 1.0f};
/* simple layout specifiers */
- func = RNA_def_function(srna, "row", "uiLayoutRow");
+ func = RNA_def_function(srna, "row", "uiLayoutRowWithHeading");
parm = RNA_def_pointer(func, "layout", "UILayout", "", "Sub-layout to put items in");
RNA_def_function_return(func, parm);
RNA_def_function_ui_description(
@@ -701,8 +701,14 @@ void RNA_api_ui_layout(StructRNA *srna)
"Sub-layout. Items placed in this sublayout are placed next to each other "
"in a row");
RNA_def_boolean(func, "align", false, "", "Align buttons to each other");
+ RNA_def_string(func,
+ "heading",
+ NULL,
+ UI_MAX_NAME_STR,
+ "Heading",
+ "Label to insert into the layout for this row");
- func = RNA_def_function(srna, "column", "uiLayoutColumn");
+ func = RNA_def_function(srna, "column", "uiLayoutColumnWithHeading");
parm = RNA_def_pointer(func, "layout", "UILayout", "", "Sub-layout to put items in");
RNA_def_function_return(func, parm);
RNA_def_function_ui_description(
@@ -710,6 +716,12 @@ void RNA_api_ui_layout(StructRNA *srna)
"Sub-layout. Items placed in this sublayout are placed under each other "
"in a column");
RNA_def_boolean(func, "align", false, "", "Align buttons to each other");
+ RNA_def_string(func,
+ "heading",
+ NULL,
+ UI_MAX_NAME_STR,
+ "Heading",
+ "Label to insert into the layout for this column");
func = RNA_def_function(srna, "column_flow", "uiLayoutColumnFlow");
RNA_def_int(func, "columns", 0, 0, INT_MAX, "", "Number of columns, 0 is automatic", 0, INT_MAX);
@@ -887,6 +899,20 @@ void RNA_api_ui_layout(StructRNA *srna)
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
api_ui_item_common(func);
+ func = RNA_def_function(srna, "prop_decorator", "uiItemDecoratorR");
+ api_ui_item_rna_common(func);
+ RNA_def_int(func,
+ "index",
+ /* RNA_NO_INDEX == -1 */
+ -1,
+ -2,
+ INT_MAX,
+ "",
+ "The index of this button, when set a single member of an array can be accessed, "
+ "when set to -1 all array members are used",
+ -2,
+ INT_MAX);
+
for (int is_menu_hold = 0; is_menu_hold < 2; is_menu_hold++) {
func = (is_menu_hold) ? RNA_def_function(srna, "operator_menu_hold", "rna_uiItemOMenuHold") :
RNA_def_function(srna, "operator", "rna_uiItemO");
@@ -1492,6 +1518,7 @@ void RNA_api_ui_layout(StructRNA *srna)
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
func = RNA_def_function(srna, "template_node_link", "uiTemplateNodeLink");
+ RNA_def_function_flag(func, FUNC_USE_CONTEXT);
parm = RNA_def_pointer(func, "ntree", "NodeTree", "", "");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
parm = RNA_def_pointer(func, "node", "Node", "", "");
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index c08a95d7e16..d1af3ea7910 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -6063,10 +6063,6 @@ static void rna_def_userdef_experimental(BlenderRNA *brna)
prop,
"Undo Legacy",
"Use legacy undo (slower than the new default one, but may be more stable in some cases)");
-
- prop = RNA_def_property(srna, "use_menu_search", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "use_menu_search", 1);
- RNA_def_property_ui_text(prop, "Menu Search", "Search actions by menus instead of operators");
}
static void rna_def_userdef_addon_collection(BlenderRNA *brna, PropertyRNA *cprop)
diff --git a/source/blender/modifiers/intern/MOD_mask.cc b/source/blender/modifiers/intern/MOD_mask.cc
index 3bdb5a3fd54..1f9017b4b18 100644
--- a/source/blender/modifiers/intern/MOD_mask.cc
+++ b/source/blender/modifiers/intern/MOD_mask.cc
@@ -46,14 +46,14 @@
#include "MOD_modifiertypes.h"
-#include "BLI_array_cxx.h"
-#include "BLI_listbase_wrapper.h"
-#include "BLI_vector.h"
+#include "BLI_array.hh"
+#include "BLI_listbase_wrapper.hh"
+#include "BLI_vector.hh"
using BLI::Array;
using BLI::ArrayRef;
using BLI::IndexRange;
-using BLI::IntrusiveListBaseWrapper;
+using BLI::ListBaseWrapper;
using BLI::MutableArrayRef;
using BLI::Vector;
@@ -93,7 +93,7 @@ static void compute_vertex_mask__armature_mode(MDeformVert *dvert,
/* Element i is true if there is a selected bone that uses vertex group i. */
Vector<bool> selected_bone_uses_group;
- for (bDeformGroup *def : IntrusiveListBaseWrapper<bDeformGroup>(ob->defbase)) {
+ for (bDeformGroup *def : ListBaseWrapper<bDeformGroup>(ob->defbase)) {
bPoseChannel *pchan = BKE_pose_channel_find_name(armature_ob->pose, def->name);
bool bone_for_group_exists = pchan && pchan->bone && (pchan->bone->flag & BONE_SELECTED);
selected_bone_uses_group.append(bone_for_group_exists);
diff --git a/source/blender/modifiers/intern/MOD_surfacedeform.c b/source/blender/modifiers/intern/MOD_surfacedeform.c
index 4ef1f32462a..b6b936dca6b 100644
--- a/source/blender/modifiers/intern/MOD_surfacedeform.c
+++ b/source/blender/modifiers/intern/MOD_surfacedeform.c
@@ -112,7 +112,7 @@ typedef struct SDefDeformData {
const SDefVert *const bind_verts;
float (*const targetCos)[3];
float (*const vertexCos)[3];
- float(*const weights);
+ float *const weights;
float const strength;
} SDefDeformData;
diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt
index a2f825ee454..469a230f467 100644
--- a/source/blender/nodes/CMakeLists.txt
+++ b/source/blender/nodes/CMakeLists.txt
@@ -21,8 +21,10 @@
set(INC
.
composite
+ function
intern
shader
+ simulation
texture
../blenkernel
../blenlib
@@ -127,6 +129,11 @@ set(SRC
composite/node_composite_tree.c
composite/node_composite_util.c
+ function/nodes/node_fn_boolean_math.cc
+ function/nodes/node_fn_float_compare.cc
+ function/nodes/node_fn_switch.cc
+ function/node_function_util.cc
+
shader/nodes/node_shader_add_shader.c
shader/nodes/node_shader_ambient_occlusion.c
shader/nodes/node_shader_attribute.c
@@ -220,6 +227,22 @@ set(SRC
shader/node_shader_tree.c
shader/node_shader_util.c
+ simulation/nodes/node_sim_common.cc
+ simulation/nodes/node_sim_emit_particles.cc
+ simulation/nodes/node_sim_execute_condition.cc
+ simulation/nodes/node_sim_force.cc
+ simulation/nodes/node_sim_multi_execute.cc
+ simulation/nodes/node_sim_particle_attribute.cc
+ simulation/nodes/node_sim_particle_birth_event.cc
+ simulation/nodes/node_sim_particle_mesh_collision_event.cc
+ simulation/nodes/node_sim_particle_mesh_emitter.cc
+ simulation/nodes/node_sim_particle_simulation.cc
+ simulation/nodes/node_sim_particle_time_step_event.cc
+ simulation/nodes/node_sim_set_particle_attribute.cc
+ simulation/nodes/node_sim_simulation_time.cc
+ simulation/node_simulation_tree.cc
+ simulation/node_simulation_util.cc
+
texture/nodes/node_texture_at.c
texture/nodes/node_texture_bricks.c
texture/nodes/node_texture_checker.c
@@ -252,12 +275,16 @@ set(SRC
intern/node_util.c
composite/node_composite_util.h
+ function/node_function_util.h
shader/node_shader_util.h
+ simulation/node_simulation_util.h
texture/node_texture_util.h
NOD_common.h
NOD_composite.h
+ NOD_function.h
NOD_shader.h
+ NOD_simulation.h
NOD_socket.h
NOD_static_types.h
NOD_texture.h
diff --git a/source/blender/nodes/NOD_common.h b/source/blender/nodes/NOD_common.h
index 26c78eab4ec..dcc4f4d0b76 100644
--- a/source/blender/nodes/NOD_common.h
+++ b/source/blender/nodes/NOD_common.h
@@ -26,6 +26,10 @@
#include "BKE_node.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
void register_node_type_frame(void);
void register_node_type_reroute(void);
@@ -42,4 +46,8 @@ struct bNodeSocket *node_group_output_find_socket(struct bNode *node, const char
void node_group_input_update(struct bNodeTree *ntree, struct bNode *node);
void node_group_output_update(struct bNodeTree *ntree, struct bNode *node);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __NOD_COMMON_H__ */
diff --git a/source/blender/nodes/NOD_function.h b/source/blender/nodes/NOD_function.h
new file mode 100644
index 00000000000..58597b3d410
--- /dev/null
+++ b/source/blender/nodes/NOD_function.h
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+#ifndef __NOD_FUNCTION_H__
+#define __NOD_FUNCTION_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void register_node_type_fn_boolean_math(void);
+void register_node_type_fn_float_compare(void);
+void register_node_type_fn_switch(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __NOD_FUNCTION_H__ */
diff --git a/source/blender/nodes/NOD_simulation.h b/source/blender/nodes/NOD_simulation.h
new file mode 100644
index 00000000000..2947d38fe83
--- /dev/null
+++ b/source/blender/nodes/NOD_simulation.h
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+#ifndef __NOD_SIMULATION_H__
+#define __NOD_SIMULATION_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern struct bNodeTreeType *ntreeType_Simulation;
+
+void register_node_tree_type_sim(void);
+
+void register_node_type_sim_group(void);
+
+void register_node_type_sim_particle_simulation(void);
+void register_node_type_sim_force(void);
+void register_node_type_sim_set_particle_attribute(void);
+void register_node_type_sim_particle_birth_event(void);
+void register_node_type_sim_particle_time_step_event(void);
+void register_node_type_sim_execute_condition(void);
+void register_node_type_sim_multi_execute(void);
+void register_node_type_sim_particle_mesh_emitter(void);
+void register_node_type_sim_particle_mesh_collision_event(void);
+void register_node_type_sim_emit_particles(void);
+void register_node_type_sim_time(void);
+void register_node_type_sim_particle_attribute(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __NOD_SIMULATION_H__ */
diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h
index 7fec3324aab..d228d92a55c 100644
--- a/source/blender/nodes/NOD_static_types.h
+++ b/source/blender/nodes/NOD_static_types.h
@@ -258,7 +258,25 @@ DefNode(TextureNode, TEX_NODE_PROC+TEX_NOISE, 0, "TEX_NO
DefNode(TextureNode, TEX_NODE_PROC+TEX_STUCCI, 0, "TEX_STUCCI", TexStucci, "Stucci", "" )
DefNode(TextureNode, TEX_NODE_PROC+TEX_DISTNOISE, 0, "TEX_DISTNOISE", TexDistNoise, "Distorted Noise", "" )
+DefNode(SimulationNode, SIM_NODE_PARTICLE_SIMULATION, 0, "PARTICLE_SIMULATION", ParticleSimulation, "Particle Simulation", "")
+DefNode(SimulationNode, SIM_NODE_FORCE, 0, "FORCE", Force, "Force", "")
+DefNode(SimulationNode, SIM_NODE_SET_PARTICLE_ATTRIBUTE, def_sim_set_particle_attribute, "SET_PARTICLE_ATTRIBUTE", SetParticleAttribute, "Set Particle Attribute", "")
+DefNode(SimulationNode, SIM_NODE_PARTICLE_BIRTH_EVENT, 0, "PARTICLE_BIRTH_EVENT", ParticleBirthEvent, "Particle Birth Event", "")
+DefNode(SimulationNode, SIM_NODE_PARTICLE_TIME_STEP_EVENT, def_sim_particle_time_step_event, "PARTICLE_TIME_STEP_EVENT", ParticleTimeStepEvent, "Particle Time Step Event", "")
+DefNode(SimulationNode, SIM_NODE_EXECUTE_CONDITION, 0, "EXECUTE_CONDITION", ExecuteCondition, "Execute Condition", "")
+DefNode(SimulationNode, SIM_NODE_MULTI_EXECUTE, 0, "MULTI_EXECUTE", MultiExecute, "Multi Execute", "")
+DefNode(SimulationNode, SIM_NODE_PARTICLE_MESH_EMITTER, 0, "PARTICLE_MESH_EMITTER", ParticleMeshEmitter, "Particle Mesh Emitter", "")
+DefNode(SimulationNode, SIM_NODE_PARTICLE_MESH_COLLISION_EVENT, 0, "PARTICLE_MESH_COLLISION_EVENT", ParticleMeshCollisionEvent, "Particle Mesh Collision Event", "")
+DefNode(SimulationNode, SIM_NODE_EMIT_PARTICLES, 0, "EMIT_PARTICLES", EmitParticles, "Emit Particles", "")
+DefNode(SimulationNode, SIM_NODE_TIME, def_sim_time, "TIME", Time, "Time", "")
+DefNode(SimulationNode, SIM_NODE_PARTICLE_ATTRIBUTE, def_sim_particle_attribute, "PARTICLE_ATTRIBUTE", ParticleAttribute, "Particle Attribute", "")
+
+DefNode(FunctionNode, FN_NODE_BOOLEAN_MATH, def_boolean_math, "BOOLEAN_MATH", BooleanMath, "Boolean Math", "");
+DefNode(FunctionNode, FN_NODE_FLOAT_COMPARE, def_float_compare, "FLOAT_COMPARE", FloatCompare, "Float Compare", "");
+DefNode(FunctionNode, FN_NODE_SWITCH, def_fn_switch, "SWITCH", Switch, "Switch", "");
+
+
/* undefine macros */
#undef DefNode
- /* clang-format on */
+/* clang-format on */
diff --git a/source/blender/nodes/function/node_function_util.cc b/source/blender/nodes/function/node_function_util.cc
new file mode 100644
index 00000000000..0927ba335fe
--- /dev/null
+++ b/source/blender/nodes/function/node_function_util.cc
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+
+#include "node_function_util.h"
+#include "node_util.h"
+
+bool fn_node_poll_default(bNodeType *UNUSED(ntype), bNodeTree *ntree)
+{
+ /* Function nodes are only supported in simulation node trees so far. */
+ return STREQ(ntree->idname, "SimulationNodeTree");
+}
+
+void fn_node_type_base(bNodeType *ntype, int type, const char *name, short nclass, short flag)
+{
+ node_type_base(ntype, type, name, nclass, flag);
+ ntype->poll = fn_node_poll_default;
+}
diff --git a/source/blender/nodes/function/node_function_util.h b/source/blender/nodes/function/node_function_util.h
new file mode 100644
index 00000000000..85e252f9bdd
--- /dev/null
+++ b/source/blender/nodes/function/node_function_util.h
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+#ifndef __NODE_FUNCTION_UTIL_H__
+#define __NODE_FUNCTION_UTIL_H__
+
+#include <string.h>
+
+#include "BLI_utildefines.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_node_types.h"
+
+#include "BKE_node.h"
+
+#include "BLT_translation.h"
+
+#include "NOD_function.h"
+
+#include "node_util.h"
+
+void fn_node_type_base(
+ struct bNodeType *ntype, int type, const char *name, short nclass, short flag);
+bool fn_node_poll_default(struct bNodeType *ntype, struct bNodeTree *ntree);
+
+#endif /* __NODE_FUNCTION_UTIL_H__ */
diff --git a/source/blender/nodes/function/nodes/node_fn_boolean_math.cc b/source/blender/nodes/function/nodes/node_fn_boolean_math.cc
new file mode 100644
index 00000000000..615ad4c6733
--- /dev/null
+++ b/source/blender/nodes/function/nodes/node_fn_boolean_math.cc
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+
+#include "BLI_listbase.h"
+#include "BLI_string.h"
+
+#include "RNA_enum_types.h"
+
+#include "node_function_util.h"
+
+static bNodeSocketTemplate fn_node_boolean_math_in[] = {
+ {SOCK_BOOLEAN, N_("Boolean")},
+ {SOCK_BOOLEAN, N_("Boolean")},
+ {-1, ""},
+};
+
+static bNodeSocketTemplate fn_node_boolean_math_out[] = {
+ {SOCK_BOOLEAN, N_("Boolean")},
+ {-1, ""},
+};
+
+static void node_boolean_math_update(bNodeTree *UNUSED(ntree), bNode *node)
+{
+ bNodeSocket *sockB = (bNodeSocket *)BLI_findlink(&node->inputs, 1);
+
+ nodeSetSocketAvailability(sockB,
+ ELEM(node->custom1, NODE_BOOLEAN_MATH_AND, NODE_BOOLEAN_MATH_OR));
+}
+
+static void node_boolean_math_label(bNodeTree *UNUSED(ntree), bNode *node, char *label, int maxlen)
+{
+ const char *name;
+ bool enum_label = RNA_enum_name(rna_enum_node_boolean_math_items, node->custom1, &name);
+ if (!enum_label) {
+ name = "Unknown";
+ }
+ BLI_strncpy(label, IFACE_(name), maxlen);
+}
+
+void register_node_type_fn_boolean_math()
+{
+ static bNodeType ntype;
+
+ fn_node_type_base(&ntype, FN_NODE_BOOLEAN_MATH, "Boolean Math", 0, 0);
+ node_type_socket_templates(&ntype, fn_node_boolean_math_in, fn_node_boolean_math_out);
+ node_type_label(&ntype, node_boolean_math_label);
+ node_type_update(&ntype, node_boolean_math_update);
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/function/nodes/node_fn_float_compare.cc b/source/blender/nodes/function/nodes/node_fn_float_compare.cc
new file mode 100644
index 00000000000..9788402850b
--- /dev/null
+++ b/source/blender/nodes/function/nodes/node_fn_float_compare.cc
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+#include "BLI_listbase.h"
+#include "BLI_string.h"
+
+#include "RNA_enum_types.h"
+
+#include "node_function_util.h"
+
+static bNodeSocketTemplate fn_node_float_compare_in[] = {
+ {SOCK_FLOAT, N_("A"), 0.0f, 0.0f, 0.0f, 0.0f, -10000.0f, 10000.0f},
+ {SOCK_FLOAT, N_("B"), 0.0f, 0.0f, 0.0f, 0.0f, -10000.0f, 10000.0f},
+ {SOCK_FLOAT, N_("Epsilon"), 0.001f, 0.0f, 0.0f, 0.0f, -10000.0f, 10000.0f},
+ {-1, ""},
+};
+
+static bNodeSocketTemplate fn_node_float_compare_out[] = {
+ {SOCK_BOOLEAN, N_("Result")},
+ {-1, ""},
+};
+
+static void node_float_compare_update(bNodeTree *UNUSED(ntree), bNode *node)
+{
+ bNodeSocket *sockEpsilon = (bNodeSocket *)BLI_findlink(&node->inputs, 2);
+
+ nodeSetSocketAvailability(
+ sockEpsilon, ELEM(node->custom1, NODE_FLOAT_COMPARE_EQUAL, NODE_FLOAT_COMPARE_NOT_EQUAL));
+}
+
+static void node_float_compare_label(bNodeTree *UNUSED(ntree),
+ bNode *node,
+ char *label,
+ int maxlen)
+{
+ const char *name;
+ bool enum_label = RNA_enum_name(rna_enum_node_float_compare_items, node->custom1, &name);
+ if (!enum_label) {
+ name = "Unknown";
+ }
+ BLI_strncpy(label, IFACE_(name), maxlen);
+}
+
+void register_node_type_fn_float_compare()
+{
+ static bNodeType ntype;
+
+ fn_node_type_base(&ntype, FN_NODE_FLOAT_COMPARE, "Boolean Math", 0, 0);
+ node_type_socket_templates(&ntype, fn_node_float_compare_in, fn_node_float_compare_out);
+ node_type_label(&ntype, node_float_compare_label);
+ node_type_update(&ntype, node_float_compare_update);
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/function/nodes/node_fn_switch.cc b/source/blender/nodes/function/nodes/node_fn_switch.cc
new file mode 100644
index 00000000000..cb721058875
--- /dev/null
+++ b/source/blender/nodes/function/nodes/node_fn_switch.cc
@@ -0,0 +1,76 @@
+/*
+ * 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.
+ */
+
+#include "BLI_listbase.h"
+#include "node_function_util.h"
+
+static bNodeSocketTemplate fn_node_switch_in[] = {
+ {SOCK_BOOLEAN, N_("Switch")},
+
+ {SOCK_FLOAT, N_("If False"), 0.0f, 0.0f, 0.0f, 0.0f, -10000.0f, 10000.0f},
+ {SOCK_INT, N_("If False"), 0, 0, 0, 0, -10000, 10000},
+ {SOCK_BOOLEAN, N_("If False")},
+ {SOCK_VECTOR, N_("If False"), 0.0f, 0.0f, 0.0f, 0.0f, -10000.0f, 10000.0f},
+ {SOCK_STRING, N_("If False")},
+ {SOCK_RGBA, N_("If False"), 0.8f, 0.8f, 0.8f, 1.0f},
+ {SOCK_OBJECT, N_("If False")},
+ {SOCK_IMAGE, N_("If False")},
+
+ {SOCK_FLOAT, N_("If True"), 0.0f, 0.0f, 0.0f, 0.0f, -10000.0f, 10000.0f},
+ {SOCK_INT, N_("If True"), 0, 0, 0, 0, -10000, 10000},
+ {SOCK_BOOLEAN, N_("If True")},
+ {SOCK_VECTOR, N_("If True"), 0.0f, 0.0f, 0.0f, 0.0f, -10000.0f, 10000.0f},
+ {SOCK_STRING, N_("If True")},
+ {SOCK_RGBA, N_("If True"), 0.8f, 0.8f, 0.8f, 1.0f},
+ {SOCK_OBJECT, N_("If True")},
+ {SOCK_IMAGE, N_("If True")},
+
+ {-1, ""},
+};
+
+static bNodeSocketTemplate fn_node_switch_out[] = {
+ {SOCK_FLOAT, N_("Result")},
+ {SOCK_INT, N_("Result")},
+ {SOCK_BOOLEAN, N_("Result")},
+ {SOCK_VECTOR, N_("Result")},
+ {SOCK_STRING, N_("Result")},
+ {SOCK_RGBA, N_("Result")},
+ {SOCK_OBJECT, N_("Result")},
+ {SOCK_IMAGE, N_("Result")},
+ {-1, ""},
+};
+
+static void fn_node_switch_update(bNodeTree *UNUSED(ntree), bNode *node)
+{
+ int index = 0;
+ LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
+ nodeSetSocketAvailability(sock, index == 0 || sock->type == node->custom1);
+ index++;
+ }
+ LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) {
+ nodeSetSocketAvailability(sock, sock->type == node->custom1);
+ }
+}
+
+void register_node_type_fn_switch()
+{
+ static bNodeType ntype;
+
+ fn_node_type_base(&ntype, FN_NODE_SWITCH, "Switch", 0, 0);
+ node_type_socket_templates(&ntype, fn_node_switch_in, fn_node_switch_out);
+ node_type_update(&ntype, fn_node_switch_update);
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/intern/node_common.h b/source/blender/nodes/intern/node_common.h
index c3314ae3c28..7810e9f1f14 100644
--- a/source/blender/nodes/intern/node_common.h
+++ b/source/blender/nodes/intern/node_common.h
@@ -26,6 +26,10 @@
#include "DNA_listBase.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct bNodeTree;
void node_group_label(struct bNodeTree *ntree, struct bNode *node, char *label, int maxlen);
@@ -33,4 +37,8 @@ bool node_group_poll_instance(struct bNode *node, struct bNodeTree *nodetree);
void ntree_update_reroute_nodes(struct bNodeTree *ntree);
+#ifdef __cplusplus
+}
+#endif
+
#endif
diff --git a/source/blender/nodes/intern/node_socket.c b/source/blender/nodes/intern/node_socket.c
index 199b469781d..668dd3829cc 100644
--- a/source/blender/nodes/intern/node_socket.c
+++ b/source/blender/nodes/intern/node_socket.c
@@ -30,6 +30,7 @@
#include "BLI_string.h"
#include "BLI_utildefines.h"
+#include "BKE_lib_id.h"
#include "BKE_node.h"
#include "RNA_access.h"
@@ -259,6 +260,22 @@ void node_socket_init_default_value(bNodeSocket *sock)
sock->default_value = dval;
break;
}
+ case SOCK_OBJECT: {
+ bNodeSocketValueObject *dval = MEM_callocN(sizeof(bNodeSocketValueObject),
+ "node socket value object");
+ dval->value = NULL;
+
+ sock->default_value = dval;
+ break;
+ }
+ case SOCK_IMAGE: {
+ bNodeSocketValueImage *dval = MEM_callocN(sizeof(bNodeSocketValueImage),
+ "node socket value image");
+ dval->value = NULL;
+
+ sock->default_value = dval;
+ break;
+ }
}
}
@@ -317,6 +334,20 @@ void node_socket_copy_default_value(bNodeSocket *to, const bNodeSocket *from)
*toval = *fromval;
break;
}
+ case SOCK_OBJECT: {
+ bNodeSocketValueObject *toval = to->default_value;
+ bNodeSocketValueObject *fromval = from->default_value;
+ *toval = *fromval;
+ id_us_plus(&toval->value->id);
+ break;
+ }
+ case SOCK_IMAGE: {
+ bNodeSocketValueImage *toval = to->default_value;
+ bNodeSocketValueImage *fromval = from->default_value;
+ *toval = *fromval;
+ id_us_plus(&toval->value->id);
+ break;
+ }
}
to->flag |= (from->flag & SOCK_HIDE_VALUE);
@@ -467,6 +498,19 @@ static bNodeSocketType *make_socket_type_virtual(void)
return stype;
}
+static bNodeSocketType *make_socket_type_effector(int type)
+{
+ bNodeSocketType *stype = make_standard_socket_type(type, PROP_NONE);
+ stype->input_link_limit = 0xFFF;
+ return stype;
+}
+
+static bNodeSocketType *make_socket_type_control_flow(int type)
+{
+ bNodeSocketType *stype = make_standard_socket_type(type, PROP_NONE);
+ return stype;
+}
+
void register_standard_node_socket_types(void)
{
/* draw callbacks are set in drawnode.c to avoid bad-level calls */
@@ -499,5 +543,15 @@ void register_standard_node_socket_types(void)
nodeRegisterSocketType(make_standard_socket_type(SOCK_SHADER, PROP_NONE));
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_OBJECT, PROP_NONE));
+
+ nodeRegisterSocketType(make_standard_socket_type(SOCK_IMAGE, PROP_NONE));
+
+ nodeRegisterSocketType(make_socket_type_effector(SOCK_EMITTERS));
+ nodeRegisterSocketType(make_socket_type_effector(SOCK_EVENTS));
+ nodeRegisterSocketType(make_socket_type_effector(SOCK_FORCES));
+
+ nodeRegisterSocketType(make_socket_type_control_flow(SOCK_CONTROL_FLOW));
+
nodeRegisterSocketType(make_socket_type_virtual());
}
diff --git a/source/blender/nodes/intern/node_util.h b/source/blender/nodes/intern/node_util.h
index a7f09d24a70..61f8fe6809d 100644
--- a/source/blender/nodes/intern/node_util.h
+++ b/source/blender/nodes/intern/node_util.h
@@ -38,6 +38,10 @@
#include "RNA_access.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct bNode;
struct bNodeTree;
@@ -103,4 +107,8 @@ void node_socket_set_vector(struct bNodeTree *ntree,
struct bNodeSocket *sock,
const float *value);
+#ifdef __cplusplus
+}
+#endif
+
#endif
diff --git a/source/blender/nodes/shader/node_shader_util.c b/source/blender/nodes/shader/node_shader_util.c
index 93d03720058..4464a61c48c 100644
--- a/source/blender/nodes/shader/node_shader_util.c
+++ b/source/blender/nodes/shader/node_shader_util.c
@@ -32,6 +32,11 @@ bool sh_node_poll_default(bNodeType *UNUSED(ntype), bNodeTree *ntree)
return STREQ(ntree->idname, "ShaderNodeTree");
}
+static bool sh_fn_poll_default(bNodeType *UNUSED(ntype), bNodeTree *ntree)
+{
+ return STREQ(ntree->idname, "ShaderNodeTree") || STREQ(ntree->idname, "SimulationNodeTree");
+}
+
void sh_node_type_base(
struct bNodeType *ntype, int type, const char *name, short nclass, short flag)
{
@@ -42,6 +47,12 @@ void sh_node_type_base(
ntype->update_internal_links = node_update_internal_links_default;
}
+void sh_fn_node_type_base(bNodeType *ntype, int type, const char *name, short nclass, short flag)
+{
+ sh_node_type_base(ntype, type, name, nclass, flag);
+ ntype->poll = sh_fn_poll_default;
+}
+
/* ****** */
void nodestack_get_vec(float *in, short type_in, bNodeStack *ns)
diff --git a/source/blender/nodes/shader/node_shader_util.h b/source/blender/nodes/shader/node_shader_util.h
index 8d525c8f23c..8834de0633e 100644
--- a/source/blender/nodes/shader/node_shader_util.h
+++ b/source/blender/nodes/shader/node_shader_util.h
@@ -72,6 +72,8 @@
bool sh_node_poll_default(struct bNodeType *ntype, struct bNodeTree *ntree);
void sh_node_type_base(
struct bNodeType *ntype, int type, const char *name, short nclass, short flag);
+void sh_fn_node_type_base(
+ struct bNodeType *ntype, int type, const char *name, short nclass, short flag);
/* ********* exec data struct, remains internal *********** */
diff --git a/source/blender/nodes/shader/nodes/node_shader_brightness.c b/source/blender/nodes/shader/nodes/node_shader_brightness.c
index d8f560277f2..cc1968cb1b1 100644
--- a/source/blender/nodes/shader/nodes/node_shader_brightness.c
+++ b/source/blender/nodes/shader/nodes/node_shader_brightness.c
@@ -46,7 +46,7 @@ void register_node_type_sh_brightcontrast(void)
{
static bNodeType ntype;
- sh_node_type_base(&ntype, SH_NODE_BRIGHTCONTRAST, "Bright/Contrast", NODE_CLASS_OP_COLOR, 0);
+ sh_fn_node_type_base(&ntype, SH_NODE_BRIGHTCONTRAST, "Bright/Contrast", NODE_CLASS_OP_COLOR, 0);
node_type_socket_templates(&ntype, sh_node_brightcontrast_in, sh_node_brightcontrast_out);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
diff --git a/source/blender/nodes/shader/nodes/node_shader_clamp.c b/source/blender/nodes/shader/nodes/node_shader_clamp.c
index c49cfcea8d3..808f9686f0a 100644
--- a/source/blender/nodes/shader/nodes/node_shader_clamp.c
+++ b/source/blender/nodes/shader/nodes/node_shader_clamp.c
@@ -54,7 +54,7 @@ void register_node_type_sh_clamp(void)
{
static bNodeType ntype;
- sh_node_type_base(&ntype, SH_NODE_CLAMP, "Clamp", NODE_CLASS_CONVERTOR, 0);
+ sh_fn_node_type_base(&ntype, SH_NODE_CLAMP, "Clamp", NODE_CLASS_CONVERTOR, 0);
node_type_socket_templates(&ntype, sh_node_clamp_in, sh_node_clamp_out);
node_type_init(&ntype, node_shader_init_clamp);
node_type_gpu(&ntype, gpu_shader_clamp);
diff --git a/source/blender/nodes/shader/nodes/node_shader_gamma.c b/source/blender/nodes/shader/nodes/node_shader_gamma.c
index b48838e5f56..747979522d1 100644
--- a/source/blender/nodes/shader/nodes/node_shader_gamma.c
+++ b/source/blender/nodes/shader/nodes/node_shader_gamma.c
@@ -62,7 +62,7 @@ void register_node_type_sh_gamma(void)
{
static bNodeType ntype;
- sh_node_type_base(&ntype, SH_NODE_GAMMA, "Gamma", NODE_CLASS_OP_COLOR, 0);
+ sh_fn_node_type_base(&ntype, SH_NODE_GAMMA, "Gamma", NODE_CLASS_OP_COLOR, 0);
node_type_socket_templates(&ntype, sh_node_gamma_in, sh_node_gamma_out);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
diff --git a/source/blender/nodes/shader/nodes/node_shader_hueSatVal.c b/source/blender/nodes/shader/nodes/node_shader_hueSatVal.c
index 7a05fc95eec..57ef51c65f6 100644
--- a/source/blender/nodes/shader/nodes/node_shader_hueSatVal.c
+++ b/source/blender/nodes/shader/nodes/node_shader_hueSatVal.c
@@ -89,7 +89,7 @@ void register_node_type_sh_hue_sat(void)
{
static bNodeType ntype;
- sh_node_type_base(&ntype, SH_NODE_HUE_SAT, "Hue Saturation Value", NODE_CLASS_OP_COLOR, 0);
+ sh_fn_node_type_base(&ntype, SH_NODE_HUE_SAT, "Hue Saturation Value", NODE_CLASS_OP_COLOR, 0);
node_type_socket_templates(&ntype, sh_node_hue_sat_in, sh_node_hue_sat_out);
node_type_size_preset(&ntype, NODE_SIZE_MIDDLE);
node_type_exec(&ntype, NULL, NULL, node_shader_exec_hue_sat);
diff --git a/source/blender/nodes/shader/nodes/node_shader_invert.c b/source/blender/nodes/shader/nodes/node_shader_invert.c
index 0d6709a1968..19fa0b0309d 100644
--- a/source/blender/nodes/shader/nodes/node_shader_invert.c
+++ b/source/blender/nodes/shader/nodes/node_shader_invert.c
@@ -69,7 +69,7 @@ void register_node_type_sh_invert(void)
{
static bNodeType ntype;
- sh_node_type_base(&ntype, SH_NODE_INVERT, "Invert", NODE_CLASS_OP_COLOR, 0);
+ sh_fn_node_type_base(&ntype, SH_NODE_INVERT, "Invert", NODE_CLASS_OP_COLOR, 0);
node_type_socket_templates(&ntype, sh_node_invert_in, sh_node_invert_out);
node_type_exec(&ntype, NULL, NULL, node_shader_exec_invert);
node_type_gpu(&ntype, gpu_shader_invert);
diff --git a/source/blender/nodes/shader/nodes/node_shader_map_range.c b/source/blender/nodes/shader/nodes/node_shader_map_range.c
index d59540cb8fa..5db7983e752 100644
--- a/source/blender/nodes/shader/nodes/node_shader_map_range.c
+++ b/source/blender/nodes/shader/nodes/node_shader_map_range.c
@@ -81,7 +81,7 @@ void register_node_type_sh_map_range(void)
{
static bNodeType ntype;
- sh_node_type_base(&ntype, SH_NODE_MAP_RANGE, "Map Range", NODE_CLASS_CONVERTOR, 0);
+ sh_fn_node_type_base(&ntype, SH_NODE_MAP_RANGE, "Map Range", NODE_CLASS_CONVERTOR, 0);
node_type_socket_templates(&ntype, sh_node_map_range_in, sh_node_map_range_out);
node_type_init(&ntype, node_shader_init_map_range);
node_type_update(&ntype, node_shader_update_map_range);
diff --git a/source/blender/nodes/shader/nodes/node_shader_math.c b/source/blender/nodes/shader/nodes/node_shader_math.c
index 08578e0e11e..8abebbf5081 100644
--- a/source/blender/nodes/shader/nodes/node_shader_math.c
+++ b/source/blender/nodes/shader/nodes/node_shader_math.c
@@ -105,7 +105,7 @@ void register_node_type_sh_math(void)
{
static bNodeType ntype;
- sh_node_type_base(&ntype, SH_NODE_MATH, "Math", NODE_CLASS_CONVERTOR, 0);
+ sh_fn_node_type_base(&ntype, SH_NODE_MATH, "Math", NODE_CLASS_CONVERTOR, 0);
node_type_socket_templates(&ntype, sh_node_math_in, sh_node_math_out);
node_type_label(&ntype, node_math_label);
node_type_gpu(&ntype, gpu_shader_math);
diff --git a/source/blender/nodes/shader/nodes/node_shader_mixRgb.c b/source/blender/nodes/shader/nodes/node_shader_mixRgb.c
index 9c318073304..93e88664d1a 100644
--- a/source/blender/nodes/shader/nodes/node_shader_mixRgb.c
+++ b/source/blender/nodes/shader/nodes/node_shader_mixRgb.c
@@ -107,7 +107,7 @@ void register_node_type_sh_mix_rgb(void)
{
static bNodeType ntype;
- sh_node_type_base(&ntype, SH_NODE_MIX_RGB, "Mix", NODE_CLASS_OP_COLOR, 0);
+ sh_fn_node_type_base(&ntype, SH_NODE_MIX_RGB, "Mix", NODE_CLASS_OP_COLOR, 0);
node_type_socket_templates(&ntype, sh_node_mix_rgb_in, sh_node_mix_rgb_out);
node_type_label(&ntype, node_blend_label);
node_type_exec(&ntype, NULL, NULL, node_shader_exec_mix_rgb);
diff --git a/source/blender/nodes/shader/nodes/node_shader_sepcombHSV.c b/source/blender/nodes/shader/nodes/node_shader_sepcombHSV.c
index 951755be4f3..2c9b77530a2 100644
--- a/source/blender/nodes/shader/nodes/node_shader_sepcombHSV.c
+++ b/source/blender/nodes/shader/nodes/node_shader_sepcombHSV.c
@@ -61,7 +61,7 @@ void register_node_type_sh_sephsv(void)
{
static bNodeType ntype;
- sh_node_type_base(&ntype, SH_NODE_SEPHSV, "Separate HSV", NODE_CLASS_CONVERTOR, 0);
+ sh_fn_node_type_base(&ntype, SH_NODE_SEPHSV, "Separate HSV", NODE_CLASS_CONVERTOR, 0);
node_type_socket_templates(&ntype, sh_node_sephsv_in, sh_node_sephsv_out);
node_type_exec(&ntype, NULL, NULL, node_shader_exec_sephsv);
node_type_gpu(&ntype, gpu_shader_sephsv);
@@ -109,7 +109,7 @@ void register_node_type_sh_combhsv(void)
{
static bNodeType ntype;
- sh_node_type_base(&ntype, SH_NODE_COMBHSV, "Combine HSV", NODE_CLASS_CONVERTOR, 0);
+ sh_fn_node_type_base(&ntype, SH_NODE_COMBHSV, "Combine HSV", NODE_CLASS_CONVERTOR, 0);
node_type_socket_templates(&ntype, sh_node_combhsv_in, sh_node_combhsv_out);
node_type_exec(&ntype, NULL, NULL, node_shader_exec_combhsv);
node_type_gpu(&ntype, gpu_shader_combhsv);
diff --git a/source/blender/nodes/shader/nodes/node_shader_sepcombRGB.c b/source/blender/nodes/shader/nodes/node_shader_sepcombRGB.c
index f10f80d5c2d..d0dc45dcedd 100644
--- a/source/blender/nodes/shader/nodes/node_shader_sepcombRGB.c
+++ b/source/blender/nodes/shader/nodes/node_shader_sepcombRGB.c
@@ -63,7 +63,7 @@ void register_node_type_sh_seprgb(void)
{
static bNodeType ntype;
- sh_node_type_base(&ntype, SH_NODE_SEPRGB, "Separate RGB", NODE_CLASS_CONVERTOR, 0);
+ sh_fn_node_type_base(&ntype, SH_NODE_SEPRGB, "Separate RGB", NODE_CLASS_CONVERTOR, 0);
node_type_socket_templates(&ntype, sh_node_seprgb_in, sh_node_seprgb_out);
node_type_exec(&ntype, NULL, NULL, node_shader_exec_seprgb);
node_type_gpu(&ntype, gpu_shader_seprgb);
@@ -113,7 +113,7 @@ void register_node_type_sh_combrgb(void)
{
static bNodeType ntype;
- sh_node_type_base(&ntype, SH_NODE_COMBRGB, "Combine RGB", NODE_CLASS_CONVERTOR, 0);
+ sh_fn_node_type_base(&ntype, SH_NODE_COMBRGB, "Combine RGB", NODE_CLASS_CONVERTOR, 0);
node_type_socket_templates(&ntype, sh_node_combrgb_in, sh_node_combrgb_out);
node_type_exec(&ntype, NULL, NULL, node_shader_exec_combrgb);
node_type_gpu(&ntype, gpu_shader_combrgb);
diff --git a/source/blender/nodes/shader/nodes/node_shader_sepcombXYZ.c b/source/blender/nodes/shader/nodes/node_shader_sepcombXYZ.c
index 55d5084b132..429b1a3e818 100644
--- a/source/blender/nodes/shader/nodes/node_shader_sepcombXYZ.c
+++ b/source/blender/nodes/shader/nodes/node_shader_sepcombXYZ.c
@@ -48,7 +48,7 @@ void register_node_type_sh_sepxyz(void)
{
static bNodeType ntype;
- sh_node_type_base(&ntype, SH_NODE_SEPXYZ, "Separate XYZ", NODE_CLASS_CONVERTOR, 0);
+ sh_fn_node_type_base(&ntype, SH_NODE_SEPXYZ, "Separate XYZ", NODE_CLASS_CONVERTOR, 0);
node_type_socket_templates(&ntype, sh_node_sepxyz_in, sh_node_sepxyz_out);
node_type_gpu(&ntype, gpu_shader_sepxyz);
@@ -80,7 +80,7 @@ void register_node_type_sh_combxyz(void)
{
static bNodeType ntype;
- sh_node_type_base(&ntype, SH_NODE_COMBXYZ, "Combine XYZ", NODE_CLASS_CONVERTOR, 0);
+ sh_fn_node_type_base(&ntype, SH_NODE_COMBXYZ, "Combine XYZ", NODE_CLASS_CONVERTOR, 0);
node_type_socket_templates(&ntype, sh_node_combxyz_in, sh_node_combxyz_out);
node_type_gpu(&ntype, gpu_shader_combxyz);
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c b/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c
index fa98f9efb74..420c5b75926 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c
@@ -137,6 +137,9 @@ static void node_shader_update_tex_musgrave(bNodeTree *UNUSED(ntree), bNode *nod
nodeSetSocketAvailability(inGainSock,
tex->musgrave_type == SHD_MUSGRAVE_HYBRID_MULTIFRACTAL ||
tex->musgrave_type == SHD_MUSGRAVE_RIDGED_MULTIFRACTAL);
+
+ bNodeSocket *outFacSock = nodeFindSocket(node, SOCK_OUT, "Fac");
+ node_sock_label(outFacSock, "Height");
}
void register_node_type_sh_tex_musgrave(void)
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_noise.c b/source/blender/nodes/shader/nodes/node_shader_tex_noise.c
index 7b67c2d1f2e..67268c102c5 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_noise.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_noise.c
@@ -91,7 +91,7 @@ void register_node_type_sh_tex_noise(void)
{
static bNodeType ntype;
- sh_node_type_base(&ntype, SH_NODE_TEX_NOISE, "Noise Texture", NODE_CLASS_TEXTURE, 0);
+ sh_fn_node_type_base(&ntype, SH_NODE_TEX_NOISE, "Noise Texture", NODE_CLASS_TEXTURE, 0);
node_type_socket_templates(&ntype, sh_node_tex_noise_in, sh_node_tex_noise_out);
node_type_init(&ntype, node_shader_init_tex_noise);
node_type_storage(
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_white_noise.c b/source/blender/nodes/shader/nodes/node_shader_tex_white_noise.c
index 1789dc44bf1..817ccdc8b6a 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_white_noise.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_white_noise.c
@@ -72,7 +72,8 @@ void register_node_type_sh_tex_white_noise(void)
{
static bNodeType ntype;
- sh_node_type_base(&ntype, SH_NODE_TEX_WHITE_NOISE, "White Noise Texture", NODE_CLASS_TEXTURE, 0);
+ sh_fn_node_type_base(
+ &ntype, SH_NODE_TEX_WHITE_NOISE, "White Noise Texture", NODE_CLASS_TEXTURE, 0);
node_type_socket_templates(&ntype, sh_node_tex_white_noise_in, sh_node_tex_white_noise_out);
node_type_init(&ntype, node_shader_init_tex_white_noise);
node_type_gpu(&ntype, gpu_shader_tex_white_noise);
diff --git a/source/blender/nodes/shader/nodes/node_shader_valToRgb.c b/source/blender/nodes/shader/nodes/node_shader_valToRgb.c
index 49f9befdce3..20f280d00c3 100644
--- a/source/blender/nodes/shader/nodes/node_shader_valToRgb.c
+++ b/source/blender/nodes/shader/nodes/node_shader_valToRgb.c
@@ -125,7 +125,7 @@ void register_node_type_sh_valtorgb(void)
{
static bNodeType ntype;
- sh_node_type_base(&ntype, SH_NODE_VALTORGB, "ColorRamp", NODE_CLASS_CONVERTOR, 0);
+ sh_fn_node_type_base(&ntype, SH_NODE_VALTORGB, "ColorRamp", NODE_CLASS_CONVERTOR, 0);
node_type_socket_templates(&ntype, sh_node_valtorgb_in, sh_node_valtorgb_out);
node_type_init(&ntype, node_shader_init_valtorgb);
node_type_size_preset(&ntype, NODE_SIZE_LARGE);
diff --git a/source/blender/nodes/shader/nodes/node_shader_vector_math.c b/source/blender/nodes/shader/nodes/node_shader_vector_math.c
index 3a6e273eb20..b719fe03d9b 100644
--- a/source/blender/nodes/shader/nodes/node_shader_vector_math.c
+++ b/source/blender/nodes/shader/nodes/node_shader_vector_math.c
@@ -134,7 +134,7 @@ void register_node_type_sh_vect_math(void)
{
static bNodeType ntype;
- sh_node_type_base(&ntype, SH_NODE_VECTOR_MATH, "Vector Math", NODE_CLASS_OP_VECTOR, 0);
+ sh_fn_node_type_base(&ntype, SH_NODE_VECTOR_MATH, "Vector Math", NODE_CLASS_OP_VECTOR, 0);
node_type_socket_templates(&ntype, sh_node_vector_math_in, sh_node_vector_math_out);
node_type_label(&ntype, node_vector_math_label);
node_type_gpu(&ntype, gpu_shader_vector_math);
diff --git a/source/blender/nodes/simulation/node_simulation_tree.cc b/source/blender/nodes/simulation/node_simulation_tree.cc
new file mode 100644
index 00000000000..3f0e70259d6
--- /dev/null
+++ b/source/blender/nodes/simulation/node_simulation_tree.cc
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "NOD_simulation.h"
+
+#include "BKE_node.h"
+
+#include "BLT_translation.h"
+
+#include "DNA_node_types.h"
+
+#include "RNA_access.h"
+
+bNodeTreeType *ntreeType_Simulation;
+
+void register_node_tree_type_sim(void)
+{
+ bNodeTreeType *tt = ntreeType_Simulation = (bNodeTreeType *)MEM_callocN(
+ sizeof(bNodeTreeType), "simulation node tree type");
+ tt->type = NTREE_SIMULATION;
+ strcpy(tt->idname, "SimulationNodeTree");
+ strcpy(tt->ui_name, N_("Simulation Editor"));
+ tt->ui_icon = 0; /* defined in drawnode.c */
+ strcpy(tt->ui_description, N_("Simulation nodes"));
+ tt->rna_ext.srna = &RNA_SimulationNodeTree;
+
+ ntreeTypeAdd(tt);
+}
diff --git a/source/blender/nodes/simulation/node_simulation_util.cc b/source/blender/nodes/simulation/node_simulation_util.cc
new file mode 100644
index 00000000000..ae875335da8
--- /dev/null
+++ b/source/blender/nodes/simulation/node_simulation_util.cc
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+#include "node_simulation_util.h"
+#include "node_util.h"
+
+bool sim_node_poll_default(bNodeType *UNUSED(ntype), bNodeTree *ntree)
+{
+ return STREQ(ntree->idname, "SimulationNodeTree");
+}
+
+void sim_node_type_base(bNodeType *ntype, int type, const char *name, short nclass, short flag)
+{
+ node_type_base(ntype, type, name, nclass, flag);
+ ntype->poll = sim_node_poll_default;
+}
diff --git a/source/blender/nodes/simulation/node_simulation_util.h b/source/blender/nodes/simulation/node_simulation_util.h
new file mode 100644
index 00000000000..adbe2ad5e8f
--- /dev/null
+++ b/source/blender/nodes/simulation/node_simulation_util.h
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+#ifndef __NODE_SIM_UTIL_H__
+#define __NODE_SIM_UTIL_H__
+
+#include <string.h>
+
+#include "BLI_utildefines.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_node_types.h"
+
+#include "BKE_node.h"
+
+#include "BLT_translation.h"
+
+#include "NOD_simulation.h"
+
+#include "node_util.h"
+
+void sim_node_type_base(
+ struct bNodeType *ntype, int type, const char *name, short nclass, short flag);
+bool sim_node_poll_default(struct bNodeType *ntype, struct bNodeTree *ntree);
+
+#endif /* __NODE_SIM_UTIL_H__ */
diff --git a/source/blender/nodes/simulation/nodes/node_sim_common.cc b/source/blender/nodes/simulation/nodes/node_sim_common.cc
new file mode 100644
index 00000000000..fbc03905d4f
--- /dev/null
+++ b/source/blender/nodes/simulation/nodes/node_sim_common.cc
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+#include "BKE_node.h"
+
+#include "NOD_simulation.h"
+
+#include "NOD_common.h"
+#include "node_common.h"
+#include "node_simulation_util.h"
+
+void register_node_type_sim_group(void)
+{
+ static bNodeType ntype;
+
+ node_type_base_custom(&ntype, "SimulationNodeGroup", "Group", 0, 0);
+ ntype.type = NODE_GROUP;
+ ntype.poll = sim_node_poll_default;
+ ntype.poll_instance = node_group_poll_instance;
+ ntype.insert_link = node_insert_link_default;
+ ntype.update_internal_links = node_update_internal_links_default;
+ ntype.rna_ext.srna = RNA_struct_find("SimulationNodeGroup");
+ BLI_assert(ntype.rna_ext.srna != NULL);
+ RNA_struct_blender_type_set(ntype.rna_ext.srna, &ntype);
+
+ node_type_socket_templates(&ntype, NULL, NULL);
+ node_type_size(&ntype, 140, 60, 400);
+ node_type_label(&ntype, node_group_label);
+ node_type_group_update(&ntype, node_group_update);
+
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/simulation/nodes/node_sim_emit_particles.cc b/source/blender/nodes/simulation/nodes/node_sim_emit_particles.cc
new file mode 100644
index 00000000000..e23984dbf34
--- /dev/null
+++ b/source/blender/nodes/simulation/nodes/node_sim_emit_particles.cc
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+#include "node_simulation_util.h"
+
+static bNodeSocketTemplate sim_node_emit_particle_in[] = {
+ {SOCK_INT, N_("Amount"), 10, 0, 0, 0, 0, 10000000},
+ {SOCK_CONTROL_FLOW, N_("Execute")},
+ {-1, ""},
+};
+
+static bNodeSocketTemplate sim_node_emit_particle_out[] = {
+ {SOCK_CONTROL_FLOW, N_("Execute")},
+ {SOCK_EMITTERS, N_("Emitter")},
+ {-1, ""},
+};
+
+void register_node_type_sim_emit_particles()
+{
+ static bNodeType ntype;
+
+ sim_node_type_base(&ntype, SIM_NODE_EMIT_PARTICLES, "Emit Particles", 0, 0);
+ node_type_socket_templates(&ntype, sim_node_emit_particle_in, sim_node_emit_particle_out);
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/simulation/nodes/node_sim_execute_condition.cc b/source/blender/nodes/simulation/nodes/node_sim_execute_condition.cc
new file mode 100644
index 00000000000..69f30d1ad0d
--- /dev/null
+++ b/source/blender/nodes/simulation/nodes/node_sim_execute_condition.cc
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+
+#include "node_simulation_util.h"
+
+static bNodeSocketTemplate sim_node_execute_condition_in[] = {
+ {SOCK_BOOLEAN, N_("Condition")},
+ {SOCK_CONTROL_FLOW, N_("If True")},
+ {SOCK_CONTROL_FLOW, N_("If False")},
+ {-1, ""},
+};
+
+static bNodeSocketTemplate sim_node_execute_condition_out[] = {
+ {SOCK_CONTROL_FLOW, N_("Execute")},
+ {-1, ""},
+};
+
+void register_node_type_sim_execute_condition()
+{
+ static bNodeType ntype;
+
+ sim_node_type_base(&ntype, SIM_NODE_EXECUTE_CONDITION, "Execute Condition", 0, 0);
+ node_type_socket_templates(
+ &ntype, sim_node_execute_condition_in, sim_node_execute_condition_out);
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/simulation/nodes/node_sim_force.cc b/source/blender/nodes/simulation/nodes/node_sim_force.cc
new file mode 100644
index 00000000000..eccd2e4e2ab
--- /dev/null
+++ b/source/blender/nodes/simulation/nodes/node_sim_force.cc
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+#include "node_simulation_util.h"
+
+static bNodeSocketTemplate sim_node_force_in[] = {
+ {SOCK_VECTOR, N_("Force"), 0.0f, 0.0f, 0.0f, 0.0f, -10000.0f, 10000.0f},
+ {-1, ""},
+};
+
+static bNodeSocketTemplate sim_node_force_out[] = {
+ {SOCK_FORCES, N_("Force")},
+ {-1, ""},
+};
+
+void register_node_type_sim_force()
+{
+ static bNodeType ntype;
+
+ sim_node_type_base(&ntype, SIM_NODE_FORCE, "Force", 0, 0);
+ node_type_socket_templates(&ntype, sim_node_force_in, sim_node_force_out);
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/simulation/nodes/node_sim_multi_execute.cc b/source/blender/nodes/simulation/nodes/node_sim_multi_execute.cc
new file mode 100644
index 00000000000..5944db7e2bc
--- /dev/null
+++ b/source/blender/nodes/simulation/nodes/node_sim_multi_execute.cc
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+#include "node_simulation_util.h"
+
+static bNodeSocketTemplate sim_node_multi_execute_in[] = {
+ {SOCK_CONTROL_FLOW, "1"},
+ {SOCK_CONTROL_FLOW, "2"},
+ {SOCK_CONTROL_FLOW, "3"},
+ {-1, ""},
+};
+
+static bNodeSocketTemplate sim_node_multi_execute_out[] = {
+ {SOCK_CONTROL_FLOW, N_("Execute")},
+ {-1, ""},
+};
+
+void register_node_type_sim_multi_execute()
+{
+ static bNodeType ntype;
+
+ sim_node_type_base(&ntype, SIM_NODE_MULTI_EXECUTE, "Multi Execute", 0, 0);
+ node_type_socket_templates(&ntype, sim_node_multi_execute_in, sim_node_multi_execute_out);
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/simulation/nodes/node_sim_particle_attribute.cc b/source/blender/nodes/simulation/nodes/node_sim_particle_attribute.cc
new file mode 100644
index 00000000000..b6b67ee334e
--- /dev/null
+++ b/source/blender/nodes/simulation/nodes/node_sim_particle_attribute.cc
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+
+#include "BLI_listbase.h"
+#include "node_simulation_util.h"
+
+static bNodeSocketTemplate sim_node_particle_attribute_in[] = {
+ {SOCK_STRING, N_("Name")},
+ {-1, ""},
+};
+
+static bNodeSocketTemplate sim_node_particle_attribute_out[] = {
+ {SOCK_FLOAT, N_("Float")},
+ {SOCK_INT, N_("Int")},
+ {SOCK_BOOLEAN, N_("Boolean")},
+ {SOCK_VECTOR, N_("Vector")},
+ {SOCK_RGBA, N_("Color")},
+ {SOCK_OBJECT, N_("Object")},
+ {SOCK_IMAGE, N_("Image")},
+ {-1, ""},
+};
+
+static void sim_node_particle_attribute_update(bNodeTree *UNUSED(ntree), bNode *node)
+{
+ LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) {
+ nodeSetSocketAvailability(sock, sock->type == node->custom1);
+ }
+}
+
+void register_node_type_sim_particle_attribute()
+{
+ static bNodeType ntype;
+
+ sim_node_type_base(&ntype, SIM_NODE_PARTICLE_ATTRIBUTE, "Particle Attribute", 0, 0);
+ node_type_socket_templates(
+ &ntype, sim_node_particle_attribute_in, sim_node_particle_attribute_out);
+ node_type_update(&ntype, sim_node_particle_attribute_update);
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/simulation/nodes/node_sim_particle_birth_event.cc b/source/blender/nodes/simulation/nodes/node_sim_particle_birth_event.cc
new file mode 100644
index 00000000000..8332a3ecd9f
--- /dev/null
+++ b/source/blender/nodes/simulation/nodes/node_sim_particle_birth_event.cc
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+#include "node_simulation_util.h"
+
+static bNodeSocketTemplate sim_node_particle_birth_event_in[] = {
+ {SOCK_CONTROL_FLOW, N_("Execute")},
+ {-1, ""},
+};
+
+static bNodeSocketTemplate sim_node_particle_birth_event_out[] = {
+ {SOCK_EVENTS, N_("Event")},
+ {-1, ""},
+};
+
+void register_node_type_sim_particle_birth_event()
+{
+ static bNodeType ntype;
+
+ sim_node_type_base(&ntype, SIM_NODE_PARTICLE_BIRTH_EVENT, "Particle Birth Event", 0, 0);
+ node_type_socket_templates(
+ &ntype, sim_node_particle_birth_event_in, sim_node_particle_birth_event_out);
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/simulation/nodes/node_sim_particle_mesh_collision_event.cc b/source/blender/nodes/simulation/nodes/node_sim_particle_mesh_collision_event.cc
new file mode 100644
index 00000000000..48671172136
--- /dev/null
+++ b/source/blender/nodes/simulation/nodes/node_sim_particle_mesh_collision_event.cc
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+#include "node_simulation_util.h"
+
+static bNodeSocketTemplate sim_node_particle_mesh_collision_event_in[] = {
+ {SOCK_OBJECT, N_("Object")},
+ {SOCK_CONTROL_FLOW, N_("Execute")},
+ {-1, ""},
+};
+
+static bNodeSocketTemplate sim_node_particle_mesh_collision_event_out[] = {
+ {SOCK_EVENTS, N_("Event")},
+ {-1, ""},
+};
+
+void register_node_type_sim_particle_mesh_collision_event()
+{
+ static bNodeType ntype;
+
+ sim_node_type_base(
+ &ntype, SIM_NODE_PARTICLE_MESH_COLLISION_EVENT, "Particle Mesh Collision Event", 0, 0);
+ node_type_socket_templates(&ntype,
+ sim_node_particle_mesh_collision_event_in,
+ sim_node_particle_mesh_collision_event_out);
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/simulation/nodes/node_sim_particle_mesh_emitter.cc b/source/blender/nodes/simulation/nodes/node_sim_particle_mesh_emitter.cc
new file mode 100644
index 00000000000..2de7be2d3eb
--- /dev/null
+++ b/source/blender/nodes/simulation/nodes/node_sim_particle_mesh_emitter.cc
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+#include "node_simulation_util.h"
+
+#include "float.h"
+
+static bNodeSocketTemplate sim_node_particle_mesh_emitter_in[] = {
+ {SOCK_OBJECT, N_("Object")},
+ {SOCK_FLOAT, N_("Rate"), 10.0f, 0.0f, 0.0f, 0.0f, 0.0f, FLT_MAX},
+ {-1, ""},
+};
+
+static bNodeSocketTemplate sim_node_particle_mesh_emitter_out[] = {
+ {SOCK_EMITTERS, N_("Emitter")},
+ {-1, ""},
+};
+
+void register_node_type_sim_particle_mesh_emitter()
+{
+ static bNodeType ntype;
+
+ sim_node_type_base(&ntype, SIM_NODE_PARTICLE_MESH_EMITTER, "Mesh Emitter", 0, 0);
+ node_type_socket_templates(
+ &ntype, sim_node_particle_mesh_emitter_in, sim_node_particle_mesh_emitter_out);
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/simulation/nodes/node_sim_particle_simulation.cc b/source/blender/nodes/simulation/nodes/node_sim_particle_simulation.cc
new file mode 100644
index 00000000000..159c9b23da1
--- /dev/null
+++ b/source/blender/nodes/simulation/nodes/node_sim_particle_simulation.cc
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+
+#include "node_simulation_util.h"
+
+static bNodeSocketTemplate sim_node_particle_simulation_in[] = {
+ {SOCK_EMITTERS, N_("Emitters")},
+ {SOCK_EVENTS, N_("Events")},
+ {SOCK_FORCES, N_("Forces")},
+ {-1, ""},
+};
+
+static bNodeSocketTemplate sim_node_particle_simulation_out[] = {
+ {-1, ""},
+};
+
+void register_node_type_sim_particle_simulation()
+{
+ static bNodeType ntype;
+
+ sim_node_type_base(
+ &ntype, SIM_NODE_PARTICLE_SIMULATION, "Particle Simulation", NODE_CLASS_OUTPUT, 0);
+ node_type_socket_templates(
+ &ntype, sim_node_particle_simulation_in, sim_node_particle_simulation_out);
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/simulation/nodes/node_sim_particle_time_step_event.cc b/source/blender/nodes/simulation/nodes/node_sim_particle_time_step_event.cc
new file mode 100644
index 00000000000..cda8ddeb644
--- /dev/null
+++ b/source/blender/nodes/simulation/nodes/node_sim_particle_time_step_event.cc
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+#include "node_simulation_util.h"
+
+static bNodeSocketTemplate sim_node_particle_time_step_event_in[] = {
+ {SOCK_CONTROL_FLOW, N_("Execute")},
+ {-1, ""},
+};
+
+static bNodeSocketTemplate sim_node_particle_time_step_event_out[] = {
+ {SOCK_EVENTS, N_("Event")},
+ {-1, ""},
+};
+
+void register_node_type_sim_particle_time_step_event()
+{
+ static bNodeType ntype;
+
+ sim_node_type_base(&ntype, SIM_NODE_PARTICLE_TIME_STEP_EVENT, "Particle Time Step Event", 0, 0);
+ node_type_socket_templates(
+ &ntype, sim_node_particle_time_step_event_in, sim_node_particle_time_step_event_out);
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/simulation/nodes/node_sim_set_particle_attribute.cc b/source/blender/nodes/simulation/nodes/node_sim_set_particle_attribute.cc
new file mode 100644
index 00000000000..8696dbe340c
--- /dev/null
+++ b/source/blender/nodes/simulation/nodes/node_sim_set_particle_attribute.cc
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+#include "BLI_listbase.h"
+#include "node_simulation_util.h"
+
+static bNodeSocketTemplate sim_node_set_particle_attribute_in[] = {
+ {SOCK_STRING, N_("Name")},
+ {SOCK_FLOAT, N_("Float"), 0.0f, 0.0f, 0.0f, 0.0f, -10000.0f, 10000.0f},
+ {SOCK_INT, N_("Int"), 0, 0, 0, 0, -10000, 10000},
+ {SOCK_BOOLEAN, N_("Boolean")},
+ {SOCK_VECTOR, N_("Vector")},
+ {SOCK_RGBA, N_("Color")},
+ {SOCK_OBJECT, N_("Object")},
+ {SOCK_IMAGE, N_("Image")},
+ {-1, ""},
+};
+
+static bNodeSocketTemplate sim_node_set_particle_attribute_out[] = {
+ {SOCK_CONTROL_FLOW, N_("Execute")},
+ {-1, ""},
+};
+
+static void sim_node_set_particle_attribute_update(bNodeTree *UNUSED(ntree), bNode *node)
+{
+ int index = 0;
+ LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
+ if (index >= 1) {
+ nodeSetSocketAvailability(sock, sock->type == node->custom1);
+ }
+ index++;
+ }
+}
+
+void register_node_type_sim_set_particle_attribute()
+{
+ static bNodeType ntype;
+
+ sim_node_type_base(&ntype, SIM_NODE_SET_PARTICLE_ATTRIBUTE, "Set Particle Attribute", 0, 0);
+ node_type_socket_templates(
+ &ntype, sim_node_set_particle_attribute_in, sim_node_set_particle_attribute_out);
+ node_type_update(&ntype, sim_node_set_particle_attribute_update);
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/simulation/nodes/node_sim_simulation_time.cc b/source/blender/nodes/simulation/nodes/node_sim_simulation_time.cc
new file mode 100644
index 00000000000..40e1c43fb69
--- /dev/null
+++ b/source/blender/nodes/simulation/nodes/node_sim_simulation_time.cc
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+#include "node_simulation_util.h"
+
+static bNodeSocketTemplate sim_node_time_out[] = {
+ {SOCK_FLOAT, N_("Time")},
+ {-1, ""},
+};
+
+void register_node_type_sim_time()
+{
+ static bNodeType ntype;
+
+ sim_node_type_base(&ntype, SIM_NODE_TIME, "Time", 0, 0);
+ node_type_socket_templates(&ntype, nullptr, sim_node_time_out);
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c
index f7901ebb7d0..77a482f8546 100644
--- a/source/blender/render/intern/source/pipeline.c
+++ b/source/blender/render/intern/source/pipeline.c
@@ -2514,7 +2514,7 @@ void RE_RenderAnim(Render *re,
{
float ctime = BKE_scene_frame_get(scene);
AnimData *adt = BKE_animdata_from_id(&scene->id);
- BKE_animsys_evaluate_animdata(scene, &scene->id, adt, ctime, ADT_RECALC_ALL, false);
+ BKE_animsys_evaluate_animdata(&scene->id, adt, ctime, ADT_RECALC_ALL, false);
}
render_update_depsgraph(re);
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index a7578291a21..96b2fcf92e7 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -1349,17 +1349,8 @@ static uiBlock *wm_block_create_redo(bContext *C, ARegion *region, void *arg_op)
}
uiLayout *col = uiLayoutColumn(layout, false);
-
- if (op->type->flag & OPTYPE_MACRO) {
- for (op = op->macro.first; op; op = op->next) {
- uiTemplateOperatorPropertyButs(
- C, col, op, UI_BUT_LABEL_ALIGN_NONE, UI_TEMPLATE_OP_PROPS_SHOW_TITLE);
- }
- }
- else {
- uiTemplateOperatorPropertyButs(
- C, col, op, UI_BUT_LABEL_ALIGN_NONE, UI_TEMPLATE_OP_PROPS_SHOW_TITLE);
- }
+ uiTemplateOperatorPropertyButs(
+ C, col, op, UI_BUT_LABEL_ALIGN_NONE, UI_TEMPLATE_OP_PROPS_SHOW_TITLE);
UI_block_bounds_set_popup(block, 6 * U.dpi_fac, NULL);
@@ -1794,13 +1785,12 @@ static int wm_search_menu_invoke(bContext *C, wmOperator *op, const wmEvent *eve
}
}
- PropertyRNA *prop = op->type->prop;
int search_type;
- if (RNA_property_is_set(op->ptr, prop)) {
- search_type = RNA_property_enum_get(op->ptr, prop);
+ if (STREQ(op->type->idname, "WM_OT_search_menu")) {
+ search_type = SEARCH_TYPE_MENU;
}
else {
- search_type = U.experimental.use_menu_search ? SEARCH_TYPE_MENU : SEARCH_TYPE_OPERATOR;
+ search_type = SEARCH_TYPE_OPERATOR;
}
static struct SearchPopupInit_Data data;
@@ -1818,20 +1808,22 @@ static void WM_OT_search_menu(wmOperatorType *ot)
{
ot->name = "Search Menu";
ot->idname = "WM_OT_search_menu";
- ot->description = "Pop-up a search menu over all available operators in current context";
+ ot->description = "Pop-up a search over all menus in the current context";
ot->invoke = wm_search_menu_invoke;
ot->exec = wm_search_menu_exec;
ot->poll = WM_operator_winactive;
+}
- static const EnumPropertyItem search_type_items[] = {
- {SEARCH_TYPE_OPERATOR, "OPERATOR", 0, "Operator", "Search all operators"},
- {SEARCH_TYPE_MENU, "MENU", 0, "Menu", "Search active menu items"},
- {0, NULL, 0, NULL, NULL},
- };
+static void WM_OT_search_operator(wmOperatorType *ot)
+{
+ ot->name = "Search Operator";
+ ot->idname = "WM_OT_search_operator";
+ ot->description = "Pop-up a search over all available operators in current context";
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", search_type_items, SEARCH_TYPE_OPERATOR, "Type", "");
+ ot->invoke = wm_search_menu_invoke;
+ ot->exec = wm_search_menu_exec;
+ ot->poll = WM_operator_winactive;
}
static int wm_call_menu_exec(bContext *C, wmOperator *op)
@@ -3806,6 +3798,7 @@ void wm_operatortypes_register(void)
WM_operatortype_append(WM_OT_operator_defaults);
WM_operatortype_append(WM_OT_splash);
WM_operatortype_append(WM_OT_search_menu);
+ WM_operatortype_append(WM_OT_search_operator);
WM_operatortype_append(WM_OT_call_menu);
WM_operatortype_append(WM_OT_call_menu_pie);
WM_operatortype_append(WM_OT_call_panel);
diff --git a/tests/gtests/CMakeLists.txt b/tests/gtests/CMakeLists.txt
index bcf77fb6de7..c02bad471ff 100644
--- a/tests/gtests/CMakeLists.txt
+++ b/tests/gtests/CMakeLists.txt
@@ -12,6 +12,7 @@ if(WITH_GTESTS)
remove_strict_flags()
add_subdirectory(testing)
+ add_subdirectory(blenkernel)
add_subdirectory(blenlib)
add_subdirectory(blenloader)
add_subdirectory(guardedalloc)
diff --git a/tests/gtests/blenkernel/BKE_armature_test.cc b/tests/gtests/blenkernel/BKE_armature_test.cc
new file mode 100644
index 00000000000..0f390a471d7
--- /dev/null
+++ b/tests/gtests/blenkernel/BKE_armature_test.cc
@@ -0,0 +1,89 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2020 Blender Foundation
+ * All rights reserved.
+ */
+
+#include "BKE_armature.h"
+
+#include "BLI_math.h"
+
+#include "testing/testing.h"
+
+static const float FLOAT_EPSILON = 1e-7;
+
+TEST(mat3_vec_to_roll, UnitMatrix)
+{
+ float unit_matrix[3][3];
+ float roll;
+
+ unit_m3(unit_matrix);
+
+ // Any vector with a unit matrix should return zero roll.
+ mat3_vec_to_roll(unit_matrix, unit_matrix[0], &roll);
+ EXPECT_FLOAT_EQ(0.0f, roll);
+
+ mat3_vec_to_roll(unit_matrix, unit_matrix[1], &roll);
+ EXPECT_FLOAT_EQ(0.0f, roll);
+
+ mat3_vec_to_roll(unit_matrix, unit_matrix[2], &roll);
+ EXPECT_FLOAT_EQ(0.0f, roll);
+
+ {
+ // Non-unit vector.
+ float vector[3] = {1.0f, 1.0f, 1.0f};
+ mat3_vec_to_roll(unit_matrix, vector, &roll);
+ EXPECT_NEAR(0.0f, roll, FLOAT_EPSILON);
+
+ // Normalized version of the above vector.
+ normalize_v3(vector);
+ mat3_vec_to_roll(unit_matrix, vector, &roll);
+ EXPECT_NEAR(0.0f, roll, FLOAT_EPSILON);
+ }
+}
+
+TEST(mat3_vec_to_roll, Rotationmatrix)
+{
+ float rotation_matrix[3][3];
+ float roll;
+
+ const float rot_around_x[3] = {1.234f, 0.0f, 0.0f};
+ eul_to_mat3(rotation_matrix, rot_around_x);
+
+ {
+ const float unit_axis_x[3] = {1.0f, 0.0f, 0.0f};
+ mat3_vec_to_roll(rotation_matrix, unit_axis_x, &roll);
+ EXPECT_NEAR(1.234f, roll, FLOAT_EPSILON);
+ }
+
+ {
+ const float unit_axis_y[3] = {0.0f, 1.0f, 0.0f};
+ mat3_vec_to_roll(rotation_matrix, unit_axis_y, &roll);
+ EXPECT_NEAR(0, roll, FLOAT_EPSILON);
+ }
+
+ {
+ const float unit_axis_z[3] = {0.0f, 0.0f, 1.0f};
+ mat3_vec_to_roll(rotation_matrix, unit_axis_z, &roll);
+ EXPECT_NEAR(0, roll, FLOAT_EPSILON);
+ }
+
+ {
+ const float between_x_and_y[3] = {1.0f, 1.0f, 0.0f};
+ mat3_vec_to_roll(rotation_matrix, between_x_and_y, &roll);
+ EXPECT_NEAR(0.57158958f, roll, FLOAT_EPSILON);
+ }
+}
diff --git a/tests/gtests/blenkernel/CMakeLists.txt b/tests/gtests/blenkernel/CMakeLists.txt
new file mode 100644
index 00000000000..69b58eddf71
--- /dev/null
+++ b/tests/gtests/blenkernel/CMakeLists.txt
@@ -0,0 +1,37 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2020, Blender Foundation
+# All rights reserved.
+# ***** END GPL LICENSE BLOCK *****
+
+set(INC
+ .
+ ..
+ ../../../source/blender/blenkernel
+ ../../../source/blender/blenlib
+ ../../../source/blender/makesdna
+ ../../../intern/guardedalloc
+ ../../../intern/atomic
+)
+
+setup_libdirs()
+include_directories(${INC})
+
+set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${PLATFORM_LINKFLAGS}")
+set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${PLATFORM_LINKFLAGS_DEBUG}")
+
+BLENDER_TEST(BKE_armature "bf_blenloader;bf_blenkernel;bf_blenlib")
diff --git a/tests/gtests/blenlib/BLI_array_ref_test.cc b/tests/gtests/blenlib/BLI_array_ref_test.cc
index aacd6113161..7a1f54e7458 100644
--- a/tests/gtests/blenlib/BLI_array_ref_test.cc
+++ b/tests/gtests/blenlib/BLI_array_ref_test.cc
@@ -1,5 +1,5 @@
-#include "BLI_array_ref.h"
-#include "BLI_vector.h"
+#include "BLI_array_ref.hh"
+#include "BLI_vector.hh"
#include "testing/testing.h"
using namespace BLI;
diff --git a/tests/gtests/blenlib/BLI_array_test.cc b/tests/gtests/blenlib/BLI_array_test.cc
index dd09c2d20f8..b1aa24aa808 100644
--- a/tests/gtests/blenlib/BLI_array_test.cc
+++ b/tests/gtests/blenlib/BLI_array_test.cc
@@ -1,4 +1,4 @@
-#include "BLI_array_cxx.h"
+#include "BLI_array.hh"
#include "testing/testing.h"
using namespace BLI;
diff --git a/tests/gtests/blenlib/BLI_index_range_test.cc b/tests/gtests/blenlib/BLI_index_range_test.cc
index 60da18b6baf..b12502f0d97 100644
--- a/tests/gtests/blenlib/BLI_index_range_test.cc
+++ b/tests/gtests/blenlib/BLI_index_range_test.cc
@@ -1,5 +1,5 @@
-#include "BLI_index_range.h"
-#include "BLI_vector.h"
+#include "BLI_index_range.hh"
+#include "BLI_vector.hh"
#include "testing/testing.h"
using BLI::ArrayRef;
diff --git a/tests/gtests/blenlib/BLI_linklist_lockfree_test.cc b/tests/gtests/blenlib/BLI_linklist_lockfree_test.cc
index 9934d1a3337..d1176527cb5 100644
--- a/tests/gtests/blenlib/BLI_linklist_lockfree_test.cc
+++ b/tests/gtests/blenlib/BLI_linklist_lockfree_test.cc
@@ -65,7 +65,7 @@ struct IndexedNode {
void concurrent_insert(TaskPool *__restrict pool, void *taskdata, int /*threadid*/)
{
- LockfreeLinkList *list = (LockfreeLinkList *)BLI_task_pool_userdata(pool);
+ LockfreeLinkList *list = (LockfreeLinkList *)BLI_task_pool_user_data(pool);
CHECK_NOTNULL(list);
IndexedNode *node = (IndexedNode *)MEM_mallocN(sizeof(IndexedNode), "test node");
node->index = POINTER_AS_INT(taskdata);
diff --git a/tests/gtests/blenlib/BLI_map_test.cc b/tests/gtests/blenlib/BLI_map_test.cc
index 7be23157e94..2d052635c88 100644
--- a/tests/gtests/blenlib/BLI_map_test.cc
+++ b/tests/gtests/blenlib/BLI_map_test.cc
@@ -1,5 +1,5 @@
-#include "BLI_map.h"
-#include "BLI_set.h"
+#include "BLI_map.hh"
+#include "BLI_set.hh"
#include "testing/testing.h"
using BLI::Map;
diff --git a/tests/gtests/blenlib/BLI_optional_test.cc b/tests/gtests/blenlib/BLI_optional_test.cc
index a25a3cbd588..e0dec5681fe 100644
--- a/tests/gtests/blenlib/BLI_optional_test.cc
+++ b/tests/gtests/blenlib/BLI_optional_test.cc
@@ -1,4 +1,4 @@
-#include "BLI_optional.h"
+#include "BLI_optional.hh"
#include "testing/testing.h"
#include <string>
diff --git a/tests/gtests/blenlib/BLI_set_test.cc b/tests/gtests/blenlib/BLI_set_test.cc
index 555140f805c..2bb0b26dd20 100644
--- a/tests/gtests/blenlib/BLI_set_test.cc
+++ b/tests/gtests/blenlib/BLI_set_test.cc
@@ -1,5 +1,5 @@
-#include "BLI_set.h"
-#include "BLI_vector.h"
+#include "BLI_set.hh"
+#include "BLI_vector.hh"
#include "testing/testing.h"
using BLI::Set;
diff --git a/tests/gtests/blenlib/BLI_stack_cxx_test.cc b/tests/gtests/blenlib/BLI_stack_cxx_test.cc
index 6376259927b..e49872f8643 100644
--- a/tests/gtests/blenlib/BLI_stack_cxx_test.cc
+++ b/tests/gtests/blenlib/BLI_stack_cxx_test.cc
@@ -1,4 +1,4 @@
-#include "BLI_stack_cxx.h"
+#include "BLI_stack.hh"
#include "testing/testing.h"
using BLI::Stack;
diff --git a/tests/gtests/blenlib/BLI_string_map_test.cc b/tests/gtests/blenlib/BLI_string_map_test.cc
index 4cb67d5fbac..5e671da86c7 100644
--- a/tests/gtests/blenlib/BLI_string_map_test.cc
+++ b/tests/gtests/blenlib/BLI_string_map_test.cc
@@ -1,5 +1,5 @@
-#include "BLI_string_map.h"
-#include "BLI_vector.h"
+#include "BLI_string_map.hh"
+#include "BLI_vector.hh"
#include "testing/testing.h"
using namespace BLI;
diff --git a/tests/gtests/blenlib/BLI_string_ref_test.cc b/tests/gtests/blenlib/BLI_string_ref_test.cc
index a268bf3215a..1c0b641bbb5 100644
--- a/tests/gtests/blenlib/BLI_string_ref_test.cc
+++ b/tests/gtests/blenlib/BLI_string_ref_test.cc
@@ -1,5 +1,5 @@
-#include "BLI_string_ref.h"
-#include "BLI_vector.h"
+#include "BLI_string_ref.hh"
+#include "BLI_vector.hh"
#include "testing/testing.h"
using BLI::StringRef;
diff --git a/tests/gtests/blenlib/BLI_task_test.cc b/tests/gtests/blenlib/BLI_task_test.cc
index d4ab9de13c4..1f8c092c66a 100644
--- a/tests/gtests/blenlib/BLI_task_test.cc
+++ b/tests/gtests/blenlib/BLI_task_test.cc
@@ -27,17 +27,19 @@ static void task_range_iter_func(void *userdata, int index, const TaskParallelTL
// printf("%d, %d, %d\n", index, data[index], *((int *)tls->userdata_chunk));
}
-static void task_range_iter_finalize_func(void *__restrict userdata,
- void *__restrict userdata_chunk)
+static void task_range_iter_reduce_func(const void *__restrict UNUSED(userdata),
+ void *__restrict join_v,
+ void *__restrict userdata_chunk)
{
- int *data = (int *)userdata;
- data[NUM_ITEMS] += *(int *)userdata_chunk;
+ int *join = (int *)join_v;
+ int *chunk = (int *)userdata_chunk;
+ *join += *chunk;
// printf("%d, %d\n", data[NUM_ITEMS], *((int *)userdata_chunk));
}
TEST(task, RangeIter)
{
- int data[NUM_ITEMS + 1] = {0};
+ int data[NUM_ITEMS] = {0};
int sum = 0;
BLI_threadapi_init();
@@ -48,7 +50,7 @@ TEST(task, RangeIter)
settings.userdata_chunk = &sum;
settings.userdata_chunk_size = sizeof(sum);
- settings.func_finalize = task_range_iter_finalize_func;
+ settings.func_reduce = task_range_iter_reduce_func;
BLI_task_parallel_range(0, NUM_ITEMS, data, task_range_iter_func, &settings);
@@ -60,7 +62,7 @@ TEST(task, RangeIter)
EXPECT_EQ(data[i], i);
expected_sum += i;
}
- EXPECT_EQ(data[NUM_ITEMS], expected_sum);
+ EXPECT_EQ(sum, expected_sum);
BLI_threadapi_exit();
}
@@ -68,7 +70,7 @@ TEST(task, RangeIter)
TEST(task, RangeIterPool)
{
const int num_tasks = 10;
- int data[num_tasks][NUM_ITEMS + 1] = {{0}};
+ int data[num_tasks][NUM_ITEMS] = {{0}};
int sum = 0;
BLI_threadapi_init();
@@ -82,7 +84,7 @@ TEST(task, RangeIterPool)
for (int j = 0; j < num_tasks; j++) {
settings.userdata_chunk = &sum;
settings.userdata_chunk_size = sizeof(sum);
- settings.func_finalize = task_range_iter_finalize_func;
+ settings.func_reduce = task_range_iter_reduce_func;
BLI_task_parallel_range_pool_push(
range_pool, 0, NUM_ITEMS, data[j], task_range_iter_func, &settings);
@@ -93,16 +95,16 @@ TEST(task, RangeIterPool)
/* Those checks should ensure us all items of the listbase were processed once, and only once -
* as expected. */
+ int expected_sum = 0;
for (int j = 0; j < num_tasks; j++) {
- int expected_sum = 0;
for (int i = 0; i < NUM_ITEMS; i++) {
- // EXPECT_EQ(data[j][i], i);
+ // EXPECT_EQ(data[j][i], i);
expected_sum += i;
}
- EXPECT_EQ(data[j][NUM_ITEMS], expected_sum);
}
+ EXPECT_EQ(sum, expected_sum);
- /* A pool can be re-used untill it is freed. */
+ /* A pool can be re-used until it is freed. */
for (int j = 0; j < num_tasks; j++) {
memset(data[j], 0, sizeof(data[j]));
@@ -112,7 +114,7 @@ TEST(task, RangeIterPool)
for (int j = 0; j < num_tasks; j++) {
settings.userdata_chunk = &sum;
settings.userdata_chunk_size = sizeof(sum);
- settings.func_finalize = task_range_iter_finalize_func;
+ settings.func_reduce = task_range_iter_reduce_func;
BLI_task_parallel_range_pool_push(
range_pool, 0, NUM_ITEMS, data[j], task_range_iter_func, &settings);
@@ -131,8 +133,8 @@ TEST(task, RangeIterPool)
// EXPECT_EQ(data[j][i], i);
expected_sum += i;
}
- EXPECT_EQ(data[j][NUM_ITEMS], expected_sum);
}
+ EXPECT_EQ(sum, expected_sum);
BLI_threadapi_exit();
}
diff --git a/tests/gtests/blenlib/BLI_vector_set_test.cc b/tests/gtests/blenlib/BLI_vector_set_test.cc
index 5ec51337aa7..410e7a1b319 100644
--- a/tests/gtests/blenlib/BLI_vector_set_test.cc
+++ b/tests/gtests/blenlib/BLI_vector_set_test.cc
@@ -1,4 +1,4 @@
-#include "BLI_vector_set.h"
+#include "BLI_vector_set.hh"
#include "testing/testing.h"
using BLI::VectorSet;
diff --git a/tests/gtests/blenlib/BLI_vector_test.cc b/tests/gtests/blenlib/BLI_vector_test.cc
index 2402ee9627f..1585b77675b 100644
--- a/tests/gtests/blenlib/BLI_vector_test.cc
+++ b/tests/gtests/blenlib/BLI_vector_test.cc
@@ -1,4 +1,4 @@
-#include "BLI_vector.h"
+#include "BLI_vector.hh"
#include "testing/testing.h"
#include <forward_list>
@@ -45,7 +45,7 @@ struct TestListValue {
int value;
};
-TEST(vector, IntrusiveListBaseConstructor)
+TEST(vector, ListBaseConstructor)
{
TestListValue *value1 = new TestListValue{0, 0, 4};
TestListValue *value2 = new TestListValue{0, 0, 5};
@@ -55,7 +55,7 @@ TEST(vector, IntrusiveListBaseConstructor)
BLI_addtail(&list, value1);
BLI_addtail(&list, value2);
BLI_addtail(&list, value3);
- Vector<TestListValue *> vec(list, true);
+ Vector<TestListValue *> vec(list);
EXPECT_EQ(vec.size(), 3);
EXPECT_EQ(vec[0]->value, 4);
diff --git a/tests/python/modules/mesh_test.py b/tests/python/modules/mesh_test.py
index 9fb487bcef9..f188d998884 100644
--- a/tests/python/modules/mesh_test.py
+++ b/tests/python/modules/mesh_test.py
@@ -41,8 +41,15 @@
import bpy
-import os
+import functools
import inspect
+import os
+
+
+# Output from this module and from blender itself will occur during tests.
+# We need to flush python so that the output is properly interleaved, otherwise
+# blender's output for one test will end up showing in the middle of another test...
+print = functools.partial(print, flush=True)
class ModifierSpec:
@@ -165,8 +172,8 @@ class MeshTest:
"""
self.operations_stack.append(operator_spec)
- def _on_failed_test(self, compare, evaluated_test_object):
- if self.update:
+ def _on_failed_test(self, compare_result, validation_success, evaluated_test_object):
+ if self.update and validation_success:
if self.verbose:
print("Test failed expectantly. Updating expected mesh...")
@@ -178,8 +185,7 @@ class MeshTest:
evaluated_test_object.name = expected_object_name
# Save file
- blend_file = bpy.data.filepath
- bpy.ops.wm.save_as_mainfile(filepath=blend_file)
+ bpy.ops.wm.save_as_mainfile(filepath=bpy.data.filepath)
self._test_updated = True
@@ -188,10 +194,10 @@ class MeshTest:
return True
else:
- blender_file = bpy.data.filepath
- print("Test failed with error: {}. Resulting object mesh '{}' did not match expected object '{}' "
- "from file blender file {}".
- format(compare, evaluated_test_object.name, self.expected_object.name, blender_file))
+ print("Test comparison result: {}".format(compare_result))
+ print("Test validation result: {}".format(validation_success))
+ print("Resulting object mesh '{}' did not match expected object '{}' from file {}".
+ format(evaluated_test_object.name, self.expected_object.name, bpy.data.filepath))
return False
@@ -306,10 +312,13 @@ class MeshTest:
print("Comparing expected mesh with resulting mesh...")
evaluated_test_mesh = evaluated_test_object.data
expected_mesh = self.expected_object.data
- compare = evaluated_test_mesh.unit_test_compare(mesh=expected_mesh)
- success = (compare == 'Same')
+ compare_result = evaluated_test_mesh.unit_test_compare(mesh=expected_mesh)
+ compare_success = (compare_result == 'Same')
+
+ # Also check if invalid geometry (which is never expected) had to be corrected...
+ validation_success = evaluated_test_mesh.validate(verbose=True) == False
- if success:
+ if compare_success and validation_success:
if self.verbose:
print("Success!")
@@ -321,7 +330,7 @@ class MeshTest:
return True
else:
- return self._on_failed_test(compare, evaluated_test_object)
+ return self._on_failed_test(compare_result, validation_success, evaluated_test_object)
class OperatorTest: