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:
authorDalai Felinto <dfelinto@gmail.com>2016-10-21 00:30:54 +0300
committerDalai Felinto <dfelinto@gmail.com>2016-10-21 00:40:30 +0300
commitd74f6b22044a925e57e5f40a2ac132df0d6f8e37 (patch)
tree375a6cd018b3adb10dc0ad0a0aa4a8c6a161ec29
parent4948b6e226bb0352e0a6ead7dadddc33bb43c908 (diff)
parent225edf4e667c12651d2c056b0fbf3a7b17080ff7 (diff)
Merge remote-tracking branch 'origin/blender2.8' into pbr-merge
Conflicts: source/blender/blenloader/intern/versioning_defaults.c source/blender/editors/space_view3d/drawobject.c source/blender/editors/space_view3d/space_view3d.c source/blender/editors/space_view3d/view3d_draw.c source/blender/gpu/CMakeLists.txt source/blender/gpu/GPU_framebuffer.h source/blender/gpu/GPU_material.h source/blender/gpu/GPU_shader.h source/blender/gpu/intern/gpu_codegen.c source/blender/gpu/intern/gpu_draw.c source/blender/gpu/intern/gpu_framebuffer.c source/blender/gpu/intern/gpu_material.c source/blender/gpu/intern/gpu_shader.c source/blender/makesdna/DNA_view3d_types.h
-rwxr-xr-xbuild_files/build_environment/install_deps.sh14
-rw-r--r--intern/cycles/blender/CMakeLists.txt1
-rw-r--r--intern/cycles/blender/addon/properties.py45
-rw-r--r--intern/cycles/blender/addon/ui.py64
-rw-r--r--intern/cycles/blender/blender_curves.cpp245
-rw-r--r--intern/cycles/blender/blender_object.cpp62
-rw-r--r--intern/cycles/blender/blender_particles.cpp92
-rw-r--r--intern/cycles/blender/blender_sync.cpp8
-rw-r--r--intern/cycles/blender/blender_sync.h6
-rw-r--r--intern/cycles/blender/blender_util.h27
-rw-r--r--intern/elbeem/extern/elbeem.h2
-rw-r--r--intern/ghost/intern/GHOST_ContextCGL.h2
-rw-r--r--intern/ghost/intern/GHOST_ContextCGL.mm30
-rw-r--r--intern/ghost/intern/GHOST_ContextGLX.cpp17
-rw-r--r--intern/ghost/intern/GHOST_ContextWGL.cpp6
-rw-r--r--intern/ghost/intern/GHOST_ContextWGL.h8
-rw-r--r--intern/ghost/intern/GHOST_WindowCocoa.mm69
-rw-r--r--intern/ghost/intern/GHOST_WindowWin32.cpp94
-rw-r--r--intern/ghost/intern/GHOST_WindowX11.cpp107
-rw-r--r--release/darwin/blender.app/Contents/Info.plist4
-rw-r--r--release/scripts/presets/hair_dynamics/default.py17
-rw-r--r--release/scripts/startup/bl_operators/object_quick_effects.py233
-rw-r--r--release/scripts/startup/bl_operators/presets.py30
-rw-r--r--release/scripts/startup/bl_operators/view3d.py2
-rw-r--r--release/scripts/startup/bl_ui/__init__.py1
-rw-r--r--release/scripts/startup/bl_ui/properties_data_modifier.py34
-rw-r--r--release/scripts/startup/bl_ui/properties_paint_common.py2
-rw-r--r--release/scripts/startup/bl_ui/properties_particle.py1408
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_cloth.py16
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_common.py107
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py40
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_smoke.py23
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_softbody.py14
-rw-r--r--release/scripts/startup/bl_ui/properties_scene.py21
-rw-r--r--release/scripts/startup/bl_ui/properties_texture.py77
-rw-r--r--release/scripts/startup/bl_ui/space_dopesheet.py2
-rw-r--r--release/scripts/startup/bl_ui/space_time.py1
-rw-r--r--release/scripts/startup/bl_ui/space_userpref.py1
-rw-r--r--release/scripts/startup/bl_ui/space_view3d.py147
-rw-r--r--release/scripts/startup/bl_ui/space_view3d_toolbar.py105
-rw-r--r--source/blender/CMakeLists.txt2
-rw-r--r--source/blender/alembic/intern/abc_exporter.cc17
-rw-r--r--source/blender/alembic/intern/abc_hair.cc18
-rw-r--r--source/blender/alembic/intern/abc_hair.h10
-rw-r--r--source/blender/alembic/intern/abc_mesh.cc2
-rw-r--r--source/blender/alembic/intern/abc_points.cc10
-rw-r--r--source/blender/alembic/intern/abc_points.h6
-rw-r--r--source/blender/blenfont/BLF_api.h6
-rw-r--r--source/blender/blenfont/intern/blf.c91
-rw-r--r--source/blender/blenfont/intern/blf_font.c34
-rw-r--r--source/blender/blenfont/intern/blf_glyph.c121
-rw-r--r--source/blender/blenfont/intern/blf_internal.h5
-rw-r--r--source/blender/blenfont/intern/blf_internal_types.h8
-rw-r--r--source/blender/blenkernel/BKE_boids.h66
-rw-r--r--source/blender/blenkernel/BKE_cloth.h3
-rw-r--r--source/blender/blenkernel/BKE_context.h1
-rw-r--r--source/blender/blenkernel/BKE_dynamicpaint.h1
-rw-r--r--source/blender/blenkernel/BKE_effect.h10
-rw-r--r--source/blender/blenkernel/BKE_library.h2
-rw-r--r--source/blender/blenkernel/BKE_main.h1
-rw-r--r--source/blender/blenkernel/BKE_modifier.h1
-rw-r--r--source/blender/blenkernel/BKE_object.h3
-rw-r--r--source/blender/blenkernel/BKE_particle.h481
-rw-r--r--source/blender/blenkernel/BKE_pointcache.h348
-rw-r--r--source/blender/blenkernel/BKE_rigidbody.h1
-rw-r--r--source/blender/blenkernel/BKE_sca.h2
-rw-r--r--source/blender/blenkernel/BKE_screen.h6
-rw-r--r--source/blender/blenkernel/BKE_softbody.h2
-rw-r--r--source/blender/blenkernel/BKE_texture.h3
-rw-r--r--source/blender/blenkernel/CMakeLists.txt9
-rw-r--r--source/blender/blenkernel/intern/anim.c2
-rw-r--r--source/blender/blenkernel/intern/anim_sys.c10
-rw-r--r--source/blender/blenkernel/intern/boids.c1618
-rw-r--r--source/blender/blenkernel/intern/bpath.c35
-rw-r--r--source/blender/blenkernel/intern/cloth.c90
-rw-r--r--source/blender/blenkernel/intern/context.c2
-rw-r--r--source/blender/blenkernel/intern/depsgraph.c196
-rw-r--r--source/blender/blenkernel/intern/dynamicpaint.c350
-rw-r--r--source/blender/blenkernel/intern/effect.c155
-rw-r--r--source/blender/blenkernel/intern/fluidsim.c1
-rw-r--r--source/blender/blenkernel/intern/group.c1
-rw-r--r--source/blender/blenkernel/intern/idcode.c4
-rw-r--r--source/blender/blenkernel/intern/ipo.c72
-rw-r--r--source/blender/blenkernel/intern/library.c17
-rw-r--r--source/blender/blenkernel/intern/library_query.c72
-rw-r--r--source/blender/blenkernel/intern/library_remap.c4
-rw-r--r--source/blender/blenkernel/intern/modifier.c7
-rw-r--r--source/blender/blenkernel/intern/object.c190
-rw-r--r--source/blender/blenkernel/intern/object_deform.c9
-rw-r--r--source/blender/blenkernel/intern/object_dupli.c332
-rw-r--r--source/blender/blenkernel/intern/object_update.c49
-rw-r--r--source/blender/blenkernel/intern/particle.c4304
-rw-r--r--source/blender/blenkernel/intern/particle_child.c739
-rw-r--r--source/blender/blenkernel/intern/particle_distribute.c1476
-rw-r--r--source/blender/blenkernel/intern/particle_system.c4362
-rw-r--r--source/blender/blenkernel/intern/pointcache.c4095
-rw-r--r--source/blender/blenkernel/intern/rigidbody.c95
-rw-r--r--source/blender/blenkernel/intern/scene.c20
-rw-r--r--source/blender/blenkernel/intern/screen.c14
-rw-r--r--source/blender/blenkernel/intern/smoke.c308
-rw-r--r--source/blender/blenkernel/intern/softbody.c69
-rw-r--r--source/blender/blenkernel/intern/texture.c44
-rw-r--r--source/blender/blenlib/BLI_math_matrix.h191
-rw-r--r--source/blender/blenlib/BLI_math_vector.h17
-rw-r--r--source/blender/blenlib/intern/math_matrix.c302
-rw-r--r--source/blender/blenlib/intern/math_vector.c14
-rw-r--r--source/blender/blenlib/intern/math_vector_inline.c16
-rw-r--r--source/blender/blenloader/intern/readfile.c467
-rw-r--r--source/blender/blenloader/intern/versioning_250.c77
-rw-r--r--source/blender/blenloader/intern/versioning_260.c36
-rw-r--r--source/blender/blenloader/intern/versioning_270.c140
-rw-r--r--source/blender/blenloader/intern/versioning_defaults.c7
-rw-r--r--source/blender/blenloader/intern/versioning_legacy.c208
-rw-r--r--source/blender/blenloader/intern/writefile.c228
-rw-r--r--source/blender/blentranslation/BLT_translation.h2
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.cc47
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.cc147
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.h2
-rw-r--r--source/blender/depsgraph/intern/depsgraph_build.cc9
-rw-r--r--source/blender/depsgraph/intern/depsgraph_tag.cc40
-rw-r--r--source/blender/editors/animation/anim_channels_defines.c115
-rw-r--r--source/blender/editors/animation/anim_channels_edit.c5
-rw-r--r--source/blender/editors/animation/anim_filter.c72
-rw-r--r--source/blender/editors/gpencil/drawgpencil.c1129
-rw-r--r--source/blender/editors/gpencil/gpencil_brush.c31
-rw-r--r--source/blender/editors/gpencil/gpencil_paint.c36
-rw-r--r--source/blender/editors/include/BIF_glutil.h61
-rw-r--r--source/blender/editors/include/ED_anim_api.h2
-rw-r--r--source/blender/editors/include/ED_buttons.h1
-rw-r--r--source/blender/editors/include/ED_object.h2
-rw-r--r--source/blender/editors/include/ED_particle.h74
-rw-r--r--source/blender/editors/include/ED_physics.h5
-rw-r--r--source/blender/editors/include/UI_interface.h6
-rw-r--r--source/blender/editors/include/UI_resources.h9
-rw-r--r--source/blender/editors/interface/interface_draw.c187
-rw-r--r--source/blender/editors/interface/interface_icons.c11
-rw-r--r--source/blender/editors/interface/interface_panel.c73
-rw-r--r--source/blender/editors/interface/interface_templates.c57
-rw-r--r--source/blender/editors/interface/interface_widgets.c100
-rw-r--r--source/blender/editors/interface/resources.c53
-rw-r--r--source/blender/editors/interface/view2d.c11
-rw-r--r--source/blender/editors/object/object_add.c18
-rw-r--r--source/blender/editors/object/object_edit.c22
-rw-r--r--source/blender/editors/object/object_intern.h1
-rw-r--r--source/blender/editors/object/object_modifier.c283
-rw-r--r--source/blender/editors/object/object_ops.c1
-rw-r--r--source/blender/editors/object/object_relations.c5
-rw-r--r--source/blender/editors/object/object_select.c41
-rw-r--r--source/blender/editors/physics/CMakeLists.txt4
-rw-r--r--source/blender/editors/physics/particle_boids.c371
-rw-r--r--source/blender/editors/physics/particle_edit.c4923
-rw-r--r--source/blender/editors/physics/particle_object.c1244
-rw-r--r--source/blender/editors/physics/physics_intern.h67
-rw-r--r--source/blender/editors/physics/physics_ops.c146
-rw-r--r--source/blender/editors/physics/physics_pointcache.c469
-rw-r--r--source/blender/editors/render/render_shading.c10
-rw-r--r--source/blender/editors/screen/area.c127
-rw-r--r--source/blender/editors/screen/glutil.c203
-rw-r--r--source/blender/editors/screen/screen_context.c6
-rw-r--r--source/blender/editors/screen/screen_edit.c16
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex.c16
-rw-r--r--source/blender/editors/space_api/spacetypes.c11
-rw-r--r--source/blender/editors/space_buttons/buttons_context.c107
-rw-r--r--source/blender/editors/space_buttons/buttons_texture.c50
-rw-r--r--source/blender/editors/space_buttons/space_buttons.c7
-rw-r--r--source/blender/editors/space_file/file_draw.c30
-rw-r--r--source/blender/editors/space_file/filesel.c2
-rw-r--r--source/blender/editors/space_graph/graph_draw.c207
-rw-r--r--source/blender/editors/space_info/info_stats.c34
-rw-r--r--source/blender/editors/space_nla/nla_buttons.c1
-rw-r--r--source/blender/editors/space_nla/nla_channels.c3
-rw-r--r--source/blender/editors/space_node/drawnode.c73
-rw-r--r--source/blender/editors/space_node/node_draw.c258
-rw-r--r--source/blender/editors/space_node/node_intern.h3
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c198
-rw-r--r--source/blender/editors/space_outliner/outliner_edit.c116
-rw-r--r--source/blender/editors/space_outliner/outliner_intern.h24
-rw-r--r--source/blender/editors/space_outliner/outliner_ops.c5
-rw-r--r--source/blender/editors/space_outliner/outliner_select.c300
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.c2
-rw-r--r--source/blender/editors/space_outliner/outliner_tree.c9
-rw-r--r--source/blender/editors/space_sequencer/sequencer_draw.c20
-rw-r--r--source/blender/editors/space_time/space_time.c260
-rw-r--r--source/blender/editors/space_view3d/CMakeLists.txt1
-rw-r--r--source/blender/editors/space_view3d/drawarmature.c8
-rw-r--r--source/blender/editors/space_view3d/drawobject.c2164
-rw-r--r--source/blender/editors/space_view3d/drawvolume.c2
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c11
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c4746
-rw-r--r--source/blender/editors/space_view3d/view3d_draw_legacy.c3647
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c4
-rw-r--r--source/blender/editors/space_view3d/view3d_fly.c49
-rw-r--r--source/blender/editors/space_view3d/view3d_header.c8
-rw-r--r--source/blender/editors/space_view3d/view3d_intern.h28
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c12
-rw-r--r--source/blender/editors/space_view3d/view3d_walk.c33
-rw-r--r--source/blender/editors/transform/transform.c2
-rw-r--r--source/blender/editors/transform/transform.h1
-rw-r--r--source/blender/editors/transform/transform_conversions.c203
-rw-r--r--source/blender/editors/transform/transform_generics.c9
-rw-r--r--source/blender/editors/transform/transform_manipulator.c155
-rw-r--r--source/blender/editors/transform/transform_orientations.c2
-rw-r--r--source/blender/editors/transform/transform_snap.c8
-rw-r--r--source/blender/editors/transform/transform_snap_object.c16
-rw-r--r--source/blender/editors/util/CMakeLists.txt1
-rw-r--r--source/blender/editors/util/ed_util.c24
-rw-r--r--source/blender/editors/util/undo.c34
-rw-r--r--source/blender/gpu/CMakeLists.txt60
-rw-r--r--source/blender/gpu/GPU_batch.h37
-rw-r--r--source/blender/gpu/GPU_debug.h15
-rw-r--r--source/blender/gpu/GPU_draw.h7
-rw-r--r--source/blender/gpu/GPU_framebuffer.h4
-rw-r--r--source/blender/gpu/GPU_immediate.h47
-rw-r--r--source/blender/gpu/GPU_material.h21
-rw-r--r--source/blender/gpu/GPU_matrix.h143
-rw-r--r--source/blender/gpu/GPU_shader.h36
-rw-r--r--source/blender/gpu/GPU_viewport.h41
-rw-r--r--source/blender/gpu/gawain/attrib_binding.c69
-rw-r--r--source/blender/gpu/gawain/attrib_binding.h24
-rw-r--r--source/blender/gpu/gawain/batch.c124
-rw-r--r--source/blender/gpu/gawain/batch.h86
-rw-r--r--source/blender/gpu/gawain/common.h41
-rw-r--r--source/blender/gpu/gawain/element.c262
-rw-r--r--source/blender/gpu/gawain/element.h55
-rw-r--r--source/blender/gpu/gawain/imm_util.c46
-rw-r--r--source/blender/gpu/gawain/imm_util.h18
-rw-r--r--source/blender/gpu/gawain/immediate.c776
-rw-r--r--source/blender/gpu/gawain/immediate.h101
-rw-r--r--source/blender/gpu/gawain/vertex_buffer.c156
-rw-r--r--source/blender/gpu/gawain/vertex_buffer.h62
-rw-r--r--source/blender/gpu/gawain/vertex_format.c203
-rw-r--r--source/blender/gpu/gawain/vertex_format.h53
-rw-r--r--source/blender/gpu/intern/gpu_basic_shader.c19
-rw-r--r--source/blender/gpu/intern/gpu_batch.c35
-rw-r--r--source/blender/gpu/intern/gpu_codegen.c10
-rw-r--r--source/blender/gpu/intern/gpu_compositing.c37
-rw-r--r--source/blender/gpu/intern/gpu_debug.c132
-rw-r--r--source/blender/gpu/intern/gpu_draw.c83
-rw-r--r--source/blender/gpu/intern/gpu_extensions.c23
-rw-r--r--source/blender/gpu/intern/gpu_framebuffer.c200
-rw-r--r--source/blender/gpu/intern/gpu_immediate.c67
-rw-r--r--source/blender/gpu/intern/gpu_init_exit.c6
-rw-r--r--source/blender/gpu/intern/gpu_material.c93
-rw-r--r--source/blender/gpu/intern/gpu_matrix.c637
-rw-r--r--source/blender/gpu/intern/gpu_shader.c505
-rw-r--r--source/blender/gpu/intern/gpu_shader_private.h40
-rw-r--r--source/blender/gpu/intern/gpu_texture.c39
-rw-r--r--source/blender/gpu/intern/gpu_viewport.c52
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_flat_color_vert.glsl20
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_outline_smooth_vert.glsl29
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_smooth_vert.glsl26
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_varying_color_outline_smooth_vert.glsl34
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_point_varying_size_varying_color_vert.glsl21
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_smooth_color_frag.glsl13
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_smooth_color_vert.glsl20
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_vert.glsl13
-rw-r--r--source/blender/gpu/shaders/gpu_shader_3D_flat_color_vert.glsl20
-rw-r--r--source/blender/gpu/shaders/gpu_shader_3D_image_vert.glsl18
-rw-r--r--source/blender/gpu/shaders/gpu_shader_3D_point_fixed_size_varying_color_vert.glsl18
-rw-r--r--source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_outline_smooth_vert.glsl29
-rw-r--r--source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_smooth_vert.glsl26
-rw-r--r--source/blender/gpu/shaders/gpu_shader_3D_point_varying_size_varying_color_vert.glsl21
-rw-r--r--source/blender/gpu/shaders/gpu_shader_3D_point_varying_size_vert.glsl16
-rw-r--r--source/blender/gpu/shaders/gpu_shader_3D_smooth_color_frag.glsl13
-rw-r--r--source/blender/gpu/shaders/gpu_shader_3D_smooth_color_vert.glsl20
-rw-r--r--source/blender/gpu/shaders/gpu_shader_3D_vert.glsl13
-rw-r--r--source/blender/gpu/shaders/gpu_shader_basic_frag.glsl2
-rw-r--r--source/blender/gpu/shaders/gpu_shader_basic_geom.glsl6
-rw-r--r--source/blender/gpu/shaders/gpu_shader_depth_only_frag.glsl6
-rw-r--r--source/blender/gpu/shaders/gpu_shader_flat_color_frag.glsl13
-rw-r--r--source/blender/gpu/shaders/gpu_shader_image_modulate_alpha_frag.glsl18
-rw-r--r--source/blender/gpu/shaders/gpu_shader_image_rect_modulate_alpha_frag.glsl18
-rw-r--r--source/blender/gpu/shaders/gpu_shader_point_uniform_color_frag.glsl21
-rw-r--r--source/blender/gpu/shaders/gpu_shader_point_uniform_color_outline_smooth_frag.glsl36
-rw-r--r--source/blender/gpu/shaders/gpu_shader_point_uniform_color_smooth_frag.glsl25
-rw-r--r--source/blender/gpu/shaders/gpu_shader_point_varying_color_frag.glsl21
-rw-r--r--source/blender/gpu/shaders/gpu_shader_point_varying_color_outline_smooth_frag.glsl37
-rw-r--r--source/blender/gpu/shaders/gpu_shader_text_frag.glsl22
-rw-r--r--source/blender/gpu/shaders/gpu_shader_text_vert.glsl24
-rw-r--r--source/blender/gpu/shaders/gpu_shader_uniform_color_frag.glsl13
-rw-r--r--source/blender/makesdna/DNA_ID.h5
-rw-r--r--source/blender/makesdna/DNA_boid_types.h225
-rw-r--r--source/blender/makesdna/DNA_dynamicpaint_types.h3
-rw-r--r--source/blender/makesdna/DNA_gpencil_types.h1
-rw-r--r--source/blender/makesdna/DNA_ipo_types.h39
-rw-r--r--source/blender/makesdna/DNA_modifier_types.h42
-rw-r--r--source/blender/makesdna/DNA_object_fluidsim.h2
-rw-r--r--source/blender/makesdna/DNA_object_force.h109
-rw-r--r--source/blender/makesdna/DNA_object_types.h7
-rw-r--r--source/blender/makesdna/DNA_outliner_types.h15
-rw-r--r--source/blender/makesdna/DNA_particle_types.h613
-rw-r--r--source/blender/makesdna/DNA_rigidbody_types.h3
-rw-r--r--source/blender/makesdna/DNA_scene_types.h36
-rw-r--r--source/blender/makesdna/DNA_screen_types.h5
-rw-r--r--source/blender/makesdna/DNA_smoke_types.h4
-rw-r--r--source/blender/makesdna/DNA_space_types.h2
-rw-r--r--source/blender/makesdna/DNA_userdef_types.h5
-rw-r--r--source/blender/makesdna/DNA_view3d_types.h18
-rw-r--r--source/blender/makesdna/intern/makesdna.c4
-rw-r--r--source/blender/makesrna/RNA_access.h24
-rw-r--r--source/blender/makesrna/RNA_enum_types.h1
-rw-r--r--source/blender/makesrna/intern/CMakeLists.txt2
-rw-r--r--source/blender/makesrna/intern/makesrna.c2
-rw-r--r--source/blender/makesrna/intern/rna_ID.c12
-rw-r--r--source/blender/makesrna/intern/rna_action.c6
-rw-r--r--source/blender/makesrna/intern/rna_boid.c674
-rw-r--r--source/blender/makesrna/intern/rna_color.c8
-rw-r--r--source/blender/makesrna/intern/rna_context.c1
-rw-r--r--source/blender/makesrna/intern/rna_dynamicpaint.c63
-rw-r--r--source/blender/makesrna/intern/rna_fluidsim.c48
-rw-r--r--source/blender/makesrna/intern/rna_image_api.c2
-rw-r--r--source/blender/makesrna/intern/rna_internal.h2
-rw-r--r--source/blender/makesrna/intern/rna_main.c7
-rw-r--r--source/blender/makesrna/intern/rna_main_api.c46
-rw-r--r--source/blender/makesrna/intern/rna_modifier.c124
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c39
-rw-r--r--source/blender/makesrna/intern/rna_object.c80
-rw-r--r--source/blender/makesrna/intern/rna_object_api.c49
-rw-r--r--source/blender/makesrna/intern/rna_object_force.c594
-rw-r--r--source/blender/makesrna/intern/rna_particle.c3571
-rw-r--r--source/blender/makesrna/intern/rna_rigidbody.c17
-rw-r--r--source/blender/makesrna/intern/rna_scene.c33
-rw-r--r--source/blender/makesrna/intern/rna_sculpt_paint.c322
-rw-r--r--source/blender/makesrna/intern/rna_smoke.c102
-rw-r--r--source/blender/makesrna/intern/rna_space.c25
-rw-r--r--source/blender/makesrna/intern/rna_texture.c45
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c4
-rw-r--r--source/blender/modifiers/CMakeLists.txt2
-rw-r--r--source/blender/modifiers/MOD_modifiertypes.h2
-rw-r--r--source/blender/modifiers/intern/MOD_build.c2
-rw-r--r--source/blender/modifiers/intern/MOD_cloth.c13
-rw-r--r--source/blender/modifiers/intern/MOD_collision.c2
-rw-r--r--source/blender/modifiers/intern/MOD_explode.c943
-rw-r--r--source/blender/modifiers/intern/MOD_laplaciandeform.c3
-rw-r--r--source/blender/modifiers/intern/MOD_particleinstance.c470
-rw-r--r--source/blender/modifiers/intern/MOD_particlesystem.c241
-rw-r--r--source/blender/modifiers/intern/MOD_shapekey.c2
-rw-r--r--source/blender/modifiers/intern/MOD_smooth.c2
-rw-r--r--source/blender/modifiers/intern/MOD_softbody.c2
-rw-r--r--source/blender/modifiers/intern/MOD_solidify.c2
-rw-r--r--source/blender/modifiers/intern/MOD_util.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_particle_info.c7
-rw-r--r--source/blender/python/generic/blf_py_api.c4
-rw-r--r--source/blender/render/intern/source/convertblender.c1291
-rw-r--r--source/blender/render/intern/source/pipeline.c28
-rw-r--r--source/blender/render/intern/source/pointdensity.c268
-rw-r--r--source/blender/render/intern/source/renderdatabase.c32
-rw-r--r--source/blender/render/intern/source/shadeinput.c1
-rw-r--r--source/blender/render/intern/source/voxeldata.c20
-rw-r--r--source/blender/windowmanager/CMakeLists.txt11
-rw-r--r--source/blender/windowmanager/WM_api.h10
-rw-r--r--source/blender/windowmanager/WM_types.h6
-rw-r--r--source/blender/windowmanager/intern/wm_draw.c51
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c106
-rw-r--r--source/blender/windowmanager/intern/wm_init_exit.c4
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c8
-rw-r--r--source/blender/windowmanager/intern/wm_stereo.c80
-rw-r--r--source/blender/windowmanager/intern/wm_window.c9
-rw-r--r--source/blender/windowmanager/manipulators/WM_manipulator_api.h110
-rw-r--r--source/blender/windowmanager/manipulators/WM_manipulator_types.h167
-rw-r--r--source/blender/windowmanager/manipulators/intern/manipulator_library/manipulator_library_intern.h100
-rw-r--r--source/blender/windowmanager/manipulators/intern/manipulator_library/manipulator_library_utils.c171
-rw-r--r--source/blender/windowmanager/manipulators/intern/wm_manipulator.c404
-rw-r--r--source/blender/windowmanager/manipulators/intern/wm_manipulator_intern.h230
-rw-r--r--source/blender/windowmanager/manipulators/intern/wm_manipulatorgroup.c586
-rw-r--r--source/blender/windowmanager/manipulators/intern/wm_manipulatormap.c760
-rw-r--r--source/blender/windowmanager/manipulators/wm_manipulator_wmapi.h90
-rw-r--r--source/blender/windowmanager/wm.h2
-rw-r--r--source/blender/windowmanager/wm_event_system.h3
-rw-r--r--source/blender/windowmanager/wm_event_types.h2
-rw-r--r--source/blenderplayer/bad_level_call_stubs/CMakeLists.txt3
-rw-r--r--source/blenderplayer/bad_level_call_stubs/stubs.c16
-rw-r--r--source/creator/creator.c2
-rw-r--r--source/creator/creator_args.c12
-rw-r--r--source/gameengine/Ketsji/BL_BlenderShader.cpp2
375 files changed, 15655 insertions, 50814 deletions
diff --git a/build_files/build_environment/install_deps.sh b/build_files/build_environment/install_deps.sh
index d6ea7d99f04..8588d235eff 100755
--- a/build_files/build_environment/install_deps.sh
+++ b/build_files/build_environment/install_deps.sh
@@ -25,7 +25,7 @@
ARGS=$( \
getopt \
-o s:i:t:h \
---long source:,install:,tmp:,info:,threads:,help,show-deps,no-sudo,no-build,no-confirm,use-cxx11,\
+--long source:,install:,tmp:,info:,threads:,help,show-deps,no-sudo,no-build,no-confirm,\
with-all,with-opencollada,\
ver-ocio:,ver-oiio:,ver-llvm:,ver-osl:,ver-osd:,ver-openvdb:,\
force-all,force-python,force-numpy,force-boost,\
@@ -104,11 +104,6 @@ ARGUMENTS_INFO="\"COMMAND LINE ARGUMENTS:
--no-confirm
Disable any interaction with user (suitable for automated run).
- --use-cxx11
- Build all libraries in cpp11 'mode' (will be mandatory soon in blender2.8 branch).
- NOTE: If your compiler is gcc-6.0 or above, you probably *want* to enable this option (since it's default
- standard starting from this version).
-
--with-all
By default, a number of optional and not-so-often needed libraries are not installed.
This option will try to install them, at the cost of potential conflicts (depending on
@@ -287,7 +282,7 @@ SUDO="sudo"
NO_BUILD=false
NO_CONFIRM=false
-USE_CXX11=false
+USE_CXX11=true # Mandatory in blender2.8
PYTHON_VERSION="3.5.1"
PYTHON_VERSION_MIN="3.5"
@@ -499,9 +494,6 @@ while true; do
--no-confirm)
NO_CONFIRM=true; shift; continue
;;
- --use-cxx11)
- USE_CXX11=true; shift; continue
- ;;
--with-all)
WITH_ALL=true; shift; continue
;;
@@ -778,7 +770,7 @@ FFMPEG_SOURCE=( "http://ffmpeg.org/releases/ffmpeg-$FFMPEG_VERSION.tar.bz2" )
CXXFLAGS_BACK=$CXXFLAGS
if [ "$USE_CXX11" = true ]; then
- WARNING "You are trying to use c++11, this *should* go smoothely with any very recent distribution
+ WARNING "C++11 is now mandatory for blender2.8, this *should* go smoothly with any very recent distribution.
However, if you are experiencing linking errors (also when building Blender itself), please try the following:
* Re-run this script with `--build-all --force-all` options.
* Ensure your gcc version is at the very least 4.8, if possible you should really rather use gcc-5.1 or above.
diff --git a/intern/cycles/blender/CMakeLists.txt b/intern/cycles/blender/CMakeLists.txt
index a79deca53e1..5cf482cfad3 100644
--- a/intern/cycles/blender/CMakeLists.txt
+++ b/intern/cycles/blender/CMakeLists.txt
@@ -25,7 +25,6 @@ set(SRC
blender_camera.cpp
blender_mesh.cpp
blender_object.cpp
- blender_particles.cpp
blender_curves.cpp
blender_logging.cpp
blender_python.cpp
diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py
index 977d7f75bb7..0c1784f8a3c 100644
--- a/intern/cycles/blender/addon/properties.py
+++ b/intern/cycles/blender/addon/properties.py
@@ -1080,49 +1080,6 @@ class CyclesCurveRenderSettings(bpy.types.PropertyGroup):
del bpy.types.Scene.cycles_curves
-class CyclesCurveSettings(bpy.types.PropertyGroup):
- @classmethod
- def register(cls):
- bpy.types.ParticleSettings.cycles = PointerProperty(
- name="Cycles Hair Settings",
- description="Cycles hair settings",
- type=cls,
- )
- cls.radius_scale = FloatProperty(
- name="Radius Scaling",
- description="Multiplier of width properties",
- min=0.0, max=1000.0,
- default=0.01,
- )
- cls.root_width = FloatProperty(
- name="Root Size",
- description="Strand's width at root",
- min=0.0, max=1000.0,
- default=1.0,
- )
- cls.tip_width = FloatProperty(
- name="Tip Multiplier",
- description="Strand's width at tip",
- min=0.0, max=1000.0,
- default=0.0,
- )
- cls.shape = FloatProperty(
- name="Strand Shape",
- description="Strand shape parameter",
- min=-1.0, max=1.0,
- default=0.0,
- )
- cls.use_closetip = BoolProperty(
- name="Close tip",
- description="Set tip radius to zero",
- default=True,
- )
-
- @classmethod
- def unregister(cls):
- del bpy.types.ParticleSettings.cycles
-
-
def register():
bpy.utils.register_class(CyclesRenderSettings)
bpy.utils.register_class(CyclesCameraSettings)
@@ -1133,7 +1090,6 @@ def register():
bpy.utils.register_class(CyclesMeshSettings)
bpy.utils.register_class(CyclesObjectSettings)
bpy.utils.register_class(CyclesCurveRenderSettings)
- bpy.utils.register_class(CyclesCurveSettings)
def unregister():
@@ -1146,4 +1102,3 @@ def unregister():
bpy.utils.unregister_class(CyclesObjectSettings)
bpy.utils.unregister_class(CyclesVisibilitySettings)
bpy.utils.unregister_class(CyclesCurveRenderSettings)
- bpy.utils.unregister_class(CyclesCurveSettings)
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index 52872d2b83f..3de309a34ea 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -1349,37 +1349,6 @@ class CyclesTexture_PT_colors(CyclesButtonsPanel, Panel):
layout.template_color_ramp(mapping, "color_ramp", expand=True)
-class CyclesParticle_PT_textures(CyclesButtonsPanel, Panel):
- bl_label = "Textures"
- bl_context = "particle"
- bl_options = {'DEFAULT_CLOSED'}
-
- @classmethod
- def poll(cls, context):
- psys = context.particle_system
- return psys and CyclesButtonsPanel.poll(context)
-
- def draw(self, context):
- layout = self.layout
-
- psys = context.particle_system
- part = psys.settings
-
- row = layout.row()
- row.template_list("TEXTURE_UL_texslots", "", part, "texture_slots", part, "active_texture_index", rows=2)
-
- col = row.column(align=True)
- col.operator("texture.slot_move", text="", icon='TRIA_UP').type = 'UP'
- col.operator("texture.slot_move", text="", icon='TRIA_DOWN').type = 'DOWN'
- col.menu("TEXTURE_MT_specials", icon='DOWNARROW_HLT', text="")
-
- if not part.active_texture:
- layout.template_ID(part, "active_texture", new="texture.new")
- else:
- slot = part.texture_slots[part.active_texture_index]
- layout.template_ID(slot, "texture", new="texture.new")
-
-
class CyclesRender_PT_CurveRendering(CyclesButtonsPanel, Panel):
bl_label = "Cycles Hair Rendering"
bl_context = "particle"
@@ -1528,37 +1497,6 @@ class CyclesRender_PT_debug(CyclesButtonsPanel, Panel):
col.prop(cscene, "debug_use_opencl_debug", text="Debug")
-class CyclesParticle_PT_CurveSettings(CyclesButtonsPanel, Panel):
- bl_label = "Cycles Hair Settings"
- bl_context = "particle"
-
- @classmethod
- def poll(cls, context):
- scene = context.scene
- ccscene = scene.cycles_curves
- psys = context.particle_system
- use_curves = ccscene.use_curves and psys
- return CyclesButtonsPanel.poll(context) and use_curves and psys.settings.type == 'HAIR'
-
- def draw(self, context):
- layout = self.layout
-
- psys = context.particle_settings
- cpsys = psys.cycles
-
- row = layout.row()
- row.prop(cpsys, "shape", text="Shape")
-
- layout.label(text="Thickness:")
- row = layout.row()
- row.prop(cpsys, "root_width", text="Root")
- row.prop(cpsys, "tip_width", text="Tip")
-
- row = layout.row()
- row.prop(cpsys, "radius_scale", text="Scaling")
- row.prop(cpsys, "use_closetip", text="Close tip")
-
-
class CyclesScene_PT_simplify(CyclesButtonsPanel, Panel):
bl_label = "Simplify"
bl_context = "scene"
@@ -1581,12 +1519,10 @@ class CyclesScene_PT_simplify(CyclesButtonsPanel, Panel):
col = split.column()
col.label(text="Viewport:")
col.prop(rd, "simplify_subdivision", text="Subdivision")
- col.prop(rd, "simplify_child_particles", text="Child Particles")
col = split.column()
col.label(text="Render:")
col.prop(rd, "simplify_subdivision_render", text="Subdivision")
- col.prop(rd, "simplify_child_particles_render", text="Child Particles")
col = layout.column()
col.prop(cscene, "use_camera_cull")
diff --git a/intern/cycles/blender/blender_curves.cpp b/intern/cycles/blender/blender_curves.cpp
index 378ae67f0c7..7b9d4f2ecdf 100644
--- a/intern/cycles/blender/blender_curves.cpp
+++ b/intern/cycles/blender/blender_curves.cpp
@@ -37,9 +37,6 @@ void curveinterp_v3_v3v3v3v3(float3 *p, float3 *v1, float3 *v2, float3 *v3, floa
void interp_weights(float t, float data[4]);
float shaperadius(float shape, float root, float tip, float time);
void InterpolateKeySegments(int seg, int segno, int key, int curve, float3 *keyloc, float *time, ParticleCurveData *CData);
-bool ObtainCacheParticleUV(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool background, int uv_num);
-bool ObtainCacheParticleVcol(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool background, int vcol_num);
-bool ObtainCacheParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool background);
void ExportCurveSegments(Scene *scene, Mesh *mesh, ParticleCurveData *CData);
void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData,
float3 RotCam, bool is_ortho);
@@ -119,220 +116,6 @@ void InterpolateKeySegments(int seg, int segno, int key, int curve, float3 *keyl
curveinterp_v3_v3v3v3v3(keyloc, &ckey_loc1, &ckey_loc2, &ckey_loc3, &ckey_loc4, t);
}
-bool ObtainCacheParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool background)
-{
- int curvenum = 0;
- int keyno = 0;
-
- if(!(mesh && b_mesh && b_ob && CData))
- return false;
-
- Transform tfm = get_transform(b_ob->matrix_world());
- Transform itfm = transform_quick_inverse(tfm);
-
- BL::Object::modifiers_iterator b_mod;
- for(b_ob->modifiers.begin(b_mod); b_mod != b_ob->modifiers.end(); ++b_mod) {
- if((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) && (background ? b_mod->show_render() : b_mod->show_viewport())) {
- BL::ParticleSystemModifier psmd((const PointerRNA)b_mod->ptr);
- BL::ParticleSystem b_psys((const PointerRNA)psmd.particle_system().ptr);
- BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr);
-
- if((b_part.render_type() == BL::ParticleSettings::render_type_PATH) && (b_part.type() == BL::ParticleSettings::type_HAIR)) {
- int shader = clamp(b_part.material()-1, 0, mesh->used_shaders.size()-1);
- int draw_step = background ? b_part.render_step() : b_part.draw_step();
- int totparts = b_psys.particles.length();
- int totchild = background ? b_psys.child_particles.length() : (int)((float)b_psys.child_particles.length() * (float)b_part.draw_percentage() / 100.0f);
- int totcurves = totchild;
-
- if(b_part.child_type() == 0 || totchild == 0)
- totcurves += totparts;
-
- if(totcurves == 0)
- continue;
-
- int ren_step = (1 << draw_step) + 1;
- if(b_part.kink() == BL::ParticleSettings::kink_SPIRAL)
- ren_step += b_part.kink_extra_steps();
-
- PointerRNA cpsys = RNA_pointer_get(&b_part.ptr, "cycles");
-
- CData->psys_firstcurve.push_back_slow(curvenum);
- CData->psys_curvenum.push_back_slow(totcurves);
- CData->psys_shader.push_back_slow(shader);
-
- float radius = get_float(cpsys, "radius_scale") * 0.5f;
-
- CData->psys_rootradius.push_back_slow(radius * get_float(cpsys, "root_width"));
- CData->psys_tipradius.push_back_slow(radius * get_float(cpsys, "tip_width"));
- CData->psys_shape.push_back_slow(get_float(cpsys, "shape"));
- CData->psys_closetip.push_back_slow(get_boolean(cpsys, "use_closetip"));
-
- int pa_no = 0;
- if(!(b_part.child_type() == 0) && totchild != 0)
- pa_no = totparts;
-
- int num_add = (totparts+totchild - pa_no);
- CData->curve_firstkey.reserve(CData->curve_firstkey.size() + num_add);
- CData->curve_keynum.reserve(CData->curve_keynum.size() + num_add);
- CData->curve_length.reserve(CData->curve_length.size() + num_add);
- CData->curvekey_co.reserve(CData->curvekey_co.size() + num_add*ren_step);
- CData->curvekey_time.reserve(CData->curvekey_time.size() + num_add*ren_step);
-
- for(; pa_no < totparts+totchild; pa_no++) {
- int keynum = 0;
- CData->curve_firstkey.push_back_slow(keyno);
-
- float curve_length = 0.0f;
- float3 pcKey;
- for(int step_no = 0; step_no < ren_step; step_no++) {
- float nco[3];
- b_psys.co_hair(*b_ob, pa_no, step_no, nco);
- float3 cKey = make_float3(nco[0], nco[1], nco[2]);
- cKey = transform_point(&itfm, cKey);
- if(step_no > 0) {
- float step_length = len(cKey - pcKey);
- if(step_length == 0.0f)
- continue;
- curve_length += step_length;
- }
- CData->curvekey_co.push_back_slow(cKey);
- CData->curvekey_time.push_back_slow(curve_length);
- pcKey = cKey;
- keynum++;
- }
- keyno += keynum;
-
- CData->curve_keynum.push_back_slow(keynum);
- CData->curve_length.push_back_slow(curve_length);
- curvenum++;
- }
- }
- }
- }
-
- return true;
-}
-
-bool ObtainCacheParticleUV(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool background, int uv_num)
-{
- if(!(mesh && b_mesh && b_ob && CData))
- return false;
-
- CData->curve_uv.clear();
-
- BL::Object::modifiers_iterator b_mod;
- for(b_ob->modifiers.begin(b_mod); b_mod != b_ob->modifiers.end(); ++b_mod) {
- if((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) && (background ? b_mod->show_render() : b_mod->show_viewport())) {
- BL::ParticleSystemModifier psmd((const PointerRNA)b_mod->ptr);
- BL::ParticleSystem b_psys((const PointerRNA)psmd.particle_system().ptr);
- BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr);
-
- if((b_part.render_type() == BL::ParticleSettings::render_type_PATH) && (b_part.type() == BL::ParticleSettings::type_HAIR)) {
- int totparts = b_psys.particles.length();
- int totchild = background ? b_psys.child_particles.length() : (int)((float)b_psys.child_particles.length() * (float)b_part.draw_percentage() / 100.0f);
- int totcurves = totchild;
-
- if(b_part.child_type() == 0 || totchild == 0)
- totcurves += totparts;
-
- if(totcurves == 0)
- continue;
-
- int pa_no = 0;
- if(!(b_part.child_type() == 0) && totchild != 0)
- pa_no = totparts;
-
- int num_add = (totparts+totchild - pa_no);
- CData->curve_uv.reserve(CData->curve_uv.size() + num_add);
-
- BL::ParticleSystem::particles_iterator b_pa;
- b_psys.particles.begin(b_pa);
- for(; pa_no < totparts+totchild; pa_no++) {
- /* Add UVs */
- BL::Mesh::tessface_uv_textures_iterator l;
- b_mesh->tessface_uv_textures.begin(l);
-
- float3 uv = make_float3(0.0f, 0.0f, 0.0f);
- if(b_mesh->tessface_uv_textures.length())
- b_psys.uv_on_emitter(psmd, *b_pa, pa_no, uv_num, &uv.x);
- CData->curve_uv.push_back_slow(uv);
-
- if(pa_no < totparts && b_pa != b_psys.particles.end())
- ++b_pa;
- }
- }
- }
- }
-
- return true;
-}
-
-bool ObtainCacheParticleVcol(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool background, int vcol_num)
-{
- if(!(mesh && b_mesh && b_ob && CData))
- return false;
-
- CData->curve_vcol.clear();
-
- BL::Object::modifiers_iterator b_mod;
- for(b_ob->modifiers.begin(b_mod); b_mod != b_ob->modifiers.end(); ++b_mod) {
- if((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) && (background ? b_mod->show_render() : b_mod->show_viewport())) {
- BL::ParticleSystemModifier psmd((const PointerRNA)b_mod->ptr);
- BL::ParticleSystem b_psys((const PointerRNA)psmd.particle_system().ptr);
- BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr);
-
- if((b_part.render_type() == BL::ParticleSettings::render_type_PATH) && (b_part.type() == BL::ParticleSettings::type_HAIR)) {
- int totparts = b_psys.particles.length();
- int totchild = background ? b_psys.child_particles.length() : (int)((float)b_psys.child_particles.length() * (float)b_part.draw_percentage() / 100.0f);
- int totcurves = totchild;
-
- if(b_part.child_type() == 0 || totchild == 0)
- totcurves += totparts;
-
- if(totcurves == 0)
- continue;
-
- int pa_no = 0;
- if(!(b_part.child_type() == 0) && totchild != 0)
- pa_no = totparts;
-
- int num_add = (totparts+totchild - pa_no);
- CData->curve_vcol.reserve(CData->curve_vcol.size() + num_add);
-
- BL::ParticleSystem::particles_iterator b_pa;
- b_psys.particles.begin(b_pa);
- for(; pa_no < totparts+totchild; pa_no++) {
- /* Add vertex colors */
- BL::Mesh::tessface_vertex_colors_iterator l;
- b_mesh->tessface_vertex_colors.begin(l);
-
- float3 vcol = make_float3(0.0f, 0.0f, 0.0f);
- if(b_mesh->tessface_vertex_colors.length())
- b_psys.mcol_on_emitter(psmd, *b_pa, pa_no, vcol_num, &vcol.x);
- CData->curve_vcol.push_back_slow(vcol);
-
- if(pa_no < totparts && b_pa != b_psys.particles.end())
- ++b_pa;
- }
- }
- }
- }
-
- return true;
-}
-
-static void set_resolution(BL::Object *b_ob, BL::Scene *scene, bool render)
-{
- BL::Object::modifiers_iterator b_mod;
- for(b_ob->modifiers.begin(b_mod); b_mod != b_ob->modifiers.end(); ++b_mod) {
- if((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) && ((b_mod->show_viewport()) || (b_mod->show_render()))) {
- BL::ParticleSystemModifier psmd((const PointerRNA)b_mod->ptr);
- BL::ParticleSystem b_psys((const PointerRNA)psmd.particle_system().ptr);
- b_psys.set_resolution(*scene, *b_ob, (render)? 2: 1);
- }
- }
-}
-
void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData,
float3 RotCam, bool is_ortho)
{
@@ -837,20 +620,6 @@ void BlenderSync::sync_curve_settings()
}
if(curve_system_manager->modified_mesh(prev_curve_system_manager)) {
- BL::BlendData::objects_iterator b_ob;
-
- for(b_data.objects.begin(b_ob); b_ob != b_data.objects.end(); ++b_ob) {
- if(object_is_mesh(*b_ob)) {
- BL::Object::particle_systems_iterator b_psys;
- for(b_ob->particle_systems.begin(b_psys); b_psys != b_ob->particle_systems.end(); ++b_psys) {
- if((b_psys->settings().render_type()==BL::ParticleSettings::render_type_PATH)&&(b_psys->settings().type()==BL::ParticleSettings::type_HAIR)) {
- BL::ID key = BKE_object_is_modified(*b_ob)? *b_ob: b_ob->data();
- mesh_map.set_recalc(key);
- object_map.set_recalc(*b_ob);
- }
- }
- }
- }
}
if(curve_system_manager->modified(prev_curve_system_manager))
@@ -875,7 +644,7 @@ void BlenderSync::sync_curves(Mesh *mesh,
/* obtain general settings */
bool use_curves = scene->curve_system_manager->use_curves;
- if(!(use_curves && b_ob.mode() != b_ob.mode_PARTICLE_EDIT)) {
+ if(!use_curves) {
if(!motion)
mesh->compute_bounds();
return;
@@ -892,11 +661,6 @@ void BlenderSync::sync_curves(Mesh *mesh,
ParticleCurveData CData;
- if(!preview)
- set_resolution(&b_ob, &b_scene, true);
-
- ObtainCacheParticleData(mesh, &b_mesh, &b_ob, &CData, !preview);
-
/* add hair geometry to mesh */
if(primitive == CURVE_TRIANGLES) {
if(triangle_method == CURVE_CAMERA_TRIANGLES) {
@@ -964,8 +728,6 @@ void BlenderSync::sync_curves(Mesh *mesh,
if(!mesh->need_attribute(scene, ustring(l->name().c_str())))
continue;
- ObtainCacheParticleVcol(mesh, &b_mesh, &b_ob, &CData, !preview, vcol_num);
-
if(primitive == CURVE_TRIANGLES) {
Attribute *attr_vcol = mesh->attributes.add(
ustring(l->name().c_str()), TypeDesc::TypeColor, ATTR_ELEMENT_CORNER_BYTE);
@@ -1005,8 +767,6 @@ void BlenderSync::sync_curves(Mesh *mesh,
if(mesh->need_attribute(scene, name) || mesh->need_attribute(scene, std)) {
Attribute *attr_uv;
- ObtainCacheParticleUV(mesh, &b_mesh, &b_ob, &CData, !preview, uv_num);
-
if(primitive == CURVE_TRIANGLES) {
if(active_render)
attr_uv = mesh->attributes.add(std, name);
@@ -1037,9 +797,6 @@ void BlenderSync::sync_curves(Mesh *mesh,
}
}
- if(!preview)
- set_resolution(&b_ob, &b_scene, false);
-
mesh->compute_bounds();
}
diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp
index f7f77dfb4cb..c8e9f3c5b89 100644
--- a/intern/cycles/blender/blender_object.cpp
+++ b/intern/cycles/blender/blender_object.cpp
@@ -465,29 +465,9 @@ static bool object_render_hide(BL::Object& b_ob,
bool parent_hide,
bool& hide_triangles)
{
- /* check if we should render or hide particle emitter */
- BL::Object::particle_systems_iterator b_psys;
-
- bool hair_present = false;
- bool show_emitter = false;
- bool hide_emitter = false;
bool hide_as_dupli_parent = false;
bool hide_as_dupli_child_original = false;
- for(b_ob.particle_systems.begin(b_psys); b_psys != b_ob.particle_systems.end(); ++b_psys) {
- if((b_psys->settings().render_type() == BL::ParticleSettings::render_type_PATH) &&
- (b_psys->settings().type()==BL::ParticleSettings::type_HAIR))
- hair_present = true;
-
- if(b_psys->settings().use_render_emitter())
- show_emitter = true;
- else
- hide_emitter = true;
- }
-
- if(show_emitter)
- hide_emitter = false;
-
/* duplicators hidden by default, except dupliframes which duplicate self */
if(b_ob.is_duplicator())
if(top_level || b_ob.dupli_type() != BL::Object::dupli_type_FRAMES)
@@ -507,17 +487,9 @@ static bool object_render_hide(BL::Object& b_ob,
parent = parent.parent();
}
- hide_triangles = hide_emitter;
+ hide_triangles = false;
- if(show_emitter) {
- return false;
- }
- else if(hair_present) {
- return hide_as_dupli_child_original;
- }
- else {
- return (hide_as_dupli_parent || hide_as_dupli_child_original);
- }
+ return (hide_as_dupli_parent || hide_as_dupli_child_original);
}
static bool object_render_hide_duplis(BL::Object& b_ob)
@@ -540,7 +512,6 @@ void BlenderSync::sync_objects(BL::SpaceView3D& b_v3d, float motion_time)
light_map.pre_sync();
mesh_map.pre_sync();
object_map.pre_sync();
- particle_system_map.pre_sync();
motion_times.clear();
}
else {
@@ -614,23 +585,16 @@ void BlenderSync::sync_objects(BL::SpaceView3D& b_v3d, float motion_time)
BL::Array<int, OBJECT_PERSISTENT_ID_SIZE> persistent_id = b_dup->persistent_id();
/* sync object and mesh or light data */
- Object *object = sync_object(b_ob,
- persistent_id.data,
- *b_dup,
- tfm,
- ob_layer,
- motion_time,
- hide_tris,
- use_camera_cull,
- camera_cull_margin,
- &use_portal);
-
- /* sync possible particle data, note particle_id
- * starts counting at 1, first is dummy particle */
- if(!motion && object) {
- sync_dupli_particle(b_ob, *b_dup, object);
- }
-
+ sync_object(b_ob,
+ persistent_id.data,
+ *b_dup,
+ tfm,
+ ob_layer,
+ motion_time,
+ hide_tris,
+ use_camera_cull,
+ camera_cull_margin,
+ &use_portal);
}
}
@@ -673,8 +637,6 @@ void BlenderSync::sync_objects(BL::SpaceView3D& b_v3d, float motion_time)
scene->mesh_manager->tag_update(scene);
if(object_map.post_sync())
scene->object_manager->tag_update(scene);
- if(particle_system_map.post_sync())
- scene->particle_system_manager->tag_update(scene);
}
if(motion)
diff --git a/intern/cycles/blender/blender_particles.cpp b/intern/cycles/blender/blender_particles.cpp
deleted file mode 100644
index dd2900a8d5b..00000000000
--- a/intern/cycles/blender/blender_particles.cpp
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright 2011-2013 Blender Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "mesh.h"
-#include "object.h"
-#include "particles.h"
-
-#include "blender_sync.h"
-#include "blender_util.h"
-
-#include "util_foreach.h"
-
-CCL_NAMESPACE_BEGIN
-
-/* Utilities */
-
-bool BlenderSync::sync_dupli_particle(BL::Object& b_ob,
- BL::DupliObject& b_dup,
- Object *object)
-{
- /* test if this dupli was generated from a particle sytem */
- BL::ParticleSystem b_psys = b_dup.particle_system();
- if(!b_psys)
- return false;
-
- object->hide_on_missing_motion = true;
-
- /* test if we need particle data */
- if(!object->mesh->need_attribute(scene, ATTR_STD_PARTICLE))
- return false;
-
- /* don't handle child particles yet */
- BL::Array<int, OBJECT_PERSISTENT_ID_SIZE> persistent_id = b_dup.persistent_id();
-
- if(persistent_id[0] >= b_psys.particles.length())
- return false;
-
- /* find particle system */
- ParticleSystemKey key(b_ob, persistent_id);
- ParticleSystem *psys;
-
- bool first_use = !particle_system_map.is_used(key);
- bool need_update = particle_system_map.sync(&psys, b_ob, b_dup.object(), key);
-
- /* no update needed? */
- if(!need_update && !object->mesh->need_update && !scene->object_manager->need_update)
- return true;
-
- /* first time used in this sync loop? clear and tag update */
- if(first_use) {
- psys->particles.clear();
- psys->tag_update(scene);
- }
-
- /* add particle */
- BL::Particle b_pa = b_psys.particles[persistent_id[0]];
- Particle pa;
-
- pa.index = persistent_id[0];
- pa.age = b_scene.frame_current() - b_pa.birth_time();
- pa.lifetime = b_pa.lifetime();
- pa.location = get_float3(b_pa.location());
- pa.rotation = get_float4(b_pa.rotation());
- pa.size = b_pa.size();
- pa.velocity = get_float3(b_pa.velocity());
- pa.angular_velocity = get_float3(b_pa.angular_velocity());
-
- psys->particles.push_back_slow(pa);
-
- if(object->particle_index != psys->particles.size() - 1)
- scene->object_manager->tag_update(scene);
- object->particle_system = psys;
- object->particle_index = psys->particles.size() - 1;
-
- /* return that this object has particle data */
- return true;
-}
-
-CCL_NAMESPACE_END
diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp
index 4ca202ac40d..e77cc122cc5 100644
--- a/intern/cycles/blender/blender_sync.cpp
+++ b/intern/cycles/blender/blender_sync.cpp
@@ -56,7 +56,6 @@ BlenderSync::BlenderSync(BL::RenderEngine& b_engine,
object_map(&scene->objects),
mesh_map(&scene->meshes),
light_map(&scene->lights),
- particle_system_map(&scene->particle_systems),
world_map(NULL),
world_recalc(false),
scene(scene),
@@ -144,12 +143,6 @@ bool BlenderSync::sync_recalc()
if(b_ob->is_updated_data() || b_ob->data().is_updated())
light_map.set_recalc(*b_ob);
}
-
- if(b_ob->is_updated_data()) {
- BL::Object::particle_systems_iterator b_psys;
- for(b_ob->particle_systems.begin(b_psys); b_psys != b_ob->particle_systems.end(); ++b_psys)
- particle_system_map.set_recalc(*b_ob);
- }
}
BL::BlendData::meshes_iterator b_mesh;
@@ -183,7 +176,6 @@ bool BlenderSync::sync_recalc()
object_map.has_recalc() ||
light_map.has_recalc() ||
mesh_map.has_recalc() ||
- particle_system_map.has_recalc() ||
BlendDataObjects_is_updated_get(&b_data.ptr) ||
world_recalc;
diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h
index b8b9597914e..8caa8070939 100644
--- a/intern/cycles/blender/blender_sync.h
+++ b/intern/cycles/blender/blender_sync.h
@@ -139,11 +139,6 @@ private:
int width, int height,
float motion_time);
- /* particles */
- bool sync_dupli_particle(BL::Object& b_ob,
- BL::DupliObject& b_dup,
- Object *object);
-
/* Images. */
void sync_images();
@@ -162,7 +157,6 @@ private:
id_map<ObjectKey, Object> object_map;
id_map<void*, Mesh> mesh_map;
id_map<ObjectKey, Light> light_map;
- id_map<ParticleSystemKey, ParticleSystem> particle_system_map;
set<Mesh*> mesh_synced;
set<Mesh*> mesh_motion_synced;
std::set<float> motion_times;
diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h
index f17a61f0ac8..ba696a83867 100644
--- a/intern/cycles/blender/blender_util.h
+++ b/intern/cycles/blender/blender_util.h
@@ -754,33 +754,6 @@ struct ObjectKey {
}
};
-/* Particle System Key */
-
-struct ParticleSystemKey {
- void *ob;
- int id[OBJECT_PERSISTENT_ID_SIZE];
-
- ParticleSystemKey(void *ob_, int id_[OBJECT_PERSISTENT_ID_SIZE])
- : ob(ob_)
- {
- if(id_)
- memcpy(id, id_, sizeof(id));
- else
- memset(id, 0, sizeof(id));
- }
-
- bool operator<(const ParticleSystemKey& k) const
- {
- /* first id is particle index, we don't compare that */
- if(ob < k.ob)
- return true;
- else if(ob == k.ob)
- return memcmp(id+1, k.id+1, sizeof(int)*(OBJECT_PERSISTENT_ID_SIZE-1)) < 0;
-
- return false;
- }
-};
-
CCL_NAMESPACE_END
#endif /* __BLENDER_UTIL_H__ */
diff --git a/intern/elbeem/extern/elbeem.h b/intern/elbeem/extern/elbeem.h
index bd50b6f08dc..3a4c18ab189 100644
--- a/intern/elbeem/extern/elbeem.h
+++ b/intern/elbeem/extern/elbeem.h
@@ -111,7 +111,7 @@ typedef struct elbeemSimulationSettings {
#define OB_FLUIDSIM_OBSTACLE 8
#define OB_FLUIDSIM_INFLOW 16
#define OB_FLUIDSIM_OUTFLOW 32
-#define OB_FLUIDSIM_PARTICLE 64
+#define OB_FLUIDSIM_PARTICLE 64 /* DEPRECATED */
#define OB_FLUIDSIM_CONTROL 128
// defines for elbeemMesh->obstacleType below (low bits) high bits (>=64) are reserved for mFsSurfGenSetting flags which are defined in solver_class.h
diff --git a/intern/ghost/intern/GHOST_ContextCGL.h b/intern/ghost/intern/GHOST_ContextCGL.h
index dd49b81b561..8186eaa759d 100644
--- a/intern/ghost/intern/GHOST_ContextCGL.h
+++ b/intern/ghost/intern/GHOST_ContextCGL.h
@@ -134,6 +134,8 @@ private:
/** The OpenGL drawing context */
NSOpenGLContext *m_openGLContext;
+ bool m_coreProfile;
+
//static CGLEWContext *s_cglewContext;
const bool m_debug;
diff --git a/intern/ghost/intern/GHOST_ContextCGL.mm b/intern/ghost/intern/GHOST_ContextCGL.mm
index 03c45f9945b..64db70197bb 100644
--- a/intern/ghost/intern/GHOST_ContextCGL.mm
+++ b/intern/ghost/intern/GHOST_ContextCGL.mm
@@ -63,6 +63,23 @@ GHOST_ContextCGL::GHOST_ContextCGL(
m_debug(contextFlags)
{
assert(openGLView != nil);
+
+ // for now be very strict about OpenGL version requested
+ switch (contextMajorVersion) {
+ case 2:
+ assert(contextMinorVersion == 1);
+ assert(contextProfileMask == 0);
+ m_coreProfile = false;
+ break;
+ case 3:
+ // Apple didn't implement 3.0 or 3.1
+ assert(contextMinorVersion == 2);
+ assert(contextProfileMask == GL_CONTEXT_CORE_PROFILE_BIT);
+ m_coreProfile = true;
+ break;
+ default:
+ assert(false);
+ }
}
@@ -170,6 +187,7 @@ GHOST_TSuccess GHOST_ContextCGL::updateDrawingContext()
static void makeAttribList(
std::vector<NSOpenGLPixelFormatAttribute>& attribs,
+ bool coreProfile,
bool stereoVisual,
int numOfAASamples,
bool needAlpha,
@@ -178,6 +196,9 @@ static void makeAttribList(
{
attribs.clear();
+ attribs.push_back(NSOpenGLPFAOpenGLProfile);
+ attribs.push_back(coreProfile ? NSOpenGLProfileVersion3_2Core : NSOpenGLProfileVersionLegacy);
+
// Pixel Format Attributes for the windowed NSOpenGLContext
attribs.push_back(NSOpenGLPFADoubleBuffer);
@@ -190,8 +211,7 @@ static void makeAttribList(
attribs.push_back(NSOpenGLPFANoRecovery);
}
- /* Removed to allow 10.4 builds, and 2 GPUs rendering is not used anyway */
- //attribs.push_back(NSOpenGLPFAAllowOfflineRenderers);
+ attribs.push_back(NSOpenGLPFAAllowOfflineRenderers); // for automatic GPU switching
attribs.push_back(NSOpenGLPFADepthSize);
attribs.push_back((NSOpenGLPixelFormatAttribute) 32);
@@ -263,7 +283,7 @@ GHOST_TSuccess GHOST_ContextCGL::initializeDrawingContext()
NSOpenGLPixelFormat *pixelFormat;
// TODO: keep pixel format for subsequent windows/contexts instead of recreating each time
- makeAttribList(attribs, m_stereoVisual, m_numOfAASamples, needAlpha, needStencil, softwareGL);
+ makeAttribList(attribs, m_coreProfile, m_stereoVisual, m_numOfAASamples, needAlpha, needStencil, softwareGL);
pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:&attribs[0]];
@@ -274,7 +294,7 @@ GHOST_TSuccess GHOST_ContextCGL::initializeDrawingContext()
// (Now that I think about it, does WGL really require the code that it has for finding a lesser match?)
attribs.clear();
- makeAttribList(attribs, m_stereoVisual, 0, needAlpha, needStencil, softwareGL);
+ makeAttribList(attribs, m_coreProfile, m_stereoVisual, 0, needAlpha, needStencil, softwareGL);
pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:&attribs[0]];
}
@@ -316,7 +336,7 @@ GHOST_TSuccess GHOST_ContextCGL::initializeDrawingContext()
[m_openGLContext release];
// create software GL context
- makeAttribList(attribs, m_stereoVisual, m_numOfAASamples, needAlpha, needStencil, softwareGL);
+ makeAttribList(attribs, m_coreProfile, m_stereoVisual, m_numOfAASamples, needAlpha, needStencil, softwareGL);
pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:&attribs[0]];
m_openGLContext = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:s_sharedOpenGLContext];
[pixelFormat release];
diff --git a/intern/ghost/intern/GHOST_ContextGLX.cpp b/intern/ghost/intern/GHOST_ContextGLX.cpp
index 9ac61db4041..60cdce83602 100644
--- a/intern/ghost/intern/GHOST_ContextGLX.cpp
+++ b/intern/ghost/intern/GHOST_ContextGLX.cpp
@@ -255,9 +255,6 @@ const bool GLXEW_ARB_create_context_robustness =
if (m_contextMajorVersion != 0) {
attribs[i++] = GLX_CONTEXT_MAJOR_VERSION_ARB;
attribs[i++] = m_contextMajorVersion;
- }
-
- if (m_contextMinorVersion != 0) {
attribs[i++] = GLX_CONTEXT_MINOR_VERSION_ARB;
attribs[i++] = m_contextMinorVersion;
}
@@ -300,8 +297,8 @@ const bool GLXEW_ARB_create_context_robustness =
}
}
else {
- /* Create legacy context */
- m_context = glXCreateContext(m_display, m_visualInfo, s_sharedContext, True);
+ /* Don't create legacy context */
+ fprintf(stderr, "Warning! GLX_ARB_create_context not available.\n");
}
GHOST_TSuccess success;
@@ -328,8 +325,14 @@ const bool GLXEW_ARB_create_context_robustness =
version = glGetString(GL_VERSION);
- if (!version || version[0] < '2' || ((version[0] == '2') && (version[2] < '1'))) {
- fprintf(stderr, "Error! Blender requires OpenGL 2.1 to run. Try updating your drivers.\n");
+#if 0 // enable this when Blender switches to 3.3 core profile
+ if (!version || version[0] < '3' || ((version[0] == '3') && (version[2] < '3'))) {
+ fprintf(stderr, "Error! Blender requires OpenGL 3.3 to run. Try updating your drivers.\n");
+#else
+ // with Mesa, the closest thing to 3.3 compatibility profile is 3.0
+ if (!version || version[0] < '3') {
+ fprintf(stderr, "Error! Blender requires OpenGL 3.0 (soon 3.3) to run. Try updating your drivers.\n");
+#endif
fflush(stderr);
/* ugly, but we get crashes unless a whole bunch of systems are patched. */
exit(0);
diff --git a/intern/ghost/intern/GHOST_ContextWGL.cpp b/intern/ghost/intern/GHOST_ContextWGL.cpp
index 64ee692797b..39ef63fa723 100644
--- a/intern/ghost/intern/GHOST_ContextWGL.cpp
+++ b/intern/ghost/intern/GHOST_ContextWGL.cpp
@@ -962,7 +962,7 @@ GHOST_TSuccess GHOST_ContextWGL::initializeDrawingContext()
strcmp(renderer, "GDI Generic") == 0) && version[0] == '1' && version[2] == '1')
{
MessageBox(m_hWnd, "Your system does not use 3D hardware acceleration.\n"
- "Blender requires a graphics driver with OpenGL 2.1 support.\n\n"
+ "Blender requires a graphics driver with OpenGL 3.3 support.\n\n"
"This may be caused by:\n"
"* A missing or faulty graphics driver installation.\n"
" Blender needs a graphics card driver to work correctly.\n"
@@ -973,8 +973,8 @@ GHOST_TSuccess GHOST_ContextWGL::initializeDrawingContext()
MB_OK | MB_ICONERROR);
exit(0);
}
- else if (version[0] < '2' || (version[0] == '2' && version[2] < '1')) {
- MessageBox(m_hWnd, "Blender requires a graphics driver with OpenGL 2.1 support.\n\n"
+ else if (version[0] < '3' || (version[0] == '3' && version[2] < '3')) {
+ MessageBox(m_hWnd, "Blender requires a graphics driver with OpenGL 3.3 support.\n\n"
"The program will now close.",
"Blender - Unsupported Graphics Driver!",
MB_OK | MB_ICONERROR);
diff --git a/intern/ghost/intern/GHOST_ContextWGL.h b/intern/ghost/intern/GHOST_ContextWGL.h
index 580b4dcb82f..99efcc5ebd7 100644
--- a/intern/ghost/intern/GHOST_ContextWGL.h
+++ b/intern/ghost/intern/GHOST_ContextWGL.h
@@ -46,14 +46,6 @@
extern "C" WGLEWContext *wglewContext;
#endif
-#ifndef GHOST_OPENGL_WGL_CONTEXT_FLAGS
-# ifdef WITH_GPU_DEBUG
-# define GHOST_OPENGL_WGL_CONTEXT_FLAGS WGL_CONTEXT_DEBUG_BIT_ARB
-# else
-# define GHOST_OPENGL_WGL_CONTEXT_FLAGS 0
-# endif
-#endif
-
#ifndef GHOST_OPENGL_WGL_RESET_NOTIFICATION_STRATEGY
#define GHOST_OPENGL_WGL_RESET_NOTIFICATION_STRATEGY 0
#endif
diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm
index 97615dcea96..b0feb11a6af 100644
--- a/intern/ghost/intern/GHOST_WindowCocoa.mm
+++ b/intern/ghost/intern/GHOST_WindowCocoa.mm
@@ -1086,82 +1086,23 @@ GHOST_TSuccess GHOST_WindowCocoa::setOrder(GHOST_TWindowOrder order)
GHOST_Context *GHOST_WindowCocoa::newDrawingContext(GHOST_TDrawingContextType type)
{
if (type == GHOST_kDrawingContextTypeOpenGL) {
-#if !defined(WITH_GL_EGL)
-#if defined(WITH_GL_PROFILE_CORE)
- GHOST_Context *context = new GHOST_ContextCGL(
- m_wantStereoVisual,
- m_wantNumOfAASamples,
- m_window,
- m_openGLView,
- GL_CONTEXT_CORE_PROFILE_BIT,
- 3, 2,
- GHOST_OPENGL_CGL_CONTEXT_FLAGS,
- GHOST_OPENGL_CGL_RESET_NOTIFICATION_STRATEGY);
-#elif defined(WITH_GL_PROFILE_ES20)
GHOST_Context *context = new GHOST_ContextCGL(
m_wantStereoVisual,
m_wantNumOfAASamples,
m_window,
m_openGLView,
- CGL_CONTEXT_ES2_PROFILE_BIT_EXT,
- 2, 0,
- GHOST_OPENGL_CGL_CONTEXT_FLAGS,
- GHOST_OPENGL_CGL_RESET_NOTIFICATION_STRATEGY);
-#elif defined(WITH_GL_PROFILE_COMPAT)
- GHOST_Context *context = new GHOST_ContextCGL(
- m_wantStereoVisual,
- m_wantNumOfAASamples,
- m_window,
- m_openGLView,
- 0, // profile bit
- 0, 0,
- m_debug_context,
- GHOST_OPENGL_CGL_RESET_NOTIFICATION_STRATEGY);
-#else
-# error
-#endif
-
-#else
#if defined(WITH_GL_PROFILE_CORE)
- GHOST_Context *context = new GHOST_ContextEGL(
- m_wantStereoVisual,
- m_wantNumOfAASamples,
- m_window,
- m_openGLView,
- EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
+ GL_CONTEXT_CORE_PROFILE_BIT,
3, 2,
- GHOST_OPENGL_EGL_CONTEXT_FLAGS,
- GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
- EGL_OPENGL_API);
-#elif defined(WITH_GL_PROFILE_ES20)
- GHOST_Context *context = new GHOST_ContextEGL(
- m_wantStereoVisual,
- m_wantNumOfAASamples,
- m_window,
- m_openGLView,
- 0, // profile bit
- 2, 0,
- GHOST_OPENGL_EGL_CONTEXT_FLAGS,
- GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
- EGL_OPENGL_ES_API);
-#elif defined(WITH_GL_PROFILE_COMPAT)
- GHOST_Context *context = new GHOST_ContextEGL(
- m_wantStereoVisual,
- m_wantNumOfAASamples,
- m_window,
- m_openGLView,
- 0, // profile bit
- 0, 0,
- GHOST_OPENGL_EGL_CONTEXT_FLAGS,
- GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
- EGL_OPENGL_API);
#else
-# error
+ 0, // no profile bit
+ 2, 1,
#endif
+ GHOST_OPENGL_CGL_CONTEXT_FLAGS,
+ GHOST_OPENGL_CGL_RESET_NOTIFICATION_STRATEGY);
-#endif
if (context->initializeDrawingContext())
return context;
else
diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp
index 2aa950f8278..1f49adecdef 100644
--- a/intern/ghost/intern/GHOST_WindowWin32.cpp
+++ b/intern/ghost/intern/GHOST_WindowWin32.cpp
@@ -610,97 +610,37 @@ GHOST_TSuccess GHOST_WindowWin32::invalidate()
GHOST_Context *GHOST_WindowWin32::newDrawingContext(GHOST_TDrawingContextType type)
{
if (type == GHOST_kDrawingContextTypeOpenGL) {
-#if !defined(WITH_GL_EGL)
+ const int profile_mask =
#if defined(WITH_GL_PROFILE_CORE)
- GHOST_Context *context = new GHOST_ContextWGL(
- m_wantStereoVisual,
- m_wantAlphaBackground,
- m_wantNumOfAASamples,
- m_hWnd,
- m_hDC,
- WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
- 3, 2,
- GHOST_OPENGL_WGL_CONTEXT_FLAGS,
- GHOST_OPENGL_WGL_RESET_NOTIFICATION_STRATEGY);
-#elif defined(WITH_GL_PROFILE_ES20)
- GHOST_Context *context = new GHOST_ContextWGL(
- m_wantStereoVisual,
- m_wantAlphaBackground,
- m_wantNumOfAASamples,
- m_hWnd,
- m_hDC,
- WGL_CONTEXT_ES2_PROFILE_BIT_EXT,
- 2, 0,
- GHOST_OPENGL_WGL_CONTEXT_FLAGS,
- GHOST_OPENGL_WGL_RESET_NOTIFICATION_STRATEGY);
+ WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
#elif defined(WITH_GL_PROFILE_COMPAT)
+ WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
+#else
+# error // must specify either core or compat at build time
+#endif
+
GHOST_Context *context = new GHOST_ContextWGL(
m_wantStereoVisual,
m_wantAlphaBackground,
m_wantNumOfAASamples,
m_hWnd,
m_hDC,
-#if 1
- 0, // profile bit
- 2, 1, // GL version requested
+ profile_mask,
+#if 0
+ 3, 3, // specific GL version requested
+ // AMD gives us exactly this version
+ // NVIDIA gives at least this version <-- desired behavior
#else
- // switch to this for Blender 2.8 development
- WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
- 3, 2,
+ 2, 1, // any GL version >= 2.1 (hopefully the latest)
+ // we check later to ensure it's >= 3.3 on Windows
+ // TODO(merwin): fix properly!
+ // 2.1 ignores the profile bit & is incompatible with core profile
+ // query version of initial dummy context, request that + profile + debug
#endif
(m_debug_context ? WGL_CONTEXT_DEBUG_BIT_ARB : 0),
GHOST_OPENGL_WGL_RESET_NOTIFICATION_STRATEGY);
-#else
-# error
-#endif
-
-#else
-#if defined(WITH_GL_PROFILE_CORE)
- GHOST_Context *context = new GHOST_ContextEGL(
- m_wantStereoVisual,
- m_wantNumOfAASamples,
- m_hWnd,
- m_hDC,
- EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
- 3, 2,
- GHOST_OPENGL_EGL_CONTEXT_FLAGS,
- GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
- EGL_OPENGL_API);
-#elif defined(WITH_GL_PROFILE_ES20)
- GHOST_Context *context = new GHOST_ContextEGL(
- m_wantStereoVisual,
- m_wantNumOfAASamples,
- m_hWnd,
- m_hDC,
- 0, // profile bit
- 2, 0,
- GHOST_OPENGL_EGL_CONTEXT_FLAGS,
- GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
- EGL_OPENGL_ES_API);
-#elif defined(WITH_GL_PROFILE_COMPAT)
- GHOST_Context *context = new GHOST_ContextEGL(
- m_wantStereoVisual,
- m_wantNumOfAASamples,
- m_hWnd,
- m_hDC,
-#if 1
- 0, // profile bit
- 2, 1, // GL version requested
-#else
- // switch to this for Blender 2.8 development
- EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT,
- 3, 2,
-#endif
- GHOST_OPENGL_EGL_CONTEXT_FLAGS,
- GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
- EGL_OPENGL_API);
-#else
-# error
-#endif
-
-#endif
if (context->initializeDrawingContext())
return context;
else
diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp
index ec2b65e67d0..a02117d517e 100644
--- a/intern/ghost/intern/GHOST_WindowX11.cpp
+++ b/intern/ghost/intern/GHOST_WindowX11.cpp
@@ -1306,33 +1306,24 @@ GHOST_WindowX11::
GHOST_Context *GHOST_WindowX11::newDrawingContext(GHOST_TDrawingContextType type)
{
if (type == GHOST_kDrawingContextTypeOpenGL) {
-#if !defined(WITH_GL_EGL)
+ // During development:
+ // try 3.3 compatibility profile
+ // fall back to 3.0 if needed
+ //
+ // Final Blender 2.8:
+ // try 3.3 core profile
+ // no fallbacks
+
+ const int profile_mask =
#if defined(WITH_GL_PROFILE_CORE)
- GHOST_Context *context = new GHOST_ContextGLX(
- m_wantStereoVisual,
- m_wantNumOfAASamples,
- m_window,
- m_display,
- m_visualInfo,
- (GLXFBConfig)m_fbconfig,
- GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
- 3, 2,
- GHOST_OPENGL_GLX_CONTEXT_FLAGS | (m_is_debug_context ? GLX_CONTEXT_DEBUG_BIT_ARB : 0),
- GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY);
-#elif defined(WITH_GL_PROFILE_ES20)
- GHOST_Context *context = new GHOST_ContextGLX(
- m_wantStereoVisual,
- m_wantNumOfAASamples,
- m_window,
- m_display,
- m_visualInfo,
- (GLXFBConfig)m_fbconfig,
- GLX_CONTEXT_ES2_PROFILE_BIT_EXT,
- 2, 0,
- GHOST_OPENGL_GLX_CONTEXT_FLAGS | (m_is_debug_context ? GLX_CONTEXT_DEBUG_BIT_ARB : 0),
- GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY);
+ GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
#elif defined(WITH_GL_PROFILE_COMPAT)
+ GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
+#else
+# error // must specify either core or compat at build time
+#endif
+
GHOST_Context *context = new GHOST_ContextGLX(
m_wantStereoVisual,
m_wantNumOfAASamples,
@@ -1340,58 +1331,34 @@ GHOST_Context *GHOST_WindowX11::newDrawingContext(GHOST_TDrawingContextType type
m_display,
m_visualInfo,
(GLXFBConfig)m_fbconfig,
- 0, // profile bit
- 0, 0,
+ profile_mask,
+ 3, 3,
GHOST_OPENGL_GLX_CONTEXT_FLAGS | (m_is_debug_context ? GLX_CONTEXT_DEBUG_BIT_ARB : 0),
GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY);
-#else
-# error
-#endif
-#else
-
-#if defined(WITH_GL_PROFILE_CORE)
- GHOST_Context *context = new GHOST_ContextEGL(
- m_wantStereoVisual,
- m_wantNumOfAASamples,
- m_window,
- m_display,
- EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
- 3, 2,
- GHOST_OPENGL_EGL_CONTEXT_FLAGS,
- GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
- EGL_OPENGL_API);
-#elif defined(WITH_GL_PROFILE_ES20)
- GHOST_Context *context = new GHOST_ContextEGL(
- m_wantStereoVisual,
- m_wantNumOfAASamples,
- m_window,
- m_display,
- 0, // profile bit
- 2, 0,
- GHOST_OPENGL_EGL_CONTEXT_FLAGS,
- GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
- EGL_OPENGL_ES_API);
-#elif defined(WITH_GL_PROFILE_COMPAT)
- GHOST_Context *context = new GHOST_ContextEGL(
- m_wantStereoVisual,
- m_wantNumOfAASamples,
- m_window,
- m_display,
- 0, // profile bit
- 0, 0,
- GHOST_OPENGL_EGL_CONTEXT_FLAGS,
- GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
- EGL_OPENGL_API);
-#else
-# error
-#endif
-
-#endif
if (context->initializeDrawingContext())
return context;
- else
+ else {
delete context;
+
+ // since that failed try 3.0 (mostly for Mesa, which doesn't implement compatibility profile)
+ context = new GHOST_ContextGLX(
+ m_wantStereoVisual,
+ m_wantNumOfAASamples,
+ m_window,
+ m_display,
+ m_visualInfo,
+ (GLXFBConfig)m_fbconfig,
+ 0, // no profile bit
+ 3, 0,
+ GHOST_OPENGL_GLX_CONTEXT_FLAGS | (m_is_debug_context ? GLX_CONTEXT_DEBUG_BIT_ARB : 0),
+ GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY);
+
+ if (context->initializeDrawingContext())
+ return context;
+ else
+ delete context;
+ }
}
return NULL;
diff --git a/release/darwin/blender.app/Contents/Info.plist b/release/darwin/blender.app/Contents/Info.plist
index 0649a2075cd..36cb5d2ccaf 100644
--- a/release/darwin/blender.app/Contents/Info.plist
+++ b/release/darwin/blender.app/Contents/Info.plist
@@ -2,6 +2,8 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
+ <key>LSMinimumSystemVersion</key>
+ <string>10.7.0</string>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
@@ -47,5 +49,7 @@
<string>NSApplication</string>
<key>NSHighResolutionCapable</key>
<true/>
+ <key>NSSupportsAutomaticGraphicsSwitching</key>
+ <true/>
</dict>
</plist>
diff --git a/release/scripts/presets/hair_dynamics/default.py b/release/scripts/presets/hair_dynamics/default.py
deleted file mode 100644
index 830d28a76f0..00000000000
--- a/release/scripts/presets/hair_dynamics/default.py
+++ /dev/null
@@ -1,17 +0,0 @@
-import bpy
-psys = bpy.context.particle_system
-cloth = bpy.context.particle_system.cloth
-settings = bpy.context.particle_system.cloth.settings
-collision = bpy.context.particle_system.cloth.collision_settings
-
-settings.quality = 5
-settings.mass = 0.30000001192092896
-settings.bending_stiffness = 0.5
-psys.settings.bending_random = 0.0
-settings.bending_damping = 0.5
-settings.air_damping = 1.0
-settings.internal_friction = 0.0
-settings.density_target = 0.0
-settings.density_strength = 0.0
-settings.voxel_cell_size = 0.10000000149011612
-settings.pin_stiffness = 0.0
diff --git a/release/scripts/startup/bl_operators/object_quick_effects.py b/release/scripts/startup/bl_operators/object_quick_effects.py
index 414855c7e35..39a0ad31625 100644
--- a/release/scripts/startup/bl_operators/object_quick_effects.py
+++ b/release/scripts/startup/bl_operators/object_quick_effects.py
@@ -47,239 +47,6 @@ def object_ensure_material(obj, mat_name):
return mat
-class QuickFur(Operator):
- bl_idname = "object.quick_fur"
- bl_label = "Quick Fur"
- bl_options = {'REGISTER', 'UNDO'}
-
- density = EnumProperty(
- name="Fur Density",
- items=(('LIGHT', "Light", ""),
- ('MEDIUM', "Medium", ""),
- ('HEAVY', "Heavy", "")),
- default='MEDIUM',
- )
- view_percentage = IntProperty(
- name="View %",
- min=1, max=100,
- soft_min=1, soft_max=100,
- default=10,
- )
- length = FloatProperty(
- name="Length",
- min=0.001, max=100,
- soft_min=0.01, soft_max=10,
- default=0.1,
- )
-
- def execute(self, context):
- fake_context = context.copy()
- mesh_objects = [obj for obj in context.selected_objects
- if obj.type == 'MESH' and obj.mode == 'OBJECT']
-
- if not mesh_objects:
- self.report({'ERROR'}, "Select at least one mesh object")
- return {'CANCELLED'}
-
- mat = bpy.data.materials.new("Fur Material")
- mat.strand.tip_size = 0.25
- mat.strand.blend_distance = 0.5
-
- for obj in mesh_objects:
- fake_context["object"] = obj
- bpy.ops.object.particle_system_add(fake_context)
-
- psys = obj.particle_systems[-1]
- psys.settings.type = 'HAIR'
-
- if self.density == 'LIGHT':
- psys.settings.count = 100
- elif self.density == 'MEDIUM':
- psys.settings.count = 1000
- elif self.density == 'HEAVY':
- psys.settings.count = 10000
-
- psys.settings.child_nbr = self.view_percentage
- psys.settings.hair_length = self.length
- psys.settings.use_strand_primitive = True
- psys.settings.use_hair_bspline = True
- psys.settings.child_type = 'INTERPOLATED'
-
- obj.data.materials.append(mat)
- psys.settings.material = len(obj.data.materials)
-
- return {'FINISHED'}
-
-
-class QuickExplode(Operator):
- bl_idname = "object.quick_explode"
- bl_label = "Quick Explode"
- bl_options = {'REGISTER', 'UNDO'}
-
- style = EnumProperty(
- name="Explode Style",
- items=(('EXPLODE', "Explode", ""),
- ('BLEND', "Blend", "")),
- default='EXPLODE',
- )
- amount = IntProperty(
- name="Amount of pieces",
- min=2, max=10000,
- soft_min=2, soft_max=10000,
- default=100,
- )
- frame_duration = IntProperty(
- name="Duration",
- min=1, max=300000,
- soft_min=1, soft_max=10000,
- default=50,
- )
-
- frame_start = IntProperty(
- name="Start Frame",
- min=1, max=300000,
- soft_min=1, soft_max=10000,
- default=1,
- )
- frame_end = IntProperty(
- name="End Frame",
- min=1, max=300000,
- soft_min=1, soft_max=10000,
- default=10,
- )
-
- velocity = FloatProperty(
- name="Outwards Velocity",
- min=0, max=300000,
- soft_min=0, soft_max=10,
- default=1,
- )
-
- fade = BoolProperty(
- name="Fade",
- description="Fade the pieces over time",
- default=True,
- )
-
- def execute(self, context):
- fake_context = context.copy()
- obj_act = context.active_object
-
- if obj_act is None or obj_act.type != 'MESH':
- self.report({'ERROR'}, "Active object is not a mesh")
- return {'CANCELLED'}
-
- mesh_objects = [obj for obj in context.selected_objects
- if obj.type == 'MESH' and obj != obj_act]
- mesh_objects.insert(0, obj_act)
-
- if self.style == 'BLEND' and len(mesh_objects) != 2:
- self.report({'ERROR'}, "Select two mesh objects")
- self.style = 'EXPLODE'
- return {'CANCELLED'}
- elif not mesh_objects:
- self.report({'ERROR'}, "Select at least one mesh object")
- return {'CANCELLED'}
-
- for obj in mesh_objects:
- if obj.particle_systems:
- self.report({'ERROR'},
- "Object %r already has a "
- "particle system" % obj.name)
-
- return {'CANCELLED'}
-
- if self.fade:
- tex = bpy.data.textures.new("Explode fade", 'BLEND')
- tex.use_color_ramp = True
-
- if self.style == 'BLEND':
- tex.color_ramp.elements[0].position = 0.333
- tex.color_ramp.elements[1].position = 0.666
-
- tex.color_ramp.elements[0].color[3] = 1.0
- tex.color_ramp.elements[1].color[3] = 0.0
-
- if self.style == 'BLEND':
- from_obj = mesh_objects[1]
- to_obj = mesh_objects[0]
-
- for obj in mesh_objects:
- fake_context["object"] = obj
- bpy.ops.object.particle_system_add(fake_context)
-
- settings = obj.particle_systems[-1].settings
- settings.count = self.amount
- settings.frame_start = self.frame_start
- settings.frame_end = self.frame_end - self.frame_duration
- settings.lifetime = self.frame_duration
- settings.normal_factor = self.velocity
- settings.render_type = 'NONE'
-
- explode = obj.modifiers.new(name='Explode', type='EXPLODE')
- explode.use_edge_cut = True
-
- if self.fade:
- explode.show_dead = False
- uv = obj.data.uv_textures.new("Explode fade")
- explode.particle_uv = uv.name
-
- mat = object_ensure_material(obj, "Explode Fade")
-
- mat.use_transparency = True
- mat.use_transparent_shadows = True
- mat.alpha = 0.0
- mat.specular_alpha = 0.0
-
- tex_slot = mat.texture_slots.add()
-
- tex_slot.texture = tex
- tex_slot.texture_coords = 'UV'
- tex_slot.uv_layer = uv.name
-
- tex_slot.use_map_alpha = True
-
- if self.style == 'BLEND':
- if obj == to_obj:
- tex_slot.alpha_factor = -1.0
- elem = tex.color_ramp.elements[1]
- else:
- elem = tex.color_ramp.elements[0]
- # Keep already defined alpha!
- elem.color[:3] = mat.diffuse_color
- else:
- tex_slot.use_map_color_diffuse = False
-
- if self.style == 'BLEND':
- settings.physics_type = 'KEYED'
- settings.use_emit_random = False
- settings.rotation_mode = 'NOR'
-
- psys = obj.particle_systems[-1]
-
- fake_context["particle_system"] = obj.particle_systems[-1]
- bpy.ops.particle.new_target(fake_context)
- bpy.ops.particle.new_target(fake_context)
-
- if obj == from_obj:
- psys.targets[1].object = to_obj
- else:
- psys.targets[0].object = from_obj
- settings.normal_factor = -self.velocity
- explode.show_unborn = False
- explode.show_dead = True
- else:
- settings.factor_random = self.velocity
- settings.angular_velocity_factor = self.velocity / 10.0
-
- return {'FINISHED'}
-
- def invoke(self, context, event):
- self.frame_start = context.scene.frame_current
- self.frame_end = self.frame_start + self.frame_duration
- return self.execute(context)
-
-
def obj_bb_minmax(obj, min_co, max_co):
for i in range(0, 8):
bb_vec = obj.matrix_world * Vector(obj.bound_box[i])
diff --git a/release/scripts/startup/bl_operators/presets.py b/release/scripts/startup/bl_operators/presets.py
index e01e509b292..ea2794195e3 100644
--- a/release/scripts/startup/bl_operators/presets.py
+++ b/release/scripts/startup/bl_operators/presets.py
@@ -384,36 +384,6 @@ class AddPresetFluid(AddPresetBase, Operator):
preset_subdir = "fluid"
-class AddPresetHairDynamics(AddPresetBase, Operator):
- """Add or remove a Hair Dynamics Preset"""
- bl_idname = "particle.hair_dynamics_preset_add"
- bl_label = "Add Hair Dynamics Preset"
- preset_menu = "PARTICLE_MT_hair_dynamics_presets"
-
- preset_defines = [
- "psys = bpy.context.particle_system",
- "cloth = bpy.context.particle_system.cloth",
- "settings = bpy.context.particle_system.cloth.settings",
- "collision = bpy.context.particle_system.cloth.collision_settings",
- ]
-
- preset_subdir = "hair_dynamics"
-
- preset_values = [
- "settings.quality",
- "settings.mass",
- "settings.bending_stiffness",
- "psys.settings.bending_random",
- "settings.bending_damping",
- "settings.air_damping",
- "settings.internal_friction",
- "settings.density_target",
- "settings.density_strength",
- "settings.voxel_cell_size",
- "settings.pin_stiffness",
- ]
-
-
class AddPresetSunSky(AddPresetBase, Operator):
"""Add or remove a Sky & Atmosphere Preset"""
bl_idname = "lamp.sunsky_preset_add"
diff --git a/release/scripts/startup/bl_operators/view3d.py b/release/scripts/startup/bl_operators/view3d.py
index df4a93bb87f..1ef9354ed0e 100644
--- a/release/scripts/startup/bl_operators/view3d.py
+++ b/release/scripts/startup/bl_operators/view3d.py
@@ -199,8 +199,6 @@ class VIEW3D_OT_select_or_deselect_all(Operator):
bpy.ops.armature.select_all(action='DESELECT')
elif active_object.mode == 'POSE':
bpy.ops.pose.select_all(action='DESELECT')
- elif active_object.mode == 'PARTICLE_EDIT':
- bpy.ops.particle.select_all(action='DESELECT')
else:
bpy.ops.object.select_all(action='DESELECT')
else:
diff --git a/release/scripts/startup/bl_ui/__init__.py b/release/scripts/startup/bl_ui/__init__.py
index 2389be6787d..ac150392109 100644
--- a/release/scripts/startup/bl_ui/__init__.py
+++ b/release/scripts/startup/bl_ui/__init__.py
@@ -47,7 +47,6 @@ _modules = [
"properties_object",
"properties_paint_common",
"properties_grease_pencil_common",
- "properties_particle",
"properties_physics_cloth",
"properties_physics_common",
"properties_physics_dynamicpaint",
diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py
index 84ee06c7d70..ce7db82e49c 100644
--- a/release/scripts/startup/bl_ui/properties_data_modifier.py
+++ b/release/scripts/startup/bl_ui/properties_data_modifier.py
@@ -688,40 +688,6 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
col = split.column()
- def PARTICLE_INSTANCE(self, layout, ob, md):
- layout.prop(md, "object")
- layout.prop(md, "particle_system_index", text="Particle System")
-
- split = layout.split()
- col = split.column()
- col.label(text="Create From:")
- col.prop(md, "use_normal")
- col.prop(md, "use_children")
- col.prop(md, "use_size")
-
- col = split.column()
- col.label(text="Show Particles When:")
- col.prop(md, "show_alive")
- col.prop(md, "show_unborn")
- col.prop(md, "show_dead")
-
- layout.separator()
-
- layout.prop(md, "use_path", text="Create Along Paths")
-
- split = layout.split()
- split.active = md.use_path
- col = split.column()
- col.row().prop(md, "axis", expand=True)
- col.prop(md, "use_preserve_shape")
-
- col = split.column()
- col.prop(md, "position", slider=True)
- col.prop(md, "random_position", text="Random", slider=True)
-
- def PARTICLE_SYSTEM(self, layout, ob, md):
- layout.label(text="Settings can be found inside the Particle context")
-
def SCREW(self, layout, ob, md):
split = layout.split()
diff --git a/release/scripts/startup/bl_ui/properties_paint_common.py b/release/scripts/startup/bl_ui/properties_paint_common.py
index cca142b645c..c18aa10e229 100644
--- a/release/scripts/startup/bl_ui/properties_paint_common.py
+++ b/release/scripts/startup/bl_ui/properties_paint_common.py
@@ -40,8 +40,6 @@ class UnifiedPaintPanel:
return toolsettings.image_paint
return None
- elif context.particle_edit_object:
- return toolsettings.particle_edit
return None
diff --git a/release/scripts/startup/bl_ui/properties_particle.py b/release/scripts/startup/bl_ui/properties_particle.py
deleted file mode 100644
index 4e2666d7e40..00000000000
--- a/release/scripts/startup/bl_ui/properties_particle.py
+++ /dev/null
@@ -1,1408 +0,0 @@
-# ##### 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 #####
-
-# <pep8 compliant>
-import bpy
-from bpy.types import Panel, Menu
-from rna_prop_ui import PropertyPanel
-from bpy.app.translations import pgettext_iface as iface_
-
-from bl_ui.properties_physics_common import (
- point_cache_ui,
- effector_weights_ui,
- basic_force_field_settings_ui,
- basic_force_field_falloff_ui,
- )
-
-
-def particle_panel_enabled(context, psys):
- if psys is None:
- return True
- phystype = psys.settings.physics_type
- if psys.settings.type in {'EMITTER', 'REACTOR'} and phystype in {'NO', 'KEYED'}:
- return True
- else:
- return (psys.point_cache.is_baked is False) and (not psys.is_edited) and (not context.particle_system_editable)
-
-
-def particle_panel_poll(cls, context):
- psys = context.particle_system
- engine = context.scene.render.engine
- settings = 0
-
- if psys:
- settings = psys.settings
- elif isinstance(context.space_data.pin_id, bpy.types.ParticleSettings):
- settings = context.space_data.pin_id
-
- if not settings:
- return False
-
- return settings.is_fluid is False and (engine in cls.COMPAT_ENGINES)
-
-
-def particle_get_settings(context):
- if context.particle_system:
- return context.particle_system.settings
- elif isinstance(context.space_data.pin_id, bpy.types.ParticleSettings):
- return context.space_data.pin_id
- return None
-
-
-class PARTICLE_MT_specials(Menu):
- bl_label = "Particle Specials"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
-
- def draw(self, context):
- layout = self.layout
-
- props = layout.operator("particle.copy_particle_systems", text="Copy Active to Selected Objects")
- props.use_active = True
- props.remove_target_particles = False
-
- props = layout.operator("particle.copy_particle_systems", text="Copy All to Selected Objects")
- props.use_active = False
- props.remove_target_particles = True
-
- layout.operator("particle.duplicate_particle_system")
-
-
-class PARTICLE_MT_hair_dynamics_presets(Menu):
- bl_label = "Hair Dynamics Presets"
- preset_subdir = "hair_dynamics"
- preset_operator = "script.execute_preset"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
- draw = Menu.draw_preset
-
-
-class ParticleButtonsPanel:
- bl_space_type = 'PROPERTIES'
- bl_region_type = 'WINDOW'
- bl_context = "particle"
-
- @classmethod
- def poll(cls, context):
- return particle_panel_poll(cls, context)
-
-
-def find_modifier(ob, psys):
- for md in ob.modifiers:
- if md.type == 'PARTICLE_SYSTEM':
- if md.particle_system == psys:
- return md
-
-
-class PARTICLE_UL_particle_systems(bpy.types.UIList):
- def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index, flt_flag):
- ob = data
- psys = item
-
- if self.layout_type in {'DEFAULT', 'COMPACT'}:
- md = find_modifier(ob, psys)
-
- layout.prop(psys, "name", text="", emboss=False, icon_value=icon)
- if md:
- layout.prop(md, "show_render", emboss=False, icon_only=True, icon='RESTRICT_RENDER_OFF' if md.show_render else 'RESTRICT_RENDER_ON')
- layout.prop(md, "show_viewport", emboss=False, icon_only=True, icon='RESTRICT_VIEW_OFF' if md.show_viewport else 'RESTRICT_VIEW_ON')
-
- elif self.layout_type == 'GRID':
- layout.alignment = 'CENTER'
- layout.label(text="", icon_value=icon)
-
-
-class PARTICLE_PT_context_particles(ParticleButtonsPanel, Panel):
- bl_label = ""
- bl_options = {'HIDE_HEADER'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
-
- @classmethod
- def poll(cls, context):
- engine = context.scene.render.engine
- return (context.particle_system or context.object or context.space_data.pin_id) and (engine in cls.COMPAT_ENGINES)
-
- def draw(self, context):
- layout = self.layout
-
- if context.scene.render.engine == 'BLENDER_GAME':
- layout.label("Not available in the Game Engine")
- return
-
- ob = context.object
- psys = context.particle_system
- part = 0
-
- if ob:
- row = layout.row()
-
- row.template_list("PARTICLE_UL_particle_systems", "particle_systems", ob, "particle_systems",
- ob.particle_systems, "active_index", rows=1)
-
- col = row.column(align=True)
- col.operator("object.particle_system_add", icon='ZOOMIN', text="")
- col.operator("object.particle_system_remove", icon='ZOOMOUT', text="")
- col.menu("PARTICLE_MT_specials", icon='DOWNARROW_HLT', text="")
-
- if psys is None:
- part = particle_get_settings(context)
-
- layout.operator("object.particle_system_add", icon='ZOOMIN', text="New")
-
- if part is None:
- return
-
- layout.template_ID(context.space_data, "pin_id")
-
- if part.is_fluid:
- layout.label(text="Settings used for fluid")
- return
-
- layout.prop(part, "type", text="Type")
-
- elif not psys.settings:
- split = layout.split(percentage=0.32)
-
- col = split.column()
- col.label(text="Settings:")
-
- col = split.column()
- col.template_ID(psys, "settings", new="particle.new")
- else:
- part = psys.settings
-
- split = layout.split(percentage=0.32)
- col = split.column()
- if part.is_fluid is False:
- col.label(text="Settings:")
- col.label(text="Type:")
-
- col = split.column()
- if part.is_fluid is False:
- row = col.row()
- row.enabled = particle_panel_enabled(context, psys)
- row.template_ID(psys, "settings", new="particle.new")
-
- if part.is_fluid:
- layout.label(text=iface_("%d fluid particles for this frame") % part.count, translate=False)
- return
-
- row = col.row()
- row.enabled = particle_panel_enabled(context, psys)
- row.prop(part, "type", text="")
- row.prop(psys, "seed")
-
- if part:
- split = layout.split(percentage=0.65)
- if part.type == 'HAIR':
- if psys is not None and psys.is_edited:
- split.operator("particle.edited_clear", text="Free Edit")
- else:
- row = split.row()
- row.enabled = particle_panel_enabled(context, psys)
- row.prop(part, "regrow_hair")
- row.prop(part, "use_advanced_hair")
- row = split.row()
- row.enabled = particle_panel_enabled(context, psys)
- row.prop(part, "hair_step")
- if psys is not None and psys.is_edited:
- if psys.is_global_hair:
- row = layout.row(align=True)
- row.operator("particle.connect_hair").all = False
- row.operator("particle.connect_hair", text="Connect All").all = True
- else:
- row = layout.row(align=True)
- row.operator("particle.disconnect_hair").all = False
- row.operator("particle.disconnect_hair", text="Disconnect All").all = True
- elif psys is not None and part.type == 'REACTOR':
- split.enabled = particle_panel_enabled(context, psys)
- split.prop(psys, "reactor_target_object")
- split.prop(psys, "reactor_target_particle_system", text="Particle System")
-
-
-class PARTICLE_PT_emission(ParticleButtonsPanel, Panel):
- bl_label = "Emission"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
-
- @classmethod
- def poll(cls, context):
- psys = context.particle_system
- settings = particle_get_settings(context)
-
- if settings is None:
- return False
- if settings.is_fluid:
- return False
- if particle_panel_poll(PARTICLE_PT_emission, context):
- return psys is None or not context.particle_system.point_cache.use_external
- return False
-
- def draw(self, context):
- layout = self.layout
-
- psys = context.particle_system
- part = particle_get_settings(context)
-
- layout.enabled = particle_panel_enabled(context, psys) and (psys is None or not psys.has_multiple_caches)
-
- row = layout.row()
- row.active = part.emit_from == 'VERT' or part.distribution != 'GRID'
- row.prop(part, "count")
-
- if part.type == 'HAIR':
- row.prop(part, "hair_length")
- if not part.use_advanced_hair:
- row = layout.row()
- row.prop(part, "use_modifier_stack")
- return
-
- if part.type != 'HAIR':
- split = layout.split()
-
- col = split.column(align=True)
- col.prop(part, "frame_start")
- col.prop(part, "frame_end")
-
- col = split.column(align=True)
- col.prop(part, "lifetime")
- col.prop(part, "lifetime_random", slider=True)
-
- layout.label(text="Emit From:")
- layout.prop(part, "emit_from", expand=True)
-
- row = layout.row()
- if part.emit_from == 'VERT':
- row.prop(part, "use_emit_random")
- elif part.distribution == 'GRID':
- row.prop(part, "invert_grid")
- row.prop(part, "hexagonal_grid")
- else:
- row.prop(part, "use_emit_random")
- row.prop(part, "use_even_distribution")
-
- if part.emit_from == 'FACE' or part.emit_from == 'VOLUME':
- layout.prop(part, "distribution", expand=True)
-
- row = layout.row()
- if part.distribution == 'JIT':
- row.prop(part, "userjit", text="Particles/Face")
- row.prop(part, "jitter_factor", text="Jittering Amount", slider=True)
- elif part.distribution == 'GRID':
- row.prop(part, "grid_resolution")
- row.prop(part, "grid_random", text="Random", slider=True)
-
- row = layout.row()
- row.prop(part, "use_modifier_stack")
-
-
-class PARTICLE_PT_hair_dynamics(ParticleButtonsPanel, Panel):
- bl_label = "Hair dynamics"
- bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
-
- @classmethod
- def poll(cls, context):
- psys = context.particle_system
- engine = context.scene.render.engine
- if psys is None:
- return False
- if psys.settings is None:
- return False
- return psys.settings.type == 'HAIR' and (engine in cls.COMPAT_ENGINES)
-
- def draw_header(self, context):
- psys = context.particle_system
- self.layout.prop(psys, "use_hair_dynamics", text="")
-
- def draw(self, context):
- layout = self.layout
-
- psys = context.particle_system
-
- if not psys.cloth:
- return
-
- cloth_md = psys.cloth
- cloth = cloth_md.settings
- result = cloth_md.solver_result
-
- layout.enabled = psys.use_hair_dynamics and psys.point_cache.is_baked is False
-
- row = layout.row(align=True)
- row.menu("PARTICLE_MT_hair_dynamics_presets", text=bpy.types.PARTICLE_MT_hair_dynamics_presets.bl_label)
- row.operator("particle.hair_dynamics_preset_add", text="", icon='ZOOMIN')
- row.operator("particle.hair_dynamics_preset_add", text="", icon='ZOOMOUT').remove_active = True
-
- split = layout.column()
-
- col = split.column()
- col.label(text="Structure")
- col.prop(cloth, "mass")
- sub = col.column(align=True)
- subsub = sub.row(align=True)
- subsub.prop(cloth, "bending_stiffness", text="Stiffness")
- subsub.prop(psys.settings, "bending_random", text="Random")
- sub.prop(cloth, "bending_damping", text="Damping")
- # XXX has no noticeable effect with stiff hair structure springs
- #col.prop(cloth, "spring_damping", text="Damping")
-
- split.separator()
-
- col = split.column()
- col.label(text="Volume")
- col.prop(cloth, "air_damping", text="Air Drag")
- col.prop(cloth, "internal_friction", slider=True)
- sub = col.column(align=True)
- sub.prop(cloth, "density_target", text="Density Target")
- sub.prop(cloth, "density_strength", slider=True, text="Strength")
- col.prop(cloth, "voxel_cell_size")
-
- split.separator()
-
- col = split.column()
- col.label(text="Pinning")
- col.prop(cloth, "pin_stiffness", text="Goal Strength")
-
- split.separator()
-
- col = split.column()
- col.label(text="Quality:")
- col.prop(cloth, "quality", text="Steps", slider=True)
-
- row = col.row()
- row.prop(psys.settings, "show_hair_grid", text="HairGrid")
-
- if result:
- box = layout.box()
-
- if not result.status:
- label = " "
- icon = 'NONE'
- elif result.status == {'SUCCESS'}:
- label = "Success"
- icon = 'NONE'
- elif result.status - {'SUCCESS'} == {'NO_CONVERGENCE'}:
- label = "No Convergence"
- icon = 'ERROR'
- else:
- label = "ERROR"
- icon = 'ERROR'
- box.label(label, icon=icon)
- box.label("Iterations: %d .. %d (avg. %d)" % (result.min_iterations, result.max_iterations, result.avg_iterations))
- box.label("Error: %.5f .. %.5f (avg. %.5f)" % (result.min_error, result.max_error, result.avg_error))
-
-
-class PARTICLE_PT_cache(ParticleButtonsPanel, Panel):
- bl_label = "Cache"
- bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
-
- @classmethod
- def poll(cls, context):
- psys = context.particle_system
- engine = context.scene.render.engine
- if psys is None:
- return False
- if psys.settings is None:
- return False
- if psys.settings.is_fluid:
- return False
- phystype = psys.settings.physics_type
- if phystype == 'NO' or phystype == 'KEYED':
- return False
- return (psys.settings.type in {'EMITTER', 'REACTOR'} or (psys.settings.type == 'HAIR' and (psys.use_hair_dynamics or psys.point_cache.is_baked))) and engine in cls.COMPAT_ENGINES
-
- def draw(self, context):
- psys = context.particle_system
-
- point_cache_ui(self, context, psys.point_cache, True, 'HAIR' if (psys.settings.type == 'HAIR') else 'PSYS')
-
-
-class PARTICLE_PT_velocity(ParticleButtonsPanel, Panel):
- bl_label = "Velocity"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
-
- @classmethod
- def poll(cls, context):
- if particle_panel_poll(PARTICLE_PT_velocity, context):
- psys = context.particle_system
- settings = particle_get_settings(context)
-
- if settings.type == 'HAIR' and not settings.use_advanced_hair:
- return False
- return settings.physics_type != 'BOIDS' and (psys is None or not psys.point_cache.use_external)
- else:
- return False
-
- def draw(self, context):
- layout = self.layout
-
- psys = context.particle_system
- part = particle_get_settings(context)
-
- layout.enabled = particle_panel_enabled(context, psys)
-
- split = layout.split()
-
- col = split.column()
- col.label(text="Emitter Geometry:")
- col.prop(part, "normal_factor")
- sub = col.column(align=True)
- sub.prop(part, "tangent_factor")
- sub.prop(part, "tangent_phase", slider=True)
-
- col = split.column()
- col.label(text="Emitter Object:")
- col.prop(part, "object_align_factor", text="")
-
- layout.label(text="Other:")
- row = layout.row()
- if part.emit_from == 'PARTICLE':
- row.prop(part, "particle_factor")
- else:
- row.prop(part, "object_factor", slider=True)
- row.prop(part, "factor_random")
-
- #if part.type=='REACTOR':
- # sub.prop(part, "reactor_factor")
- # sub.prop(part, "reaction_shape", slider=True)
-
-
-class PARTICLE_PT_rotation(ParticleButtonsPanel, Panel):
- bl_label = "Rotation"
- bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
-
- @classmethod
- def poll(cls, context):
- if particle_panel_poll(PARTICLE_PT_rotation, context):
- psys = context.particle_system
- settings = particle_get_settings(context)
-
- if settings.type == 'HAIR' and not settings.use_advanced_hair:
- return False
- return settings.physics_type != 'BOIDS' and (psys is None or not psys.point_cache.use_external)
- else:
- return False
-
- def draw_header(self, context):
- psys = context.particle_system
- if psys:
- part = psys.settings
- else:
- part = context.space_data.pin_id
-
- self.layout.prop(part, "use_rotations", text="")
-
- def draw(self, context):
- layout = self.layout
-
- psys = context.particle_system
- if psys:
- part = psys.settings
- else:
- part = context.space_data.pin_id
-
- layout.enabled = particle_panel_enabled(context, psys) and part.use_rotations
-
- layout.label(text="Initial Orientation:")
-
- split = layout.split()
-
- col = split.column(align=True)
- col.prop(part, "rotation_mode", text="")
- col.prop(part, "rotation_factor_random", slider=True, text="Random")
-
- col = split.column(align=True)
- col.prop(part, "phase_factor", slider=True)
- col.prop(part, "phase_factor_random", text="Random", slider=True)
-
- if part.type != 'HAIR':
- layout.label(text="Angular Velocity:")
-
- split = layout.split()
-
- col = split.column(align=True)
- col.prop(part, "angular_velocity_mode", text="")
- sub = col.column(align=True)
- sub.active = part.angular_velocity_mode != 'NONE'
- sub.prop(part, "angular_velocity_factor", text="")
-
- col = split.column()
- col.prop(part, "use_dynamic_rotation")
-
-
-class PARTICLE_PT_physics(ParticleButtonsPanel, Panel):
- bl_label = "Physics"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
-
- @classmethod
- def poll(cls, context):
- if particle_panel_poll(PARTICLE_PT_physics, context):
- psys = context.particle_system
- settings = particle_get_settings(context)
-
- if settings.type == 'HAIR' and not settings.use_advanced_hair:
- return False
- return psys is None or not psys.point_cache.use_external
- else:
- return False
-
- def draw(self, context):
- layout = self.layout
-
- psys = context.particle_system
- part = particle_get_settings(context)
-
- layout.enabled = particle_panel_enabled(context, psys)
-
- layout.prop(part, "physics_type", expand=True)
-
- row = layout.row()
- col = row.column(align=True)
- col.prop(part, "particle_size")
- col.prop(part, "size_random", slider=True)
-
- if part.physics_type != 'NO':
- col = row.column(align=True)
- col.prop(part, "mass")
- col.prop(part, "use_multiply_size_mass", text="Multiply mass with size")
-
- if part.physics_type in {'NEWTON', 'FLUID'}:
- split = layout.split()
-
- col = split.column()
- col.label(text="Forces:")
- col.prop(part, "brownian_factor")
- col.prop(part, "drag_factor", slider=True)
- col.prop(part, "damping", slider=True)
-
- col = split.column()
- col.label(text="Integration:")
- col.prop(part, "integrator", text="")
- col.prop(part, "timestep")
- sub = col.row()
- sub.prop(part, "subframes")
- supports_courant = part.physics_type == 'FLUID'
- subsub = sub.row()
- subsub.enabled = supports_courant
- subsub.prop(part, "use_adaptive_subframes", text="")
- if supports_courant and part.use_adaptive_subframes:
- col.prop(part, "courant_target", text="Threshold")
-
- row = layout.row()
- row.prop(part, "use_size_deflect")
- row.prop(part, "use_die_on_collision")
-
- layout.prop(part, "collision_group")
-
- if part.physics_type == 'FLUID':
- fluid = part.fluid
-
- split = layout.split()
- sub = split.row()
- sub.prop(fluid, "solver", expand=True)
-
- split = layout.split()
-
- col = split.column()
- col.label(text="Fluid properties:")
- col.prop(fluid, "stiffness", text="Stiffness")
- col.prop(fluid, "linear_viscosity", text="Viscosity")
- col.prop(fluid, "buoyancy", text="Buoyancy", slider=True)
-
- col = split.column()
- col.label(text="Advanced:")
-
- if fluid.solver == 'DDR':
- sub = col.row()
- sub.prop(fluid, "repulsion", slider=fluid.factor_repulsion)
- sub.prop(fluid, "factor_repulsion", text="")
-
- sub = col.row()
- sub.prop(fluid, "stiff_viscosity", slider=fluid.factor_stiff_viscosity)
- sub.prop(fluid, "factor_stiff_viscosity", text="")
-
- sub = col.row()
- sub.prop(fluid, "fluid_radius", slider=fluid.factor_radius)
- sub.prop(fluid, "factor_radius", text="")
-
- sub = col.row()
- sub.prop(fluid, "rest_density", slider=fluid.use_factor_density)
- sub.prop(fluid, "use_factor_density", text="")
-
- if fluid.solver == 'CLASSICAL':
- # With the classical solver, it is possible to calculate the
- # spacing between particles when the fluid is at rest. This
- # makes it easier to set stable initial conditions.
- particle_volume = part.mass / fluid.rest_density
- spacing = pow(particle_volume, 1.0 / 3.0)
- sub = col.row()
- sub.label(text="Spacing: %g" % spacing)
-
- elif fluid.solver == 'DDR':
- split = layout.split()
-
- col = split.column()
- col.label(text="Springs:")
- col.prop(fluid, "spring_force", text="Force")
- col.prop(fluid, "use_viscoelastic_springs")
- sub = col.column(align=True)
- sub.active = fluid.use_viscoelastic_springs
- sub.prop(fluid, "yield_ratio", slider=True)
- sub.prop(fluid, "plasticity", slider=True)
-
- col = split.column()
- col.label(text="Advanced:")
- sub = col.row()
- sub.prop(fluid, "rest_length", slider=fluid.factor_rest_length)
- sub.prop(fluid, "factor_rest_length", text="")
- col.label(text="")
- sub = col.column()
- sub.active = fluid.use_viscoelastic_springs
- sub.prop(fluid, "use_initial_rest_length")
- sub.prop(fluid, "spring_frames", text="Frames")
-
- elif part.physics_type == 'KEYED':
- split = layout.split()
- sub = split.column()
-
- row = layout.row()
- col = row.column()
- col.active = not psys.use_keyed_timing
- col.prop(part, "keyed_loops", text="Loops")
- if psys:
- row.prop(psys, "use_keyed_timing", text="Use Timing")
-
- layout.label(text="Keys:")
- elif part.physics_type == 'BOIDS':
- boids = part.boids
-
- row = layout.row()
- row.prop(boids, "use_flight")
- row.prop(boids, "use_land")
- row.prop(boids, "use_climb")
-
- split = layout.split()
-
- col = split.column(align=True)
- col.active = boids.use_flight
- col.prop(boids, "air_speed_max")
- col.prop(boids, "air_speed_min", slider=True)
- col.prop(boids, "air_acc_max", slider=True)
- col.prop(boids, "air_ave_max", slider=True)
- col.prop(boids, "air_personal_space")
- row = col.row(align=True)
- row.active = (boids.use_land or boids.use_climb) and boids.use_flight
- row.prop(boids, "land_smooth")
-
- col = split.column(align=True)
- col.active = boids.use_land or boids.use_climb
- col.prop(boids, "land_speed_max")
- col.prop(boids, "land_jump_speed")
- col.prop(boids, "land_acc_max", slider=True)
- col.prop(boids, "land_ave_max", slider=True)
- col.prop(boids, "land_personal_space")
- col.prop(boids, "land_stick_force")
-
- layout.prop(part, "collision_group")
-
- split = layout.split()
-
- col = split.column(align=True)
- col.label(text="Battle:")
- col.prop(boids, "health")
- col.prop(boids, "strength")
- col.prop(boids, "aggression")
- col.prop(boids, "accuracy")
- col.prop(boids, "range")
-
- col = split.column()
- col.label(text="Misc:")
- col.prop(boids, "bank", slider=True)
- col.prop(boids, "pitch", slider=True)
- col.prop(boids, "height", slider=True)
-
- if psys and part.physics_type in {'KEYED', 'BOIDS', 'FLUID'}:
- if part.physics_type == 'BOIDS':
- layout.label(text="Relations:")
- elif part.physics_type == 'FLUID':
- layout.label(text="Fluid interaction:")
-
- row = layout.row()
- row.template_list("UI_UL_list", "particle_targets", psys, "targets", psys, "active_particle_target_index", rows=4)
-
- col = row.column()
- sub = col.row()
- subsub = sub.column(align=True)
- subsub.operator("particle.new_target", icon='ZOOMIN', text="")
- subsub.operator("particle.target_remove", icon='ZOOMOUT', text="")
- sub = col.row()
- subsub = sub.column(align=True)
- subsub.operator("particle.target_move_up", icon='MOVE_UP_VEC', text="")
- subsub.operator("particle.target_move_down", icon='MOVE_DOWN_VEC', text="")
-
- key = psys.active_particle_target
- if key:
- row = layout.row()
- if part.physics_type == 'KEYED':
- col = row.column()
- #doesn't work yet
- #col.alert = key.valid
- col.prop(key, "object", text="")
- col.prop(key, "system", text="System")
- col = row.column()
- col.active = psys.use_keyed_timing
- col.prop(key, "time")
- col.prop(key, "duration")
- elif part.physics_type == 'BOIDS':
- sub = row.row()
- #doesn't work yet
- #sub.alert = key.valid
- sub.prop(key, "object", text="")
- sub.prop(key, "system", text="System")
-
- layout.prop(key, "alliance", expand=True)
- elif part.physics_type == 'FLUID':
- sub = row.row()
- #doesn't work yet
- #sub.alert = key.valid
- sub.prop(key, "object", text="")
- sub.prop(key, "system", text="System")
-
-
-class PARTICLE_PT_boidbrain(ParticleButtonsPanel, Panel):
- bl_label = "Boid Brain"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
-
- @classmethod
- def poll(cls, context):
- psys = context.particle_system
- settings = particle_get_settings(context)
- engine = context.scene.render.engine
-
- if settings is None:
- return False
- if psys is not None and psys.point_cache.use_external:
- return False
- return settings.physics_type == 'BOIDS' and engine in cls.COMPAT_ENGINES
-
- def draw(self, context):
- layout = self.layout
-
- boids = particle_get_settings(context).boids
-
- layout.enabled = particle_panel_enabled(context, context.particle_system)
-
- # Currently boids can only use the first state so these are commented out for now.
- #row = layout.row()
- #row.template_list("UI_UL_list", "particle_boids", boids, "states",
- # boids, "active_boid_state_index", compact="True")
- #col = row.row()
- #sub = col.row(align=True)
- #sub.operator("boid.state_add", icon='ZOOMIN', text="")
- #sub.operator("boid.state_del", icon='ZOOMOUT', text="")
- #sub = row.row(align=True)
- #sub.operator("boid.state_move_up", icon='MOVE_UP_VEC', text="")
- #sub.operator("boid.state_move_down", icon='MOVE_DOWN_VEC', text="")
-
- state = boids.active_boid_state
-
- #layout.prop(state, "name", text="State name")
-
- row = layout.row()
- row.prop(state, "ruleset_type")
- if state.ruleset_type == 'FUZZY':
- row.prop(state, "rule_fuzzy", slider=True)
- else:
- row.label(text="")
-
- row = layout.row()
- row.template_list("UI_UL_list", "particle_boids_rules", state, "rules", state, "active_boid_rule_index", rows=4)
-
- col = row.column()
- sub = col.row()
- subsub = sub.column(align=True)
- subsub.operator_menu_enum("boid.rule_add", "type", icon='ZOOMIN', text="")
- subsub.operator("boid.rule_del", icon='ZOOMOUT', text="")
- sub = col.row()
- subsub = sub.column(align=True)
- subsub.operator("boid.rule_move_up", icon='MOVE_UP_VEC', text="")
- subsub.operator("boid.rule_move_down", icon='MOVE_DOWN_VEC', text="")
-
- rule = state.active_boid_rule
-
- if rule:
- row = layout.row()
- row.prop(rule, "name", text="")
- #somebody make nice icons for boids here please! -jahka
- row.prop(rule, "use_in_air", icon='MOVE_UP_VEC', text="")
- row.prop(rule, "use_on_land", icon='MOVE_DOWN_VEC', text="")
-
- row = layout.row()
-
- if rule.type == 'GOAL':
- row.prop(rule, "object")
- row = layout.row()
- row.prop(rule, "use_predict")
- elif rule.type == 'AVOID':
- row.prop(rule, "object")
- row = layout.row()
- row.prop(rule, "use_predict")
- row.prop(rule, "fear_factor")
- elif rule.type == 'FOLLOW_PATH':
- row.label(text="Not yet functional")
- elif rule.type == 'AVOID_COLLISION':
- row.prop(rule, "use_avoid")
- row.prop(rule, "use_avoid_collision")
- row.prop(rule, "look_ahead")
- elif rule.type == 'FOLLOW_LEADER':
- row.prop(rule, "object", text="")
- row.prop(rule, "distance")
- row = layout.row()
- row.prop(rule, "use_line")
- sub = row.row()
- sub.active = rule.line
- sub.prop(rule, "queue_count")
- elif rule.type == 'AVERAGE_SPEED':
- row.prop(rule, "speed", slider=True)
- row.prop(rule, "wander", slider=True)
- row.prop(rule, "level", slider=True)
- elif rule.type == 'FIGHT':
- row.prop(rule, "distance")
- row.prop(rule, "flee_distance")
-
-
-class PARTICLE_PT_render(ParticleButtonsPanel, Panel):
- bl_label = "Render"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
-
- @classmethod
- def poll(cls, context):
- settings = particle_get_settings(context)
- engine = context.scene.render.engine
- if settings is None:
- return False
-
- return engine in cls.COMPAT_ENGINES
-
- def draw(self, context):
- layout = self.layout
-
- psys = context.particle_system
- part = particle_get_settings(context)
-
- if psys:
- row = layout.row()
- if part.render_type in {'OBJECT', 'GROUP'}:
- row.enabled = False
- row.prop(part, "material_slot", text="")
- row.prop(psys, "parent")
-
- split = layout.split()
-
- col = split.column()
- col.prop(part, "use_render_emitter")
- col.prop(part, "use_parent_particles")
-
- col = split.column()
- col.prop(part, "show_unborn")
- col.prop(part, "use_dead")
-
- layout.prop(part, "render_type", expand=True)
-
- split = layout.split()
-
- col = split.column()
-
- if part.render_type == 'LINE':
- col.prop(part, "line_length_tail")
- col.prop(part, "line_length_head")
-
- split.prop(part, "use_velocity_length")
- elif part.render_type == 'PATH':
- col.prop(part, "use_strand_primitive")
- sub = col.column()
- sub.active = (part.use_strand_primitive is False)
- sub.prop(part, "use_render_adaptive")
- sub = col.column()
- sub.active = part.use_render_adaptive or part.use_strand_primitive is True
- sub.prop(part, "adaptive_angle")
- sub = col.column()
- sub.active = (part.use_render_adaptive is True and part.use_strand_primitive is False)
- sub.prop(part, "adaptive_pixel")
- col.prop(part, "use_hair_bspline")
- col.prop(part, "render_step", text="Steps")
-
- col = split.column()
- col.label(text="Timing:")
- col.prop(part, "use_absolute_path_time")
-
- if part.type == 'HAIR' or psys.point_cache.is_baked:
- col.prop(part, "path_start", text="Start", slider=not part.use_absolute_path_time)
- else:
- col.prop(part, "trail_count")
-
- col.prop(part, "path_end", text="End", slider=not part.use_absolute_path_time)
- col.prop(part, "length_random", text="Random", slider=True)
-
- row = layout.row()
- col = row.column()
-
- if part.type == 'HAIR' and part.use_strand_primitive is True and part.child_type == 'INTERPOLATED':
- layout.prop(part, "use_simplify")
- if part.use_simplify is True:
- row = layout.row()
- row.prop(part, "simplify_refsize")
- row.prop(part, "simplify_rate")
- row.prop(part, "simplify_transition")
- row = layout.row()
- row.prop(part, "use_simplify_viewport")
- sub = row.row()
- sub.active = part.use_simplify_viewport is True
- sub.prop(part, "simplify_viewport")
-
- elif part.render_type == 'OBJECT':
- col.prop(part, "dupli_object")
- sub = col.row()
- sub.prop(part, "use_global_dupli")
- sub.prop(part, "use_rotation_dupli")
- sub.prop(part, "use_scale_dupli")
- elif part.render_type == 'GROUP':
- col.prop(part, "dupli_group")
- split = layout.split()
-
- col = split.column()
- col.prop(part, "use_whole_group")
- sub = col.column()
- sub.active = (part.use_whole_group is False)
- sub.prop(part, "use_group_pick_random")
- sub.prop(part, "use_group_count")
-
- col = split.column()
- sub = col.column()
- sub.active = (part.use_whole_group is False)
- sub.prop(part, "use_global_dupli")
- sub.prop(part, "use_rotation_dupli")
- sub.prop(part, "use_scale_dupli")
-
- if part.use_group_count and not part.use_whole_group:
- row = layout.row()
- row.template_list("UI_UL_list", "particle_dupli_weights", part, "dupli_weights",
- part, "active_dupliweight_index")
-
- col = row.column()
- sub = col.row()
- subsub = sub.column(align=True)
- subsub.operator("particle.dupliob_copy", icon='ZOOMIN', text="")
- subsub.operator("particle.dupliob_remove", icon='ZOOMOUT', text="")
- subsub.operator("particle.dupliob_move_up", icon='MOVE_UP_VEC', text="")
- subsub.operator("particle.dupliob_move_down", icon='MOVE_DOWN_VEC', text="")
-
- weight = part.active_dupliweight
- if weight:
- row = layout.row()
- row.prop(weight, "count")
-
- elif part.render_type == 'BILLBOARD':
- ob = context.object
-
- col.label(text="Align:")
-
- row = layout.row()
- row.prop(part, "billboard_align", expand=True)
- row.prop(part, "lock_billboard", text="Lock")
- row = layout.row()
- row.prop(part, "billboard_object")
-
- row = layout.row()
- col = row.column(align=True)
- col.label(text="Tilt:")
- col.prop(part, "billboard_tilt", text="Angle", slider=True)
- col.prop(part, "billboard_tilt_random", text="Random", slider=True)
- col = row.column()
- col.prop(part, "billboard_offset")
-
- row = layout.row()
- col = row.column()
- col.prop(part, "billboard_size", text="Scale")
- if part.billboard_align == 'VEL':
- col = row.column(align=True)
- col.label("Velocity Scale:")
- col.prop(part, "billboard_velocity_head", text="Head")
- col.prop(part, "billboard_velocity_tail", text="Tail")
-
- if psys:
- col = layout.column()
- col.prop_search(psys, "billboard_normal_uv", ob.data, "uv_textures")
- col.prop_search(psys, "billboard_time_index_uv", ob.data, "uv_textures")
-
- split = layout.split(percentage=0.33)
- split.label(text="Split UVs:")
- split.prop(part, "billboard_uv_split", text="Number of splits")
-
- if psys:
- col = layout.column()
- col.active = part.billboard_uv_split > 1
- col.prop_search(psys, "billboard_split_uv", ob.data, "uv_textures")
-
- row = col.row()
- row.label(text="Animate:")
- row.prop(part, "billboard_animation", text="")
- row.label(text="Offset:")
- row.prop(part, "billboard_offset_split", text="")
-
- if part.render_type == 'HALO' or part.render_type == 'LINE' or part.render_type == 'BILLBOARD':
- row = layout.row()
- col = row.column()
- col.prop(part, "trail_count")
- if part.trail_count > 1:
- col.prop(part, "use_absolute_path_time", text="Length in frames")
- col = row.column()
- col.prop(part, "path_end", text="Length", slider=not part.use_absolute_path_time)
- col.prop(part, "length_random", text="Random", slider=True)
- else:
- col = row.column()
- col.label(text="")
-
- if part.render_type in {'OBJECT', 'GROUP'} and not part.use_advanced_hair:
- row = layout.row(align=True)
- row.prop(part, "particle_size")
- row.prop(part, "size_random", slider=True)
-
-
-class PARTICLE_PT_draw(ParticleButtonsPanel, Panel):
- bl_label = "Display"
- bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
-
- @classmethod
- def poll(cls, context):
- settings = particle_get_settings(context)
- engine = context.scene.render.engine
- if settings is None:
- return False
- return engine in cls.COMPAT_ENGINES
-
- def draw(self, context):
- layout = self.layout
-
- psys = context.particle_system
- part = particle_get_settings(context)
-
- row = layout.row()
- row.prop(part, "draw_method", expand=True)
- row.prop(part, "show_guide_hairs")
-
- if part.draw_method == 'NONE' or (part.render_type == 'NONE' and part.draw_method == 'RENDER'):
- return
-
- path = (part.render_type == 'PATH' and part.draw_method == 'RENDER') or part.draw_method == 'PATH'
-
- row = layout.row()
- row.prop(part, "draw_percentage", slider=True)
- if part.draw_method != 'RENDER' or part.render_type == 'HALO':
- row.prop(part, "draw_size")
- else:
- row.label(text="")
-
- if part.draw_percentage != 100 and psys is not None:
- if part.type == 'HAIR':
- if psys.use_hair_dynamics and psys.point_cache.is_baked is False:
- layout.row().label(text="Display percentage makes dynamics inaccurate without baking!")
- else:
- phystype = part.physics_type
- if phystype != 'NO' and phystype != 'KEYED' and psys.point_cache.is_baked is False:
- layout.row().label(text="Display percentage makes dynamics inaccurate without baking!")
-
- row = layout.row()
- col = row.column()
- col.prop(part, "show_size")
- col.prop(part, "show_velocity")
- col.prop(part, "show_number")
- if part.physics_type == 'BOIDS':
- col.prop(part, "show_health")
-
- col = row.column(align=True)
- col.label(text="Color:")
- col.prop(part, "draw_color", text="")
- sub = col.row(align=True)
- sub.active = (part.draw_color in {'VELOCITY', 'ACCELERATION'})
- sub.prop(part, "color_maximum", text="Max")
-
- if path:
- col.prop(part, "draw_step")
-
-
-class PARTICLE_PT_children(ParticleButtonsPanel, Panel):
- bl_label = "Children"
- bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
-
- @classmethod
- def poll(cls, context):
- return particle_panel_poll(cls, context)
-
- def draw(self, context):
- layout = self.layout
-
- psys = context.particle_system
- part = particle_get_settings(context)
-
- layout.row().prop(part, "child_type", expand=True)
-
- if part.child_type == 'NONE':
- return
-
- row = layout.row()
-
- col = row.column(align=True)
- col.prop(part, "child_nbr", text="Display")
- col.prop(part, "rendered_child_count", text="Render")
-
- if part.child_type == 'INTERPOLATED':
- col = row.column()
- if psys:
- col.prop(psys, "child_seed", text="Seed")
- col.prop(part, "virtual_parents", slider=True)
- col.prop(part, "create_long_hair_children")
- else:
- col = row.column(align=True)
- col.prop(part, "child_size", text="Size")
- col.prop(part, "child_size_random", text="Random")
-
- split = layout.split()
-
- col = split.column()
- col.label(text="Effects:")
-
- sub = col.column(align=True)
- sub.prop(part, "use_clump_curve")
- if part.use_clump_curve:
- sub.template_curve_mapping(part, "clump_curve")
- else:
- sub.prop(part, "clump_factor", slider=True)
- sub.prop(part, "clump_shape", slider=True)
- sub = col.column(align=True)
- sub.prop(part, "use_clump_noise")
- subsub = sub.column()
- subsub.enabled = part.use_clump_noise
- subsub.prop(part, "clump_noise_size")
-
- sub = col.column(align=True)
- sub.prop(part, "child_length", slider=True)
- sub.prop(part, "child_length_threshold", slider=True)
-
- if part.child_type == 'SIMPLE':
- sub = col.column(align=True)
- sub.prop(part, "child_radius", text="Radius")
- sub.prop(part, "child_roundness", text="Roundness", slider=True)
- if psys:
- sub.prop(psys, "child_seed", text="Seed")
- elif part.virtual_parents > 0.0:
- sub = col.column(align=True)
- sub.label(text="Parting not")
- sub.label(text="available with")
- sub.label(text="virtual parents")
- else:
- sub = col.column(align=True)
- sub.prop(part, "child_parting_factor", text="Parting", slider=True)
- sub.prop(part, "child_parting_min", text="Min")
- sub.prop(part, "child_parting_max", text="Max")
-
- col = split.column()
-
- col.prop(part, "use_roughness_curve")
- if part.use_roughness_curve:
- sub = col.column()
- sub.template_curve_mapping(part, "roughness_curve")
- sub.prop(part, "roughness_1", text="Roughness")
- sub.prop(part, "roughness_1_size", text="Size")
- else:
- col.label(text="Roughness:")
-
- sub = col.column(align=True)
- sub.prop(part, "roughness_1", text="Uniform")
- sub.prop(part, "roughness_1_size", text="Size")
-
- sub = col.column(align=True)
- sub.prop(part, "roughness_endpoint", "Endpoint")
- sub.prop(part, "roughness_end_shape")
-
- sub = col.column(align=True)
- sub.prop(part, "roughness_2", text="Random")
- sub.prop(part, "roughness_2_size", text="Size")
- sub.prop(part, "roughness_2_threshold", slider=True)
-
- layout.row().label(text="Kink:")
- layout.row().prop(part, "kink", expand=True)
-
- split = layout.split()
- split.active = part.kink != 'NO'
-
- if part.kink == 'SPIRAL':
- col = split.column()
- sub = col.column(align=True)
- sub.prop(part, "kink_amplitude", text="Radius")
- sub.prop(part, "kink_amplitude_random", text="Random", slider=True)
- sub = col.column(align=True)
- sub.prop(part, "kink_axis")
- sub.prop(part, "kink_axis_random", text="Random", slider=True)
- col = split.column(align=True)
- col.prop(part, "kink_frequency", text="Frequency")
- col.prop(part, "kink_shape", text="Shape", slider=True)
- col.prop(part, "kink_extra_steps", text="Steps")
- else:
- col = split.column()
- sub = col.column(align=True)
- sub.prop(part, "kink_amplitude")
- sub.prop(part, "kink_amplitude_clump", text="Clump", slider=True)
- col.prop(part, "kink_flat", slider=True)
- col = split.column(align=True)
- col.prop(part, "kink_frequency")
- col.prop(part, "kink_shape", slider=True)
-
-
-class PARTICLE_PT_field_weights(ParticleButtonsPanel, Panel):
- bl_label = "Field Weights"
- bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
-
- @classmethod
- def poll(cls, context):
- return particle_panel_poll(cls, context)
-
- def draw(self, context):
- part = particle_get_settings(context)
- effector_weights_ui(self, context, part.effector_weights, 'PSYS')
-
- if part.type == 'HAIR':
- row = self.layout.row()
- row.prop(part.effector_weights, "apply_to_hair_growing")
- row.prop(part, "apply_effector_to_children")
- row = self.layout.row()
- row.prop(part, "effect_hair", slider=True)
-
-
-class PARTICLE_PT_force_fields(ParticleButtonsPanel, Panel):
- bl_label = "Force Field Settings"
- bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
-
- def draw(self, context):
- layout = self.layout
-
- part = particle_get_settings(context)
-
- row = layout.row()
- row.prop(part, "use_self_effect")
- row.prop(part, "effector_amount", text="Amount")
-
- split = layout.split(percentage=0.2)
- split.label(text="Type 1:")
- split.prop(part.force_field_1, "type", text="")
- basic_force_field_settings_ui(self, context, part.force_field_1)
- if part.force_field_1.type != 'NONE':
- layout.label(text="Falloff:")
- basic_force_field_falloff_ui(self, context, part.force_field_1)
-
- if part.force_field_1.type != 'NONE':
- layout.label(text="")
-
- split = layout.split(percentage=0.2)
- split.label(text="Type 2:")
- split.prop(part.force_field_2, "type", text="")
- basic_force_field_settings_ui(self, context, part.force_field_2)
- if part.force_field_2.type != 'NONE':
- layout.label(text="Falloff:")
- basic_force_field_falloff_ui(self, context, part.force_field_2)
-
-
-class PARTICLE_PT_vertexgroups(ParticleButtonsPanel, Panel):
- bl_label = "Vertex Groups"
- bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
-
- @classmethod
- def poll(cls, context):
- if context.particle_system is None:
- return False
- return particle_panel_poll(cls, context)
-
- def draw(self, context):
- layout = self.layout
-
- ob = context.object
- psys = context.particle_system
-
- col = layout.column()
- row = col.row(align=True)
- row.prop_search(psys, "vertex_group_density", ob, "vertex_groups", text="Density")
- row.prop(psys, "invert_vertex_group_density", text="", toggle=True, icon='ARROW_LEFTRIGHT')
-
- row = col.row(align=True)
- row.prop_search(psys, "vertex_group_length", ob, "vertex_groups", text="Length")
- row.prop(psys, "invert_vertex_group_length", text="", toggle=True, icon='ARROW_LEFTRIGHT')
-
- row = col.row(align=True)
- row.prop_search(psys, "vertex_group_clump", ob, "vertex_groups", text="Clump")
- row.prop(psys, "invert_vertex_group_clump", text="", toggle=True, icon='ARROW_LEFTRIGHT')
-
- row = col.row(align=True)
- row.prop_search(psys, "vertex_group_kink", ob, "vertex_groups", text="Kink")
- row.prop(psys, "invert_vertex_group_kink", text="", toggle=True, icon='ARROW_LEFTRIGHT')
-
- row = col.row(align=True)
- row.prop_search(psys, "vertex_group_roughness_1", ob, "vertex_groups", text="Roughness 1")
- row.prop(psys, "invert_vertex_group_roughness_1", text="", toggle=True, icon='ARROW_LEFTRIGHT')
-
- row = col.row(align=True)
- row.prop_search(psys, "vertex_group_roughness_2", ob, "vertex_groups", text="Roughness 2")
- row.prop(psys, "invert_vertex_group_roughness_2", text="", toggle=True, icon='ARROW_LEFTRIGHT')
-
- row = col.row(align=True)
- row.prop_search(psys, "vertex_group_roughness_end", ob, "vertex_groups", text="Roughness End")
- row.prop(psys, "invert_vertex_group_roughness_end", text="", toggle=True, icon='ARROW_LEFTRIGHT')
-
- # Commented out vertex groups don't work and are still waiting for better implementation
- # row = layout.row()
- # row.prop_search(psys, "vertex_group_velocity", ob, "vertex_groups", text="Velocity")
- # row.prop(psys, "invert_vertex_group_velocity", text="")
-
- # row = layout.row()
- # row.prop_search(psys, "vertex_group_size", ob, "vertex_groups", text="Size")
- # row.prop(psys, "invert_vertex_group_size", text="")
-
- # row = layout.row()
- # row.prop_search(psys, "vertex_group_tangent", ob, "vertex_groups", text="Tangent")
- # row.prop(psys, "invert_vertex_group_tangent", text="")
-
- # row = layout.row()
- # row.prop_search(psys, "vertex_group_rotation", ob, "vertex_groups", text="Rotation")
- # row.prop(psys, "invert_vertex_group_rotation", text="")
-
- # row = layout.row()
- # row.prop_search(psys, "vertex_group_field", ob, "vertex_groups", text="Field")
- # row.prop(psys, "invert_vertex_group_field", text="")
-
-
-class PARTICLE_PT_custom_props(ParticleButtonsPanel, PropertyPanel, Panel):
- COMPAT_ENGINES = {'BLENDER_RENDER'}
- _context_path = "particle_system.settings"
- _property_type = bpy.types.ParticleSettings
-
-if __name__ == "__main__": # only for live edit.
- bpy.utils.register_module(__name__)
diff --git a/release/scripts/startup/bl_ui/properties_physics_cloth.py b/release/scripts/startup/bl_ui/properties_physics_cloth.py
index 3ebf2691b4c..0362cc42371 100644
--- a/release/scripts/startup/bl_ui/properties_physics_cloth.py
+++ b/release/scripts/startup/bl_ui/properties_physics_cloth.py
@@ -21,13 +21,13 @@ import bpy
from bpy.types import Menu, Panel
from bl_ui.properties_physics_common import (
- point_cache_ui,
effector_weights_ui,
)
def cloth_panel_enabled(md):
- return md.point_cache.is_baked is False
+ return True
+ #return md.point_cache.is_baked is False
class CLOTH_MT_presets(Menu):
@@ -64,6 +64,8 @@ class PHYSICS_PT_cloth(PhysicButtonsPanel, Panel):
split = layout.split(percentage=0.25)
+ col = split.column()
+
split.label(text="Presets:")
sub = split.row(align=True)
sub.menu("CLOTH_MT_presets", text=bpy.types.CLOTH_MT_presets.bl_label)
@@ -130,16 +132,6 @@ class PHYSICS_PT_cloth(PhysicButtonsPanel, Panel):
sub.prop_search(cloth, "rest_shape_key", key, "key_blocks", text="")
-class PHYSICS_PT_cloth_cache(PhysicButtonsPanel, Panel):
- bl_label = "Cloth Cache"
- bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
-
- def draw(self, context):
- md = context.cloth
- point_cache_ui(self, context, md.point_cache, cloth_panel_enabled(md), 'CLOTH')
-
-
class PHYSICS_PT_cloth_collision(PhysicButtonsPanel, Panel):
bl_label = "Cloth Collision"
bl_options = {'DEFAULT_CLOSED'}
diff --git a/release/scripts/startup/bl_ui/properties_physics_common.py b/release/scripts/startup/bl_ui/properties_physics_common.py
index 277b59d187d..ea4bbc76f43 100644
--- a/release/scripts/startup/bl_ui/properties_physics_common.py
+++ b/release/scripts/startup/bl_ui/properties_physics_common.py
@@ -98,113 +98,6 @@ class PHYSICS_PT_add(PhysicButtonsPanel, Panel):
'CONSTRAINT') # RB_TODO needs better icon
-# cache-type can be 'PSYS' 'HAIR' 'SMOKE' etc
-
-def point_cache_ui(self, context, cache, enabled, cachetype):
- layout = self.layout
-
- layout.context_pointer_set("point_cache", cache)
-
- if not cachetype == 'RIGID_BODY':
- row = layout.row()
- row.template_list("UI_UL_list", "point_caches", cache, "point_caches",
- cache.point_caches, "active_index", rows=1)
- col = row.column(align=True)
- col.operator("ptcache.add", icon='ZOOMIN', text="")
- col.operator("ptcache.remove", icon='ZOOMOUT', text="")
-
- row = layout.row()
- if cachetype in {'PSYS', 'HAIR', 'SMOKE'}:
- row.prop(cache, "use_external")
-
- if cachetype == 'SMOKE':
- row.prop(cache, "use_library_path", "Use Lib Path")
-
- if cache.use_external:
- split = layout.split(percentage=0.35)
- col = split.column()
- col.label(text="Index Number:")
- col.label(text="File Path:")
-
- col = split.column()
- col.prop(cache, "index", text="")
- col.prop(cache, "filepath", text="")
-
- cache_info = cache.info
- if cache_info:
- layout.label(text=cache_info)
- else:
- if cachetype in {'SMOKE', 'DYNAMIC_PAINT'}:
- if not bpy.data.is_saved:
- layout.label(text="Cache is disabled until the file is saved")
- layout.enabled = False
-
- if not cache.use_external or cachetype == 'SMOKE':
- row = layout.row(align=True)
-
- if cachetype not in {'PSYS', 'DYNAMIC_PAINT'}:
- row.enabled = enabled
- row.prop(cache, "frame_start")
- row.prop(cache, "frame_end")
- if cachetype not in {'SMOKE', 'CLOTH', 'DYNAMIC_PAINT', 'RIGID_BODY'}:
- row.prop(cache, "frame_step")
-
- if cachetype != 'SMOKE':
- layout.label(text=cache.info)
-
- can_bake = True
-
- if cachetype not in {'SMOKE', 'DYNAMIC_PAINT', 'RIGID_BODY'}:
- split = layout.split()
- split.enabled = enabled and bpy.data.is_saved
-
- col = split.column()
- col.prop(cache, "use_disk_cache")
-
- col = split.column()
- col.active = cache.use_disk_cache
- col.prop(cache, "use_library_path", "Use Lib Path")
-
- row = layout.row()
- row.enabled = enabled and bpy.data.is_saved
- row.active = cache.use_disk_cache
- row.label(text="Compression:")
- row.prop(cache, "compression", expand=True)
-
- layout.separator()
-
- if cache.id_data.library and not cache.use_disk_cache:
- can_bake = False
-
- col = layout.column(align=True)
- col.label(text="Linked object baking requires Disk Cache to be enabled", icon='INFO')
- else:
- layout.separator()
-
- split = layout.split()
- split.active = can_bake
-
- col = split.column()
-
- if cache.is_baked is True:
- col.operator("ptcache.free_bake", text="Free Bake")
- else:
- col.operator("ptcache.bake", text="Bake").bake = True
-
- sub = col.row()
- sub.enabled = (cache.is_frame_skip or cache.is_outdated) and enabled
- sub.operator("ptcache.bake", text="Calculate To Frame").bake = False
-
- sub = col.column()
- sub.enabled = enabled
- sub.operator("ptcache.bake_from_cache", text="Current Cache to Bake")
-
- col = split.column()
- col.operator("ptcache.bake_all", text="Bake All Dynamics").bake = True
- col.operator("ptcache.free_bake_all", text="Free All Bakes")
- col.operator("ptcache.bake_all", text="Update All To Frame").bake = False
-
-
def effector_weights_ui(self, context, weights, weight_type):
layout = self.layout
diff --git a/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py b/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py
index 6c3a3246cf6..b3640463224 100644
--- a/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py
+++ b/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py
@@ -21,7 +21,6 @@ import bpy
from bpy.types import Panel, UIList
from bl_ui.properties_physics_common import (
- point_cache_ui,
effector_weights_ui,
)
@@ -125,10 +124,8 @@ class PHYSICS_PT_dynamic_paint(PhysicButtonsPanel, Panel):
col = split.column()
if not use_shading_nodes:
- sub = col.column()
- sub.active = (brush.paint_source != 'PARTICLE_SYSTEM')
- sub.prop(brush, "use_material")
- if brush.use_material and brush.paint_source != 'PARTICLE_SYSTEM' and not use_shading_nodes:
+ col.prop(brush, "use_material")
+ if brush.use_material and not use_shading_nodes:
col.prop(brush, "material", text="")
col.prop(brush, "paint_alpha", text="Alpha Factor")
else:
@@ -393,29 +390,6 @@ class PHYSICS_PT_dp_effects(PhysicButtonsPanel, Panel):
row.prop(surface, "shrink_speed")
-class PHYSICS_PT_dp_cache(PhysicButtonsPanel, Panel):
- bl_label = "Dynamic Paint Cache"
- bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
-
- @classmethod
- def poll(cls, context):
- md = context.dynamic_paint
- rd = context.scene.render
- return (md and
- md.ui_type == 'CANVAS' and
- md.canvas_settings and
- md.canvas_settings.canvas_surfaces.active and
- md.canvas_settings.canvas_surfaces.active.is_cache_user and
- (rd.engine in cls.COMPAT_ENGINES))
-
- def draw(self, context):
- surface = context.dynamic_paint.canvas_settings.canvas_surfaces.active
- cache = surface.point_cache
-
- point_cache_ui(self, context, cache, (cache.is_baked is False), 'DYNAMIC_PAINT')
-
-
class PHYSICS_PT_dp_brush_source(PhysicButtonsPanel, Panel):
bl_label = "Dynamic Paint Source"
COMPAT_ENGINES = {'BLENDER_RENDER'}
@@ -436,16 +410,6 @@ class PHYSICS_PT_dp_brush_source(PhysicButtonsPanel, Panel):
col = split.column()
col.prop(brush, "paint_source")
- if brush.paint_source == 'PARTICLE_SYSTEM':
- col.prop_search(brush, "particle_system", ob, "particle_systems", text="")
- if brush.particle_system:
- col.label(text="Particle effect:")
- sub = col.column()
- sub.active = not brush.use_particle_radius
- sub.prop(brush, "solid_radius", text="Solid Radius")
- col.prop(brush, "use_particle_radius", text="Use Particle's Radius")
- col.prop(brush, "smooth_radius", text="Smooth radius")
-
if brush.paint_source in {'DISTANCE', 'VOLUME_DISTANCE', 'POINT'}:
col.prop(brush, "paint_distance", text="Paint Distance")
split = layout.row().split(percentage=0.4)
diff --git a/release/scripts/startup/bl_ui/properties_physics_smoke.py b/release/scripts/startup/bl_ui/properties_physics_smoke.py
index df03f23a4b5..9d9dd529322 100644
--- a/release/scripts/startup/bl_ui/properties_physics_smoke.py
+++ b/release/scripts/startup/bl_ui/properties_physics_smoke.py
@@ -21,7 +21,6 @@ import bpy
from bpy.types import Panel
from bl_ui.properties_physics_common import (
- point_cache_ui,
effector_weights_ui,
)
@@ -55,8 +54,6 @@ class PHYSICS_PT_smoke(PhysicButtonsPanel, Panel):
split = layout.split()
- split.enabled = not domain.point_cache.is_baked
-
col = split.column()
col.label(text="Resolution:")
col.prop(domain, "resolution_max", text="Divisions")
@@ -87,14 +84,7 @@ class PHYSICS_PT_smoke(PhysicButtonsPanel, Panel):
col = split.column()
col.label(text="Flow Source:")
col.prop(flow, "smoke_flow_source", expand=False, text="")
- if flow.smoke_flow_source == 'PARTICLES':
- col.label(text="Particle System:")
- col.prop_search(flow, "particle_system", ob, "particle_systems", text="")
- col.prop(flow, "use_particle_size", text="Set Size")
- sub = col.column()
- sub.active = flow.use_particle_size
- sub.prop(flow, "particle_size")
- else:
+ if flow.smoke_flow_source == 'MESH':
col.prop(flow, "surface_distance")
col.prop(flow, "volume_density")
@@ -179,7 +169,6 @@ class PHYSICS_PT_smoke_fire(PhysicButtonsPanel, Panel):
domain = context.smoke.domain_settings
split = layout.split()
- split.enabled = not domain.point_cache.is_baked
col = split.column(align=True)
col.label(text="Reaction:")
@@ -216,7 +205,6 @@ class PHYSICS_PT_smoke_adaptive_domain(PhysicButtonsPanel, Panel):
layout.active = domain.use_adaptive_domain
split = layout.split()
- split.enabled = (not domain.point_cache.is_baked)
col = split.column(align=True)
col.label(text="Resolution:")
@@ -252,7 +240,6 @@ class PHYSICS_PT_smoke_highres(PhysicButtonsPanel, Panel):
layout.active = md.use_high_resolution
split = layout.split()
- split.enabled = not md.point_cache.is_baked
col = split.column()
col.label(text="Resolution:")
@@ -316,10 +303,7 @@ class PHYSICS_PT_smoke_cache(PhysicButtonsPanel, Panel):
layout.prop(domain, "cache_file_format")
- if cache_file_format == 'POINTCACHE':
- layout.label(text="Compression:")
- layout.prop(domain, "point_cache_compress_type", expand=True)
- elif cache_file_format == 'OPENVDB':
+ if cache_file_format == 'OPENVDB':
if not bpy.app.build_options.openvdb:
layout.label("Built without OpenVDB support")
return
@@ -330,9 +314,6 @@ class PHYSICS_PT_smoke_cache(PhysicButtonsPanel, Panel):
row.label("Data Depth:")
row.prop(domain, "data_depth", expand=True, text="Data Depth")
- cache = domain.point_cache
- point_cache_ui(self, context, cache, (cache.is_baked is False), 'SMOKE')
-
class PHYSICS_PT_smoke_field_weights(PhysicButtonsPanel, Panel):
bl_label = "Smoke Field Weights"
diff --git a/release/scripts/startup/bl_ui/properties_physics_softbody.py b/release/scripts/startup/bl_ui/properties_physics_softbody.py
index a458af739f2..e873bb40013 100644
--- a/release/scripts/startup/bl_ui/properties_physics_softbody.py
+++ b/release/scripts/startup/bl_ui/properties_physics_softbody.py
@@ -21,13 +21,13 @@ import bpy
from bpy.types import Panel
from bl_ui.properties_physics_common import (
- point_cache_ui,
effector_weights_ui,
)
def softbody_panel_enabled(md):
- return (md.point_cache.is_baked is False)
+ return True
+ #return (md.point_cache.is_baked is False)
class PhysicButtonsPanel:
@@ -71,16 +71,6 @@ class PHYSICS_PT_softbody(PhysicButtonsPanel, Panel):
layout.prop(softbody, "collision_group")
-class PHYSICS_PT_softbody_cache(PhysicButtonsPanel, Panel):
- bl_label = "Soft Body Cache"
- bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
-
- def draw(self, context):
- md = context.soft_body
- point_cache_ui(self, context, md.point_cache, softbody_panel_enabled(md), 'SOFTBODY')
-
-
class PHYSICS_PT_softbody_goal(PhysicButtonsPanel, Panel):
bl_label = "Soft Body Goal"
bl_options = {'DEFAULT_CLOSED'}
diff --git a/release/scripts/startup/bl_ui/properties_scene.py b/release/scripts/startup/bl_ui/properties_scene.py
index d6253ec7fbc..7b7e2367a42 100644
--- a/release/scripts/startup/bl_ui/properties_scene.py
+++ b/release/scripts/startup/bl_ui/properties_scene.py
@@ -27,7 +27,6 @@ from bpy.types import (
from rna_prop_ui import PropertyPanel
from bl_ui.properties_physics_common import (
- point_cache_ui,
effector_weights_ui,
)
@@ -371,24 +370,6 @@ class SCENE_PT_rigid_body_world(SceneButtonsPanel, Panel):
col.prop(rbw, "solver_iterations", text="Solver Iterations")
-class SCENE_PT_rigid_body_cache(SceneButtonsPanel, Panel):
- bl_label = "Rigid Body Cache"
- bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
-
- @classmethod
- def poll(cls, context):
- rd = context.scene.render
- scene = context.scene
- return scene and scene.rigidbody_world and (rd.engine in cls.COMPAT_ENGINES)
-
- def draw(self, context):
- scene = context.scene
- rbw = scene.rigidbody_world
-
- point_cache_ui(self, context, rbw.point_cache, rbw.point_cache.is_baked is False and rbw.enabled, 'RIGID_BODY')
-
-
class SCENE_PT_rigid_body_field_weights(SceneButtonsPanel, Panel):
bl_label = "Rigid Body Field Weights"
bl_options = {'DEFAULT_CLOSED'}
@@ -427,12 +408,10 @@ class SCENE_PT_simplify(SceneButtonsPanel, Panel):
col = split.column()
col.label(text="Viewport:")
col.prop(rd, "simplify_subdivision", text="Subdivision")
- col.prop(rd, "simplify_child_particles", text="Child Particles")
col = split.column()
col.label(text="Render:")
col.prop(rd, "simplify_subdivision_render", text="Subdivision")
- col.prop(rd, "simplify_child_particles_render", text="Child Particles")
col.prop(rd, "simplify_shadow_samples", text="Shadow Samples")
col.prop(rd, "simplify_ao_sss", text="AO and SSS")
col.prop(rd, "use_simplify_triangulate")
diff --git a/release/scripts/startup/bl_ui/properties_texture.py b/release/scripts/startup/bl_ui/properties_texture.py
index caf19a9e469..9bbef2ebdaf 100644
--- a/release/scripts/startup/bl_ui/properties_texture.py
+++ b/release/scripts/startup/bl_ui/properties_texture.py
@@ -26,7 +26,6 @@ from bpy.types import (
Lamp,
Material,
Object,
- ParticleSettings,
Texture,
World,
)
@@ -101,9 +100,6 @@ def context_tex_datablock(context):
if idblock:
return idblock
- if context.particle_system:
- idblock = context.particle_system.settings
-
return idblock
@@ -142,8 +138,6 @@ class TEXTURE_PT_context_texture(TextureButtonsPanel, Panel):
context.lamp or
context.texture or
context.line_style or
- context.particle_system or
- isinstance(context.space_data.pin_id, ParticleSettings) or
context.texture_user) and
(engine in cls.COMPAT_ENGINES))
@@ -811,18 +805,7 @@ class TEXTURE_PT_pointdensity(TextureButtonsPanel, Panel):
split = layout.split()
col = split.column()
- if pd.point_source == 'PARTICLE_SYSTEM':
- col.label(text="Object:")
- col.prop(pd, "object", text="")
-
- sub = col.column()
- sub.enabled = bool(pd.object)
- if pd.object:
- sub.label(text="System:")
- sub.prop_search(pd, "particle_system", pd.object, "particle_systems", text="")
- sub.label(text="Cache:")
- sub.prop(pd, "particle_cache_space", text="")
- else:
+ if pd.point_source == 'OBJECT':
col.label(text="Object:")
col.prop(pd, "object", text="")
col.label(text="Cache:")
@@ -831,13 +814,7 @@ class TEXTURE_PT_pointdensity(TextureButtonsPanel, Panel):
col.separator()
col.label(text="Color Source:")
- if pd.point_source == 'PARTICLE_SYSTEM':
- col.prop(pd, "particle_color_source", text="")
- if pd.particle_color_source in {'PARTICLE_SPEED', 'PARTICLE_VELOCITY'}:
- col.prop(pd, "speed_scale")
- if pd.particle_color_source in {'PARTICLE_SPEED', 'PARTICLE_AGE'}:
- layout.template_color_ramp(pd, "color_ramp", expand=True)
- else:
+ if pd.point_source == 'OBJECT':
col.prop(pd, "vertex_color_source", text="")
if pd.vertex_color_source == 'VERTEX_COLOR':
if pd.object and pd.object.data:
@@ -854,8 +831,6 @@ class TEXTURE_PT_pointdensity(TextureButtonsPanel, Panel):
col.prop(pd, "falloff", text="")
if pd.falloff == 'SOFT':
col.prop(pd, "falloff_soft")
- if pd.falloff == 'PARTICLE_VELOCITY':
- col.prop(pd, "falloff_speed_scale")
col.prop(pd, "use_falloff_curve")
@@ -1147,35 +1122,6 @@ class TEXTURE_PT_influence(TextureSlotPanel, Panel):
col = split.column()
factor_but(col, "use_map_zenith_up", "zenith_up_factor", "Zenith Up")
factor_but(col, "use_map_zenith_down", "zenith_down_factor", "Zenith Down")
- elif isinstance(idblock, ParticleSettings):
- split = layout.split()
-
- col = split.column()
- col.label(text="General:")
- factor_but(col, "use_map_time", "time_factor", "Time")
- factor_but(col, "use_map_life", "life_factor", "Lifetime")
- factor_but(col, "use_map_density", "density_factor", "Density")
- factor_but(col, "use_map_size", "size_factor", "Size")
-
- col = split.column()
- col.label(text="Physics:")
- factor_but(col, "use_map_velocity", "velocity_factor", "Velocity")
- factor_but(col, "use_map_damp", "damp_factor", "Damp")
- factor_but(col, "use_map_gravity", "gravity_factor", "Gravity")
- factor_but(col, "use_map_field", "field_factor", "Force Fields")
-
- layout.label(text="Hair:")
-
- split = layout.split()
-
- col = split.column()
- factor_but(col, "use_map_length", "length_factor", "Length")
- factor_but(col, "use_map_clump", "clump_factor", "Clump")
-
- col = split.column()
- factor_but(col, "use_map_kink_amp", "kink_amp_factor", "Kink Amplitude")
- factor_but(col, "use_map_kink_freq", "kink_freq_factor", "Kink Frequency")
- factor_but(col, "use_map_rough", "rough_factor", "Rough")
elif isinstance(idblock, FreestyleLineStyle):
split = layout.split()
@@ -1187,18 +1133,17 @@ class TEXTURE_PT_influence(TextureSlotPanel, Panel):
layout.separator()
- if not isinstance(idblock, ParticleSettings):
- split = layout.split()
+ split = layout.split()
- col = split.column()
- col.prop(tex, "blend_type", text="Blend")
- col.prop(tex, "use_rgb_to_intensity")
- # color is used on gray-scale textures even when use_rgb_to_intensity is disabled.
- col.prop(tex, "color", text="")
+ col = split.column()
+ col.prop(tex, "blend_type", text="Blend")
+ col.prop(tex, "use_rgb_to_intensity")
+ # color is used on gray-scale textures even when use_rgb_to_intensity is disabled.
+ col.prop(tex, "color", text="")
- col = split.column()
- col.prop(tex, "invert", text="Negative")
- col.prop(tex, "use_stencil")
+ col = split.column()
+ col.prop(tex, "invert", text="Negative")
+ col.prop(tex, "use_stencil")
if isinstance(idblock, Material) or isinstance(idblock, World):
col.prop(tex, "default_value", text="DVar", slider=True)
diff --git a/release/scripts/startup/bl_ui/space_dopesheet.py b/release/scripts/startup/bl_ui/space_dopesheet.py
index 4d365c8dc08..be9752a463e 100644
--- a/release/scripts/startup/bl_ui/space_dopesheet.py
+++ b/release/scripts/startup/bl_ui/space_dopesheet.py
@@ -92,8 +92,6 @@ def dopesheet_filter(layout, context, genericFiltersOnly=False):
row.prop(dopesheet, "show_lattices", text="")
if bpy.data.armatures:
row.prop(dopesheet, "show_armatures", text="")
- if bpy.data.particles:
- row.prop(dopesheet, "show_particles", text="")
if bpy.data.speakers:
row.prop(dopesheet, "show_speakers", text="")
if bpy.data.linestyles:
diff --git a/release/scripts/startup/bl_ui/space_time.py b/release/scripts/startup/bl_ui/space_time.py
index 508e62e4f56..894be977822 100644
--- a/release/scripts/startup/bl_ui/space_time.py
+++ b/release/scripts/startup/bl_ui/space_time.py
@@ -171,7 +171,6 @@ class TIME_MT_cache(Menu):
col = layout.column()
col.enabled = st.show_cache
col.prop(st, "cache_softbody")
- col.prop(st, "cache_particles")
col.prop(st, "cache_cloth")
col.prop(st, "cache_smoke")
col.prop(st, "cache_dynamicpaint")
diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py
index dcafac66fca..ab51e703e37 100644
--- a/release/scripts/startup/bl_ui/space_userpref.py
+++ b/release/scripts/startup/bl_ui/space_userpref.py
@@ -371,7 +371,6 @@ class USERPREF_PT_edit(Panel):
col.prop(edit, "use_duplicate_texture", text="Texture")
#col.prop(edit, "use_duplicate_fcurve", text="F-Curve")
col.prop(edit, "use_duplicate_action", text="Action")
- col.prop(edit, "use_duplicate_particle", text="Particle")
class USERPREF_PT_system(Panel):
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index c86b049eb81..44968632d4b 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -49,12 +49,9 @@ class VIEW3D_HT_header(Header):
if obj:
mode = obj.mode
- # Particle edit
- if mode == 'PARTICLE_EDIT':
- row.prop(toolsettings.particle_edit, "select_mode", text="", expand=True)
# Occlude geometry
- if ((view.viewport_shade not in {'BOUNDBOX', 'WIREFRAME'} and (mode == 'PARTICLE_EDIT' or (mode == 'EDIT' and obj.type == 'MESH'))) or
+ if ((view.viewport_shade not in {'BOUNDBOX', 'WIREFRAME'} and (mode == 'EDIT' and obj.type == 'MESH')) or
(mode == 'WEIGHT_PAINT')):
row.prop(view, "use_occlude_geometry", text="")
@@ -64,7 +61,7 @@ class VIEW3D_HT_header(Header):
row.prop(toolsettings, "proportional_edit", icon_only=True)
if toolsettings.proportional_edit != 'DISABLED':
row.prop(toolsettings, "proportional_edit_falloff", icon_only=True)
- elif mode in {'EDIT', 'PARTICLE_EDIT'}:
+ elif mode == 'EDIT':
row = layout.row(align=True)
row.prop(toolsettings, "proportional_edit", icon_only=True)
if toolsettings.proportional_edit != 'DISABLED':
@@ -703,35 +700,6 @@ class VIEW3D_MT_select_pose(Menu):
layout.operator("object.select_pattern", text="Select Pattern...")
-class VIEW3D_MT_select_particle(Menu):
- bl_label = "Select"
-
- def draw(self, context):
- layout = self.layout
-
- layout.operator("view3d.select_border")
-
- layout.separator()
-
- layout.operator("particle.select_all").action = 'TOGGLE'
- layout.operator("particle.select_linked")
- layout.operator("particle.select_all", text="Inverse").action = 'INVERT'
-
- layout.separator()
-
- layout.operator("particle.select_more")
- layout.operator("particle.select_less")
-
- layout.separator()
-
- layout.operator("particle.select_random")
-
- layout.separator()
-
- layout.operator("particle.select_roots", text="Roots")
- layout.operator("particle.select_tips", text="Tips")
-
-
class VIEW3D_MT_edit_mesh_select_similar(Menu):
bl_label = "Select Similar"
@@ -1922,87 +1890,8 @@ class VIEW3D_MT_hide_mask(Menu):
props = layout.operator("paint.mask_lasso_gesture", text="Lasso Mask")
-# ********** Particle menu **********
-
-
-class VIEW3D_MT_particle(Menu):
- bl_label = "Particle"
-
- def draw(self, context):
- layout = self.layout
-
- particle_edit = context.tool_settings.particle_edit
-
- layout.operator("ed.undo")
- layout.operator("ed.redo")
- layout.operator("ed.undo_history")
-
- layout.separator()
-
- layout.operator("particle.mirror")
-
- layout.separator()
-
- layout.operator("particle.remove_doubles")
- layout.operator("particle.delete")
-
- if particle_edit.select_mode == 'POINT':
- layout.operator("particle.subdivide")
-
layout.operator("particle.unify_length")
- layout.operator("particle.rekey")
- layout.operator("particle.weight_set")
-
- layout.separator()
-
- layout.menu("VIEW3D_MT_particle_showhide")
-
-
-class VIEW3D_MT_particle_specials(Menu):
- bl_label = "Specials"
-
- def draw(self, context):
- layout = self.layout
-
- particle_edit = context.tool_settings.particle_edit
-
- layout.operator("particle.rekey")
- layout.operator("particle.delete")
- layout.operator("particle.remove_doubles")
layout.operator("particle.unify_length")
-
- if particle_edit.select_mode == 'POINT':
- layout.operator("particle.subdivide")
-
- layout.operator("particle.weight_set")
- layout.separator()
-
- layout.operator("particle.mirror")
-
- if particle_edit.select_mode == 'POINT':
- layout.separator()
- layout.operator("particle.select_roots")
- layout.operator("particle.select_tips")
-
- layout.separator()
-
- layout.operator("particle.select_random")
-
- layout.separator()
-
- layout.operator("particle.select_more")
- layout.operator("particle.select_less")
-
- layout.separator()
-
- layout.operator("particle.select_all").action = 'TOGGLE'
- layout.operator("particle.select_linked")
- layout.operator("particle.select_all", text="Inverse").action = 'INVERT'
-
-
-class VIEW3D_MT_particle_showhide(ShowHideMenu, Menu):
- _operator_name = "particle"
-
# ********** Pose Menu **********
@@ -3088,6 +2977,31 @@ class VIEW3D_MT_edit_gpencil_transform(Menu):
# ********** Panel **********
+class VIEW3D_PT_viewport_debug(Panel):
+ bl_space_type = 'VIEW_3D'
+ bl_region_type = 'UI'
+ bl_label = "Modern Viewport"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ @classmethod
+ def poll(cls, context):
+ view = context.space_data
+ return (view)
+
+ def draw_header(self, context):
+ view = context.space_data
+ self.layout.prop(view, "use_modern_viewport", text="")
+
+ def draw(self, context):
+ layout = self.layout
+ view = context.space_data
+
+ layout.active = view.use_modern_viewport
+
+ col = layout.column()
+ col.label(text="Placeholder for debugging options")
+
+
class VIEW3D_PT_grease_pencil(GreasePencilDataPanel, Panel):
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
@@ -3201,7 +3115,7 @@ class VIEW3D_PT_view3d_display(Panel):
@classmethod
def poll(cls, context):
view = context.space_data
- return (view)
+ return (view) and not view.use_modern_viewport
def draw(self, context):
layout = self.layout
@@ -3304,6 +3218,11 @@ class VIEW3D_PT_view3d_shading(Panel):
bl_region_type = 'UI'
bl_label = "Shading"
+ @classmethod
+ def poll(cls, context):
+ view = context.space_data
+ return (view) and not view.use_modern_viewport
+
def draw(self, context):
layout = self.layout
diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
index 8019c8d2f34..71f81483aac 100644
--- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
@@ -942,37 +942,12 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
settings = self.paint_settings(context)
brush = settings.brush
- if not context.particle_edit_object:
- col = layout.split().column()
- col.template_ID_preview(settings, "brush", new="brush.add", rows=3, cols=8)
-
- # Particle Mode #
- if context.particle_edit_object:
- tool = settings.tool
-
- layout.column().prop(settings, "tool", expand=True)
-
- if tool != 'NONE':
- col = layout.column()
- col.prop(brush, "size", slider=True)
- if tool != 'ADD':
- col.prop(brush, "strength", slider=True)
-
- if tool == 'ADD':
- col.prop(brush, "count")
- col = layout.column()
- col.prop(settings, "use_default_interpolate")
- col.prop(brush, "steps", slider=True)
- col.prop(settings, "default_key_count", slider=True)
- elif tool == 'LENGTH':
- layout.prop(brush, "length_mode", expand=True)
- elif tool == 'PUFF':
- layout.prop(brush, "puff_mode", expand=True)
- layout.prop(brush, "use_puff_volume")
+ col = layout.split().column()
+ col.template_ID_preview(settings, "brush", new="brush.add", rows=3, cols=8)
# Sculpt Mode #
- elif context.sculpt_object and brush:
+ if context.sculpt_object and brush:
capabilities = brush.sculpt_capabilities
col = layout.column()
@@ -1657,7 +1632,7 @@ class VIEW3D_PT_tools_brush_appearance(Panel, View3DPaintPanel):
@classmethod
def poll(cls, context):
settings = cls.paint_settings(context)
- return (settings is not None) and (not isinstance(settings, bpy.types.ParticleEdit))
+ return (settings is not None)
def draw(self, context):
layout = self.layout
@@ -1880,78 +1855,6 @@ class VIEW3D_MT_tools_projectpaint_stencil(Menu):
props.value = i
-class VIEW3D_PT_tools_particlemode(View3DPanel, Panel):
- """Default tools for particle mode"""
- bl_context = "particlemode"
- bl_label = "Options"
- bl_category = "Tools"
-
- def draw(self, context):
- layout = self.layout
-
- pe = context.tool_settings.particle_edit
- ob = pe.object
-
- layout.prop(pe, "type", text="")
-
- ptcache = None
-
- if pe.type == 'PARTICLES':
- if ob.particle_systems:
- if len(ob.particle_systems) > 1:
- layout.template_list("UI_UL_list", "particle_systems", ob, "particle_systems",
- ob.particle_systems, "active_index", rows=2, maxrows=3)
-
- ptcache = ob.particle_systems.active.point_cache
- else:
- for md in ob.modifiers:
- if md.type == pe.type:
- ptcache = md.point_cache
-
- if ptcache and len(ptcache.point_caches) > 1:
- layout.template_list("UI_UL_list", "particles_point_caches", ptcache, "point_caches",
- ptcache.point_caches, "active_index", rows=2, maxrows=3)
-
- if not pe.is_editable:
- layout.label(text="Point cache must be baked")
- layout.label(text="in memory to enable editing!")
-
- col = layout.column(align=True)
- if pe.is_hair:
- col.active = pe.is_editable
- col.prop(pe, "use_emitter_deflect", text="Deflect emitter")
- sub = col.row(align=True)
- sub.active = pe.use_emitter_deflect
- sub.prop(pe, "emitter_distance", text="Distance")
-
- col = layout.column(align=True)
- col.active = pe.is_editable
- col.label(text="Keep:")
- col.prop(pe, "use_preserve_length", text="Lengths")
- col.prop(pe, "use_preserve_root", text="Root")
- if not pe.is_hair:
- col.label(text="Correct:")
- col.prop(pe, "use_auto_velocity", text="Velocity")
- col.prop(ob.data, "use_mirror_x")
-
- col.prop(pe, "shape_object")
- col.operator("particle.shape_cut")
-
- col = layout.column(align=True)
- col.active = pe.is_editable
- col.label(text="Draw:")
- col.prop(pe, "draw_step", text="Path Steps")
- if pe.is_hair:
- col.prop(pe, "show_particles", text="Children")
- else:
- if pe.type == 'PARTICLES':
- col.prop(pe, "show_particles", text="Particles")
- col.prop(pe, "use_fade_time")
- sub = col.row(align=True)
- sub.active = pe.use_fade_time
- sub.prop(pe, "fade_frames", slider=True)
-
-
# Grease Pencil drawing tools
class VIEW3D_PT_tools_grease_pencil_draw(GreasePencilDrawingToolsPanel, Panel):
bl_space_type = 'VIEW_3D'
diff --git a/source/blender/CMakeLists.txt b/source/blender/CMakeLists.txt
index 6f2b78e0845..d49ceb1636b 100644
--- a/source/blender/CMakeLists.txt
+++ b/source/blender/CMakeLists.txt
@@ -29,7 +29,6 @@ set(SRC_DNA_INC
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_actuator_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_anim_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_armature_types.h
- ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_boid_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_brush_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_cachefile_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_camera_types.h
@@ -68,7 +67,6 @@ set(SRC_DNA_INC
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_object_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_outliner_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_packedFile_types.h
- ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_particle_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_property_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_rigidbody_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_scene_types.h
diff --git a/source/blender/alembic/intern/abc_exporter.cc b/source/blender/alembic/intern/abc_exporter.cc
index d259721e192..5e66d6c2dc7 100644
--- a/source/blender/alembic/intern/abc_exporter.cc
+++ b/source/blender/alembic/intern/abc_exporter.cc
@@ -55,7 +55,6 @@ extern "C" {
#include "BKE_idprop.h"
#include "BKE_main.h"
#include "BKE_modifier.h"
-#include "BKE_particle.h"
#include "BKE_scene.h"
}
@@ -502,22 +501,6 @@ void AbcExporter::createShapeWriter(Object *ob, Object *dupliObParent)
return;
}
- ParticleSystem *psys = static_cast<ParticleSystem *>(ob->particlesystem.first);
-
- for (; psys; psys = psys->next) {
- if (!psys_check_enabled(ob, psys, G.is_rendering) || !psys->part) {
- continue;
- }
-
- if (psys->part->type == PART_HAIR) {
- m_settings.export_child_hairs = true;
- m_shapes.push_back(new AbcHairWriter(m_scene, ob, xform, m_shape_sampling_index, m_settings, psys));
- }
- else if (psys->part->type == PART_EMITTER) {
- m_shapes.push_back(new AbcPointsWriter(m_scene, ob, xform, m_shape_sampling_index, m_settings, psys));
- }
- }
-
switch(ob->type) {
case OB_MESH:
{
diff --git a/source/blender/alembic/intern/abc_hair.cc b/source/blender/alembic/intern/abc_hair.cc
index 14bcf6731ea..f10cfbadda8 100644
--- a/source/blender/alembic/intern/abc_hair.cc
+++ b/source/blender/alembic/intern/abc_hair.cc
@@ -37,7 +37,6 @@ extern "C" {
#include "BKE_DerivedMesh.h"
#include "BKE_object.h"
-#include "BKE_particle.h"
}
using Alembic::Abc::P3fArraySamplePtr;
@@ -54,13 +53,15 @@ AbcHairWriter::AbcHairWriter(Scene *scene,
AbcTransformWriter *parent,
uint32_t time_sampling,
ExportSettings &settings,
- ParticleSystem *psys)
+ void *UNUSED(psys))
: AbcObjectWriter(scene, ob, time_sampling, settings, parent)
{
- m_psys = psys;
+ m_psys = NULL; // = psys;
+#if 0
OCurves curves(parent->alembicXform(), psys->name, m_time_sampling);
m_schema = curves.getSchema();
+#endif
}
void AbcHairWriter::do_write()
@@ -68,7 +69,7 @@ void AbcHairWriter::do_write()
if (!m_psys) {
return;
}
-
+#if 0
ParticleSystemModifierData *psmd = psys_get_modifier(m_object, m_psys);
if (!psmd->dm_final) {
@@ -116,15 +117,17 @@ void AbcHairWriter::do_write()
m_sample.setSelfBounds(bounds());
m_schema.set(m_sample);
+#endif
}
void AbcHairWriter::write_hair_sample(DerivedMesh *dm,
- ParticleSettings *part,
+ void *part,
std::vector<Imath::V3f> &verts,
std::vector<Imath::V3f> &norm_values,
std::vector<Imath::V2f> &uv_values,
std::vector<int32_t> &hvertices)
{
+#if 0
/* Get untransformed vertices, there's a xform under the hair. */
float inv_mat[4][4];
invert_m4_m4_safe(inv_mat, m_object->obmat);
@@ -225,15 +228,17 @@ void AbcHairWriter::write_hair_sample(DerivedMesh *dm,
++path;
}
}
+#endif
}
void AbcHairWriter::write_hair_child_sample(DerivedMesh *dm,
- ParticleSettings *part,
+ void *part,
std::vector<Imath::V3f> &verts,
std::vector<Imath::V3f> &norm_values,
std::vector<Imath::V2f> &uv_values,
std::vector<int32_t> &hvertices)
{
+#if 0
/* Get untransformed vertices, there's a xform under the hair. */
float inv_mat[4][4];
invert_m4_m4_safe(inv_mat, m_object->obmat);
@@ -287,4 +292,5 @@ void AbcHairWriter::write_hair_child_sample(DerivedMesh *dm,
++path;
}
}
+#endif
}
diff --git a/source/blender/alembic/intern/abc_hair.h b/source/blender/alembic/intern/abc_hair.h
index d132b60be12..bbd5f2c4361 100644
--- a/source/blender/alembic/intern/abc_hair.h
+++ b/source/blender/alembic/intern/abc_hair.h
@@ -26,13 +26,11 @@
#include "abc_object.h"
struct DerivedMesh;
-struct ParticleSettings;
-struct ParticleSystem;
/* ************************************************************************** */
class AbcHairWriter : public AbcObjectWriter {
- ParticleSystem *m_psys;
+ /*ParticleSystem*/ void *m_psys;
Alembic::AbcGeom::OCurvesSchema m_schema;
Alembic::AbcGeom::OCurvesSchema::Sample m_sample;
@@ -43,20 +41,20 @@ public:
AbcTransformWriter *parent,
uint32_t time_sampling,
ExportSettings &settings,
- ParticleSystem *psys);
+ /*ParticleSystem*/void *psys);
private:
virtual void do_write();
void write_hair_sample(DerivedMesh *dm,
- ParticleSettings *part,
+ /*ParticleSettings*/ void *part,
std::vector<Imath::V3f> &verts,
std::vector<Imath::V3f> &norm_values,
std::vector<Imath::V2f> &uv_values,
std::vector<int32_t> &hvertices);
void write_hair_child_sample(DerivedMesh *dm,
- ParticleSettings *part,
+ /*ParticleSettings*/ void *part,
std::vector<Imath::V3f> &verts,
std::vector<Imath::V3f> &norm_values,
std::vector<Imath::V2f> &uv_values,
diff --git a/source/blender/alembic/intern/abc_mesh.cc b/source/blender/alembic/intern/abc_mesh.cc
index bb5d5ce3566..9b19a063e4e 100644
--- a/source/blender/alembic/intern/abc_mesh.cc
+++ b/source/blender/alembic/intern/abc_mesh.cc
@@ -262,7 +262,7 @@ static ModifierData *get_subsurf_modifier(Scene *scene, Object *ob)
}
/* mesh is not a subsurf. break */
- if ((md->type != eModifierType_Displace) && (md->type != eModifierType_ParticleSystem)) {
+ if ((md->type != eModifierType_Displace) /*&& (md->type != eModifierType_ParticleSystem)*/) {
return NULL;
}
}
diff --git a/source/blender/alembic/intern/abc_points.cc b/source/blender/alembic/intern/abc_points.cc
index 03014547416..bf9c483901d 100644
--- a/source/blender/alembic/intern/abc_points.cc
+++ b/source/blender/alembic/intern/abc_points.cc
@@ -35,7 +35,6 @@ extern "C" {
#include "BKE_lattice.h"
#include "BKE_mesh.h"
#include "BKE_object.h"
-#include "BKE_particle.h"
#include "BKE_scene.h"
#include "BLI_math.h"
@@ -62,13 +61,15 @@ AbcPointsWriter::AbcPointsWriter(Scene *scene,
AbcTransformWriter *parent,
uint32_t time_sampling,
ExportSettings &settings,
- ParticleSystem *psys)
+ void *UNUSED(psys))
: AbcObjectWriter(scene, ob, time_sampling, settings, parent)
{
- m_psys = psys;
+ m_psys = NULL; // = psys;
+#if 0
OPoints points(parent->alembicXform(), psys->name, m_time_sampling);
m_schema = points.getSchema();
+#endif
}
void AbcPointsWriter::do_write()
@@ -76,7 +77,7 @@ void AbcPointsWriter::do_write()
if (!m_psys) {
return;
}
-
+#if 0
std::vector<Imath::V3f> points;
std::vector<Imath::V3f> velocities;
std::vector<float> widths;
@@ -133,6 +134,7 @@ void AbcPointsWriter::do_write()
m_sample.setSelfBounds(bounds());
m_schema.set(m_sample);
+#endif
}
/* ************************************************************************** */
diff --git a/source/blender/alembic/intern/abc_points.h b/source/blender/alembic/intern/abc_points.h
index 51f3103bd8b..cfa51e66a22 100644
--- a/source/blender/alembic/intern/abc_points.h
+++ b/source/blender/alembic/intern/abc_points.h
@@ -28,14 +28,12 @@
#include "abc_object.h"
#include "abc_customdata.h"
-class ParticleSystem;
-
/* ************************************************************************** */
class AbcPointsWriter : public AbcObjectWriter {
Alembic::AbcGeom::OPointsSchema m_schema;
Alembic::AbcGeom::OPointsSchema::Sample m_sample;
- ParticleSystem *m_psys;
+ /*ParticleSystem*/ void *m_psys;
public:
AbcPointsWriter(Scene *scene,
@@ -43,7 +41,7 @@ public:
AbcTransformWriter *parent,
uint32_t time_sampling,
ExportSettings &settings,
- ParticleSystem *psys);
+ /*ParticleSystem*/ void *psys);
void do_write();
};
diff --git a/source/blender/blenfont/BLF_api.h b/source/blender/blenfont/BLF_api.h
index 1f38d64924c..3da0434687c 100644
--- a/source/blender/blenfont/BLF_api.h
+++ b/source/blender/blenfont/BLF_api.h
@@ -34,6 +34,9 @@
#include "BLI_compiler_attrs.h"
+/* enable this only if needed (unused circa 2016) */
+#define BLF_BLUR_ENABLE 0
+
struct rctf;
struct ColorManagedDisplay;
struct ResultBLF;
@@ -144,7 +147,10 @@ void BLF_rotation(int fontid, float angle);
void BLF_clipping(int fontid, float xmin, float ymin, float xmax, float ymax);
void BLF_clipping_default(float xmin, float ymin, float xmax, float ymax);
void BLF_wordwrap(int fontid, int wrap_width);
+
+#if BLF_BLUR_ENABLE
void BLF_blur(int fontid, int size);
+#endif
void BLF_enable(int fontid, int option);
void BLF_disable(int fontid, int option);
diff --git a/source/blender/blenfont/intern/blf.c b/source/blender/blenfont/intern/blf.c
index 132a0ec3808..1ce4753cc39 100644
--- a/source/blender/blenfont/intern/blf.c
+++ b/source/blender/blenfont/intern/blf.c
@@ -56,7 +56,9 @@
#include "IMB_colormanagement.h"
#ifndef BLF_STANDALONE
-#include "GPU_basic_shader.h"
+#include "GPU_shader.h"
+#include "GPU_matrix.h"
+#include "GPU_immediate.h"
#endif
#include "blf_internal_types.h"
@@ -453,6 +455,7 @@ void BLF_size(int fontid, int size, int dpi)
}
}
+#if BLF_BLUR_ENABLE
void BLF_blur(int fontid, int size)
{
FontBLF *font = blf_get(fontid);
@@ -461,6 +464,7 @@ void BLF_blur(int fontid, int size)
font->blur = size;
}
}
+#endif
void BLF_draw_default(float x, float y, float z, const char *str, size_t len)
{
@@ -490,7 +494,7 @@ void BLF_rotation_default(float angle)
}
}
-static void blf_draw_gl__start(FontBLF *font, GLint *mode)
+static void blf_draw_gl__start(FontBLF *font)
{
/*
* The pixmap alignment hack is handle
@@ -500,52 +504,48 @@ static void blf_draw_gl__start(FontBLF *font, GLint *mode)
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-#ifndef BLF_STANDALONE
- GPU_basic_shader_bind(GPU_SHADER_TEXTURE_2D | GPU_SHADER_USE_COLOR);
-#endif
-
- /* Save the current matrix mode. */
- glGetIntegerv(GL_MATRIX_MODE, mode);
-
- glMatrixMode(GL_TEXTURE);
- glPushMatrix();
- glLoadIdentity();
-
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
+ gpuMatrixBegin3D_legacy();
if (font->flags & BLF_MATRIX)
- glMultMatrixf(font->m);
+ gpuMultMatrix3D((float (*)[4])font->m);
- glTranslate3fv(font->pos);
+ gpuTranslate3fv(font->pos);
if (font->flags & BLF_ASPECT)
- glScalef(font->aspect[0], font->aspect[1], font->aspect[2]);
+ gpuScale3fv(font->aspect);
if (font->flags & BLF_ROTATION) /* radians -> degrees */
- glRotatef(font->angle * (float)(180.0 / M_PI), 0.0f, 0.0f, 1.0f);
+ gpuRotateAxis(RAD2DEG(font->angle), 'Z');
+
+ float temp_color[4];
+ glGetFloatv(GL_CURRENT_COLOR, temp_color); /* TODO(merwin): new BLF_color function? */
+ rgba_float_to_uchar(font->color, temp_color);
+
+#ifndef BLF_STANDALONE
+ VertexFormat *format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ unsigned texCoord = add_attrib(format, "texCoord", GL_FLOAT, 2, KEEP_FLOAT);
+ unsigned color = add_attrib(format, "color", GL_UNSIGNED_BYTE, 4, NORMALIZE_INT_TO_FLOAT);
+
+ BLI_assert(pos == BLF_POS_ID);
+ BLI_assert(texCoord == BLF_COORD_ID);
+ BLI_assert(color == BLF_COLOR_ID);
- if (font->shadow || font->blur)
- glGetFloatv(GL_CURRENT_COLOR, font->orig_col);
+ immBindBuiltinProgram(GPU_SHADER_TEXT);
+#endif
/* always bind the texture for the first glyph */
font->tex_bind_state = -1;
}
-static void blf_draw_gl__end(GLint mode)
+static void blf_draw_gl__end(void)
{
- glMatrixMode(GL_TEXTURE);
- glPopMatrix();
-
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
-
- if (mode != GL_MODELVIEW)
- glMatrixMode(mode);
+ gpuMatrixEnd();
#ifndef BLF_STANDALONE
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
+ immUnbindProgram();
#endif
+
glDisable(GL_BLEND);
}
@@ -554,23 +554,26 @@ void BLF_draw_ex(
struct ResultBLF *r_info)
{
FontBLF *font = blf_get(fontid);
- GLint mode;
BLF_RESULT_CHECK_INIT(r_info);
if (font && font->glyph_cache) {
- blf_draw_gl__start(font, &mode);
+ blf_draw_gl__start(font);
if (font->flags & BLF_WORD_WRAP) {
blf_font_draw__wrap(font, str, len, r_info);
}
else {
blf_font_draw(font, str, len, r_info);
}
- blf_draw_gl__end(mode);
+ blf_draw_gl__end();
}
}
void BLF_draw(int fontid, const char *str, size_t len)
{
+ if (len == 0 || str[0] == '\0') {
+ return;
+ }
+
BLF_draw_ex(fontid, str, len, NULL);
}
@@ -579,12 +582,11 @@ void BLF_draw_ascii_ex(
struct ResultBLF *r_info)
{
FontBLF *font = blf_get(fontid);
- GLint mode;
BLF_RESULT_CHECK_INIT(r_info);
if (font && font->glyph_cache) {
- blf_draw_gl__start(font, &mode);
+ blf_draw_gl__start(font);
if (font->flags & BLF_WORD_WRAP) {
/* use non-ascii draw function for word-wrap */
blf_font_draw__wrap(font, str, len, r_info);
@@ -592,24 +594,31 @@ void BLF_draw_ascii_ex(
else {
blf_font_draw_ascii(font, str, len, r_info);
}
- blf_draw_gl__end(mode);
+ blf_draw_gl__end();
}
}
void BLF_draw_ascii(int fontid, const char *str, size_t len)
{
+ if (len == 0 || str[0] == '\0') {
+ return;
+ }
+
BLF_draw_ascii_ex(fontid, str, len, NULL);
}
int BLF_draw_mono(int fontid, const char *str, size_t len, int cwidth)
{
+ if (len == 0 || str[0] == '\0') {
+ return 0;
+ }
+
FontBLF *font = blf_get(fontid);
- GLint mode;
int columns = 0;
if (font && font->glyph_cache) {
- blf_draw_gl__start(font, &mode);
+ blf_draw_gl__start(font);
columns = blf_font_draw_mono(font, str, len, cwidth);
- blf_draw_gl__end(mode);
+ blf_draw_gl__end();
}
return columns;
@@ -855,7 +864,7 @@ void BLF_shadow(int fontid, int level, const float rgba[4])
if (font) {
font->shadow = level;
- copy_v4_v4(font->shadow_col, rgba);
+ rgba_float_to_uchar(font->shadow_color, rgba);
}
}
diff --git a/source/blender/blenfont/intern/blf_font.c b/source/blender/blenfont/intern/blf_font.c
index 44a1d08f1fd..71350a0f8dc 100644
--- a/source/blender/blenfont/intern/blf_font.c
+++ b/source/blender/blenfont/intern/blf_font.c
@@ -58,6 +58,8 @@
#include "BIF_gl.h"
#include "BLF_api.h"
+#include "GPU_immediate.h"
+
#include "blf_internal_types.h"
#include "blf_internal.h"
@@ -172,6 +174,23 @@ static void blf_font_ensure_ascii_table(FontBLF *font)
} \
} (void)0
+static unsigned verts_needed(const FontBLF *font, const char *str, size_t len)
+{
+ unsigned length = (unsigned)((len == INT_MAX) ? strlen(str) : len);
+ unsigned quad_ct = 1;
+
+ if (font->flags & BLF_SHADOW) {
+ if (font->shadow == 0)
+ quad_ct += 1;
+ if (font->shadow <= 4)
+ quad_ct += 9; /* 3x3 kernel */
+ else
+ quad_ct += 25; /* 5x5 kernel */
+ }
+
+ return length * quad_ct * 4;
+}
+
static void blf_font_draw_ex(
FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info,
int pen_y)
@@ -187,6 +206,9 @@ static void blf_font_draw_ex(
blf_font_ensure_ascii_table(font);
+ immBeginAtMost(GL_QUADS, verts_needed(font, str, len));
+ /* at most because some glyphs might be clipped & not drawn */
+
while ((i < len) && str[i]) {
BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table);
@@ -204,6 +226,8 @@ static void blf_font_draw_ex(
g_prev = g;
}
+ immEnd();
+
if (r_info) {
r_info->lines = 1;
r_info->width = pen_x;
@@ -229,6 +253,8 @@ static void blf_font_draw_ascii_ex(
blf_font_ensure_ascii_table(font);
+ immBeginAtMost(GL_QUADS, verts_needed(font, str, len));
+
while ((c = *(str++)) && len--) {
BLI_assert(c < 128);
if ((g = glyph_ascii_table[c]) == NULL)
@@ -243,6 +269,8 @@ static void blf_font_draw_ascii_ex(
g_prev = g;
}
+ immEnd();
+
if (r_info) {
r_info->lines = 1;
r_info->width = pen_x;
@@ -265,6 +293,8 @@ int blf_font_draw_mono(FontBLF *font, const char *str, size_t len, int cwidth)
blf_font_ensure_ascii_table(font);
+ immBeginAtMost(GL_QUADS, verts_needed(font, str, len));
+
while ((i < len) && str[i]) {
BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table);
@@ -284,6 +314,8 @@ int blf_font_draw_mono(FontBLF *font, const char *str, size_t len, int cwidth)
pen_x += cwidth * col;
}
+ immEnd();
+
return columns;
}
@@ -922,7 +954,9 @@ static void blf_font_fill(FontBLF *font)
font->size = 0;
BLI_listbase_clear(&font->cache);
font->glyph_cache = NULL;
+#if BLF_BLUR_ENABLE
font->blur = 0;
+#endif
font->max_tex_size = -1;
font->buf_info.fbuf = NULL;
diff --git a/source/blender/blenfont/intern/blf_glyph.c b/source/blender/blenfont/intern/blf_glyph.c
index aa7d539538b..b1bab13f3ae 100644
--- a/source/blender/blenfont/intern/blf_glyph.c
+++ b/source/blender/blenfont/intern/blf_glyph.c
@@ -56,7 +56,7 @@
#include "BLF_api.h"
#ifndef BLF_STANDALONE
-#include "GPU_basic_shader.h"
+#include "GPU_immediate.h"
#endif
#include "blf_internal_types.h"
@@ -182,17 +182,6 @@ static void blf_glyph_cache_texture(FontBLF *font, GlyphCacheBLF *gc)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-
-#ifndef BLF_STANDALONE
- /* needed since basic shader doesn't support alpha-only textures,
- * while we could add support this is only used in a few places
- * (an alternative could be to have a simple shader for BLF). */
- if (GLEW_ARB_texture_swizzle && GPU_basic_shader_use_glsl_get()) {
- GLint swizzle_mask[] = {GL_ONE, GL_ONE, GL_ONE, GL_ALPHA};
- glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzle_mask);
- }
-#endif
-
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA8, gc->p2_width, gc->p2_height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, NULL);
}
@@ -326,73 +315,73 @@ void blf_glyph_free(GlyphBLF *g)
MEM_freeN(g);
}
-static void blf_texture_draw(float uv[2][2], float dx, float y1, float dx1, float y2)
+static void blf_texture_draw(const unsigned char color[4], float uv[2][2], float dx, float y1, float dx1, float y2)
{
- glBegin(GL_QUADS);
- glTexCoord2f(uv[0][0], uv[0][1]);
- glVertex2f(dx, y1);
-
- glTexCoord2f(uv[0][0], uv[1][1]);
- glVertex2f(dx, y2);
-
- glTexCoord2f(uv[1][0], uv[1][1]);
- glVertex2f(dx1, y2);
-
- glTexCoord2f(uv[1][0], uv[0][1]);
- glVertex2f(dx1, y1);
- glEnd();
+ immAttrib2f(BLF_COORD_ID, uv[0][0], uv[0][1]);
+ immSkipAttrib(BLF_COLOR_ID); /* skip color of most vertices */
+ immVertex2f(BLF_POS_ID, dx, y1);
+
+ immAttrib2f(BLF_COORD_ID, uv[0][0], uv[1][1]);
+ immSkipAttrib(BLF_COLOR_ID);
+ immVertex2f(BLF_POS_ID, dx, y2);
+
+ immAttrib2f(BLF_COORD_ID, uv[1][0], uv[1][1]);
+ immSkipAttrib(BLF_COLOR_ID);
+ immVertex2f(BLF_POS_ID, dx1, y2);
+
+ immAttrib2f(BLF_COORD_ID, uv[1][0], uv[0][1]);
+ immAttrib4ubv(BLF_COLOR_ID, color); /* set color of provoking vertex */
+ immVertex2f(BLF_POS_ID, dx1, y1);
}
-static void blf_texture5_draw(const float shadow_col[4], float uv[2][2], float x1, float y1, float x2, float y2)
+static void blf_texture5_draw(const unsigned char color_in[4], float uv[2][2], float x1, float y1, float x2, float y2)
{
const float soft[25] = {1 / 60.0f, 1 / 60.0f, 2 / 60.0f, 1 / 60.0f, 1 / 60.0f,
1 / 60.0f, 3 / 60.0f, 5 / 60.0f, 3 / 60.0f, 1 / 60.0f,
2 / 60.0f, 5 / 60.0f, 8 / 60.0f, 5 / 60.0f, 2 / 60.0f,
1 / 60.0f, 3 / 60.0f, 5 / 60.0f, 3 / 60.0f, 1 / 60.0f,
1 / 60.0f, 1 / 60.0f, 2 / 60.0f, 1 / 60.0f, 1 / 60.0f};
-
+
const float *fp = soft;
- float color[4];
+ unsigned char color[4];
float dx, dy;
- color[0] = shadow_col[0];
- color[1] = shadow_col[1];
- color[2] = shadow_col[2];
-
+ color[0] = color_in[0];
+ color[1] = color_in[1];
+ color[2] = color_in[2];
+
+ const float alpha_in = (1 / 255.0f) * color_in[3];
+
for (dx = -2; dx < 3; dx++) {
for (dy = -2; dy < 3; dy++, fp++) {
- color[3] = *(fp) * shadow_col[3];
- glColor4fv(color);
- blf_texture_draw(uv, x1 + dx, y1 + dy, x2 + dx, y2 + dy);
+ color[3] = FTOCHAR(*fp * alpha_in);
+ blf_texture_draw(color, uv, x1 + dx, y1 + dy, x2 + dx, y2 + dy);
}
}
-
- glColor4fv(color);
}
-static void blf_texture3_draw(const float shadow_col[4], float uv[2][2], float x1, float y1, float x2, float y2)
+static void blf_texture3_draw(const unsigned char color_in[4], float uv[2][2], float x1, float y1, float x2, float y2)
{
const float soft[9] = {1 / 16.0f, 2 / 16.0f, 1 / 16.0f,
2 / 16.0f, 4 / 16.0f, 2 / 16.0f,
1 / 16.0f, 2 / 16.0f, 1 / 16.0f};
const float *fp = soft;
- float color[4];
+ unsigned char color[4];
float dx, dy;
- color[0] = shadow_col[0];
- color[1] = shadow_col[1];
- color[2] = shadow_col[2];
+ color[0] = color_in[0];
+ color[1] = color_in[1];
+ color[2] = color_in[2];
+
+ const float alpha_in = (1 / 255.0f) * color_in[3];
for (dx = -1; dx < 2; dx++) {
for (dy = -1; dy < 2; dy++, fp++) {
- color[3] = *(fp) * shadow_col[3];
- glColor4fv(color);
- blf_texture_draw(uv, x1 + dx, y1 + dy, x2 + dx, y2 + dy);
+ color[3] = FTOCHAR(*fp * alpha_in);
+ blf_texture_draw(color, uv, x1 + dx, y1 + dy, x2 + dx, y2 + dy);
}
}
-
- glColor4fv(color);
}
static void blf_glyph_calc_rect(rctf *rect, GlyphBLF *g, float x, float y)
@@ -486,39 +475,37 @@ void blf_glyph_render(FontBLF *font, GlyphBLF *g, float x, float y)
glBindTexture(GL_TEXTURE_2D, (font->tex_bind_state = g->tex));
}
+ /* TODO: blur & shadow in shader, single quad per glyph */
+
if (font->flags & BLF_SHADOW) {
rctf rect_ofs;
blf_glyph_calc_rect(&rect_ofs, g,
x + (float)font->shadow_x,
y + (float)font->shadow_y);
- switch (font->shadow) {
- case 3:
- blf_texture3_draw(font->shadow_col, g->uv, rect_ofs.xmin, rect_ofs.ymin, rect_ofs.xmax, rect_ofs.ymax);
- break;
- case 5:
- blf_texture5_draw(font->shadow_col, g->uv, rect_ofs.xmin, rect_ofs.ymin, rect_ofs.xmax, rect_ofs.ymax);
- break;
- default:
- glColor4fv(font->shadow_col);
- blf_texture_draw(g->uv, rect_ofs.xmin, rect_ofs.ymin, rect_ofs.xmax, rect_ofs.ymax);
- break;
+ if (font->shadow == 0) {
+ blf_texture_draw(font->shadow_color, g->uv, rect_ofs.xmin, rect_ofs.ymin, rect_ofs.xmax, rect_ofs.ymax);
+ }
+ else if (font->shadow <= 4) {
+ blf_texture3_draw(font->shadow_color, g->uv, rect_ofs.xmin, rect_ofs.ymin, rect_ofs.xmax, rect_ofs.ymax);
+ }
+ else {
+ blf_texture5_draw(font->shadow_color, g->uv, rect_ofs.xmin, rect_ofs.ymin, rect_ofs.xmax, rect_ofs.ymax);
}
-
- glColor4fv(font->orig_col);
}
+#if BLF_BLUR_ENABLE
switch (font->blur) {
case 3:
- blf_texture3_draw(font->orig_col, g->uv, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+ blf_texture3_draw(font->color, g->uv, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
break;
case 5:
- blf_texture5_draw(font->orig_col, g->uv, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+ blf_texture5_draw(font->color, g->uv, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
break;
default:
- blf_texture_draw(g->uv, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
- break;
+ blf_texture_draw(font->color, g->uv, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
}
-
- return;
+#else
+ blf_texture_draw(font->color, g->uv, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+#endif
}
diff --git a/source/blender/blenfont/intern/blf_internal.h b/source/blender/blenfont/intern/blf_internal.h
index d9d758ce548..ba17e050399 100644
--- a/source/blender/blenfont/intern/blf_internal.h
+++ b/source/blender/blenfont/intern/blf_internal.h
@@ -37,6 +37,11 @@ struct GlyphBLF;
struct GlyphCacheBLF;
struct rctf;
+/* vertex attribute IDs (fixed IDs so we don't have to pass them around) */
+#define BLF_POS_ID 0
+#define BLF_COORD_ID 1
+#define BLF_COLOR_ID 2
+
unsigned int blf_next_p2(unsigned int x);
unsigned int blf_hash(unsigned int val);
diff --git a/source/blender/blenfont/intern/blf_internal_types.h b/source/blender/blenfont/intern/blf_internal_types.h
index 0fac576a8cc..9164a02b2cc 100644
--- a/source/blender/blenfont/intern/blf_internal_types.h
+++ b/source/blender/blenfont/intern/blf_internal_types.h
@@ -175,8 +175,10 @@ typedef struct FontBLF {
/* angle in radians. */
float angle;
+#if 0 /* BLF_BLUR_ENABLE */
/* blur: 3 or 5 large kernel */
int blur;
+#endif
/* shadow level. */
int shadow;
@@ -186,10 +188,10 @@ typedef struct FontBLF {
int shadow_y;
/* shadow color. */
- float shadow_col[4];
+ unsigned char shadow_color[4];
- /* store color here when drawing shadow or blur. */
- float orig_col[4];
+ /* main text color. */
+ unsigned char color[4];
/* Multiplied this matrix with the current one before
* draw the text! see blf_draw__start.
diff --git a/source/blender/blenkernel/BKE_boids.h b/source/blender/blenkernel/BKE_boids.h
deleted file mode 100644
index 582cd0cef8d..00000000000
--- a/source/blender/blenkernel/BKE_boids.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * ***** 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) 2009 by Janne Karhu.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-#ifndef __BKE_BOIDS_H__
-#define __BKE_BOIDS_H__
-
-/** \file BKE_boids.h
- * \ingroup bke
- * \since 2009
- * \author Janne Karhu
- */
-
-#include "DNA_boid_types.h"
-
-struct RNG;
-
-typedef struct BoidBrainData {
- struct ParticleSimulationData *sim;
- struct ParticleSettings *part;
- float timestep, cfra, dfra;
- float wanted_co[3], wanted_speed;
-
- /* Goal stuff */
- struct Object *goal_ob;
- float goal_co[3];
- float goal_nor[3];
- float goal_priority;
-
- struct RNG *rng;
-} BoidBrainData;
-
-void boids_precalc_rules(struct ParticleSettings *part, float cfra);
-void boid_brain(BoidBrainData *bbd, int p, struct ParticleData *pa);
-void boid_body(BoidBrainData *bbd, struct ParticleData *pa);
-void boid_default_settings(BoidSettings *boids);
-BoidRule *boid_new_rule(int type);
-BoidState *boid_new_state(BoidSettings *boids);
-BoidState *boid_duplicate_state(BoidSettings *boids, BoidState *state);
-void boid_free_settings(BoidSettings *boids);
-BoidSettings *boid_copy_settings(BoidSettings *boids);
-BoidState *boid_get_current_state(BoidSettings *boids);
-#endif
diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h
index 36330242f18..56d9b2439fb 100644
--- a/source/blender/blenkernel/BKE_cloth.h
+++ b/source/blender/blenkernel/BKE_cloth.h
@@ -237,9 +237,6 @@ int cloth_uses_vgroup(struct ClothModifierData *clmd);
void bvhtree_update_from_cloth(struct ClothModifierData *clmd, bool moving);
void bvhselftree_update_from_cloth(struct ClothModifierData *clmd, bool moving);
-// needed for button_object.c
-void cloth_clear_cache (struct Object *ob, struct ClothModifierData *clmd, float framenr );
-
// needed for cloth.c
int cloth_add_spring (struct ClothModifierData *clmd, unsigned int indexA, unsigned int indexB, float restlength, int spring_type);
diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h
index 4da6a61cbfa..c6795f87eab 100644
--- a/source/blender/blenkernel/BKE_context.h
+++ b/source/blender/blenkernel/BKE_context.h
@@ -109,7 +109,6 @@ enum {
CTX_MODE_PAINT_WEIGHT,
CTX_MODE_PAINT_VERTEX,
CTX_MODE_PAINT_TEXTURE,
- CTX_MODE_PARTICLE,
CTX_MODE_OBJECT
};
diff --git a/source/blender/blenkernel/BKE_dynamicpaint.h b/source/blender/blenkernel/BKE_dynamicpaint.h
index 5abb53d4c52..c552a618cd8 100644
--- a/source/blender/blenkernel/BKE_dynamicpaint.h
+++ b/source/blender/blenkernel/BKE_dynamicpaint.h
@@ -73,7 +73,6 @@ void dynamicPaint_freeCanvas(struct DynamicPaintModifierData *pmd);
void dynamicPaint_freeBrush(struct DynamicPaintModifierData *pmd);
void dynamicPaint_freeSurfaceData(struct DynamicPaintSurface *surface);
-void dynamicPaint_cacheUpdateFrames(struct DynamicPaintSurface *surface);
bool dynamicPaint_surfaceHasColorPreview(struct DynamicPaintSurface *surface);
bool dynamicPaint_outputLayerExists(struct DynamicPaintSurface *surface, struct Object *ob, int output);
void dynamicPaintSurface_updateType(struct DynamicPaintSurface *surface);
diff --git a/source/blender/blenkernel/BKE_effect.h b/source/blender/blenkernel/BKE_effect.h
index b934ec7166d..90fe3601372 100644
--- a/source/blender/blenkernel/BKE_effect.h
+++ b/source/blender/blenkernel/BKE_effect.h
@@ -41,9 +41,7 @@ struct Object;
struct Scene;
struct ListBase;
struct Group;
-struct ParticleSimulationData;
-struct ParticleData;
-struct ParticleKey;
+struct PointCacheKey;
struct EffectorWeights *BKE_add_effector_weights(struct Group *group);
struct PartDeflect *object_add_collision_fields(int type);
@@ -95,7 +93,6 @@ typedef struct EffectorCache {
struct Scene *scene;
struct Object *ob;
- struct ParticleSystem *psys;
struct SurfaceModifierData *surmd;
struct PartDeflect *pd;
@@ -110,17 +107,14 @@ typedef struct EffectorCache {
} EffectorCache;
void free_partdeflect(struct PartDeflect *pd);
-struct ListBase *pdInitEffectors(struct Scene *scene, struct Object *ob_src, struct ParticleSystem *psys_src, struct EffectorWeights *weights, bool for_simulation);
+struct ListBase *pdInitEffectors(struct Scene *scene, struct Object *ob_src, struct EffectorWeights *weights, bool for_simulation);
void pdEndEffectors(struct ListBase **effectors);
void pdPrecalculateEffectors(struct ListBase *effectors);
void pdDoEffectors(struct ListBase *effectors, struct ListBase *colliders, struct EffectorWeights *weights, struct EffectedPoint *point, float *force, float *impulse);
-void pd_point_from_particle(struct ParticleSimulationData *sim, struct ParticleData *pa, struct ParticleKey *state, struct EffectedPoint *point);
void pd_point_from_loc(struct Scene *scene, float *loc, float *vel, int index, struct EffectedPoint *point);
void pd_point_from_soft(struct Scene *scene, float *loc, float *vel, int index, struct EffectedPoint *point);
-/* needed for boids */
-float effector_falloff(struct EffectorCache *eff, struct EffectorData *efd, struct EffectedPoint *point, struct EffectorWeights *weights);
int closest_point_on_surface(SurfaceModifierData *surmd, const float co[3], float surface_co[3], float surface_nor[3], float surface_vel[3]);
int get_effector_data(struct EffectorCache *eff, struct EffectorData *efd, struct EffectedPoint *point, int real_velocity);
diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h
index 0d82de09165..7882bdf1126 100644
--- a/source/blender/blenkernel/BKE_library.h
+++ b/source/blender/blenkernel/BKE_library.h
@@ -94,7 +94,7 @@ void id_clear_lib_data_ex(struct Main *bmain, struct ID *id, const bool id_in_ma
struct ListBase *which_libbase(struct Main *mainlib, short type);
-#define MAX_LIBARRAY 35
+#define MAX_LIBARRAY 34
int set_listbasepointers(struct Main *main, struct ListBase *lb[MAX_LIBARRAY]);
/* Main API */
diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h
index a4f5c425282..7eba01e6d5a 100644
--- a/source/blender/blenkernel/BKE_main.h
+++ b/source/blender/blenkernel/BKE_main.h
@@ -96,7 +96,6 @@ typedef struct Main {
ListBase action;
ListBase nodetree;
ListBase brush;
- ListBase particle;
ListBase palettes;
ListBase paintcurves;
ListBase wm;
diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h
index f6c08909d23..ab0b120faf3 100644
--- a/source/blender/blenkernel/BKE_modifier.h
+++ b/source/blender/blenkernel/BKE_modifier.h
@@ -374,7 +374,6 @@ int modifiers_getCageIndex(struct Scene *scene, struct Object *ob,
bool modifiers_isModifierEnabled(struct Object *ob, int modifierType);
bool modifiers_isSoftbodyEnabled(struct Object *ob);
bool modifiers_isClothEnabled(struct Object *ob);
-bool modifiers_isParticleEnabled(struct Object *ob);
struct Object *modifiers_isDeformedByArmature(struct Object *ob);
struct Object *modifiers_isDeformedByLattice(struct Object *ob);
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index cf07a178fe8..29e84336526 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -55,10 +55,7 @@ void BKE_object_workob_calc_parent(struct Scene *scene, struct Object *ob, struc
void BKE_object_transform_copy(struct Object *ob_tar, const struct Object *ob_src);
struct SoftBody *copy_softbody(const struct SoftBody *sb, bool copy_caches);
struct BulletSoftBody *copy_bulletsoftbody(struct BulletSoftBody *sb);
-struct ParticleSystem *BKE_object_copy_particlesystem(struct ParticleSystem *psys);
-void BKE_object_copy_particlesystems(struct Object *ob_dst, const struct Object *ob_src);
void BKE_object_copy_softbody(struct Object *ob_dst, const struct Object *ob_src);
-void BKE_object_free_particlesystems(struct Object *ob);
void BKE_object_free_softbody(struct Object *ob);
void BKE_object_free_bulletsoftbody(struct Object *ob);
void BKE_object_free_curve_cache(struct Object *ob);
diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h
deleted file mode 100644
index b3e3968ca9b..00000000000
--- a/source/blender/blenkernel/BKE_particle.h
+++ /dev/null
@@ -1,481 +0,0 @@
-/*
- * ***** 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) 2007 by Janne Karhu.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Adaptive time step
- * Classical SPH
- * Copyright 2011-2012 AutoCRC
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-#ifndef __BKE_PARTICLE_H__
-#define __BKE_PARTICLE_H__
-
-/** \file BKE_particle.h
- * \ingroup bke
- */
-
-#include "BLI_utildefines.h"
-
-#include "DNA_particle_types.h"
-#include "DNA_object_types.h"
-
-#include "BKE_customdata.h"
-
-struct ParticleSystemModifierData;
-struct ParticleSystem;
-struct ParticleKey;
-struct ParticleSettings;
-
-struct Main;
-struct Object;
-struct Scene;
-struct DerivedMesh;
-struct ModifierData;
-struct MTFace;
-struct MCol;
-struct MFace;
-struct MVert;
-struct LatticeDeformData;
-struct LinkNode;
-struct KDTree;
-struct RNG;
-struct BVHTreeRay;
-struct BVHTreeRayHit;
-struct EdgeHash;
-
-#define PARTICLE_COLLISION_MAX_COLLISIONS 10
-
-#define PARTICLE_P ParticleData * pa; int p
-#define LOOP_PARTICLES for (p = 0, pa = psys->particles; p < psys->totpart; p++, pa++)
-#define LOOP_EXISTING_PARTICLES for (p = 0, pa = psys->particles; p < psys->totpart; p++, pa++) if (!(pa->flag & PARS_UNEXIST))
-#define LOOP_SHOWN_PARTICLES for (p = 0, pa = psys->particles; p < psys->totpart; p++, pa++) if (!(pa->flag & (PARS_UNEXIST | PARS_NO_DISP)))
-/* OpenMP: Can only advance one variable within loop definition. */
-#define LOOP_DYNAMIC_PARTICLES for (p = 0; p < psys->totpart; p++) if ((pa = psys->particles + p)->state.time > 0.0f)
-
-/* fast but sure way to get the modifier*/
-#define PARTICLE_PSMD ParticleSystemModifierData * psmd = sim->psmd ? sim->psmd : psys_get_modifier(sim->ob, sim->psys)
-
-/* common stuff that many particle functions need */
-typedef struct ParticleSimulationData {
- struct Scene *scene;
- struct Object *ob;
- struct ParticleSystem *psys;
- struct ParticleSystemModifierData *psmd;
- struct ListBase *colliders;
- /* Courant number. This is used to implement an adaptive time step. Only the
- * maximum value per time step is important. Only sph_integrate makes use of
- * this at the moment. Other solvers could, too. */
- float courant_num;
-} ParticleSimulationData;
-
-typedef struct SPHData {
- ParticleSystem *psys[10];
- ParticleData *pa;
- float mass;
- struct EdgeHash *eh;
- float *gravity;
- float hfac;
- /* Average distance to neighbours (other particles in the support domain),
- * for calculating the Courant number (adaptive time step). */
- int pass;
- float element_size;
- float flow[3];
-
- /* Integrator callbacks. This allows different SPH implementations. */
- void (*force_cb) (void *sphdata_v, ParticleKey *state, float *force, float *impulse);
- void (*density_cb) (void *rangedata_v, int index, const float co[3], float squared_dist);
-} SPHData;
-
-typedef struct ParticleTexture {
- float ivel; /* used in reset */
- float time, life, exist, size; /* used in init */
- float damp, gravity, field; /* used in physics */
- float length, clump, kink_freq, kink_amp, effector; /* used in path caching */
- float rough1, rough2, roughe; /* used in path caching */
-} ParticleTexture;
-
-typedef struct ParticleSeam {
- float v0[3], v1[3];
- float nor[3], dir[3], tan[3];
- float length2;
-} ParticleSeam;
-
-typedef struct ParticleCacheKey {
- float co[3];
- float vel[3];
- float rot[4];
- float col[3];
- float time;
- int segments;
-} ParticleCacheKey;
-
-typedef struct ParticleThreadContext {
- /* shared */
- struct ParticleSimulationData sim;
- struct DerivedMesh *dm;
- struct Material *ma;
-
- /* distribution */
- struct KDTree *tree;
-
- struct ParticleSeam *seams;
- int totseam;
-
- float *jit, *jitoff, *weight;
- float maxweight;
- int *index, *skip, jitlevel;
-
- int cfrom, distr;
-
- struct ParticleData *tpars;
-
- /* path caching */
- bool editupdate;
- int between, segments, extra_segments;
- int totchild, totparent, parent_pass;
-
- float cfra;
-
- float *vg_length, *vg_clump, *vg_kink;
- float *vg_rough1, *vg_rough2, *vg_roughe;
- float *vg_effector;
-
- struct CurveMapping *clumpcurve;
- struct CurveMapping *roughcurve;
-} ParticleThreadContext;
-
-typedef struct ParticleTask {
- ParticleThreadContext *ctx;
- struct RNG *rng, *rng_path;
- int begin, end;
-} ParticleTask;
-
-typedef struct ParticleBillboardData {
- struct Object *ob;
- float vec[3], vel[3];
- float offset[2];
- float size[2];
- float tilt, random, time;
- int uv[3];
- int lock, num;
- int totnum;
- int lifetime;
- short align, uv_split, anim, split_offset;
-} ParticleBillboardData;
-
-typedef struct ParticleCollisionElement {
- /* pointers to original data */
- float *x[3], *v[3];
-
- /* values interpolated from original data*/
- float x0[3], x1[3], x2[3], p[3];
-
- /* results for found intersection point */
- float nor[3], vel[3], uv[2];
-
- /* count of original data (1-4) */
- int tot;
-
- /* index of the collision face */
- int index;
-
- /* flags for inversed normal / particle already inside element at start */
- short inv_nor, inside;
-} ParticleCollisionElement;
-
-/* container for moving data between deflet_particle and particle_intersect_face */
-typedef struct ParticleCollision {
- struct Object *current;
- struct Object *hit;
- struct Object *skip[PARTICLE_COLLISION_MAX_COLLISIONS+1];
- struct Object *emitter;
-
- struct CollisionModifierData *md; // collision modifier for current object;
-
- float f; // time factor of previous collision, needed for substracting face velocity
- float fac1, fac2;
-
- float cfra, old_cfra;
-
- float original_ray_length; //original length of co2-co1, needed for collision time evaluation
-
- int skip_count;
-
- ParticleCollisionElement pce;
-
- /* total_time is the amount of time in this subframe
- * inv_total_time is the opposite
- * inv_timestep is the inverse of the amount of time in this frame */
- float total_time, inv_total_time, inv_timestep;
-
- float radius;
- float co1[3], co2[3];
- float ve1[3], ve2[3];
-
- float acc[3], boid_z;
-
- int boid;
-} ParticleCollision;
-
-typedef struct ParticleDrawData {
- float *vdata, *vd; /* vertice data */
- float *ndata, *nd; /* normal data */
- float *cdata, *cd; /* color data */
- float *vedata, *ved; /* velocity data */
- float *ma_col;
- int tot_vec_size, flag;
- int totpoint, totve;
-} ParticleDrawData;
-
-#define PARTICLE_DRAW_DATA_UPDATED 1
-
-#define PSYS_FRAND_COUNT 1024
-extern unsigned int PSYS_FRAND_SEED_OFFSET[PSYS_FRAND_COUNT];
-extern unsigned int PSYS_FRAND_SEED_MULTIPLIER[PSYS_FRAND_COUNT];
-extern float PSYS_FRAND_BASE[PSYS_FRAND_COUNT];
-
-void psys_init_rng(void);
-
-BLI_INLINE float psys_frand(ParticleSystem *psys, unsigned int seed)
-{
- /* XXX far from ideal, this simply scrambles particle random numbers a bit
- * to avoid obvious correlations.
- * Can't use previous psys->frand arrays because these require initialization
- * inside psys_check_enabled, which wreaks havok in multithreaded depgraph updates.
- */
- unsigned int offset = PSYS_FRAND_SEED_OFFSET[psys->seed % PSYS_FRAND_COUNT];
- unsigned int multiplier = PSYS_FRAND_SEED_MULTIPLIER[psys->seed % PSYS_FRAND_COUNT];
- return PSYS_FRAND_BASE[(offset + seed * multiplier) % PSYS_FRAND_COUNT];
-}
-
-BLI_INLINE void psys_frand_vec(ParticleSystem *psys, unsigned int seed, float vec[3])
-{
- unsigned int offset = PSYS_FRAND_SEED_OFFSET[psys->seed % PSYS_FRAND_COUNT];
- unsigned int multiplier = PSYS_FRAND_SEED_MULTIPLIER[psys->seed % PSYS_FRAND_COUNT];
- vec[0] = PSYS_FRAND_BASE[(offset + (seed + 0) * multiplier) % PSYS_FRAND_COUNT];
- vec[1] = PSYS_FRAND_BASE[(offset + (seed + 1) * multiplier) % PSYS_FRAND_COUNT];
- vec[2] = PSYS_FRAND_BASE[(offset + (seed + 2) * multiplier) % PSYS_FRAND_COUNT];
-}
-
-/* ----------- functions needed outside particlesystem ---------------- */
-/* particle.c */
-int count_particles(struct ParticleSystem *psys);
-int count_particles_mod(struct ParticleSystem *psys, int totgr, int cur);
-
-int psys_get_child_number(struct Scene *scene, struct ParticleSystem *psys);
-int psys_get_tot_child(struct Scene *scene, struct ParticleSystem *psys);
-
-struct ParticleSystem *psys_get_current(struct Object *ob);
-/* for rna */
-short psys_get_current_num(struct Object *ob);
-void psys_set_current_num(Object *ob, int index);
-/* UNUSED */
-// struct Object *psys_find_object(struct Scene *scene, struct ParticleSystem *psys);
-
-struct LatticeDeformData *psys_create_lattice_deform_data(struct ParticleSimulationData *sim);
-
-bool psys_in_edit_mode(struct Scene *scene, struct ParticleSystem *psys);
-bool psys_check_enabled(struct Object *ob, struct ParticleSystem *psys, const bool use_render_params);
-bool psys_check_edited(struct ParticleSystem *psys);
-
-void psys_check_group_weights(struct ParticleSettings *part);
-int psys_uses_gravity(struct ParticleSimulationData *sim);
-
-/* free */
-void BKE_particlesettings_free(struct ParticleSettings *part);
-void psys_free_path_cache(struct ParticleSystem *psys, struct PTCacheEdit *edit);
-void psys_free(struct Object *ob, struct ParticleSystem *psys);
-
-void psys_render_set(struct Object *ob, struct ParticleSystem *psys, float viewmat[4][4], float winmat[4][4], int winx, int winy, int timeoffset);
-void psys_render_restore(struct Object *ob, struct ParticleSystem *psys);
-bool psys_render_simplify_params(struct ParticleSystem *psys, struct ChildParticle *cpa, float *params);
-
-void psys_interpolate_uvs(const struct MTFace *tface, int quad, const float w[4], float uvco[2]);
-void psys_interpolate_mcol(const struct MCol *mcol, int quad, const float w[4], struct MCol *mc);
-
-void copy_particle_key(struct ParticleKey *to, struct ParticleKey *from, int time);
-
-CustomDataMask psys_emitter_customdata_mask(struct ParticleSystem *psys);
-void psys_particle_on_emitter(struct ParticleSystemModifierData *psmd, int distr, int index, int index_dmcache,
- float fuv[4], float foffset, float vec[3], float nor[3],
- float utan[3], float vtan[3], float orco[3], float ornor[3]);
-struct ParticleSystemModifierData *psys_get_modifier(struct Object *ob, struct ParticleSystem *psys);
-
-struct ModifierData *object_add_particle_system(struct Scene *scene, struct Object *ob, const char *name);
-void object_remove_particle_system(struct Scene *scene, struct Object *ob);
-struct ParticleSettings *psys_new_settings(const char *name, struct Main *main);
-struct ParticleSettings *BKE_particlesettings_copy(struct Main *bmain, struct ParticleSettings *part);
-void BKE_particlesettings_make_local(struct Main *bmain, struct ParticleSettings *part, const bool lib_local);
-
-void psys_reset(struct ParticleSystem *psys, int mode);
-
-void psys_find_parents(struct ParticleSimulationData *sim, const bool use_render_params);
-
-void psys_cache_paths(struct ParticleSimulationData *sim, float cfra, const bool use_render_params);
-void psys_cache_edit_paths(struct Scene *scene, struct Object *ob, struct PTCacheEdit *edit, float cfra, const bool use_render_params);
-void psys_cache_child_paths(struct ParticleSimulationData *sim, float cfra, const bool editupdate, const bool use_render_params);
-int do_guides(struct ParticleSettings *part, struct ListBase *effectors, ParticleKey *state, int pa_num, float time);
-void precalc_guides(struct ParticleSimulationData *sim, struct ListBase *effectors);
-float psys_get_timestep(struct ParticleSimulationData *sim);
-float psys_get_child_time(struct ParticleSystem *psys, struct ChildParticle *cpa, float cfra, float *birthtime, float *dietime);
-float psys_get_child_size(struct ParticleSystem *psys, struct ChildParticle *cpa, float cfra, float *pa_time);
-void psys_get_particle_on_path(struct ParticleSimulationData *sim, int pa_num, struct ParticleKey *state, const bool vel);
-int psys_get_particle_state(struct ParticleSimulationData *sim, int p, struct ParticleKey *state, int always);
-
-/* child paths */
-void BKE_particlesettings_clump_curve_init(struct ParticleSettings *part);
-void BKE_particlesettings_rough_curve_init(struct ParticleSettings *part);
-void psys_apply_child_modifiers(struct ParticleThreadContext *ctx, struct ListBase *modifiers,
- struct ChildParticle *cpa, struct ParticleTexture *ptex, const float orco[3], const float ornor[3], float hairmat[4][4],
- struct ParticleCacheKey *keys, struct ParticleCacheKey *parent_keys, const float parent_orco[3]);
-
-void psys_sph_init(struct ParticleSimulationData *sim, struct SPHData *sphdata);
-void psys_sph_finalise(struct SPHData *sphdata);
-void psys_sph_density(struct BVHTree *tree, struct SPHData *data, float co[3], float vars[2]);
-
-/* for anim.c */
-void psys_get_dupli_texture(struct ParticleSystem *psys, struct ParticleSettings *part,
- struct ParticleSystemModifierData *psmd, struct ParticleData *pa, struct ChildParticle *cpa,
- float uv[2], float orco[3]);
-void psys_get_dupli_path_transform(struct ParticleSimulationData *sim, struct ParticleData *pa, struct ChildParticle *cpa,
- struct ParticleCacheKey *cache, float mat[4][4], float *scale);
-
-void psys_thread_context_init(struct ParticleThreadContext *ctx, struct ParticleSimulationData *sim);
-void psys_thread_context_free(struct ParticleThreadContext *ctx);
-void psys_tasks_create(struct ParticleThreadContext *ctx, int startpart, int endpart, struct ParticleTask **r_tasks, int *r_numtasks);
-void psys_tasks_free(struct ParticleTask *tasks, int numtasks);
-
-void psys_make_billboard(ParticleBillboardData *bb, float xvec[3], float yvec[3], float zvec[3], float center[3]);
-void psys_apply_hair_lattice(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys);
-
-/* particle_system.c */
-struct ParticleSystem *psys_get_target_system(struct Object *ob, struct ParticleTarget *pt);
-void psys_count_keyed_targets(struct ParticleSimulationData *sim);
-void psys_update_particle_tree(struct ParticleSystem *psys, float cfra);
-void psys_changed_type(struct Object *ob, struct ParticleSystem *psys);
-
-void psys_make_temp_pointcache(struct Object *ob, struct ParticleSystem *psys);
-void psys_get_pointcache_start_end(struct Scene *scene, ParticleSystem *psys, int *sfra, int *efra);
-
-void psys_check_boid_data(struct ParticleSystem *psys);
-
-void psys_get_birth_coords(struct ParticleSimulationData *sim, struct ParticleData *pa, struct ParticleKey *state, float dtime, float cfra);
-
-void particle_system_update(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys, const bool use_render_params);
-
-/* Callback format for performing operations on ID-pointers for particle systems */
-typedef void (*ParticleSystemIDFunc)(struct ParticleSystem *psys, struct ID **idpoin, void *userdata, int cd_flag);
-
-void BKE_particlesystem_id_loop(struct ParticleSystem *psys, ParticleSystemIDFunc func, void *userdata);
-
-/* ----------- functions needed only inside particlesystem ------------ */
-/* particle.c */
-void psys_disable_all(struct Object *ob);
-void psys_enable_all(struct Object *ob);
-
-void free_hair(struct Object *ob, struct ParticleSystem *psys, int dynamics);
-void free_keyed_keys(struct ParticleSystem *psys);
-void psys_free_particles(struct ParticleSystem *psys);
-void psys_free_children(struct ParticleSystem *psys);
-
-void psys_interpolate_particle(short type, struct ParticleKey keys[4], float dt, struct ParticleKey *result, bool velocity);
-void psys_vec_rot_to_face(struct DerivedMesh *dm, struct ParticleData *pa, float vec[3]);
-void psys_mat_hair_to_object(struct Object *ob, struct DerivedMesh *dm, short from, struct ParticleData *pa, float hairmat[4][4]);
-void psys_mat_hair_to_global(struct Object *ob, struct DerivedMesh *dm, short from, struct ParticleData *pa, float hairmat[4][4]);
-void psys_mat_hair_to_orco(struct Object *ob, struct DerivedMesh *dm, short from, struct ParticleData *pa, float hairmat[4][4]);
-
-float psys_get_dietime_from_cache(struct PointCache *cache, int index);
-
-void psys_free_pdd(struct ParticleSystem *psys);
-
-float *psys_cache_vgroup(struct DerivedMesh *dm, struct ParticleSystem *psys, int vgroup);
-void psys_get_texture(struct ParticleSimulationData *sim, struct ParticleData *pa, struct ParticleTexture *ptex, int event, float cfra);
-void psys_interpolate_face(struct MVert *mvert, struct MFace *mface, struct MTFace *tface,
- float (*orcodata)[3], float w[4], float vec[3], float nor[3], float utan[3], float vtan[3],
- float orco[3], float ornor[3]);
-float psys_particle_value_from_verts(struct DerivedMesh *dm, short from, struct ParticleData *pa, float *values);
-void psys_get_from_key(struct ParticleKey *key, float loc[3], float vel[3], float rot[4], float *time);
-
-/* BLI_bvhtree_ray_cast callback */
-void BKE_psys_collision_neartest_cb(void *userdata, int index, const struct BVHTreeRay *ray, struct BVHTreeRayHit *hit);
-void psys_particle_on_dm(struct DerivedMesh *dm_final, int from, int index, int index_dmcache,
- const float fw[4], float foffset, float vec[3], float nor[3], float utan[3], float vtan[3],
- float orco[3], float ornor[3]);
-
-/* particle_system.c */
-void distribute_particles(struct ParticleSimulationData *sim, int from);
-void initialize_particle(struct ParticleSimulationData *sim, struct ParticleData *pa);
-void psys_calc_dmcache(struct Object *ob, struct DerivedMesh *dm_final, struct DerivedMesh *dm_deformed, struct ParticleSystem *psys);
-int psys_particle_dm_face_lookup(struct DerivedMesh *dm_final, struct DerivedMesh *dm_deformed, int findex, const float fw[4], struct LinkNode **poly_nodes);
-
-void reset_particle(struct ParticleSimulationData *sim, struct ParticleData *pa, float dtime, float cfra);
-
-float psys_get_current_display_percentage(struct ParticleSystem *psys);
-
-typedef struct ParticleRenderElem {
- int curchild, totchild, reduce;
- float lambda, t, scalemin, scalemax;
-} ParticleRenderElem;
-
-typedef struct ParticleRenderData {
- ChildParticle *child;
- ParticleCacheKey **pathcache;
- ParticleCacheKey **childcache;
- ListBase pathcachebufs, childcachebufs;
- int totchild, totcached, totchildcache;
- struct DerivedMesh *dm;
- int totdmvert, totdmedge, totdmface;
-
- float mat[4][4];
- float viewmat[4][4], winmat[4][4];
- int winx, winy;
-
- int do_simplify;
- int timeoffset;
- ParticleRenderElem *elems;
-
- /* ORIGINDEX */
- const int *index_mf_to_mpoly;
- const int *index_mp_to_orig;
-} ParticleRenderData;
-
-/* psys_reset */
-#define PSYS_RESET_ALL 1
-#define PSYS_RESET_DEPSGRAPH 2
-/* #define PSYS_RESET_CHILDREN 3 */ /*UNUSED*/
-#define PSYS_RESET_CACHE_MISS 4
-
-/* index_dmcache */
-#define DMCACHE_NOTFOUND -1
-#define DMCACHE_ISCHILD -2
-
-/* **** Depsgraph evaluation **** */
-
-struct EvaluationContext;
-
-void BKE_particle_system_eval(struct EvaluationContext *eval_ctx,
- struct Scene *scene,
- struct Object *ob,
- struct ParticleSystem *psys);
-
-#endif
diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h
deleted file mode 100644
index 02f6c435ee2..00000000000
--- a/source/blender/blenkernel/BKE_pointcache.h
+++ /dev/null
@@ -1,348 +0,0 @@
-/*
- * ***** 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) 2006 Blender Foundation.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): Campbell Barton <ideasman42@gmail.com>
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-#ifndef __BKE_POINTCACHE_H__
-#define __BKE_POINTCACHE_H__
-
-/** \file BKE_pointcache.h
- * \ingroup bke
- */
-
-#include "DNA_ID.h"
-#include "DNA_dynamicpaint_types.h"
-#include "DNA_object_force.h"
-#include "DNA_boid_types.h"
-#include <stdio.h> /* for FILE */
-
-/* Point cache clearing option, for BKE_ptcache_id_clear, before
- * and after are non inclusive (they wont remove the cfra) */
-#define PTCACHE_CLEAR_ALL 0
-#define PTCACHE_CLEAR_FRAME 1
-#define PTCACHE_CLEAR_BEFORE 2
-#define PTCACHE_CLEAR_AFTER 3
-
-/* Point cache reset options */
-#define PTCACHE_RESET_DEPSGRAPH 0
-#define PTCACHE_RESET_BAKED 1
-#define PTCACHE_RESET_OUTDATED 2
-/* #define PTCACHE_RESET_FREE 3 */ /*UNUSED*/
-
-/* Add the blendfile name after blendcache_ */
-#define PTCACHE_EXT ".bphys"
-#define PTCACHE_PATH "blendcache_"
-
-/* File open options, for BKE_ptcache_file_open */
-#define PTCACHE_FILE_READ 0
-#define PTCACHE_FILE_WRITE 1
-#define PTCACHE_FILE_UPDATE 2
-
-/* PTCacheID types */
-#define PTCACHE_TYPE_SOFTBODY 0
-#define PTCACHE_TYPE_PARTICLES 1
-#define PTCACHE_TYPE_CLOTH 2
-#define PTCACHE_TYPE_SMOKE_DOMAIN 3
-#define PTCACHE_TYPE_SMOKE_HIGHRES 4
-#define PTCACHE_TYPE_DYNAMICPAINT 5
-#define PTCACHE_TYPE_RIGIDBODY 6
-
-/* high bits reserved for flags that need to be stored in file */
-#define PTCACHE_TYPEFLAG_COMPRESS (1 << 16)
-#define PTCACHE_TYPEFLAG_EXTRADATA (1 << 17)
-
-#define PTCACHE_TYPEFLAG_TYPEMASK 0x0000FFFF
-#define PTCACHE_TYPEFLAG_FLAGMASK 0xFFFF0000
-
-/* PTCache read return code */
-#define PTCACHE_READ_EXACT 1
-#define PTCACHE_READ_INTERPOLATED 2
-#define PTCACHE_READ_OLD 3
-
-/* Structs */
-struct ClothModifierData;
-struct ListBase;
-struct Main;
-struct Object;
-struct ParticleKey;
-struct ParticleSystem;
-struct PointCache;
-struct Scene;
-struct SmokeModifierData;
-struct SoftBody;
-struct RigidBodyWorld;
-
-struct OpenVDBReader;
-struct OpenVDBWriter;
-
-/* temp structure for read/write */
-typedef struct PTCacheData {
- unsigned int index;
- float loc[3];
- float vel[3];
- float rot[4];
- float ave[3];
- float size;
- float times[3];
- struct BoidData boids;
-} PTCacheData;
-
-typedef struct PTCacheFile {
- FILE *fp;
-
- int frame, old_format;
- unsigned int totpoint, type;
- unsigned int data_types, flag;
-
- struct PTCacheData data;
- void *cur[BPHYS_TOT_DATA];
-} PTCacheFile;
-
-#define PTCACHE_VEL_PER_SEC 1
-
-enum {
- PTCACHE_FILE_PTCACHE = 0,
- PTCACHE_FILE_OPENVDB = 1,
-};
-
-typedef struct PTCacheID {
- struct PTCacheID *next, *prev;
-
- struct Scene *scene;
- struct Object *ob;
- void *calldata;
- unsigned int type, file_type;
- unsigned int stack_index;
- unsigned int flag;
-
- unsigned int default_step;
- unsigned int max_step;
-
- /* flags defined in DNA_object_force.h */
- unsigned int data_types, info_types;
-
- /* copies point data to cache data */
- int (*write_point)(int index, void *calldata, void **data, int cfra);
- /* copies cache cata to point data */
- void (*read_point)(int index, void *calldata, void **data, float cfra, float *old_data);
- /* interpolated between previously read point data and cache data */
- void (*interpolate_point)(int index, void *calldata, void **data, float cfra, float cfra1, float cfra2, float *old_data);
-
- /* copies point data to cache data */
- int (*write_stream)(PTCacheFile *pf, void *calldata);
- /* copies cache cata to point data */
- int (*read_stream)(PTCacheFile *pf, void *calldata);
-
- /* copies point data to cache data */
- int (*write_openvdb_stream)(struct OpenVDBWriter *writer, void *calldata);
- /* copies cache cata to point data */
- int (*read_openvdb_stream)(struct OpenVDBReader *reader, void *calldata);
-
- /* copies custom extradata to cache data */
- void (*write_extra_data)(void *calldata, struct PTCacheMem *pm, int cfra);
- /* copies custom extradata to cache data */
- void (*read_extra_data)(void *calldata, struct PTCacheMem *pm, float cfra);
- /* copies custom extradata to cache data */
- void (*interpolate_extra_data)(void *calldata, struct PTCacheMem *pm, float cfra, float cfra1, float cfra2);
-
- /* total number of simulated points (the cfra parameter is just for using same function pointer with totwrite) */
- int (*totpoint)(void *calldata, int cfra);
- /* report error if number of points does not match */
- void (*error)(void *calldata, const char *message);
- /* number of points written for current cache frame */
- int (*totwrite)(void *calldata, int cfra);
-
- int (*write_header)(PTCacheFile *pf);
- int (*read_header)(PTCacheFile *pf);
-
- struct PointCache *cache;
- /* used for setting the current cache from ptcaches list */
- struct PointCache **cache_ptr;
- struct ListBase *ptcaches;
-} PTCacheID;
-
-typedef struct PTCacheBaker {
- struct Main *main;
- struct Scene *scene;
- int bake;
- int render;
- int anim_init;
- int quick_step;
- struct PTCacheID pid;
-
- void (*update_progress)(void *data, float progress, int *cancel);
- void *bake_job;
-} PTCacheBaker;
-
-/* PTCacheEditKey->flag */
-#define PEK_SELECT 1
-#define PEK_TAG 2
-#define PEK_HIDE 4
-#define PEK_USE_WCO 8
-
-typedef struct PTCacheEditKey {
- float *co;
- float *vel;
- float *rot;
- float *time;
-
- float world_co[3];
- float ftime;
- float length;
- short flag;
-} PTCacheEditKey;
-
-/* PTCacheEditPoint->flag */
-#define PEP_TAG 1
-#define PEP_EDIT_RECALC 2
-#define PEP_TRANSFORM 4
-#define PEP_HIDE 8
-
-typedef struct PTCacheEditPoint {
- struct PTCacheEditKey *keys;
- int totkey;
- short flag;
-} PTCacheEditPoint;
-
-typedef struct PTCacheUndo {
- struct PTCacheUndo *next, *prev;
- struct PTCacheEditPoint *points;
-
- /* particles stuff */
- struct ParticleData *particles;
- struct KDTree *emitter_field;
- float *emitter_cosnos;
- int psys_flag;
-
- /* cache stuff */
- struct ListBase mem_cache;
-
- int totpoint;
- char name[64];
-} PTCacheUndo;
-
-typedef struct PTCacheEdit {
- ListBase undo;
- struct PTCacheUndo *curundo;
- PTCacheEditPoint *points;
-
- struct PTCacheID pid;
-
- /* particles stuff */
- struct ParticleSystem *psys;
- struct KDTree *emitter_field;
- float *emitter_cosnos; /* localspace face centers and normals (average of its verts), from the derived mesh */
- int *mirror_cache;
-
- struct ParticleCacheKey **pathcache; /* path cache (runtime) */
- ListBase pathcachebufs;
-
- int totpoint, totframes, totcached, edited;
-
- unsigned char sel_col[3];
- unsigned char nosel_col[3];
-} PTCacheEdit;
-
-/* Particle functions */
-void BKE_ptcache_make_particle_key(struct ParticleKey *key, int index, void **data, float time);
-
-/**************** Creating ID's ****************************/
-void BKE_ptcache_id_from_softbody(PTCacheID *pid, struct Object *ob, struct SoftBody *sb);
-void BKE_ptcache_id_from_particles(PTCacheID *pid, struct Object *ob, struct ParticleSystem *psys);
-void BKE_ptcache_id_from_cloth(PTCacheID *pid, struct Object *ob, struct ClothModifierData *clmd);
-void BKE_ptcache_id_from_smoke(PTCacheID *pid, struct Object *ob, struct SmokeModifierData *smd);
-void BKE_ptcache_id_from_dynamicpaint(PTCacheID *pid, struct Object *ob, struct DynamicPaintSurface *surface);
-void BKE_ptcache_id_from_rigidbody(PTCacheID *pid, struct Object *ob, struct RigidBodyWorld *rbw);
-
-void BKE_ptcache_ids_from_object(struct ListBase *lb, struct Object *ob, struct Scene *scene, int duplis);
-
-/***************** Global funcs ****************************/
-void BKE_ptcache_remove(void);
-
-/************ ID specific functions ************************/
-void BKE_ptcache_id_clear(PTCacheID *id, int mode, unsigned int cfra);
-int BKE_ptcache_id_exist(PTCacheID *id, int cfra);
-int BKE_ptcache_id_reset(struct Scene *scene, PTCacheID *id, int mode);
-void BKE_ptcache_id_time(PTCacheID *pid, struct Scene *scene, float cfra, int *startframe, int *endframe, float *timescale);
-int BKE_ptcache_object_reset(struct Scene *scene, struct Object *ob, int mode);
-
-void BKE_ptcache_update_info(PTCacheID *pid);
-
-/*********** General cache reading/writing ******************/
-
-/* Size of cache data type. */
-int BKE_ptcache_data_size(int data_type);
-
-/* Is point with indes in memory cache */
-int BKE_ptcache_mem_index_find(struct PTCacheMem *pm, unsigned int index);
-
-/* Memory cache read/write helpers. */
-void BKE_ptcache_mem_pointers_init(struct PTCacheMem *pm);
-void BKE_ptcache_mem_pointers_incr(struct PTCacheMem *pm);
-int BKE_ptcache_mem_pointers_seek(int point_index, struct PTCacheMem *pm);
-
-/* Main cache reading call. */
-int BKE_ptcache_read(PTCacheID *pid, float cfra, bool no_extrapolate_old);
-
-/* Main cache writing call. */
-int BKE_ptcache_write(PTCacheID *pid, unsigned int cfra);
-
-/******************* Allocate & free ***************/
-struct PointCache *BKE_ptcache_add(struct ListBase *ptcaches);
-void BKE_ptcache_free_mem(struct ListBase *mem_cache);
-void BKE_ptcache_free(struct PointCache *cache);
-void BKE_ptcache_free_list(struct ListBase *ptcaches);
-struct PointCache *BKE_ptcache_copy_list(struct ListBase *ptcaches_new, const struct ListBase *ptcaches_old, bool copy_data);
-
-/********************** Baking *********************/
-
-/* Bakes cache with cache_step sized jumps in time, not accurate but very fast. */
-void BKE_ptcache_quick_cache_all(struct Main *bmain, struct Scene *scene);
-
-/* Bake cache or simulate to current frame with settings defined in the baker. */
-void BKE_ptcache_bake(struct PTCacheBaker *baker);
-
-/* Convert disk cache to memory cache. */
-void BKE_ptcache_disk_to_mem(struct PTCacheID *pid);
-
-/* Convert memory cache to disk cache. */
-void BKE_ptcache_mem_to_disk(struct PTCacheID *pid);
-
-/* Convert disk cache to memory cache and vice versa. Clears the cache that was converted. */
-void BKE_ptcache_toggle_disk_cache(struct PTCacheID *pid);
-
-/* Rename all disk cache files with a new name. Doesn't touch the actual content of the files. */
-void BKE_ptcache_disk_cache_rename(struct PTCacheID *pid, const char *name_src, const char *name_dst);
-
-/* Loads simulation from external (disk) cache files. */
-void BKE_ptcache_load_external(struct PTCacheID *pid);
-
-/* Set correct flags after successful simulation step */
-void BKE_ptcache_validate(struct PointCache *cache, int framenr);
-
-/* Set correct flags after unsuccessful simulation step */
-void BKE_ptcache_invalidate(struct PointCache *cache);
-
-#endif
diff --git a/source/blender/blenkernel/BKE_rigidbody.h b/source/blender/blenkernel/BKE_rigidbody.h
index 272abc42899..6731356a5af 100644
--- a/source/blender/blenkernel/BKE_rigidbody.h
+++ b/source/blender/blenkernel/BKE_rigidbody.h
@@ -99,7 +99,6 @@ void BKE_rigidbody_remove_constraint(struct Scene *scene, struct Object *ob);
void BKE_rigidbody_aftertrans_update(struct Object *ob, float loc[3], float rot[3], float quat[4], float rotAxis[3], float rotAngle);
void BKE_rigidbody_sync_transforms(struct RigidBodyWorld *rbw, struct Object *ob, float ctime);
bool BKE_rigidbody_check_sim_running(struct RigidBodyWorld *rbw, float ctime);
-void BKE_rigidbody_cache_reset(struct RigidBodyWorld *rbw);
void BKE_rigidbody_rebuild_world(struct Scene *scene, float ctime);
void BKE_rigidbody_do_simulation(struct Scene *scene, float ctime);
diff --git a/source/blender/blenkernel/BKE_sca.h b/source/blender/blenkernel/BKE_sca.h
index a504f1bac3d..2993540bb4f 100644
--- a/source/blender/blenkernel/BKE_sca.h
+++ b/source/blender/blenkernel/BKE_sca.h
@@ -86,7 +86,7 @@ void BKE_sca_controllers_id_loop(struct ListBase *contlist, SCAControllerIDFunc
void BKE_sca_actuators_id_loop(struct ListBase *atclist, SCAActuatorIDFunc func, void *userdata);
-const char *sca_state_name_get(Object *ob, short bit);
+const char *sca_state_name_get(struct Object *ob, short bit);
#endif
diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h
index 14e978b23f2..010810ad0cc 100644
--- a/source/blender/blenkernel/BKE_screen.h
+++ b/source/blender/blenkernel/BKE_screen.h
@@ -49,6 +49,7 @@ struct bScreen;
struct uiLayout;
struct uiList;
struct wmKeyConfig;
+struct wmManipulatorMap;
struct wmNotifier;
struct wmWindow;
struct wmWindowManager;
@@ -96,6 +97,9 @@ typedef struct SpaceType {
/* on startup, define dropboxes for spacetype+regions */
void (*dropboxes)(void);
+ /* initialize manipulator-map-types and manipulator-group-types with the region */
+ void (*manipulators)(void);
+
/* return context data */
int (*context)(const struct bContext *, const char *, struct bContextDataResult *);
@@ -284,6 +288,8 @@ void BKE_spacedata_id_unref(struct ScrArea *sa, struct SpaceLink *sl, struct ID
struct ARegion *BKE_area_region_copy(struct SpaceType *st, struct ARegion *ar);
void BKE_area_region_free(struct SpaceType *st, struct ARegion *ar);
void BKE_screen_area_free(struct ScrArea *sa);
+/* Manipulator-maps of a region need to be freed with the region. Uses callback to avoid low-level call. */
+void BKE_region_callback_free_manipulatormap_set(void (*callback)(struct wmManipulatorMap *));
struct ARegion *BKE_area_find_region_type(struct ScrArea *sa, int type);
struct ARegion *BKE_area_find_region_active_win(struct ScrArea *sa);
diff --git a/source/blender/blenkernel/BKE_softbody.h b/source/blender/blenkernel/BKE_softbody.h
index 486fe8ed5a8..4bce0cd609c 100644
--- a/source/blender/blenkernel/BKE_softbody.h
+++ b/source/blender/blenkernel/BKE_softbody.h
@@ -68,7 +68,7 @@ extern void sbObjectToSoftbody(struct Object *ob);
/* pass NULL to unlink again */
extern void sbSetInterruptCallBack(int (*f)(void));
-extern void SB_estimate_transform(Object *ob, float lloc[3], float lrot[3][3], float lscale[3][3]);
+extern void SB_estimate_transform(struct Object *ob, float lloc[3], float lrot[3][3], float lscale[3][3]);
#endif
diff --git a/source/blender/blenkernel/BKE_texture.h b/source/blender/blenkernel/BKE_texture.h
index 1c5ea946f59..df1fd945eb4 100644
--- a/source/blender/blenkernel/BKE_texture.h
+++ b/source/blender/blenkernel/BKE_texture.h
@@ -47,7 +47,6 @@ struct Main;
struct Material;
struct MTex;
struct OceanTex;
-struct ParticleSettings;
struct PointDensity;
struct Tex;
struct TexMapping;
@@ -87,7 +86,6 @@ struct Tex *give_current_lamp_texture(struct Lamp *la);
struct Tex *give_current_linestyle_texture(struct FreestyleLineStyle *linestyle);
struct Tex *give_current_world_texture(struct World *world);
struct Tex *give_current_brush_texture(struct Brush *br);
-struct Tex *give_current_particle_texture(struct ParticleSettings *part);
struct bNode *give_current_material_texture_node(struct Material *ma);
@@ -99,7 +97,6 @@ void set_current_world_texture(struct World *wo, struct Tex *tex);
void set_current_material_texture(struct Material *ma, struct Tex *tex);
void set_current_lamp_texture(struct Lamp *la, struct Tex *tex);
void set_current_linestyle_texture(struct FreestyleLineStyle *linestyle, struct Tex *tex);
-void set_current_particle_texture(struct ParticleSettings *part, struct Tex *tex);
bool has_current_material_texture(struct Material *ma);
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 157c4408d6a..ca55ba0226a 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -76,7 +76,6 @@ set(SRC
intern/blender_undo.c
intern/blendfile.c
intern/bmfont.c
- intern/boids.c
intern/bpath.c
intern/brush.c
intern/bullet.c
@@ -148,13 +147,8 @@ set(SRC
intern/outliner_treehash.c
intern/packedFile.c
intern/paint.c
- intern/particle.c
- intern/particle_child.c
- intern/particle_distribute.c
- intern/particle_system.c
intern/pbvh.c
intern/pbvh_bmesh.c
- intern/pointcache.c
intern/property.c
intern/report.c
intern/rigidbody.c
@@ -203,7 +197,6 @@ set(SRC
BKE_blendfile.h
BKE_bmfont.h
BKE_bmfont_types.h
- BKE_boids.h
BKE_bpath.h
BKE_brush.h
BKE_bullet.h
@@ -268,9 +261,7 @@ set(SRC
BKE_outliner_treehash.h
BKE_packedFile.h
BKE_paint.h
- BKE_particle.h
BKE_pbvh.h
- BKE_pointcache.h
BKE_property.h
BKE_report.h
BKE_rigidbody.h
diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c
index 7d3d12ac112..17d76bb290a 100644
--- a/source/blender/blenkernel/intern/anim.c
+++ b/source/blender/blenkernel/intern/anim.c
@@ -41,6 +41,7 @@
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
#include "DNA_key_types.h"
+#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "BKE_curve.h"
@@ -49,7 +50,6 @@
#include "BKE_key.h"
#include "BKE_main.h"
#include "BKE_object.h"
-#include "BKE_particle.h"
#include "BKE_scene.h"
#include "BKE_anim.h"
#include "BKE_report.h"
diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c
index e3764adb969..bfdbb510091 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -88,7 +88,6 @@ bool id_type_can_have_animdata(const short id_type)
case ID_OB:
case ID_ME: case ID_MB: case ID_CU: case ID_AR: case ID_LT:
case ID_KE:
- case ID_PA:
case ID_MA: case ID_TE: case ID_NT:
case ID_LA: case ID_CA: case ID_WO:
case ID_LS:
@@ -1135,9 +1134,6 @@ void BKE_animdata_main_cb(Main *mainptr, ID_AnimData_Edit_Callback func, void *u
/* meshes */
ANIMDATA_IDS_CB(mainptr->mesh.first);
- /* particles */
- ANIMDATA_IDS_CB(mainptr->particle.first);
-
/* speakers */
ANIMDATA_IDS_CB(mainptr->speaker.first);
@@ -1231,9 +1227,6 @@ void BKE_animdata_fix_paths_rename_all(ID *ref_id, const char *prefix, const cha
/* meshes */
RENAMEFIX_ANIM_IDS(mainptr->mesh.first);
- /* particles */
- RENAMEFIX_ANIM_IDS(mainptr->particle.first);
-
/* speakers */
RENAMEFIX_ANIM_IDS(mainptr->speaker.first);
@@ -2866,9 +2859,6 @@ void BKE_animsys_evaluate_all_animation(Main *main, Scene *scene, float ctime)
/* meshes */
EVAL_ANIM_IDS(main->mesh.first, ADT_RECALC_ANIM);
- /* particles */
- EVAL_ANIM_IDS(main->particle.first, ADT_RECALC_ANIM);
-
/* speakers */
EVAL_ANIM_IDS(main->speaker.first, ADT_RECALC_ANIM);
diff --git a/source/blender/blenkernel/intern/boids.c b/source/blender/blenkernel/intern/boids.c
deleted file mode 100644
index b4bc83bf94c..00000000000
--- a/source/blender/blenkernel/intern/boids.c
+++ /dev/null
@@ -1,1618 +0,0 @@
-/*
- * ***** 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) 2009 by Janne Karhu.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/blenkernel/intern/boids.c
- * \ingroup bke
- */
-
-
-#include <string.h>
-#include <math.h>
-
-#include "MEM_guardedalloc.h"
-
-#include "DNA_object_force.h"
-#include "DNA_scene_types.h"
-
-#include "BLI_rand.h"
-#include "BLI_math.h"
-#include "BLI_blenlib.h"
-#include "BLI_kdtree.h"
-#include "BLI_utildefines.h"
-
-#include "BKE_collision.h"
-#include "BKE_effect.h"
-#include "BKE_boids.h"
-#include "BKE_particle.h"
-
-#include "BKE_modifier.h"
-
-#include "RNA_enum_types.h"
-
-typedef struct BoidValues {
- float max_speed, max_acc;
- float max_ave, min_speed;
- float personal_space, jump_speed;
-} BoidValues;
-
-static int apply_boid_rule(BoidBrainData *bbd, BoidRule *rule, BoidValues *val, ParticleData *pa, float fuzziness);
-
-static int rule_none(BoidRule *UNUSED(rule), BoidBrainData *UNUSED(data), BoidValues *UNUSED(val), ParticleData *UNUSED(pa))
-{
- return 0;
-}
-
-static int rule_goal_avoid(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, ParticleData *pa)
-{
- BoidRuleGoalAvoid *gabr = (BoidRuleGoalAvoid*) rule;
- BoidSettings *boids = bbd->part->boids;
- BoidParticle *bpa = pa->boid;
- EffectedPoint epoint;
- ListBase *effectors = bbd->sim->psys->effectors;
- EffectorCache *cur, *eff = NULL;
- EffectorCache temp_eff;
- EffectorData efd, cur_efd;
- float mul = (rule->type == eBoidRuleType_Avoid ? 1.0 : -1.0);
- float priority = 0.0f, len = 0.0f;
- int ret = 0;
-
- int p = 0;
- efd.index = cur_efd.index = &p;
-
- pd_point_from_particle(bbd->sim, pa, &pa->state, &epoint);
-
- /* first find out goal/predator with highest priority */
- if (effectors) for (cur = effectors->first; cur; cur=cur->next) {
- Object *eob = cur->ob;
- PartDeflect *pd = cur->pd;
-
- if (gabr->ob && (rule->type != eBoidRuleType_Goal || gabr->ob != bpa->ground)) {
- if (gabr->ob == eob) {
- /* TODO: effectors with multiple points */
- if (get_effector_data(cur, &efd, &epoint, 0)) {
- if (cur->pd && cur->pd->forcefield == PFIELD_BOID)
- priority = mul * pd->f_strength * effector_falloff(cur, &efd, &epoint, bbd->part->effector_weights);
- else
- priority = 1.0;
-
- eff = cur;
- }
- break;
- }
- }
- else if (rule->type == eBoidRuleType_Goal && eob == bpa->ground) {
- /* skip current object */
- }
- else if (pd->forcefield == PFIELD_BOID && mul * pd->f_strength > 0.0f && get_effector_data(cur, &cur_efd, &epoint, 0)) {
- float temp = mul * pd->f_strength * effector_falloff(cur, &cur_efd, &epoint, bbd->part->effector_weights);
-
- if (temp == 0.0f) {
- /* do nothing */
- }
- else if (temp > priority) {
- priority = temp;
- eff = cur;
- efd = cur_efd;
- len = efd.distance;
- }
- /* choose closest object with same priority */
- else if (temp == priority && efd.distance < len) {
- eff = cur;
- efd = cur_efd;
- len = efd.distance;
- }
- }
- }
-
- /* if the object doesn't have effector data we have to fake it */
- if (eff == NULL && gabr->ob) {
- memset(&temp_eff, 0, sizeof(EffectorCache));
- temp_eff.ob = gabr->ob;
- temp_eff.scene = bbd->sim->scene;
- eff = &temp_eff;
- get_effector_data(eff, &efd, &epoint, 0);
- priority = 1.0f;
- }
-
- /* then use that effector */
- if (priority > (rule->type==eBoidRuleType_Avoid ? gabr->fear_factor : 0.0f)) { /* with avoid, factor is "fear factor" */
- Object *eob = eff->ob;
- PartDeflect *pd = eff->pd;
- float surface = (pd && pd->shape == PFIELD_SHAPE_SURFACE) ? 1.0f : 0.0f;
-
- if (gabr->options & BRULE_GOAL_AVOID_PREDICT) {
- /* estimate future location of target */
- get_effector_data(eff, &efd, &epoint, 1);
-
- mul_v3_fl(efd.vel, efd.distance / (val->max_speed * bbd->timestep));
- add_v3_v3(efd.loc, efd.vel);
- sub_v3_v3v3(efd.vec_to_point, pa->prev_state.co, efd.loc);
- efd.distance = len_v3(efd.vec_to_point);
- }
-
- if (rule->type == eBoidRuleType_Goal && boids->options & BOID_ALLOW_CLIMB && surface!=0.0f) {
- if (!bbd->goal_ob || bbd->goal_priority < priority) {
- bbd->goal_ob = eob;
- copy_v3_v3(bbd->goal_co, efd.loc);
- copy_v3_v3(bbd->goal_nor, efd.nor);
- }
- }
- else if (rule->type == eBoidRuleType_Avoid && bpa->data.mode == eBoidMode_Climbing &&
- priority > 2.0f * gabr->fear_factor) {
- /* detach from surface and try to fly away from danger */
- negate_v3_v3(efd.vec_to_point, bpa->gravity);
- }
-
- copy_v3_v3(bbd->wanted_co, efd.vec_to_point);
- mul_v3_fl(bbd->wanted_co, mul);
-
- bbd->wanted_speed = val->max_speed * priority;
-
- /* with goals factor is approach velocity factor */
- if (rule->type == eBoidRuleType_Goal && boids->landing_smoothness > 0.0f) {
- float len2 = 2.0f*len_v3(pa->prev_state.vel);
-
- surface *= pa->size * boids->height;
-
- if (len2 > 0.0f && efd.distance - surface < len2) {
- len2 = (efd.distance - surface)/len2;
- bbd->wanted_speed *= powf(len2, boids->landing_smoothness);
- }
- }
-
- ret = 1;
- }
-
- return ret;
-}
-
-static int rule_avoid_collision(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, ParticleData *pa)
-{
- const int raycast_flag = BVH_RAYCAST_DEFAULT & ~(BVH_RAYCAST_WATERTIGHT);
- BoidRuleAvoidCollision *acbr = (BoidRuleAvoidCollision*) rule;
- KDTreeNearest *ptn = NULL;
- ParticleTarget *pt;
- BoidParticle *bpa = pa->boid;
- ColliderCache *coll;
- float vec[3] = {0.0f, 0.0f, 0.0f}, loc[3] = {0.0f, 0.0f, 0.0f};
- float co1[3], vel1[3], co2[3], vel2[3];
- float len, t, inp, t_min = 2.0f;
- int n, neighbors = 0, nearest = 0;
- int ret = 0;
-
- //check deflector objects first
- if (acbr->options & BRULE_ACOLL_WITH_DEFLECTORS && bbd->sim->colliders) {
- ParticleCollision col;
- BVHTreeRayHit hit;
- float radius = val->personal_space * pa->size, ray_dir[3];
-
- memset(&col, 0, sizeof(ParticleCollision));
-
- copy_v3_v3(col.co1, pa->prev_state.co);
- add_v3_v3v3(col.co2, pa->prev_state.co, pa->prev_state.vel);
- sub_v3_v3v3(ray_dir, col.co2, col.co1);
- mul_v3_fl(ray_dir, acbr->look_ahead);
- col.f = 0.0f;
- hit.index = -1;
- hit.dist = col.original_ray_length = normalize_v3(ray_dir);
-
- /* find out closest deflector object */
- for (coll = bbd->sim->colliders->first; coll; coll=coll->next) {
- /* don't check with current ground object */
- if (coll->ob == bpa->ground)
- continue;
-
- col.current = coll->ob;
- col.md = coll->collmd;
-
- if (col.md && col.md->bvhtree) {
- BLI_bvhtree_ray_cast_ex(
- col.md->bvhtree, col.co1, ray_dir, radius, &hit,
- BKE_psys_collision_neartest_cb, &col, raycast_flag);
- }
- }
- /* then avoid that object */
- if (hit.index>=0) {
- t = hit.dist/col.original_ray_length;
-
- /* avoid head-on collision */
- if (dot_v3v3(col.pce.nor, pa->prev_state.ave) < -0.99f) {
- /* don't know why, but uneven range [0.0, 1.0] */
- /* works much better than even [-1.0, 1.0] */
- bbd->wanted_co[0] = BLI_rng_get_float(bbd->rng);
- bbd->wanted_co[1] = BLI_rng_get_float(bbd->rng);
- bbd->wanted_co[2] = BLI_rng_get_float(bbd->rng);
- }
- else {
- copy_v3_v3(bbd->wanted_co, col.pce.nor);
- }
-
- mul_v3_fl(bbd->wanted_co, (1.0f - t) * val->personal_space * pa->size);
-
- bbd->wanted_speed = sqrtf(t) * len_v3(pa->prev_state.vel);
- bbd->wanted_speed = MAX2(bbd->wanted_speed, val->min_speed);
-
- return 1;
- }
- }
-
- //check boids in own system
- if (acbr->options & BRULE_ACOLL_WITH_BOIDS) {
- neighbors = BLI_kdtree_range_search__normal(
- bbd->sim->psys->tree, pa->prev_state.co, pa->prev_state.ave,
- &ptn, acbr->look_ahead * len_v3(pa->prev_state.vel));
- if (neighbors > 1) for (n=1; n<neighbors; n++) {
- copy_v3_v3(co1, pa->prev_state.co);
- copy_v3_v3(vel1, pa->prev_state.vel);
- copy_v3_v3(co2, (bbd->sim->psys->particles + ptn[n].index)->prev_state.co);
- copy_v3_v3(vel2, (bbd->sim->psys->particles + ptn[n].index)->prev_state.vel);
-
- sub_v3_v3v3(loc, co1, co2);
-
- sub_v3_v3v3(vec, vel1, vel2);
-
- inp = dot_v3v3(vec, vec);
-
- /* velocities not parallel */
- if (inp != 0.0f) {
- t = -dot_v3v3(loc, vec)/inp;
- /* cpa is not too far in the future so investigate further */
- if (t > 0.0f && t < t_min) {
- madd_v3_v3fl(co1, vel1, t);
- madd_v3_v3fl(co2, vel2, t);
-
- sub_v3_v3v3(vec, co2, co1);
-
- len = normalize_v3(vec);
-
- /* distance of cpa is close enough */
- if (len < 2.0f * val->personal_space * pa->size) {
- t_min = t;
-
- mul_v3_fl(vec, len_v3(vel1));
- mul_v3_fl(vec, (2.0f - t)/2.0f);
- sub_v3_v3v3(bbd->wanted_co, vel1, vec);
- bbd->wanted_speed = len_v3(bbd->wanted_co);
- ret = 1;
- }
- }
- }
- }
- }
- if (ptn) { MEM_freeN(ptn); ptn=NULL; }
-
- /* check boids in other systems */
- for (pt=bbd->sim->psys->targets.first; pt; pt=pt->next) {
- ParticleSystem *epsys = psys_get_target_system(bbd->sim->ob, pt);
-
- if (epsys) {
- BLI_assert(epsys->tree != NULL);
- neighbors = BLI_kdtree_range_search__normal(
- epsys->tree, pa->prev_state.co, pa->prev_state.ave,
- &ptn, acbr->look_ahead * len_v3(pa->prev_state.vel));
-
- if (neighbors > 0) for (n=0; n<neighbors; n++) {
- copy_v3_v3(co1, pa->prev_state.co);
- copy_v3_v3(vel1, pa->prev_state.vel);
- copy_v3_v3(co2, (epsys->particles + ptn[n].index)->prev_state.co);
- copy_v3_v3(vel2, (epsys->particles + ptn[n].index)->prev_state.vel);
-
- sub_v3_v3v3(loc, co1, co2);
-
- sub_v3_v3v3(vec, vel1, vel2);
-
- inp = dot_v3v3(vec, vec);
-
- /* velocities not parallel */
- if (inp != 0.0f) {
- t = -dot_v3v3(loc, vec)/inp;
- /* cpa is not too far in the future so investigate further */
- if (t > 0.0f && t < t_min) {
- madd_v3_v3fl(co1, vel1, t);
- madd_v3_v3fl(co2, vel2, t);
-
- sub_v3_v3v3(vec, co2, co1);
-
- len = normalize_v3(vec);
-
- /* distance of cpa is close enough */
- if (len < 2.0f * val->personal_space * pa->size) {
- t_min = t;
-
- mul_v3_fl(vec, len_v3(vel1));
- mul_v3_fl(vec, (2.0f - t)/2.0f);
- sub_v3_v3v3(bbd->wanted_co, vel1, vec);
- bbd->wanted_speed = len_v3(bbd->wanted_co);
- ret = 1;
- }
- }
- }
- }
-
- if (ptn) { MEM_freeN(ptn); ptn=NULL; }
- }
- }
-
-
- if (ptn && nearest==0)
- MEM_freeN(ptn);
-
- return ret;
-}
-static int rule_separate(BoidRule *UNUSED(rule), BoidBrainData *bbd, BoidValues *val, ParticleData *pa)
-{
- KDTreeNearest *ptn = NULL;
- ParticleTarget *pt;
- float len = 2.0f * val->personal_space * pa->size + 1.0f;
- float vec[3] = {0.0f, 0.0f, 0.0f};
- int neighbors = BLI_kdtree_range_search(
- bbd->sim->psys->tree, pa->prev_state.co,
- &ptn, 2.0f * val->personal_space * pa->size);
- int ret = 0;
-
- if (neighbors > 1 && ptn[1].dist!=0.0f) {
- sub_v3_v3v3(vec, pa->prev_state.co, bbd->sim->psys->particles[ptn[1].index].state.co);
- mul_v3_fl(vec, (2.0f * val->personal_space * pa->size - ptn[1].dist) / ptn[1].dist);
- add_v3_v3(bbd->wanted_co, vec);
- bbd->wanted_speed = val->max_speed;
- len = ptn[1].dist;
- ret = 1;
- }
- if (ptn) { MEM_freeN(ptn); ptn=NULL; }
-
- /* check other boid systems */
- for (pt=bbd->sim->psys->targets.first; pt; pt=pt->next) {
- ParticleSystem *epsys = psys_get_target_system(bbd->sim->ob, pt);
-
- if (epsys) {
- neighbors = BLI_kdtree_range_search(
- epsys->tree, pa->prev_state.co,
- &ptn, 2.0f * val->personal_space * pa->size);
-
- if (neighbors > 0 && ptn[0].dist < len) {
- sub_v3_v3v3(vec, pa->prev_state.co, ptn[0].co);
- mul_v3_fl(vec, (2.0f * val->personal_space * pa->size - ptn[0].dist) / ptn[1].dist);
- add_v3_v3(bbd->wanted_co, vec);
- bbd->wanted_speed = val->max_speed;
- len = ptn[0].dist;
- ret = 1;
- }
-
- if (ptn) { MEM_freeN(ptn); ptn=NULL; }
- }
- }
- return ret;
-}
-static int rule_flock(BoidRule *UNUSED(rule), BoidBrainData *bbd, BoidValues *UNUSED(val), ParticleData *pa)
-{
- KDTreeNearest ptn[11];
- float vec[3] = {0.0f, 0.0f, 0.0f}, loc[3] = {0.0f, 0.0f, 0.0f};
- int neighbors = BLI_kdtree_find_nearest_n__normal(bbd->sim->psys->tree, pa->state.co, pa->prev_state.ave, ptn, 11);
- int n;
- int ret = 0;
-
- if (neighbors > 1) {
- for (n=1; n<neighbors; n++) {
- add_v3_v3(loc, bbd->sim->psys->particles[ptn[n].index].prev_state.co);
- add_v3_v3(vec, bbd->sim->psys->particles[ptn[n].index].prev_state.vel);
- }
-
- mul_v3_fl(loc, 1.0f/((float)neighbors - 1.0f));
- mul_v3_fl(vec, 1.0f/((float)neighbors - 1.0f));
-
- sub_v3_v3(loc, pa->prev_state.co);
- sub_v3_v3(vec, pa->prev_state.vel);
-
- add_v3_v3(bbd->wanted_co, vec);
- add_v3_v3(bbd->wanted_co, loc);
- bbd->wanted_speed = len_v3(bbd->wanted_co);
-
- ret = 1;
- }
- return ret;
-}
-static int rule_follow_leader(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, ParticleData *pa)
-{
- BoidRuleFollowLeader *flbr = (BoidRuleFollowLeader*) rule;
- float vec[3] = {0.0f, 0.0f, 0.0f}, loc[3] = {0.0f, 0.0f, 0.0f};
- float mul, len;
- int n = (flbr->queue_size <= 1) ? bbd->sim->psys->totpart : flbr->queue_size;
- int i, ret = 0, p = pa - bbd->sim->psys->particles;
-
- if (flbr->ob) {
- float vec2[3], t;
-
- /* first check we're not blocking the leader */
- sub_v3_v3v3(vec, flbr->loc, flbr->oloc);
- mul_v3_fl(vec, 1.0f/bbd->timestep);
-
- sub_v3_v3v3(loc, pa->prev_state.co, flbr->oloc);
-
- mul = dot_v3v3(vec, vec);
-
- /* leader is not moving */
- if (mul < 0.01f) {
- len = len_v3(loc);
- /* too close to leader */
- if (len < 2.0f * val->personal_space * pa->size) {
- copy_v3_v3(bbd->wanted_co, loc);
- bbd->wanted_speed = val->max_speed;
- return 1;
- }
- }
- else {
- t = dot_v3v3(loc, vec)/mul;
-
- /* possible blocking of leader in near future */
- if (t > 0.0f && t < 3.0f) {
- copy_v3_v3(vec2, vec);
- mul_v3_fl(vec2, t);
-
- sub_v3_v3v3(vec2, loc, vec2);
-
- len = len_v3(vec2);
-
- if (len < 2.0f * val->personal_space * pa->size) {
- copy_v3_v3(bbd->wanted_co, vec2);
- bbd->wanted_speed = val->max_speed * (3.0f - t)/3.0f;
- return 1;
- }
- }
- }
-
- /* not blocking so try to follow leader */
- if (p && flbr->options & BRULE_LEADER_IN_LINE) {
- copy_v3_v3(vec, bbd->sim->psys->particles[p-1].prev_state.vel);
- copy_v3_v3(loc, bbd->sim->psys->particles[p-1].prev_state.co);
- }
- else {
- copy_v3_v3(loc, flbr->oloc);
- sub_v3_v3v3(vec, flbr->loc, flbr->oloc);
- mul_v3_fl(vec, 1.0f/bbd->timestep);
- }
-
- /* fac is seconds behind leader */
- madd_v3_v3fl(loc, vec, -flbr->distance);
-
- sub_v3_v3v3(bbd->wanted_co, loc, pa->prev_state.co);
- bbd->wanted_speed = len_v3(bbd->wanted_co);
-
- ret = 1;
- }
- else if (p % n) {
- float vec2[3], t, t_min = 3.0f;
-
- /* first check we're not blocking any leaders */
- for (i = 0; i< bbd->sim->psys->totpart; i+=n) {
- copy_v3_v3(vec, bbd->sim->psys->particles[i].prev_state.vel);
-
- sub_v3_v3v3(loc, pa->prev_state.co, bbd->sim->psys->particles[i].prev_state.co);
-
- mul = dot_v3v3(vec, vec);
-
- /* leader is not moving */
- if (mul < 0.01f) {
- len = len_v3(loc);
- /* too close to leader */
- if (len < 2.0f * val->personal_space * pa->size) {
- copy_v3_v3(bbd->wanted_co, loc);
- bbd->wanted_speed = val->max_speed;
- return 1;
- }
- }
- else {
- t = dot_v3v3(loc, vec)/mul;
-
- /* possible blocking of leader in near future */
- if (t > 0.0f && t < t_min) {
- copy_v3_v3(vec2, vec);
- mul_v3_fl(vec2, t);
-
- sub_v3_v3v3(vec2, loc, vec2);
-
- len = len_v3(vec2);
-
- if (len < 2.0f * val->personal_space * pa->size) {
- t_min = t;
- copy_v3_v3(bbd->wanted_co, loc);
- bbd->wanted_speed = val->max_speed * (3.0f - t)/3.0f;
- ret = 1;
- }
- }
- }
- }
-
- if (ret) return 1;
-
- /* not blocking so try to follow leader */
- if (flbr->options & BRULE_LEADER_IN_LINE) {
- copy_v3_v3(vec, bbd->sim->psys->particles[p-1].prev_state.vel);
- copy_v3_v3(loc, bbd->sim->psys->particles[p-1].prev_state.co);
- }
- else {
- copy_v3_v3(vec, bbd->sim->psys->particles[p - p%n].prev_state.vel);
- copy_v3_v3(loc, bbd->sim->psys->particles[p - p%n].prev_state.co);
- }
-
- /* fac is seconds behind leader */
- madd_v3_v3fl(loc, vec, -flbr->distance);
-
- sub_v3_v3v3(bbd->wanted_co, loc, pa->prev_state.co);
- bbd->wanted_speed = len_v3(bbd->wanted_co);
-
- ret = 1;
- }
-
- return ret;
-}
-static int rule_average_speed(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, ParticleData *pa)
-{
- BoidParticle *bpa = pa->boid;
- BoidRuleAverageSpeed *asbr = (BoidRuleAverageSpeed*)rule;
- float vec[3] = {0.0f, 0.0f, 0.0f};
-
- if (asbr->wander > 0.0f) {
- /* abuse pa->r_ave for wandering */
- bpa->wander[0] += asbr->wander * (-1.0f + 2.0f * BLI_rng_get_float(bbd->rng));
- bpa->wander[1] += asbr->wander * (-1.0f + 2.0f * BLI_rng_get_float(bbd->rng));
- bpa->wander[2] += asbr->wander * (-1.0f + 2.0f * BLI_rng_get_float(bbd->rng));
-
- normalize_v3(bpa->wander);
-
- copy_v3_v3(vec, bpa->wander);
-
- mul_qt_v3(pa->prev_state.rot, vec);
-
- copy_v3_v3(bbd->wanted_co, pa->prev_state.ave);
-
- mul_v3_fl(bbd->wanted_co, 1.1f);
-
- add_v3_v3(bbd->wanted_co, vec);
-
- /* leveling */
- if (asbr->level > 0.0f && psys_uses_gravity(bbd->sim)) {
- project_v3_v3v3(vec, bbd->wanted_co, bbd->sim->scene->physics_settings.gravity);
- mul_v3_fl(vec, asbr->level);
- sub_v3_v3(bbd->wanted_co, vec);
- }
- }
- else {
- copy_v3_v3(bbd->wanted_co, pa->prev_state.ave);
-
- /* may happen at birth */
- if (dot_v2v2(bbd->wanted_co, bbd->wanted_co)==0.0f) {
- bbd->wanted_co[0] = 2.0f*(0.5f - BLI_rng_get_float(bbd->rng));
- bbd->wanted_co[1] = 2.0f*(0.5f - BLI_rng_get_float(bbd->rng));
- bbd->wanted_co[2] = 2.0f*(0.5f - BLI_rng_get_float(bbd->rng));
- }
-
- /* leveling */
- if (asbr->level > 0.0f && psys_uses_gravity(bbd->sim)) {
- project_v3_v3v3(vec, bbd->wanted_co, bbd->sim->scene->physics_settings.gravity);
- mul_v3_fl(vec, asbr->level);
- sub_v3_v3(bbd->wanted_co, vec);
- }
-
- }
- bbd->wanted_speed = asbr->speed * val->max_speed;
-
- return 1;
-}
-static int rule_fight(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, ParticleData *pa)
-{
- BoidRuleFight *fbr = (BoidRuleFight*)rule;
- KDTreeNearest *ptn = NULL;
- ParticleTarget *pt;
- ParticleData *epars;
- ParticleData *enemy_pa = NULL;
- BoidParticle *bpa;
- /* friends & enemies */
- float closest_enemy[3] = {0.0f, 0.0f, 0.0f};
- float closest_dist = fbr->distance + 1.0f;
- float f_strength = 0.0f, e_strength = 0.0f;
- float health = 0.0f;
- int n, ret = 0;
-
- /* calculate own group strength */
- int neighbors = BLI_kdtree_range_search(
- bbd->sim->psys->tree, pa->prev_state.co,
- &ptn, fbr->distance);
- for (n=0; n<neighbors; n++) {
- bpa = bbd->sim->psys->particles[ptn[n].index].boid;
- health += bpa->data.health;
- }
-
- f_strength += bbd->part->boids->strength * health;
-
- if (ptn) { MEM_freeN(ptn); ptn=NULL; }
-
- /* add other friendlies and calculate enemy strength and find closest enemy */
- for (pt=bbd->sim->psys->targets.first; pt; pt=pt->next) {
- ParticleSystem *epsys = psys_get_target_system(bbd->sim->ob, pt);
- if (epsys) {
- epars = epsys->particles;
-
- neighbors = BLI_kdtree_range_search(
- epsys->tree, pa->prev_state.co,
- &ptn, fbr->distance);
-
- health = 0.0f;
-
- for (n=0; n<neighbors; n++) {
- bpa = epars[ptn[n].index].boid;
- health += bpa->data.health;
-
- if (n==0 && pt->mode==PTARGET_MODE_ENEMY && ptn[n].dist < closest_dist) {
- copy_v3_v3(closest_enemy, ptn[n].co);
- closest_dist = ptn[n].dist;
- enemy_pa = epars + ptn[n].index;
- }
- }
- if (pt->mode==PTARGET_MODE_ENEMY)
- e_strength += epsys->part->boids->strength * health;
- else if (pt->mode==PTARGET_MODE_FRIEND)
- f_strength += epsys->part->boids->strength * health;
-
- if (ptn) { MEM_freeN(ptn); ptn=NULL; }
- }
- }
- /* decide action if enemy presence found */
- if (e_strength > 0.0f) {
- sub_v3_v3v3(bbd->wanted_co, closest_enemy, pa->prev_state.co);
-
- /* attack if in range */
- if (closest_dist <= bbd->part->boids->range + pa->size + enemy_pa->size) {
- float damage = BLI_rng_get_float(bbd->rng);
- float enemy_dir[3];
-
- normalize_v3_v3(enemy_dir, bbd->wanted_co);
-
- /* fight mode */
- bbd->wanted_speed = 0.0f;
-
- /* must face enemy to fight */
- if (dot_v3v3(pa->prev_state.ave, enemy_dir)>0.5f) {
- bpa = enemy_pa->boid;
- bpa->data.health -= bbd->part->boids->strength * bbd->timestep * ((1.0f-bbd->part->boids->accuracy)*damage + bbd->part->boids->accuracy);
- }
- }
- else {
- /* approach mode */
- bbd->wanted_speed = val->max_speed;
- }
-
- /* check if boid doesn't want to fight */
- bpa = pa->boid;
- if (bpa->data.health/bbd->part->boids->health * bbd->part->boids->aggression < e_strength / f_strength) {
- /* decide to flee */
- if (closest_dist < fbr->flee_distance * fbr->distance) {
- negate_v3(bbd->wanted_co);
- bbd->wanted_speed = val->max_speed;
- }
- else { /* wait for better odds */
- bbd->wanted_speed = 0.0f;
- }
- }
-
- ret = 1;
- }
-
- return ret;
-}
-
-typedef int (*boid_rule_cb)(BoidRule *rule, BoidBrainData *data, BoidValues *val, ParticleData *pa);
-
-static boid_rule_cb boid_rules[] = {
- rule_none,
- rule_goal_avoid,
- rule_goal_avoid,
- rule_avoid_collision,
- rule_separate,
- rule_flock,
- rule_follow_leader,
- rule_average_speed,
- rule_fight,
- //rule_help,
- //rule_protect,
- //rule_hide,
- //rule_follow_path,
- //rule_follow_wall
-};
-
-static void set_boid_values(BoidValues *val, BoidSettings *boids, ParticleData *pa)
-{
- BoidParticle *bpa = pa->boid;
-
- if (ELEM(bpa->data.mode, eBoidMode_OnLand, eBoidMode_Climbing)) {
- val->max_speed = boids->land_max_speed * bpa->data.health/boids->health;
- val->max_acc = boids->land_max_acc * val->max_speed;
- val->max_ave = boids->land_max_ave * (float)M_PI * bpa->data.health/boids->health;
- val->min_speed = 0.0f; /* no minimum speed on land */
- val->personal_space = boids->land_personal_space;
- val->jump_speed = boids->land_jump_speed * bpa->data.health/boids->health;
- }
- else {
- val->max_speed = boids->air_max_speed * bpa->data.health/boids->health;
- val->max_acc = boids->air_max_acc * val->max_speed;
- val->max_ave = boids->air_max_ave * (float)M_PI * bpa->data.health/boids->health;
- val->min_speed = boids->air_min_speed * boids->air_max_speed;
- val->personal_space = boids->air_personal_space;
- val->jump_speed = 0.0f; /* no jumping in air */
- }
-}
-
-static Object *boid_find_ground(BoidBrainData *bbd, ParticleData *pa, float ground_co[3], float ground_nor[3])
-{
- const int raycast_flag = BVH_RAYCAST_DEFAULT & ~(BVH_RAYCAST_WATERTIGHT);
- BoidParticle *bpa = pa->boid;
-
- if (bpa->data.mode == eBoidMode_Climbing) {
- SurfaceModifierData *surmd = NULL;
- float x[3], v[3];
-
- surmd = (SurfaceModifierData *)modifiers_findByType(bpa->ground, eModifierType_Surface );
-
- /* take surface velocity into account */
- closest_point_on_surface(surmd, pa->state.co, x, NULL, v);
- add_v3_v3(x, v);
-
- /* get actual position on surface */
- closest_point_on_surface(surmd, x, ground_co, ground_nor, NULL);
-
- return bpa->ground;
- }
- else {
- float zvec[3] = {0.0f, 0.0f, 2000.0f};
- ParticleCollision col;
- ColliderCache *coll;
- BVHTreeRayHit hit;
- float radius = 0.0f, t, ray_dir[3];
-
- if (!bbd->sim->colliders)
- return NULL;
-
- memset(&col, 0, sizeof(ParticleCollision));
-
- /* first try to find below boid */
- copy_v3_v3(col.co1, pa->state.co);
- sub_v3_v3v3(col.co2, pa->state.co, zvec);
- sub_v3_v3v3(ray_dir, col.co2, col.co1);
- col.f = 0.0f;
- hit.index = -1;
- hit.dist = col.original_ray_length = normalize_v3(ray_dir);
- col.pce.inside = 0;
-
- for (coll = bbd->sim->colliders->first; coll; coll = coll->next) {
- col.current = coll->ob;
- col.md = coll->collmd;
- col.fac1 = col.fac2 = 0.f;
-
- if (col.md && col.md->bvhtree) {
- BLI_bvhtree_ray_cast_ex(
- col.md->bvhtree, col.co1, ray_dir, radius, &hit,
- BKE_psys_collision_neartest_cb, &col, raycast_flag);
- }
- }
- /* then use that object */
- if (hit.index>=0) {
- t = hit.dist/col.original_ray_length;
- interp_v3_v3v3(ground_co, col.co1, col.co2, t);
- normalize_v3_v3(ground_nor, col.pce.nor);
- return col.hit;
- }
-
- /* couldn't find below, so find upmost deflector object */
- add_v3_v3v3(col.co1, pa->state.co, zvec);
- sub_v3_v3v3(col.co2, pa->state.co, zvec);
- sub_v3_v3(col.co2, zvec);
- sub_v3_v3v3(ray_dir, col.co2, col.co1);
- col.f = 0.0f;
- hit.index = -1;
- hit.dist = col.original_ray_length = normalize_v3(ray_dir);
-
- for (coll = bbd->sim->colliders->first; coll; coll = coll->next) {
- col.current = coll->ob;
- col.md = coll->collmd;
-
- if (col.md && col.md->bvhtree) {
- BLI_bvhtree_ray_cast_ex(
- col.md->bvhtree, col.co1, ray_dir, radius, &hit,
- BKE_psys_collision_neartest_cb, &col, raycast_flag);
- }
- }
- /* then use that object */
- if (hit.index>=0) {
- t = hit.dist/col.original_ray_length;
- interp_v3_v3v3(ground_co, col.co1, col.co2, t);
- normalize_v3_v3(ground_nor, col.pce.nor);
- return col.hit;
- }
-
- /* default to z=0 */
- copy_v3_v3(ground_co, pa->state.co);
- ground_co[2] = 0;
- ground_nor[0] = ground_nor[1] = 0.0f;
- ground_nor[2] = 1.0f;
- return NULL;
- }
-}
-static int boid_rule_applies(ParticleData *pa, BoidSettings *UNUSED(boids), BoidRule *rule)
-{
- BoidParticle *bpa = pa->boid;
-
- if (rule==NULL)
- return 0;
-
- if (ELEM(bpa->data.mode, eBoidMode_OnLand, eBoidMode_Climbing) && rule->flag & BOIDRULE_ON_LAND)
- return 1;
-
- if (bpa->data.mode==eBoidMode_InAir && rule->flag & BOIDRULE_IN_AIR)
- return 1;
-
- return 0;
-}
-void boids_precalc_rules(ParticleSettings *part, float cfra)
-{
- BoidState *state = part->boids->states.first;
- BoidRule *rule;
- for (; state; state=state->next) {
- for (rule = state->rules.first; rule; rule=rule->next) {
- if (rule->type==eBoidRuleType_FollowLeader) {
- BoidRuleFollowLeader *flbr = (BoidRuleFollowLeader*) rule;
-
- if (flbr->ob && flbr->cfra != cfra) {
- /* save object locations for velocity calculations */
- copy_v3_v3(flbr->oloc, flbr->loc);
- copy_v3_v3(flbr->loc, flbr->ob->obmat[3]);
- flbr->cfra = cfra;
- }
- }
- }
- }
-}
-static void boid_climb(BoidSettings *boids, ParticleData *pa, float *surface_co, float *surface_nor)
-{
- BoidParticle *bpa = pa->boid;
- float nor[3], vel[3];
- copy_v3_v3(nor, surface_nor);
-
- /* gather apparent gravity */
- madd_v3_v3fl(bpa->gravity, surface_nor, -1.0f);
- normalize_v3(bpa->gravity);
-
- /* raise boid it's size from surface */
- mul_v3_fl(nor, pa->size * boids->height);
- add_v3_v3v3(pa->state.co, surface_co, nor);
-
- /* remove normal component from velocity */
- project_v3_v3v3(vel, pa->state.vel, surface_nor);
- sub_v3_v3v3(pa->state.vel, pa->state.vel, vel);
-}
-static float boid_goal_signed_dist(float *boid_co, float *goal_co, float *goal_nor)
-{
- float vec[3];
-
- sub_v3_v3v3(vec, boid_co, goal_co);
-
- return dot_v3v3(vec, goal_nor);
-}
-/* wanted_co is relative to boid location */
-static int apply_boid_rule(BoidBrainData *bbd, BoidRule *rule, BoidValues *val, ParticleData *pa, float fuzziness)
-{
- if (rule==NULL)
- return 0;
-
- if (boid_rule_applies(pa, bbd->part->boids, rule)==0)
- return 0;
-
- if (boid_rules[rule->type](rule, bbd, val, pa)==0)
- return 0;
-
- if (fuzziness < 0.0f || compare_len_v3v3(bbd->wanted_co, pa->prev_state.vel, fuzziness * len_v3(pa->prev_state.vel))==0)
- return 1;
- else
- return 0;
-}
-static BoidState *get_boid_state(BoidSettings *boids, ParticleData *pa)
-{
- BoidState *state = boids->states.first;
- BoidParticle *bpa = pa->boid;
-
- for (; state; state=state->next) {
- if (state->id==bpa->data.state_id)
- return state;
- }
-
- /* for some reason particle isn't at a valid state */
- state = boids->states.first;
- if (state)
- bpa->data.state_id = state->id;
-
- return state;
-}
-//static int boid_condition_is_true(BoidCondition *cond)
-//{
-// /* TODO */
-// return 0;
-//}
-
-/* determines the velocity the boid wants to have */
-void boid_brain(BoidBrainData *bbd, int p, ParticleData *pa)
-{
- BoidRule *rule;
- BoidSettings *boids = bbd->part->boids;
- BoidValues val;
- BoidState *state = get_boid_state(boids, pa);
- BoidParticle *bpa = pa->boid;
- ParticleSystem *psys = bbd->sim->psys;
- int rand;
- //BoidCondition *cond;
-
- if (bpa->data.health <= 0.0f) {
- pa->alive = PARS_DYING;
- pa->dietime = bbd->cfra;
- return;
- }
-
- //planned for near future
- //cond = state->conditions.first;
- //for (; cond; cond=cond->next) {
- // if (boid_condition_is_true(cond)) {
- // pa->boid->state_id = cond->state_id;
- // state = get_boid_state(boids, pa);
- // break; /* only first true condition is used */
- // }
- //}
-
- zero_v3(bbd->wanted_co);
- bbd->wanted_speed = 0.0f;
-
- /* create random seed for every particle & frame */
- rand = (int)(psys_frand(psys, psys->seed + p) * 1000);
- rand = (int)(psys_frand(psys, (int)bbd->cfra + rand) * 1000);
-
- set_boid_values(&val, bbd->part->boids, pa);
-
- /* go through rules */
- switch (state->ruleset_type) {
- case eBoidRulesetType_Fuzzy:
- {
- for (rule = state->rules.first; rule; rule = rule->next) {
- if (apply_boid_rule(bbd, rule, &val, pa, state->rule_fuzziness))
- break; /* only first nonzero rule that comes through fuzzy rule is applied */
- }
- break;
- }
- case eBoidRulesetType_Random:
- {
- /* use random rule for each particle (always same for same particle though) */
- const int n = BLI_listbase_count(&state->rules);
- if (n) {
- rule = BLI_findlink(&state->rules, rand % n);
- apply_boid_rule(bbd, rule, &val, pa, -1.0);
- }
- break;
- }
- case eBoidRulesetType_Average:
- {
- float wanted_co[3] = {0.0f, 0.0f, 0.0f}, wanted_speed = 0.0f;
- int n = 0;
- for (rule = state->rules.first; rule; rule=rule->next) {
- if (apply_boid_rule(bbd, rule, &val, pa, -1.0f)) {
- add_v3_v3(wanted_co, bbd->wanted_co);
- wanted_speed += bbd->wanted_speed;
- n++;
- zero_v3(bbd->wanted_co);
- bbd->wanted_speed = 0.0f;
- }
- }
-
- if (n > 1) {
- mul_v3_fl(wanted_co, 1.0f/(float)n);
- wanted_speed /= (float)n;
- }
-
- copy_v3_v3(bbd->wanted_co, wanted_co);
- bbd->wanted_speed = wanted_speed;
- break;
- }
-
- }
-
- /* decide on jumping & liftoff */
- if (bpa->data.mode == eBoidMode_OnLand) {
- /* fuzziness makes boids capable of misjudgement */
- float mul = 1.0f + state->rule_fuzziness;
-
- if (boids->options & BOID_ALLOW_FLIGHT && bbd->wanted_co[2] > 0.0f) {
- float cvel[3], dir[3];
-
- copy_v3_v3(dir, pa->prev_state.ave);
- normalize_v2(dir);
-
- copy_v3_v3(cvel, bbd->wanted_co);
- normalize_v2(cvel);
-
- if (dot_v2v2(cvel, dir) > 0.95f / mul)
- bpa->data.mode = eBoidMode_Liftoff;
- }
- else if (val.jump_speed > 0.0f) {
- float jump_v[3];
- int jump = 0;
-
- /* jump to get to a location */
- if (bbd->wanted_co[2] > 0.0f) {
- float cvel[3], dir[3];
- float z_v, ground_v, cur_v;
- float len;
-
- copy_v3_v3(dir, pa->prev_state.ave);
- normalize_v2(dir);
-
- copy_v3_v3(cvel, bbd->wanted_co);
- normalize_v2(cvel);
-
- len = len_v2(pa->prev_state.vel);
-
- /* first of all, are we going in a suitable direction? */
- /* or at a suitably slow speed */
- if (dot_v2v2(cvel, dir) > 0.95f / mul || len <= state->rule_fuzziness) {
- /* try to reach goal at highest point of the parabolic path */
- cur_v = len_v2(pa->prev_state.vel);
- z_v = sasqrt(-2.0f * bbd->sim->scene->physics_settings.gravity[2] * bbd->wanted_co[2]);
- ground_v = len_v2(bbd->wanted_co)*sasqrt(-0.5f * bbd->sim->scene->physics_settings.gravity[2] / bbd->wanted_co[2]);
-
- len = sasqrt((ground_v-cur_v)*(ground_v-cur_v) + z_v*z_v);
-
- if (len < val.jump_speed * mul || bbd->part->boids->options & BOID_ALLOW_FLIGHT) {
- jump = 1;
-
- len = MIN2(len, val.jump_speed);
-
- copy_v3_v3(jump_v, dir);
- jump_v[2] = z_v;
- mul_v3_fl(jump_v, ground_v);
-
- normalize_v3(jump_v);
- mul_v3_fl(jump_v, len);
- add_v2_v2v2(jump_v, jump_v, pa->prev_state.vel);
- }
- }
- }
-
- /* jump to go faster */
- if (jump == 0 && val.jump_speed > val.max_speed && bbd->wanted_speed > val.max_speed) {
-
- }
-
- if (jump) {
- copy_v3_v3(pa->prev_state.vel, jump_v);
- bpa->data.mode = eBoidMode_Falling;
- }
- }
- }
-}
-/* tries to realize the wanted velocity taking all constraints into account */
-void boid_body(BoidBrainData *bbd, ParticleData *pa)
-{
- BoidSettings *boids = bbd->part->boids;
- BoidParticle *bpa = pa->boid;
- BoidValues val;
- EffectedPoint epoint;
- float acc[3] = {0.0f, 0.0f, 0.0f}, tan_acc[3], nor_acc[3];
- float dvec[3], bvec[3];
- float new_dir[3], new_speed;
- float old_dir[3], old_speed;
- float wanted_dir[3];
- float q[4], mat[3][3]; /* rotation */
- float ground_co[3] = {0.0f, 0.0f, 0.0f}, ground_nor[3] = {0.0f, 0.0f, 1.0f};
- float force[3] = {0.0f, 0.0f, 0.0f};
- float pa_mass=bbd->part->mass, dtime=bbd->dfra*bbd->timestep;
-
- set_boid_values(&val, boids, pa);
-
- /* make sure there's something in new velocity, location & rotation */
- copy_particle_key(&pa->state, &pa->prev_state, 0);
-
- if (bbd->part->flag & PART_SIZEMASS)
- pa_mass*=pa->size;
-
- /* if boids can't fly they fall to the ground */
- if ((boids->options & BOID_ALLOW_FLIGHT)==0 && ELEM(bpa->data.mode, eBoidMode_OnLand, eBoidMode_Climbing)==0 && psys_uses_gravity(bbd->sim))
- bpa->data.mode = eBoidMode_Falling;
-
- if (bpa->data.mode == eBoidMode_Falling) {
- /* Falling boids are only effected by gravity. */
- acc[2] = bbd->sim->scene->physics_settings.gravity[2];
- }
- else {
- /* figure out acceleration */
- float landing_level = 2.0f;
- float level = landing_level + 1.0f;
- float new_vel[3];
-
- if (bpa->data.mode == eBoidMode_Liftoff) {
- bpa->data.mode = eBoidMode_InAir;
- bpa->ground = boid_find_ground(bbd, pa, ground_co, ground_nor);
- }
- else if (bpa->data.mode == eBoidMode_InAir && boids->options & BOID_ALLOW_LAND) {
- /* auto-leveling & landing if close to ground */
-
- bpa->ground = boid_find_ground(bbd, pa, ground_co, ground_nor);
-
- /* level = how many particle sizes above ground */
- level = (pa->prev_state.co[2] - ground_co[2])/(2.0f * pa->size) - 0.5f;
-
- landing_level = - boids->landing_smoothness * pa->prev_state.vel[2] * pa_mass;
-
- if (pa->prev_state.vel[2] < 0.0f) {
- if (level < 1.0f) {
- bbd->wanted_co[0] = bbd->wanted_co[1] = bbd->wanted_co[2] = 0.0f;
- bbd->wanted_speed = 0.0f;
- bpa->data.mode = eBoidMode_Falling;
- }
- else if (level < landing_level) {
- bbd->wanted_speed *= (level - 1.0f)/landing_level;
- bbd->wanted_co[2] *= (level - 1.0f)/landing_level;
- }
- }
- }
-
- copy_v3_v3(old_dir, pa->prev_state.ave);
- new_speed = normalize_v3_v3(wanted_dir, bbd->wanted_co);
-
- /* first check if we have valid direction we want to go towards */
- if (new_speed == 0.0f) {
- copy_v3_v3(new_dir, old_dir);
- }
- else {
- float old_dir2[2], wanted_dir2[2], nor[3], angle;
- copy_v2_v2(old_dir2, old_dir);
- normalize_v2(old_dir2);
- copy_v2_v2(wanted_dir2, wanted_dir);
- normalize_v2(wanted_dir2);
-
- /* choose random direction to turn if wanted velocity */
- /* is directly behind regardless of z-coordinate */
- if (dot_v2v2(old_dir2, wanted_dir2) < -0.99f) {
- wanted_dir[0] = 2.0f*(0.5f - BLI_rng_get_float(bbd->rng));
- wanted_dir[1] = 2.0f*(0.5f - BLI_rng_get_float(bbd->rng));
- wanted_dir[2] = 2.0f*(0.5f - BLI_rng_get_float(bbd->rng));
- normalize_v3(wanted_dir);
- }
-
- /* constrain direction with maximum angular velocity */
- angle = saacos(dot_v3v3(old_dir, wanted_dir));
- angle = min_ff(angle, val.max_ave);
-
- cross_v3_v3v3(nor, old_dir, wanted_dir);
- axis_angle_to_quat(q, nor, angle);
- copy_v3_v3(new_dir, old_dir);
- mul_qt_v3(q, new_dir);
- normalize_v3(new_dir);
-
- /* save direction in case resulting velocity too small */
- axis_angle_to_quat(q, nor, angle*dtime);
- copy_v3_v3(pa->state.ave, old_dir);
- mul_qt_v3(q, pa->state.ave);
- normalize_v3(pa->state.ave);
- }
-
- /* constrain speed with maximum acceleration */
- old_speed = len_v3(pa->prev_state.vel);
-
- if (bbd->wanted_speed < old_speed)
- new_speed = MAX2(bbd->wanted_speed, old_speed - val.max_acc);
- else
- new_speed = MIN2(bbd->wanted_speed, old_speed + val.max_acc);
-
- /* combine direction and speed */
- copy_v3_v3(new_vel, new_dir);
- mul_v3_fl(new_vel, new_speed);
-
- /* maintain minimum flying velocity if not landing */
- if (level >= landing_level) {
- float len2 = dot_v2v2(new_vel, new_vel);
- float root;
-
- len2 = MAX2(len2, val.min_speed*val.min_speed);
- root = sasqrt(new_speed*new_speed - len2);
-
- new_vel[2] = new_vel[2] < 0.0f ? -root : root;
-
- normalize_v2(new_vel);
- mul_v2_fl(new_vel, sasqrt(len2));
- }
-
- /* finally constrain speed to max speed */
- new_speed = normalize_v3(new_vel);
- mul_v3_fl(new_vel, MIN2(new_speed, val.max_speed));
-
- /* get acceleration from difference of velocities */
- sub_v3_v3v3(acc, new_vel, pa->prev_state.vel);
-
- /* break acceleration to components */
- project_v3_v3v3(tan_acc, acc, pa->prev_state.ave);
- sub_v3_v3v3(nor_acc, acc, tan_acc);
- }
-
- /* account for effectors */
- pd_point_from_particle(bbd->sim, pa, &pa->state, &epoint);
- pdDoEffectors(bbd->sim->psys->effectors, bbd->sim->colliders, bbd->part->effector_weights, &epoint, force, NULL);
-
- if (ELEM(bpa->data.mode, eBoidMode_OnLand, eBoidMode_Climbing)) {
- float length = normalize_v3(force);
-
- length = MAX2(0.0f, length - boids->land_stick_force);
-
- mul_v3_fl(force, length);
- }
-
- add_v3_v3(acc, force);
-
- /* store smoothed acceleration for nice banking etc. */
- madd_v3_v3fl(bpa->data.acc, acc, dtime);
- mul_v3_fl(bpa->data.acc, 1.0f / (1.0f + dtime));
-
- /* integrate new location & velocity */
-
- /* by regarding the acceleration as a force at this stage we*/
- /* can get better control allthough it's a bit unphysical */
- mul_v3_fl(acc, 1.0f/pa_mass);
-
- copy_v3_v3(dvec, acc);
- mul_v3_fl(dvec, dtime*dtime*0.5f);
-
- copy_v3_v3(bvec, pa->prev_state.vel);
- mul_v3_fl(bvec, dtime);
- add_v3_v3(dvec, bvec);
- add_v3_v3(pa->state.co, dvec);
-
- madd_v3_v3fl(pa->state.vel, acc, dtime);
-
- //if (bpa->data.mode != eBoidMode_InAir)
- bpa->ground = boid_find_ground(bbd, pa, ground_co, ground_nor);
-
- /* change modes, constrain movement & keep track of down vector */
- switch (bpa->data.mode) {
- case eBoidMode_InAir:
- {
- float grav[3];
-
- grav[0] = 0.0f;
- grav[1] = 0.0f;
- grav[2] = bbd->sim->scene->physics_settings.gravity[2] < 0.0f ? -1.0f : 0.0f;
-
- /* don't take forward acceleration into account (better banking) */
- if (dot_v3v3(bpa->data.acc, pa->state.vel) > 0.0f) {
- project_v3_v3v3(dvec, bpa->data.acc, pa->state.vel);
- sub_v3_v3v3(dvec, bpa->data.acc, dvec);
- }
- else {
- copy_v3_v3(dvec, bpa->data.acc);
- }
-
- /* gather apparent gravity */
- madd_v3_v3v3fl(bpa->gravity, grav, dvec, -boids->banking);
- normalize_v3(bpa->gravity);
-
- /* stick boid on goal when close enough */
- if (bbd->goal_ob && boid_goal_signed_dist(pa->state.co, bbd->goal_co, bbd->goal_nor) <= pa->size * boids->height) {
- bpa->data.mode = eBoidMode_Climbing;
- bpa->ground = bbd->goal_ob;
- boid_find_ground(bbd, pa, ground_co, ground_nor);
- boid_climb(boids, pa, ground_co, ground_nor);
- }
- else if (pa->state.co[2] <= ground_co[2] + pa->size * boids->height) {
- /* land boid when below ground */
- if (boids->options & BOID_ALLOW_LAND) {
- pa->state.co[2] = ground_co[2] + pa->size * boids->height;
- pa->state.vel[2] = 0.0f;
- bpa->data.mode = eBoidMode_OnLand;
- }
- /* fly above ground */
- else if (bpa->ground) {
- pa->state.co[2] = ground_co[2] + pa->size * boids->height;
- pa->state.vel[2] = 0.0f;
- }
- }
- break;
- }
- case eBoidMode_Falling:
- {
- float grav[3];
-
- grav[0] = 0.0f;
- grav[1] = 0.0f;
- grav[2] = bbd->sim->scene->physics_settings.gravity[2] < 0.0f ? -1.0f : 0.0f;
-
-
- /* gather apparent gravity */
- madd_v3_v3fl(bpa->gravity, grav, dtime);
- normalize_v3(bpa->gravity);
-
- if (boids->options & BOID_ALLOW_LAND) {
- /* stick boid on goal when close enough */
- if (bbd->goal_ob && boid_goal_signed_dist(pa->state.co, bbd->goal_co, bbd->goal_nor) <= pa->size * boids->height) {
- bpa->data.mode = eBoidMode_Climbing;
- bpa->ground = bbd->goal_ob;
- boid_find_ground(bbd, pa, ground_co, ground_nor);
- boid_climb(boids, pa, ground_co, ground_nor);
- }
- /* land boid when really near ground */
- else if (pa->state.co[2] <= ground_co[2] + 1.01f * pa->size * boids->height) {
- pa->state.co[2] = ground_co[2] + pa->size * boids->height;
- pa->state.vel[2] = 0.0f;
- bpa->data.mode = eBoidMode_OnLand;
- }
- /* if we're falling, can fly and want to go upwards lets fly */
- else if (boids->options & BOID_ALLOW_FLIGHT && bbd->wanted_co[2] > 0.0f)
- bpa->data.mode = eBoidMode_InAir;
- }
- else
- bpa->data.mode = eBoidMode_InAir;
- break;
- }
- case eBoidMode_Climbing:
- {
- boid_climb(boids, pa, ground_co, ground_nor);
- //float nor[3];
- //copy_v3_v3(nor, ground_nor);
-
- ///* gather apparent gravity to r_ve */
- //madd_v3_v3fl(pa->r_ve, ground_nor, -1.0);
- //normalize_v3(pa->r_ve);
-
- ///* raise boid it's size from surface */
- //mul_v3_fl(nor, pa->size * boids->height);
- //add_v3_v3v3(pa->state.co, ground_co, nor);
-
- ///* remove normal component from velocity */
- //project_v3_v3v3(v, pa->state.vel, ground_nor);
- //sub_v3_v3v3(pa->state.vel, pa->state.vel, v);
- break;
- }
- case eBoidMode_OnLand:
- {
- /* stick boid on goal when close enough */
- if (bbd->goal_ob && boid_goal_signed_dist(pa->state.co, bbd->goal_co, bbd->goal_nor) <= pa->size * boids->height) {
- bpa->data.mode = eBoidMode_Climbing;
- bpa->ground = bbd->goal_ob;
- boid_find_ground(bbd, pa, ground_co, ground_nor);
- boid_climb(boids, pa, ground_co, ground_nor);
- }
- /* ground is too far away so boid falls */
- else if (pa->state.co[2]-ground_co[2] > 1.1f * pa->size * boids->height)
- bpa->data.mode = eBoidMode_Falling;
- else {
- /* constrain to surface */
- pa->state.co[2] = ground_co[2] + pa->size * boids->height;
- pa->state.vel[2] = 0.0f;
- }
-
- if (boids->banking > 0.0f) {
- float grav[3];
- /* Don't take gravity's strength in to account, */
- /* otherwise amount of banking is hard to control. */
- negate_v3_v3(grav, ground_nor);
-
- project_v3_v3v3(dvec, bpa->data.acc, pa->state.vel);
- sub_v3_v3v3(dvec, bpa->data.acc, dvec);
-
- /* gather apparent gravity */
- madd_v3_v3v3fl(bpa->gravity, grav, dvec, -boids->banking);
- normalize_v3(bpa->gravity);
- }
- else {
- /* gather negative surface normal */
- madd_v3_v3fl(bpa->gravity, ground_nor, -1.0f);
- normalize_v3(bpa->gravity);
- }
- break;
- }
- }
-
- /* save direction to state.ave unless the boid is falling */
- /* (boids can't effect their direction when falling) */
- if (bpa->data.mode!=eBoidMode_Falling && len_v3(pa->state.vel) > 0.1f*pa->size) {
- copy_v3_v3(pa->state.ave, pa->state.vel);
- pa->state.ave[2] *= bbd->part->boids->pitch;
- normalize_v3(pa->state.ave);
- }
-
- /* apply damping */
- if (ELEM(bpa->data.mode, eBoidMode_OnLand, eBoidMode_Climbing))
- mul_v3_fl(pa->state.vel, 1.0f - 0.2f*bbd->part->dampfac);
-
- /* calculate rotation matrix based on forward & down vectors */
- if (bpa->data.mode == eBoidMode_InAir) {
- copy_v3_v3(mat[0], pa->state.ave);
-
- project_v3_v3v3(dvec, bpa->gravity, pa->state.ave);
- sub_v3_v3v3(mat[2], bpa->gravity, dvec);
- normalize_v3(mat[2]);
- }
- else {
- project_v3_v3v3(dvec, pa->state.ave, bpa->gravity);
- sub_v3_v3v3(mat[0], pa->state.ave, dvec);
- normalize_v3(mat[0]);
-
- copy_v3_v3(mat[2], bpa->gravity);
- }
- negate_v3(mat[2]);
- cross_v3_v3v3(mat[1], mat[2], mat[0]);
-
- /* apply rotation */
- mat3_to_quat_is_ok(q, mat);
- copy_qt_qt(pa->state.rot, q);
-}
-
-BoidRule *boid_new_rule(int type)
-{
- BoidRule *rule = NULL;
- if (type <= 0)
- return NULL;
-
- switch (type) {
- case eBoidRuleType_Goal:
- case eBoidRuleType_Avoid:
- rule = MEM_callocN(sizeof(BoidRuleGoalAvoid), "BoidRuleGoalAvoid");
- break;
- case eBoidRuleType_AvoidCollision:
- rule = MEM_callocN(sizeof(BoidRuleAvoidCollision), "BoidRuleAvoidCollision");
- ((BoidRuleAvoidCollision*)rule)->look_ahead = 2.0f;
- break;
- case eBoidRuleType_FollowLeader:
- rule = MEM_callocN(sizeof(BoidRuleFollowLeader), "BoidRuleFollowLeader");
- ((BoidRuleFollowLeader*)rule)->distance = 1.0f;
- break;
- case eBoidRuleType_AverageSpeed:
- rule = MEM_callocN(sizeof(BoidRuleAverageSpeed), "BoidRuleAverageSpeed");
- ((BoidRuleAverageSpeed*)rule)->speed = 0.5f;
- break;
- case eBoidRuleType_Fight:
- rule = MEM_callocN(sizeof(BoidRuleFight), "BoidRuleFight");
- ((BoidRuleFight*)rule)->distance = 100.0f;
- ((BoidRuleFight*)rule)->flee_distance = 100.0f;
- break;
- default:
- rule = MEM_callocN(sizeof(BoidRule), "BoidRule");
- break;
- }
-
- rule->type = type;
- rule->flag |= BOIDRULE_IN_AIR|BOIDRULE_ON_LAND;
- BLI_strncpy(rule->name, rna_enum_boidrule_type_items[type-1].name, sizeof(rule->name));
-
- return rule;
-}
-void boid_default_settings(BoidSettings *boids)
-{
- boids->air_max_speed = 10.0f;
- boids->air_max_acc = 0.5f;
- boids->air_max_ave = 0.5f;
- boids->air_personal_space = 1.0f;
-
- boids->land_max_speed = 5.0f;
- boids->land_max_acc = 0.5f;
- boids->land_max_ave = 0.5f;
- boids->land_personal_space = 1.0f;
-
- boids->options = BOID_ALLOW_FLIGHT;
-
- boids->landing_smoothness = 3.0f;
- boids->banking = 1.0f;
- boids->pitch = 1.0f;
- boids->height = 1.0f;
-
- boids->health = 1.0f;
- boids->accuracy = 1.0f;
- boids->aggression = 2.0f;
- boids->range = 1.0f;
- boids->strength = 0.1f;
-}
-
-BoidState *boid_new_state(BoidSettings *boids)
-{
- BoidState *state = MEM_callocN(sizeof(BoidState), "BoidState");
-
- state->id = boids->last_state_id++;
- if (state->id)
- BLI_snprintf(state->name, sizeof(state->name), "State %i", state->id);
- else
- strcpy(state->name, "State");
-
- state->rule_fuzziness = 0.5;
- state->volume = 1.0f;
- state->channels |= ~0;
-
- return state;
-}
-
-BoidState *boid_duplicate_state(BoidSettings *boids, BoidState *state)
-{
- BoidState *staten = MEM_dupallocN(state);
-
- BLI_duplicatelist(&staten->rules, &state->rules);
- BLI_duplicatelist(&staten->conditions, &state->conditions);
- BLI_duplicatelist(&staten->actions, &state->actions);
-
- staten->id = boids->last_state_id++;
-
- return staten;
-}
-void boid_free_settings(BoidSettings *boids)
-{
- if (boids) {
- BoidState *state = boids->states.first;
-
- for (; state; state=state->next) {
- BLI_freelistN(&state->rules);
- BLI_freelistN(&state->conditions);
- BLI_freelistN(&state->actions);
- }
-
- BLI_freelistN(&boids->states);
-
- MEM_freeN(boids);
- }
-}
-BoidSettings *boid_copy_settings(BoidSettings *boids)
-{
- BoidSettings *nboids = NULL;
-
- if (boids) {
- BoidState *state;
- BoidState *nstate;
-
- nboids = MEM_dupallocN(boids);
-
- BLI_duplicatelist(&nboids->states, &boids->states);
-
- state = boids->states.first;
- nstate = nboids->states.first;
- for (; state; state=state->next, nstate=nstate->next) {
- BLI_duplicatelist(&nstate->rules, &state->rules);
- BLI_duplicatelist(&nstate->conditions, &state->conditions);
- BLI_duplicatelist(&nstate->actions, &state->actions);
- }
- }
-
- return nboids;
-}
-BoidState *boid_get_current_state(BoidSettings *boids)
-{
- BoidState *state = boids->states.first;
-
- for (; state; state=state->next) {
- if (state->flag & BOIDSTATE_CURRENT)
- break;
- }
-
- return state;
-}
-
diff --git a/source/blender/blenkernel/intern/bpath.c b/source/blender/blenkernel/intern/bpath.c
index 487b8ffa2b5..4121bde4d0b 100644
--- a/source/blender/blenkernel/intern/bpath.c
+++ b/source/blender/blenkernel/intern/bpath.c
@@ -56,7 +56,6 @@
#include "DNA_object_fluidsim.h"
#include "DNA_object_force.h"
#include "DNA_object_types.h"
-#include "DNA_particle_types.h"
#include "DNA_sequence_types.h"
#include "DNA_sound_types.h"
#include "DNA_text_types.h"
@@ -463,20 +462,6 @@ void BKE_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int
{
Object *ob = (Object *)id;
ModifierData *md;
- ParticleSystem *psys;
-
-#define BPATH_TRAVERSE_POINTCACHE(ptcaches) \
- { \
- PointCache *cache; \
- for (cache = (ptcaches).first; cache; cache = cache->next) { \
- if (cache->flag & PTCACHE_DISK_CACHE) { \
- rewrite_path_fixed(cache->path, \
- visit_cb, \
- absbase, \
- bpath_user_data); \
- } \
- } \
- } (void)0
/* do via modifiers instead */
#if 0
@@ -492,16 +477,6 @@ void BKE_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int
rewrite_path_fixed(fluidmd->fss->surfdataPath, visit_cb, absbase, bpath_user_data);
}
}
- else if (md->type == eModifierType_Smoke) {
- SmokeModifierData *smd = (SmokeModifierData *)md;
- if (smd->type & MOD_SMOKE_TYPE_DOMAIN) {
- BPATH_TRAVERSE_POINTCACHE(smd->domain->ptcaches[0]);
- }
- }
- else if (md->type == eModifierType_Cloth) {
- ClothModifierData *clmd = (ClothModifierData *) md;
- BPATH_TRAVERSE_POINTCACHE(clmd->ptcaches);
- }
else if (md->type == eModifierType_Ocean) {
OceanModifierData *omd = (OceanModifierData *) md;
rewrite_path_fixed(omd->cachepath, visit_cb, absbase, bpath_user_data);
@@ -512,16 +487,6 @@ void BKE_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int
}
}
- if (ob->soft) {
- BPATH_TRAVERSE_POINTCACHE(ob->soft->ptcaches);
- }
-
- for (psys = ob->particlesystem.first; psys; psys = psys->next) {
- BPATH_TRAVERSE_POINTCACHE(psys->ptcaches);
- }
-
-#undef BPATH_TRAVERSE_POINTCACHE
-
break;
}
case ID_SO:
diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c
index 28ef3f6f248..87733341cdd 100644
--- a/source/blender/blenkernel/intern/cloth.c
+++ b/source/blender/blenkernel/intern/cloth.c
@@ -45,7 +45,6 @@
#include "BKE_effect.h"
#include "BKE_global.h"
#include "BKE_modifier.h"
-#include "BKE_pointcache.h"
#include "BPH_mass_spring.h"
@@ -131,9 +130,6 @@ void cloth_init(ClothModifierData *clmd )
if (!clmd->sim_parms->effector_weights)
clmd->sim_parms->effector_weights = BKE_add_effector_weights(NULL);
-
- if (clmd->point_cache)
- clmd->point_cache->step = 1;
}
static BVHTree *bvhselftree_build_from_cloth (ClothModifierData *clmd, float epsilon)
@@ -304,35 +300,16 @@ void bvhselftree_update_from_cloth(ClothModifierData *clmd, bool moving)
}
}
-void cloth_clear_cache(Object *ob, ClothModifierData *clmd, float framenr)
-{
- PTCacheID pid;
-
- BKE_ptcache_id_from_cloth(&pid, ob, clmd);
-
- // don't do anything as long as we're in editmode!
- if (pid.cache->edit && ob->mode & OB_MODE_PARTICLE_EDIT)
- return;
-
- BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_AFTER, framenr);
-}
-
static int do_init_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *result, int framenr)
{
- PointCache *cache;
-
- cache= clmd->point_cache;
-
/* initialize simulation data if it didn't exist already */
if (clmd->clothObject == NULL) {
if (!cloth_from_object(ob, clmd, result, framenr, 1)) {
- BKE_ptcache_invalidate(cache);
modifier_setError(&(clmd->modifier), "Can't initialize cloth");
return 0;
}
if (clmd->clothObject == NULL) {
- BKE_ptcache_invalidate(cache);
modifier_setError(&(clmd->modifier), "Null cloth object");
return 0;
}
@@ -370,7 +347,7 @@ static int do_step_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *resul
mul_m4_v3(ob->obmat, verts->xconst);
}
- effectors = pdInitEffectors(clmd->scene, ob, NULL, clmd->sim_parms->effector_weights, true);
+ effectors = pdInitEffectors(clmd->scene, ob, clmd->sim_parms->effector_weights, true);
if (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_DYNAMIC_BASEMESH )
cloth_update_verts ( ob, clmd, result );
@@ -402,27 +379,14 @@ static int do_step_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *resul
************************************************/
void clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, DerivedMesh *dm, float (*vertexCos)[3])
{
- PointCache *cache;
- PTCacheID pid;
- float timescale;
- int framenr, startframe, endframe;
- int cache_result;
+ int framenr = scene->r.cfra, startframe = scene->r.sfra, endframe = scene->r.efra;
clmd->scene= scene; /* nice to pass on later :) */
- framenr= (int)scene->r.cfra;
- cache= clmd->point_cache;
- BKE_ptcache_id_from_cloth(&pid, ob, clmd);
- BKE_ptcache_id_time(&pid, scene, framenr, &startframe, &endframe, &timescale);
- clmd->sim_parms->timescale= timescale * clmd->sim_parms->time_scale;
+ clmd->sim_parms->timescale = 1.0f;
if (clmd->sim_parms->reset || (clmd->clothObject && dm->getNumVerts(dm) != clmd->clothObject->mvert_num)) {
clmd->sim_parms->reset = 0;
- cache->flag |= PTCACHE_OUTDATED;
- BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED);
- BKE_ptcache_validate(cache, 0);
- cache->last_exact= 0;
- cache->flag &= ~PTCACHE_REDO_NEEDED;
}
// unused in the moment, calculated separately in implicit.c
@@ -430,7 +394,6 @@ void clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, Derived
/* simulation is only active during a specific period */
if (framenr < startframe) {
- BKE_ptcache_invalidate(cache);
return;
}
else if (framenr > endframe) {
@@ -442,59 +405,18 @@ void clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, Derived
return;
if (framenr == startframe) {
- BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED);
do_init_cloth(ob, clmd, dm, framenr);
- BKE_ptcache_validate(cache, framenr);
- cache->flag &= ~PTCACHE_REDO_NEEDED;
clmd->clothObject->last_frame= framenr;
return;
}
- /* try to read from cache */
- bool can_simulate = (framenr == clmd->clothObject->last_frame+1) && !(cache->flag & PTCACHE_BAKED);
-
- cache_result = BKE_ptcache_read(&pid, (float)framenr+scene->r.subframe, can_simulate);
-
- if (cache_result == PTCACHE_READ_EXACT || cache_result == PTCACHE_READ_INTERPOLATED ||
- (!can_simulate && cache_result == PTCACHE_READ_OLD)) {
- BKE_cloth_solver_set_positions(clmd);
- cloth_to_object (ob, clmd, vertexCos);
-
- BKE_ptcache_validate(cache, framenr);
-
- if (cache_result == PTCACHE_READ_INTERPOLATED && cache->flag & PTCACHE_REDO_NEEDED)
- BKE_ptcache_write(&pid, framenr);
-
- clmd->clothObject->last_frame= framenr;
-
- return;
- }
- else if (cache_result==PTCACHE_READ_OLD) {
- BKE_cloth_solver_set_positions(clmd);
- }
- else if ( /*ob->id.lib ||*/ (cache->flag & PTCACHE_BAKED)) { /* 2.4x disabled lib, but this can be used in some cases, testing further - campbell */
- /* if baked and nothing in cache, do nothing */
- BKE_ptcache_invalidate(cache);
+ if (framenr!=clmd->clothObject->last_frame+1)
return;
- }
-
- if (!can_simulate)
- return;
-
- /* if on second frame, write cache for first frame */
- if (cache->simframe == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0))
- BKE_ptcache_write(&pid, startframe);
- clmd->sim_parms->timescale *= framenr - cache->simframe;
+ clmd->sim_parms->timescale *= 1.0f;
/* do simulation */
- BKE_ptcache_validate(cache, framenr);
-
- if (!do_step_cloth(ob, clmd, dm, framenr)) {
- BKE_ptcache_invalidate(cache);
- }
- else
- BKE_ptcache_write(&pid, framenr);
+ do_step_cloth(ob, clmd, dm, framenr);
cloth_to_object (ob, clmd, vertexCos);
clmd->clothObject->last_frame= framenr;
diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c
index 926ca8da192..2fb28cb2c1b 100644
--- a/source/blender/blenkernel/intern/context.c
+++ b/source/blender/blenkernel/intern/context.c
@@ -925,7 +925,6 @@ int CTX_data_mode_enum(const bContext *C)
else if (ob->mode & OB_MODE_WEIGHT_PAINT) return CTX_MODE_PAINT_WEIGHT;
else if (ob->mode & OB_MODE_VERTEX_PAINT) return CTX_MODE_PAINT_VERTEX;
else if (ob->mode & OB_MODE_TEXTURE_PAINT) return CTX_MODE_PAINT_TEXTURE;
- else if (ob->mode & OB_MODE_PARTICLE_EDIT) return CTX_MODE_PARTICLE;
}
}
@@ -948,7 +947,6 @@ static const char *data_mode_strings[] = {
"weightpaint",
"vertexpaint",
"imagepaint",
- "particlemode",
"objectmode",
NULL
};
diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c
index 5f8332dcf0c..184688b5e74 100644
--- a/source/blender/blenkernel/intern/depsgraph.c
+++ b/source/blender/blenkernel/intern/depsgraph.c
@@ -54,6 +54,8 @@
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_node_types.h"
+#include "DNA_object_types.h"
+#include "DNA_object_force.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_windowmanager_types.h"
@@ -81,8 +83,6 @@
#include "BKE_modifier.h"
#include "BKE_object.h"
#include "BKE_paint.h"
-#include "BKE_particle.h"
-#include "BKE_pointcache.h"
#include "BKE_scene.h"
#include "BKE_screen.h"
#include "BKE_tracking.h"
@@ -478,7 +478,7 @@ void dag_add_collision_relations(DagForest *dag, Scene *scene, Object *ob, DagNo
void dag_add_forcefield_relations(DagForest *dag, Scene *scene, Object *ob, DagNode *node, EffectorWeights *effector_weights, bool add_absorption, int skip_forcefield, const char *name)
{
- ListBase *effectors = pdInitEffectors(scene, ob, NULL, effector_weights, false);
+ ListBase *effectors = pdInitEffectors(scene, ob, effector_weights, false);
if (effectors) {
for (EffectorCache *eff = effectors->first; eff; eff = eff->next) {
@@ -507,7 +507,6 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Main *bmain, Sc
DagNode *node2;
DagNode *node3;
Key *key;
- ParticleSystem *psys;
int addtoroot = 1;
node = dag_get_node(dag, ob);
@@ -749,79 +748,6 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Main *bmain, Sc
dag_add_lamp_driver_relations(dag, node, ob->data);
}
- /* particles */
- psys = ob->particlesystem.first;
- if (psys) {
- GroupObject *go;
-
- for (; psys; psys = psys->next) {
- BoidRule *rule = NULL;
- BoidState *state = NULL;
- ParticleSettings *part = psys->part;
-
- if (part->adt) {
- dag_add_driver_relation(part->adt, dag, node, 1);
- }
-
- dag_add_relation(dag, node, node, DAG_RL_OB_DATA, "Particle-Object Relation");
-
- if (!psys_check_enabled(ob, psys, G.is_rendering))
- continue;
-
- if (ELEM(part->phystype, PART_PHYS_KEYED, PART_PHYS_BOIDS)) {
- ParticleTarget *pt = psys->targets.first;
-
- for (; pt; pt = pt->next) {
- if (pt->ob && BLI_findlink(&pt->ob->particlesystem, pt->psys - 1)) {
- node2 = dag_get_node(dag, pt->ob);
- dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Particle Targets");
- }
- }
- }
-
- if (part->ren_as == PART_DRAW_OB && part->dup_ob) {
- node2 = dag_get_node(dag, part->dup_ob);
- /* note that this relation actually runs in the wrong direction, the problem
- * is that dupli system all have this (due to parenting), and the render
- * engine instancing assumes particular ordering of objects in list */
- dag_add_relation(dag, node, node2, DAG_RL_OB_OB, "Particle Object Visualization");
- if (part->dup_ob->type == OB_MBALL)
- dag_add_relation(dag, node, node2, DAG_RL_DATA_DATA, "Particle Object Visualization");
- }
-
- if (part->ren_as == PART_DRAW_GR && part->dup_group) {
- for (go = part->dup_group->gobject.first; go; go = go->next) {
- node2 = dag_get_node(dag, go->ob);
- dag_add_relation(dag, node2, node, DAG_RL_OB_OB, "Particle Group Visualization");
- }
- }
-
- if (part->type != PART_HAIR) {
- /* Actual code uses get_collider_cache */
- dag_add_collision_relations(dag, scene, ob, node, part->collision_group, ob->lay, eModifierType_Collision, NULL, true, "Particle Collision");
- }
-
- dag_add_forcefield_relations(dag, scene, ob, node, part->effector_weights, part->type == PART_HAIR, 0, "Particle Force Field");
-
- if (part->boids) {
- for (state = part->boids->states.first; state; state = state->next) {
- for (rule = state->rules.first; rule; rule = rule->next) {
- Object *ruleob = NULL;
- if (rule->type == eBoidRuleType_Avoid)
- ruleob = ((BoidRuleGoalAvoid *)rule)->ob;
- else if (rule->type == eBoidRuleType_FollowLeader)
- ruleob = ((BoidRuleFollowLeader *)rule)->ob;
-
- if (ruleob) {
- node2 = dag_get_node(dag, ruleob);
- dag_add_relation(dag, node2, node, DAG_RL_OB_DATA, "Boid Rule");
- }
- }
- }
- }
- }
- }
-
/* object constraints */
for (con = ob->constraints.first; con; con = con->next) {
const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
@@ -1887,38 +1813,6 @@ static unsigned int flush_layer_node(Scene *sce, DagNode *node, int curtime)
return node->lay;
}
-/* node was checked to have lasttime != curtime, and is of type ID_OB */
-static void flush_pointcache_reset(Main *bmain, Scene *scene, DagNode *node,
- int curtime, unsigned int lay, bool reset)
-{
- DagAdjList *itA;
- Object *ob;
-
- node->lasttime = curtime;
-
- for (itA = node->child; itA; itA = itA->next) {
- if (itA->node->type == ID_OB) {
- if (itA->node->lasttime != curtime) {
- ob = (Object *)(itA->node->ob);
-
- if (reset || (ob->recalc & OB_RECALC_ALL)) {
- if (BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_DEPSGRAPH)) {
- /* Don't tag nodes which are on invisible layer. */
- if (itA->node->lay & lay) {
- ob->recalc |= OB_RECALC_DATA;
- lib_id_recalc_data_tag(bmain, &ob->id);
- }
- }
-
- flush_pointcache_reset(bmain, scene, itA->node, curtime, lay, true);
- }
- else
- flush_pointcache_reset(bmain, scene, itA->node, curtime, lay, false);
- }
- }
- }
-}
-
/* flush layer flags to dependencies */
static void dag_scene_flush_layers(Scene *sce, int lay)
{
@@ -1996,7 +1890,6 @@ void DAG_scene_flush_update(Main *bmain, Scene *sce, unsigned int lay, const sho
{
DagNode *firstnode;
DagAdjList *itA;
- Object *ob;
int lasttime;
if (!DEG_depsgraph_use_legacy()) {
@@ -2024,24 +1917,6 @@ void DAG_scene_flush_update(Main *bmain, Scene *sce, unsigned int lay, const sho
if (!time) {
sce->theDag->time++; /* so we know which nodes were accessed */
lasttime = sce->theDag->time;
- for (itA = firstnode->child; itA; itA = itA->next) {
- if (itA->node->lasttime != lasttime && itA->node->type == ID_OB) {
- ob = (Object *)(itA->node->ob);
-
- if (ob->recalc & OB_RECALC_ALL) {
- if (BKE_ptcache_object_reset(sce, ob, PTCACHE_RESET_DEPSGRAPH)) {
- ob->recalc |= OB_RECALC_DATA;
- lib_id_recalc_data_tag(bmain, &ob->id);
- }
-
- flush_pointcache_reset(bmain, sce, itA->node, lasttime,
- lay, true);
- }
- else
- flush_pointcache_reset(bmain, sce, itA->node, lasttime,
- lay, false);
- }
- }
}
dag_tag_renderlayers(sce, lay);
@@ -2234,8 +2109,6 @@ static void dag_object_time_update_flags(Main *bmain, Scene *scene, Object *ob)
ob->recalc |= OB_RECALC_DATA;
}
}
- if (ob->particlesystem.first)
- ob->recalc |= OB_RECALC_DATA;
break;
case OB_CURVE:
case OB_SURF:
@@ -2274,17 +2147,6 @@ static void dag_object_time_update_flags(Main *bmain, Scene *scene, Object *ob)
ob->recalc |= OB_RECALC_DATA;
adt->recalc |= ADT_RECALC_ANIM;
}
-
- if (ob->particlesystem.first) {
- ParticleSystem *psys = ob->particlesystem.first;
-
- for (; psys; psys = psys->next) {
- if (psys_check_enabled(ob, psys, G.is_rendering)) {
- ob->recalc |= OB_RECALC_DATA;
- break;
- }
- }
- }
}
if (ob->recalc & OB_RECALC_OB)
@@ -2576,7 +2438,6 @@ static void dag_id_flush_update(Main *bmain, Scene *sce, ID *id)
/* set flags & pointcache for object */
if (GS(id->name) == ID_OB) {
ob = (Object *)id;
- BKE_ptcache_object_reset(sce, ob, PTCACHE_RESET_DEPSGRAPH);
/* So if someone tagged object recalc directly,
* id_tag_update bit-field stays relevant
@@ -2607,7 +2468,6 @@ static void dag_id_flush_update(Main *bmain, Scene *sce, ID *id)
if (!(ob && obt == ob) && obt->data == id) {
obt->recalc |= OB_RECALC_DATA;
lib_id_recalc_data_tag(bmain, &obt->id);
- BKE_ptcache_object_reset(sce, obt, PTCACHE_RESET_DEPSGRAPH);
}
}
}
@@ -2635,30 +2495,6 @@ static void dag_id_flush_update(Main *bmain, Scene *sce, ID *id)
obt->recalc |= OB_RECALC_DATA;
lib_id_recalc_data_tag(bmain, &obt->id);
}
-
- /* particle settings can use the texture as well */
- if (obt->particlesystem.first) {
- ParticleSystem *psys = obt->particlesystem.first;
- MTex **mtexp, *mtex;
- int a;
- for (; psys; psys = psys->next) {
- mtexp = psys->part->mtex;
- for (a = 0; a < MAX_MTEX; a++, mtexp++) {
- mtex = *mtexp;
- if (mtex && mtex->tex == (Tex *)id) {
- obt->recalc |= OB_RECALC_DATA;
- lib_id_recalc_data_tag(bmain, &obt->id);
-
- if (mtex->mapto & PAMAP_INIT)
- psys->recalc |= PSYS_RECALC_RESET;
- if (mtex->mapto & PAMAP_CHILD)
- psys->recalc |= PSYS_RECALC_CHILD;
-
- BKE_ptcache_object_reset(sce, obt, PTCACHE_RESET_DEPSGRAPH);
- }
- }
- }
- }
}
}
@@ -2670,20 +2506,10 @@ static void dag_id_flush_update(Main *bmain, Scene *sce, ID *id)
obt->flag |= (OB_RECALC_OB | OB_RECALC_DATA);
lib_id_recalc_tag(bmain, &obt->id);
lib_id_recalc_data_tag(bmain, &obt->id);
- BKE_ptcache_object_reset(sce, obt, PTCACHE_RESET_DEPSGRAPH);
}
}
}
- /* set flags based on particle settings */
- if (idtype == ID_PA) {
- ParticleSystem *psys;
- for (obt = bmain->object.first; obt; obt = obt->id.next)
- for (psys = obt->particlesystem.first; psys; psys = psys->next)
- if (&psys->part->id == id)
- BKE_ptcache_object_reset(sce, obt, PTCACHE_RESET_DEPSGRAPH);
- }
-
if (ELEM(idtype, ID_MA, ID_TE)) {
obt = sce->basact ? sce->basact->object : NULL;
if (obt && obt->mode & OB_MODE_TEXTURE_PAINT) {
@@ -2953,7 +2779,7 @@ void DAG_id_tag_update_ex(Main *bmain, ID *id, short flag)
if (flag) {
if (flag & OB_RECALC_OB)
lib_id_recalc_tag(bmain, id);
- if (flag & (OB_RECALC_DATA | PSYS_RECALC))
+ if (flag & OB_RECALC_DATA)
lib_id_recalc_data_tag(bmain, id);
}
else
@@ -2969,20 +2795,6 @@ void DAG_id_tag_update_ex(Main *bmain, ID *id, short flag)
ob = (Object *)id;
ob->recalc |= (flag & OB_RECALC_ALL);
}
- else if (idtype == ID_PA) {
- ParticleSystem *psys;
- /* this is weak still, should be done delayed as well */
- for (ob = bmain->object.first; ob; ob = ob->id.next) {
- for (psys = ob->particlesystem.first; psys; psys = psys->next) {
- if (&psys->part->id == id) {
- ob->recalc |= (flag & OB_RECALC_ALL);
- psys->recalc |= (flag & PSYS_RECALC);
- lib_id_recalc_tag(bmain, &ob->id);
- lib_id_recalc_data_tag(bmain, &ob->id);
- }
- }
- }
- }
else {
/* disable because this is called on various ID types automatically.
* where printing warning is not useful. for now just ignore */
diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c
index c7399047ed5..587e4a35806 100644
--- a/source/blender/blenkernel/intern/dynamicpaint.c
+++ b/source/blender/blenkernel/intern/dynamicpaint.c
@@ -48,6 +48,7 @@
#include "DNA_meshdata_types.h"
#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
+#include "DNA_object_force.h"
#include "DNA_scene_types.h"
#include "DNA_texture_types.h"
@@ -68,8 +69,6 @@
#include "BKE_mesh_mapping.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
-#include "BKE_particle.h"
-#include "BKE_pointcache.h"
#include "BKE_scene.h"
#include "BKE_texture.h"
@@ -563,7 +562,7 @@ static bool boundsIntersectDist(Bounds3D *b1, Bounds3D *b2, const float dist)
}
/* check whether bounds intersects a point with given radius */
-static bool boundIntersectPoint(Bounds3D *b, float point[3], const float radius)
+static bool UNUSED_FUNCTION(boundIntersectPoint)(Bounds3D *b, float point[3], const float radius)
{
if (!b->valid)
return false;
@@ -862,7 +861,7 @@ static void surface_freeUnusedData(DynamicPaintSurface *surface)
return;
/* free bakedata if not active or surface is baked */
- if (!(surface->flags & MOD_DPAINT_ACTIVE) || (surface->pointcache && surface->pointcache->flag & PTCACHE_BAKED)) {
+ if (!(surface->flags & MOD_DPAINT_ACTIVE)) {
free_bakeData(surface->data);
}
}
@@ -897,10 +896,6 @@ void dynamicPaint_freeSurfaceData(DynamicPaintSurface *surface)
void dynamicPaint_freeSurface(DynamicPaintSurface *surface)
{
- /* point cache */
- BKE_ptcache_free_list(&(surface->ptcaches));
- surface->pointcache = NULL;
-
if (surface->effector_weights)
MEM_freeN(surface->effector_weights);
surface->effector_weights = NULL;
@@ -961,11 +956,6 @@ DynamicPaintSurface *dynamicPaint_createNewSurface(DynamicPaintCanvasSettings *c
surface->format = MOD_DPAINT_SURFACE_F_VERTEX;
surface->type = MOD_DPAINT_SURFACE_T_PAINT;
- /* cache */
- surface->pointcache = BKE_ptcache_add(&(surface->ptcaches));
- surface->pointcache->flag |= PTCACHE_DISK_CACHE;
- surface->pointcache->step = 1;
-
/* Set initial values */
surface->flags = MOD_DPAINT_ANTIALIAS | MOD_DPAINT_MULALPHA | MOD_DPAINT_DRY_LOG | MOD_DPAINT_DISSOLVE_LOG |
MOD_DPAINT_ACTIVE | MOD_DPAINT_PREVIEW | MOD_DPAINT_OUT1 | MOD_DPAINT_USE_DRYING;
@@ -1056,8 +1046,6 @@ bool dynamicPaint_createType(struct DynamicPaintModifierData *pmd, int type, str
return false;
brush->pmd = pmd;
- brush->psys = NULL;
-
brush->flags = MOD_DPAINT_ABS_ALPHA | MOD_DPAINT_RAMP_ALPHA;
brush->collision = MOD_DPAINT_COL_VOLUME;
@@ -1211,7 +1199,6 @@ void dynamicPaint_Modifier_copy(struct DynamicPaintModifierData *pmd, struct Dyn
t_brush->particle_radius = brush->particle_radius;
t_brush->particle_smooth = brush->particle_smooth;
t_brush->paint_distance = brush->paint_distance;
- t_brush->psys = brush->psys;
if (brush->paint_ramp)
memcpy(t_brush->paint_ramp, brush->paint_ramp, sizeof(ColorBand));
@@ -1944,15 +1931,6 @@ static DerivedMesh *dynamicPaint_Modifier_apply(
return result;
}
-/* update cache frame range */
-void dynamicPaint_cacheUpdateFrames(DynamicPaintSurface *surface)
-{
- if (surface->pointcache) {
- surface->pointcache->startframe = surface->start_frame;
- surface->pointcache->endframe = surface->end_frame;
- }
-}
-
static void canvas_copyDerivedMesh(DynamicPaintCanvasSettings *canvas, DerivedMesh *dm)
{
if (canvas->dm) {
@@ -2001,31 +1979,10 @@ static void dynamicPaint_frameUpdate(DynamicPaintModifierData *pmd, Scene *scene
if (no_surface_data || current_frame != surface->current_frame ||
(int)scene->r.cfra == surface->start_frame)
{
- PointCache *cache = surface->pointcache;
- PTCacheID pid;
surface->current_frame = current_frame;
- /* read point cache */
- BKE_ptcache_id_from_dynamicpaint(&pid, ob, surface);
- pid.cache->startframe = surface->start_frame;
- pid.cache->endframe = surface->end_frame;
- BKE_ptcache_id_time(&pid, scene, (float)scene->r.cfra, NULL, NULL, NULL);
-
- /* reset non-baked cache at first frame */
- if ((int)scene->r.cfra == surface->start_frame && !(cache->flag & PTCACHE_BAKED)) {
- cache->flag |= PTCACHE_REDO_NEEDED;
- BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED);
- cache->flag &= ~PTCACHE_REDO_NEEDED;
- }
-
- /* try to read from cache */
- bool can_simulate = ((int)scene->r.cfra == current_frame) && !(cache->flag & PTCACHE_BAKED);
-
- if (BKE_ptcache_read(&pid, (float)scene->r.cfra, can_simulate)) {
- BKE_ptcache_validate(cache, (int)scene->r.cfra);
- }
- /* if read failed and we're on surface range do recalculate */
- else if (can_simulate) {
+ /* if we're on surface range do recalculate */
+ if ((int)scene->r.cfra == current_frame) {
/* calculate surface frame */
canvas->flags |= MOD_DPAINT_BAKING;
dynamicPaint_calculateFrame(surface, scene, ob, current_frame);
@@ -2037,9 +1994,6 @@ static void dynamicPaint_frameUpdate(DynamicPaintModifierData *pmd, Scene *scene
{
canvas_copyDerivedMesh(canvas, dm);
}
-
- BKE_ptcache_validate(cache, surface->current_frame);
- BKE_ptcache_write(&pid, surface->current_frame);
}
}
}
@@ -3499,7 +3453,6 @@ typedef struct DynamicPaintPaintData {
const float *avg_brushNor;
const Vec3f *brushVelocity;
- const ParticleSystem *psys;
const float solidradius;
void *treeData;
@@ -3948,283 +3901,6 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface,
return 1;
}
-/*
- * Paint a particle system to the surface
- */
-static void dynamic_paint_paint_particle_cell_point_cb_ex(
- void *userdata, void *UNUSED(userdata_chunk), const int id, const int UNUSED(threadid))
-{
- const DynamicPaintPaintData *data = userdata;
-
- const DynamicPaintSurface *surface = data->surface;
- const PaintSurfaceData *sData = surface->data;
- const PaintBakeData *bData = sData->bData;
- VolumeGrid *grid = bData->grid;
-
- const DynamicPaintBrushSettings *brush = data->brush;
-
- const ParticleSystem *psys = data->psys;
-
- const float timescale = data->timescale;
- const int c_index = data->c_index;
-
- KDTree *tree = data->treeData;
-
- const float solidradius = data->solidradius;
- const float smooth = brush->particle_smooth * surface->radius_scale;
- const float range = solidradius + smooth;
- const float particle_timestep = 0.04f * psys->part->timetweak;
-
- const int index = grid->t_index[grid->s_pos[c_index] + id];
- float disp_intersect = 0.0f;
- float radius = 0.0f;
- float strength = 0.0f;
- int part_index = -1;
-
- /*
- * With predefined radius, there is no variation between particles.
- * It's enough to just find the nearest one.
- */
- {
- KDTreeNearest nearest;
- float smooth_range, part_solidradius;
-
- /* Find nearest particle and get distance to it */
- BLI_kdtree_find_nearest(tree, bData->realCoord[bData->s_pos[index]].v, &nearest);
- /* if outside maximum range, no other particle can influence either */
- if (nearest.dist > range)
- return;
-
- if (brush->flags & MOD_DPAINT_PART_RAD) {
- /* use particles individual size */
- ParticleData *pa = psys->particles + nearest.index;
- part_solidradius = pa->size;
- }
- else {
- part_solidradius = solidradius;
- }
- radius = part_solidradius + smooth;
- if (nearest.dist < radius) {
- /* distances inside solid radius has maximum influence -> dist = 0 */
- smooth_range = max_ff(0.0f, (nearest.dist - part_solidradius));
- /* do smoothness if enabled */
- if (smooth)
- smooth_range /= smooth;
-
- strength = 1.0f - smooth_range;
- disp_intersect = radius - nearest.dist;
- part_index = nearest.index;
- }
- }
- /* If using random per particle radius and closest particle didn't give max influence */
- if (brush->flags & MOD_DPAINT_PART_RAD && strength < 1.0f && psys->part->randsize > 0.0f) {
- /*
- * If we use per particle radius, we have to sample all particles
- * within max radius range
- */
- KDTreeNearest *nearest;
-
- float smooth_range = smooth * (1.0f - strength), dist;
- /* calculate max range that can have particles with higher influence than the nearest one */
- const float max_range = smooth - strength * smooth + solidradius;
- /* Make gcc happy! */
- dist = max_range;
-
- const int particles = BLI_kdtree_range_search(
- tree, bData->realCoord[bData->s_pos[index]].v, &nearest, max_range);
-
- /* Find particle that produces highest influence */
- for (int n = 0; n < particles; n++) {
- ParticleData *pa = &psys->particles[nearest[n].index];
-
- /* skip if out of range */
- if (nearest[n].dist > (pa->size + smooth))
- continue;
-
- /* update hit data */
- const float s_range = nearest[n].dist - pa->size;
- /* skip if higher influence is already found */
- if (smooth_range < s_range)
- continue;
-
- /* update hit data */
- smooth_range = s_range;
- dist = nearest[n].dist;
- part_index = nearest[n].index;
-
- /* If inside solid range and no disp depth required, no need to seek further */
- if ((s_range < 0.0f) && !ELEM(surface->type, MOD_DPAINT_SURFACE_T_DISPLACE, MOD_DPAINT_SURFACE_T_WAVE)) {
- break;
- }
- }
-
- if (nearest)
- MEM_freeN(nearest);
-
- /* now calculate influence for this particle */
- const float rad = radius + smooth;
- if ((rad - dist) > disp_intersect) {
- disp_intersect = radius - dist;
- radius = rad;
- }
-
- /* do smoothness if enabled */
- CLAMP_MIN(smooth_range, 0.0f);
- if (smooth)
- smooth_range /= smooth;
-
- const float str = 1.0f - smooth_range;
- /* if influence is greater, use this one */
- if (str > strength)
- strength = str;
- }
-
- if (strength > 0.001f) {
- float paintColor[4] = {0.0f};
- float depth = 0.0f;
- float velocity_val = 0.0f;
-
- /* apply velocity */
- if ((brush->flags & MOD_DPAINT_USES_VELOCITY) && (part_index != -1)) {
- float velocity[3];
- ParticleData *pa = psys->particles + part_index;
- mul_v3_v3fl(velocity, pa->state.vel, particle_timestep);
-
- /* substract canvas point velocity */
- if (bData->velocity) {
- sub_v3_v3(velocity, bData->velocity[index].v);
- }
- velocity_val = normalize_v3(velocity);
-
- /* store brush velocity for smudge */
- if ((surface->type == MOD_DPAINT_SURFACE_T_PAINT) &&
- (brush->flags & MOD_DPAINT_DO_SMUDGE && bData->brush_velocity))
- {
- copy_v3_v3(&bData->brush_velocity[index * 4], velocity);
- bData->brush_velocity[index * 4 + 3] = velocity_val;
- }
- }
-
- if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
- copy_v3_v3(paintColor, &brush->r);
- }
- else if (ELEM(surface->type, MOD_DPAINT_SURFACE_T_DISPLACE, MOD_DPAINT_SURFACE_T_WAVE)) {
- /* get displace depth */
- disp_intersect = (1.0f - sqrtf(disp_intersect / radius)) * radius;
- depth = max_ff(0.0f, (radius - disp_intersect) / bData->bNormal[index].normal_scale);
- }
-
- dynamicPaint_updatePointData(surface, index, brush, paintColor, strength, depth, velocity_val, timescale);
- }
-}
-
-static int dynamicPaint_paintParticles(DynamicPaintSurface *surface,
- ParticleSystem *psys,
- DynamicPaintBrushSettings *brush,
- float timescale)
-{
- ParticleSettings *part = psys->part;
- PaintSurfaceData *sData = surface->data;
- PaintBakeData *bData = sData->bData;
- VolumeGrid *grid = bData->grid;
-
- KDTree *tree;
- int particlesAdded = 0;
- int invalidParticles = 0;
- int p = 0;
-
- const float solidradius = surface->radius_scale *
- ((brush->flags & MOD_DPAINT_PART_RAD) ? part->size : brush->particle_radius);
- const float smooth = brush->particle_smooth * surface->radius_scale;
-
- const float range = solidradius + smooth;
-
- Bounds3D part_bb = {{0}};
-
- if (psys->totpart < 1)
- return 1;
-
- /*
- * Build a kd-tree to optimize distance search
- */
- tree = BLI_kdtree_new(psys->totpart);
-
- /* loop through particles and insert valid ones to the tree */
- p = 0;
- for (ParticleData *pa = psys->particles; p < psys->totpart; p++, pa++) {
- /* Proceed only if particle is active */
- if ((pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN) == 0) ||
- (pa->alive == PARS_DEAD && (part->flag & PART_DIED) == 0) ||
- (pa->flag & PARS_UNEXIST))
- {
- continue;
- }
-
- /* for debug purposes check if any NAN particle proceeds
- * For some reason they get past activity check, this should rule most of them out */
- if (isnan(pa->state.co[0]) || isnan(pa->state.co[1]) || isnan(pa->state.co[2])) {
- invalidParticles++;
- continue;
- }
-
- /* make sure particle is close enough to canvas */
- if (!boundIntersectPoint(&grid->grid_bounds, pa->state.co, range))
- continue;
-
- BLI_kdtree_insert(tree, p, pa->state.co);
-
- /* calc particle system bounds */
- boundInsert(&part_bb, pa->state.co);
-
- particlesAdded++;
- }
- if (invalidParticles)
- printf("Warning: Invalid particle(s) found!\n");
-
- /* If no suitable particles were found, exit */
- if (particlesAdded < 1) {
- BLI_kdtree_free(tree);
- return 1;
- }
-
- /* begin thread safe malloc */
- BLI_begin_threaded_malloc();
-
- /* only continue if particle bb is close enough to canvas bb */
- if (boundsIntersectDist(&grid->grid_bounds, &part_bb, range)) {
- int c_index;
- int total_cells = grid->dim[0] * grid->dim[1] * grid->dim[2];
-
- /* balance tree */
- BLI_kdtree_balance(tree);
-
- /* loop through space partitioning grid */
- for (c_index = 0; c_index < total_cells; c_index++) {
- /* check cell bounding box */
- if (!grid->s_num[c_index] ||
- !boundsIntersectDist(&grid->bounds[c_index], &part_bb, range))
- {
- continue;
- }
-
- /* loop through cell points */
- DynamicPaintPaintData data = {
- .surface = surface,
- .brush = brush, .psys = psys,
- .solidradius = solidradius, .timescale = timescale, .c_index = c_index,
- .treeData = tree,
- };
- BLI_task_parallel_range_ex(0, grid->s_num[c_index], &data, NULL, 0,
- dynamic_paint_paint_particle_cell_point_cb_ex,
- grid->s_num[c_index] > 250, true);
- }
- }
- BLI_end_threaded_malloc();
- BLI_kdtree_free(tree);
-
- return 1;
-}
-
/* paint a single point of defined proximity radius to the surface */
static void dynamic_paint_paint_single_point_cb_ex(
void *userdata, void *UNUSED(userdata_chunk), const int index, const int UNUSED(threadid))
@@ -4658,7 +4334,7 @@ static int dynamicPaint_prepareEffectStep(
/* Init force data if required */
if (surface->effect & MOD_DPAINT_EFFECT_DO_DRIP) {
- ListBase *effectors = pdInitEffectors(scene, ob, NULL, surface->effector_weights, true);
+ ListBase *effectors = pdInitEffectors(scene, ob, surface->effector_weights, true);
/* allocate memory for force data (dir vector + strength) */
*force = MEM_mallocN(sData->total_points * 4 * sizeof(float), "PaintEffectForces");
@@ -5562,20 +5238,8 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su
dynamicPaint_updateBrushMaterials(brushObj, brush->mat, scene, &bMats);
/* Apply brush on the surface depending on it's collision type */
- /* Particle brush: */
- if (brush->collision == MOD_DPAINT_COL_PSYS) {
- if (brush->psys && brush->psys->part &&
- ELEM(brush->psys->part->type, PART_EMITTER, PART_FLUID) &&
- psys_check_enabled(brushObj, brush->psys, G.is_rendering))
- {
- /* Paint a particle system */
- BKE_animsys_evaluate_animdata(scene, &brush->psys->part->id, brush->psys->part->adt,
- BKE_scene_frame_get(scene), ADT_RECALC_ANIM);
- dynamicPaint_paintParticles(surface, brush->psys, brush, timescale);
- }
- }
/* Object center distance: */
- else if (brush->collision == MOD_DPAINT_COL_POINT && brushObj != ob) {
+ if (brush->collision == MOD_DPAINT_COL_POINT && brushObj != ob) {
dynamicPaint_paintSinglePoint(surface, brushObj->loc, brush, brushObj, &bMats, scene, timescale);
}
/* Mesh volume/proximity: */
diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c
index 7e6897a2858..9afcd7f2bbb 100644
--- a/source/blender/blenkernel/intern/effect.c
+++ b/source/blender/blenkernel/intern/effect.c
@@ -43,7 +43,6 @@
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
#include "DNA_object_force.h"
-#include "DNA_particle_types.h"
#include "DNA_texture_types.h"
#include "DNA_scene_types.h"
@@ -67,7 +66,6 @@
#include "BKE_library.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
-#include "BKE_particle.h"
#include "BKE_scene.h"
#include "BKE_smoke.h"
@@ -145,12 +143,11 @@ void free_partdeflect(PartDeflect *pd)
MEM_freeN(pd);
}
-static EffectorCache *new_effector_cache(Scene *scene, Object *ob, ParticleSystem *psys, PartDeflect *pd)
+static EffectorCache *new_effector_cache(Scene *scene, Object *ob, PartDeflect *pd)
{
EffectorCache *eff = MEM_callocN(sizeof(EffectorCache), "EffectorCache");
eff->scene = scene;
eff->ob = ob;
- eff->psys = psys;
eff->pd = pd;
eff->frame = -1;
return eff;
@@ -173,40 +170,16 @@ static void add_object_to_effectors(ListBase **effectors, Scene *scene, Effector
if (*effectors == NULL)
*effectors = MEM_callocN(sizeof(ListBase), "effectors list");
- eff = new_effector_cache(scene, ob, NULL, ob->pd);
+ eff = new_effector_cache(scene, ob, ob->pd);
/* make sure imat is up to date */
invert_m4_m4(ob->imat, ob->obmat);
BLI_addtail(*effectors, eff);
}
-static void add_particles_to_effectors(ListBase **effectors, Scene *scene, EffectorWeights *weights, Object *ob, ParticleSystem *psys, ParticleSystem *psys_src, bool for_simulation)
-{
- ParticleSettings *part= psys->part;
-
- if ( !psys_check_enabled(ob, psys, G.is_rendering) )
- return;
-
- if ( psys == psys_src && (part->flag & PART_SELF_EFFECT) == 0)
- return;
-
- if ( part->pd && part->pd->forcefield && (!for_simulation || weights->weight[part->pd->forcefield] != 0.0f)) {
- if (*effectors == NULL)
- *effectors = MEM_callocN(sizeof(ListBase), "effectors list");
-
- BLI_addtail(*effectors, new_effector_cache(scene, ob, psys, part->pd));
- }
-
- if (part->pd2 && part->pd2->forcefield && (!for_simulation || weights->weight[part->pd2->forcefield] != 0.0f)) {
- if (*effectors == NULL)
- *effectors = MEM_callocN(sizeof(ListBase), "effectors list");
-
- BLI_addtail(*effectors, new_effector_cache(scene, ob, psys, part->pd2));
- }
-}
/* returns ListBase handle with objects taking part in the effecting */
-ListBase *pdInitEffectors(Scene *scene, Object *ob_src, ParticleSystem *psys_src,
+ListBase *pdInitEffectors(Scene *scene, Object *ob_src,
EffectorWeights *weights, bool for_simulation)
{
Base *base;
@@ -220,13 +193,6 @@ ListBase *pdInitEffectors(Scene *scene, Object *ob_src, ParticleSystem *psys_src
if ( (go->ob->lay & layer) ) {
if ( go->ob->pd && go->ob->pd->forcefield )
add_object_to_effectors(&effectors, scene, weights, go->ob, ob_src, for_simulation);
-
- if ( go->ob->particlesystem.first ) {
- ParticleSystem *psys= go->ob->particlesystem.first;
-
- for ( ; psys; psys=psys->next )
- add_particles_to_effectors(&effectors, scene, weights, go->ob, psys, psys_src, for_simulation);
- }
}
}
}
@@ -235,13 +201,6 @@ ListBase *pdInitEffectors(Scene *scene, Object *ob_src, ParticleSystem *psys_src
if ( (base->lay & layer) ) {
if ( base->object->pd && base->object->pd->forcefield )
add_object_to_effectors(&effectors, scene, weights, base->object, ob_src, for_simulation);
-
- if ( base->object->particlesystem.first ) {
- ParticleSystem *psys= base->object->particlesystem.first;
-
- for ( ; psys; psys=psys->next )
- add_particles_to_effectors(&effectors, scene, weights, base->object, psys, psys_src, for_simulation);
- }
}
}
}
@@ -294,8 +253,6 @@ static void precalculate_effector(EffectorCache *eff)
if (eff->ob->type == OB_CURVE)
eff->flag |= PE_USE_NORMAL_DATA;
}
- else if (eff->psys)
- psys_update_particle_tree(eff->psys, eff->scene->r.cfra);
/* Store object velocity */
if (eff->ob) {
@@ -318,36 +275,6 @@ void pdPrecalculateEffectors(ListBase *effectors)
}
-void pd_point_from_particle(ParticleSimulationData *sim, ParticleData *pa, ParticleKey *state, EffectedPoint *point)
-{
- ParticleSettings *part = sim->psys->part;
- point->loc = state->co;
- point->vel = state->vel;
- point->index = pa - sim->psys->particles;
- point->size = pa->size;
- point->charge = 0.0f;
-
- if (part->pd && part->pd->forcefield == PFIELD_CHARGE)
- point->charge += part->pd->f_strength;
-
- if (part->pd2 && part->pd2->forcefield == PFIELD_CHARGE)
- point->charge += part->pd2->f_strength;
-
- point->vel_to_sec = 1.0f;
- point->vel_to_frame = psys_get_timestep(sim);
-
- point->flag = 0;
-
- if (sim->psys->part->flag & PART_ROT_DYN) {
- point->ave = state->ave;
- point->rot = state->rot;
- }
- else
- point->ave = point->rot = NULL;
-
- point->psys = sim->psys;
-}
-
void pd_point_from_loc(Scene *scene, float *loc, float *vel, int index, EffectedPoint *point)
{
point->loc = loc;
@@ -361,7 +288,6 @@ void pd_point_from_loc(Scene *scene, float *loc, float *vel, int index, Effected
point->flag = 0;
point->ave = point->rot = NULL;
- point->psys = NULL;
}
void pd_point_from_soft(Scene *scene, float *loc, float *vel, int index, EffectedPoint *point)
{
@@ -376,8 +302,6 @@ void pd_point_from_soft(Scene *scene, float *loc, float *vel, int index, Effecte
point->flag = PE_WIND_AS_SPEED;
point->ave = point->rot = NULL;
-
- point->psys = NULL;
}
/************************************************/
/* Effectors */
@@ -490,7 +414,7 @@ static float falloff_func_rad(PartDeflect *pd, float fac)
return falloff_func(fac, pd->flag&PFIELD_USEMINR, pd->minrad, pd->flag&PFIELD_USEMAXR, pd->maxrad, pd->f_power_r);
}
-float effector_falloff(EffectorCache *eff, EffectorData *efd, EffectedPoint *UNUSED(point), EffectorWeights *weights)
+static float effector_falloff(EffectorCache *eff, EffectorData *efd, EffectedPoint *UNUSED(point), EffectorWeights *weights)
{
float temp[3];
float falloff = weights ? weights->weight[0] * weights->weight[eff->pd->forcefield] : 1.0f;
@@ -565,7 +489,6 @@ int closest_point_on_surface(SurfaceModifierData *surmd, const float co[3], floa
}
int get_effector_data(EffectorCache *eff, EffectorData *efd, EffectedPoint *point, int real_velocity)
{
- float cfra = eff->scene->r.cfra;
int ret = 0;
/* In case surface object is in Edit mode when loading the .blend, surface modifier is never executed
@@ -602,43 +525,6 @@ int get_effector_data(EffectorCache *eff, EffectorData *efd, EffectedPoint *poin
ret = 1;
}
}
- else if (eff->psys) {
- ParticleData *pa = eff->psys->particles + *efd->index;
- ParticleKey state;
-
- /* exclude the particle itself for self effecting particles */
- if (eff->psys == point->psys && *efd->index == point->index) {
- /* pass */
- }
- else {
- ParticleSimulationData sim= {NULL};
- sim.scene= eff->scene;
- sim.ob= eff->ob;
- sim.psys= eff->psys;
-
- /* TODO: time from actual previous calculated frame (step might not be 1) */
- state.time = cfra - 1.0f;
- ret = psys_get_particle_state(&sim, *efd->index, &state, 0);
-
- /* TODO */
- //if (eff->pd->forcefiled == PFIELD_HARMONIC && ret==0) {
- // if (pa->dietime < eff->psys->cfra)
- // eff->flag |= PE_VELOCITY_TO_IMPULSE;
- //}
-
- copy_v3_v3(efd->loc, state.co);
-
- /* rather than use the velocity use rotated x-axis (defaults to velocity) */
- efd->nor[0] = 1.f;
- efd->nor[1] = efd->nor[2] = 0.f;
- mul_qt_v3(state.rot, efd->nor);
-
- if (real_velocity)
- copy_v3_v3(efd->vel, state.vel);
-
- efd->size = pa->size;
- }
- }
else {
/* use center of object for distance calculus */
const Object *ob = eff->ob;
@@ -690,7 +576,7 @@ int get_effector_data(EffectorCache *eff, EffectorData *efd, EffectedPoint *poin
return ret;
}
-static void get_effector_tot(EffectorCache *eff, EffectorData *efd, EffectedPoint *point, int *tot, int *p, int *step)
+static void get_effector_tot(EffectorCache *eff, EffectorData *efd, EffectedPoint *point, int *tot, int *p)
{
*p = 0;
efd->index = p;
@@ -703,31 +589,6 @@ static void get_effector_tot(EffectorCache *eff, EffectorData *efd, EffectedPoin
*tot = *p+1;
}
}
- else if (eff->psys) {
- *tot = eff->psys->totpart;
-
- if (eff->pd->forcefield == PFIELD_CHARGE) {
- /* Only the charge of the effected particle is used for
- * interaction, not fall-offs. If the fall-offs aren't the
- * same this will be unphysical, but for animation this
- * could be the wanted behavior. If you want physical
- * correctness the fall-off should be spherical 2.0 anyways.
- */
- efd->charge = eff->pd->f_strength;
- }
- else if (eff->pd->forcefield == PFIELD_HARMONIC && (eff->pd->flag & PFIELD_MULTIPLE_SPRINGS)==0) {
- /* every particle is mapped to only one harmonic effector particle */
- *p= point->index % eff->psys->totpart;
- *tot= *p + 1;
- }
-
- if (eff->psys->part->effector_amount) {
- int totpart = eff->psys->totpart;
- int amount = eff->psys->part->effector_amount;
-
- *step = (totpart > amount) ? totpart/amount : 1;
- }
- }
else {
*tot = 1;
}
@@ -990,7 +851,7 @@ void pdDoEffectors(ListBase *effectors, ListBase *colliders, EffectorWeights *we
*/
EffectorCache *eff;
EffectorData efd;
- int p=0, tot = 1, step = 1;
+ int p=0, tot = 1;
/* Cycle through collected objects, get total of (1/(gravity_strength * dist^gravity_power)) */
/* Check for min distance here? (yes would be cool to add that, ton) */
@@ -998,9 +859,9 @@ void pdDoEffectors(ListBase *effectors, ListBase *colliders, EffectorWeights *we
if (effectors) for (eff = effectors->first; eff; eff=eff->next) {
/* object effectors were fully checked to be OK to evaluate! */
- get_effector_tot(eff, &efd, point, &tot, &p, &step);
+ get_effector_tot(eff, &efd, point, &tot, &p);
- for (; p<tot; p+=step) {
+ for (; p<tot; p++) {
if (get_effector_data(eff, &efd, point, 0)) {
efd.falloff= effector_falloff(eff, &efd, point, weights);
diff --git a/source/blender/blenkernel/intern/fluidsim.c b/source/blender/blenkernel/intern/fluidsim.c
index 8247336d915..8874e059d6c 100644
--- a/source/blender/blenkernel/intern/fluidsim.c
+++ b/source/blender/blenkernel/intern/fluidsim.c
@@ -43,7 +43,6 @@
#include "DNA_object_fluidsim.h"
#include "DNA_object_force.h" // for pointcache
#include "DNA_object_types.h"
-#include "DNA_particle_types.h"
#include "DNA_scene_types.h"
#include "BLI_math.h"
diff --git a/source/blender/blenkernel/intern/group.c b/source/blender/blenkernel/intern/group.c
index 9b011dbb003..708472fa4a5 100644
--- a/source/blender/blenkernel/intern/group.c
+++ b/source/blender/blenkernel/intern/group.c
@@ -40,7 +40,6 @@
#include "DNA_material_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
-#include "DNA_particle_types.h"
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
diff --git a/source/blender/blenkernel/intern/idcode.c b/source/blender/blenkernel/intern/idcode.c
index 70d037d85f3..c76d072cb64 100644
--- a/source/blender/blenkernel/intern/idcode.c
+++ b/source/blender/blenkernel/intern/idcode.c
@@ -78,7 +78,6 @@ static IDType idtypes[] = {
{ ID_MSK, "Mask", "masks", BLT_I18NCONTEXT_ID_MASK, IDTYPE_FLAGS_ISLINKABLE },
{ ID_NT, "NodeTree", "node_groups", BLT_I18NCONTEXT_ID_NODETREE, IDTYPE_FLAGS_ISLINKABLE },
{ ID_OB, "Object", "objects", BLT_I18NCONTEXT_ID_OBJECT, IDTYPE_FLAGS_ISLINKABLE },
- { ID_PA, "ParticleSettings", "particles", BLT_I18NCONTEXT_ID_PARTICLESETTINGS, IDTYPE_FLAGS_ISLINKABLE },
{ ID_PAL, "Palettes", "palettes", BLT_I18NCONTEXT_ID_PALETTE, IDTYPE_FLAGS_ISLINKABLE },
{ ID_PC, "PaintCurve", "paint_curves", BLT_I18NCONTEXT_ID_PAINTCURVE, IDTYPE_FLAGS_ISLINKABLE },
{ ID_SCE, "Scene", "scenes", BLT_I18NCONTEXT_ID_SCENE, IDTYPE_FLAGS_ISLINKABLE },
@@ -200,7 +199,6 @@ int BKE_idcode_to_idfilter(const short idcode)
CASE_IDFILTER(MSK);
CASE_IDFILTER(NT);
CASE_IDFILTER(OB);
- CASE_IDFILTER(PA);
CASE_IDFILTER(PAL);
CASE_IDFILTER(PC);
CASE_IDFILTER(SCE);
@@ -244,7 +242,6 @@ short BKE_idcode_from_idfilter(const int idfilter)
CASE_IDFILTER(MSK);
CASE_IDFILTER(NT);
CASE_IDFILTER(OB);
- CASE_IDFILTER(PA);
CASE_IDFILTER(PAL);
CASE_IDFILTER(PC);
CASE_IDFILTER(SCE);
@@ -291,7 +288,6 @@ int BKE_idcode_to_index(const short idcode)
CASE_IDINDEX(MSK);
CASE_IDINDEX(NT);
CASE_IDINDEX(OB);
- CASE_IDINDEX(PA);
CASE_IDINDEX(PAL);
CASE_IDINDEX(PC);
CASE_IDINDEX(SCE);
diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c
index 730d5a93758..b7eb80cbe2a 100644
--- a/source/blender/blenkernel/intern/ipo.c
+++ b/source/blender/blenkernel/intern/ipo.c
@@ -739,74 +739,6 @@ static const char *world_adrcodes_to_paths(int adrcode, int *array_index)
return NULL;
}
-/* Particle Types */
-static const char *particle_adrcodes_to_paths(int adrcode, int *array_index)
-{
- /* set array index like this in-case nothing sets it correctly */
- *array_index = 0;
-
- /* result depends on adrcode */
- switch (adrcode) {
- case PART_CLUMP:
- return "settings.clump_factor";
- case PART_AVE:
- return "settings.angular_velocity_factor";
- case PART_SIZE:
- return "settings.particle_size";
- case PART_DRAG:
- return "settings.drag_factor";
- case PART_BROWN:
- return "settings.brownian_factor";
- case PART_DAMP:
- return "settings.damp_factor";
- case PART_LENGTH:
- return "settings.length";
- case PART_GRAV_X:
- *array_index = 0; return "settings.acceleration";
- case PART_GRAV_Y:
- *array_index = 1; return "settings.acceleration";
- case PART_GRAV_Z:
- *array_index = 2; return "settings.acceleration";
- case PART_KINK_AMP:
- return "settings.kink_amplitude";
- case PART_KINK_FREQ:
- return "settings.kink_frequency";
- case PART_KINK_SHAPE:
- return "settings.kink_shape";
- case PART_BB_TILT:
- return "settings.billboard_tilt";
-
- /* PartDeflect needs to be sorted out properly in rna_object_force;
- * If anyone else works on this, but is unfamiliar, these particular
- * settings reference the particles of the system themselves
- * being used as forces -- it will use the same rna structure
- * as the similar object forces */
-#if 0
- case PART_PD_FSTR:
- if (part->pd) poin = &(part->pd->f_strength);
- break;
- case PART_PD_FFALL:
- if (part->pd) poin = &(part->pd->f_power);
- break;
- case PART_PD_FMAXD:
- if (part->pd) poin = &(part->pd->maxdist);
- break;
- case PART_PD2_FSTR:
- if (part->pd2) poin = &(part->pd2->f_strength);
- break;
- case PART_PD2_FFALL:
- if (part->pd2) poin = &(part->pd2->f_power);
- break;
- case PART_PD2_FMAXD:
- if (part->pd2) poin = &(part->pd2->maxdist);
- break;
-#endif
-
- }
-
- return NULL;
-}
-
/* ------- */
/* Allocate memory for RNA-path for some property given a blocktype, adrcode, and 'root' parts of path
@@ -872,10 +804,6 @@ static char *get_rna_access(ID *id, int blocktype, int adrcode, char actname[],
propname = world_adrcodes_to_paths(adrcode, &dummy_index);
break;
- case ID_PA: /* particle */
- propname = particle_adrcodes_to_paths(adrcode, &dummy_index);
- break;
-
case ID_CU: /* curve */
/* this used to be a 'dummy' curve which got evaluated on the fly...
* now we've got real var for this!
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index 14612151a8e..4ed1fad7323 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -112,7 +112,6 @@
#include "BKE_node.h"
#include "BKE_object.h"
#include "BKE_paint.h"
-#include "BKE_particle.h"
#include "BKE_packedFile.h"
#include "BKE_sound.h"
#include "BKE_speaker.h"
@@ -409,9 +408,6 @@ bool id_make_local(Main *bmain, ID *id, const bool test, const bool lib_local)
case ID_BR:
if (!test) BKE_brush_make_local(bmain, (Brush *)id, lib_local);
return true;
- case ID_PA:
- if (!test) BKE_particlesettings_make_local(bmain, (ParticleSettings *)id, lib_local);
- return true;
case ID_GD:
if (!test) BKE_gpencil_make_local(bmain, (bGPdata *)id, lib_local);
return true;
@@ -516,9 +512,6 @@ bool id_copy(Main *bmain, ID *id, ID **newid, bool test)
case ID_BR:
if (!test) *newid = (ID *)BKE_brush_copy(bmain, (Brush *)id);
return true;
- case ID_PA:
- if (!test) *newid = (ID *)BKE_particlesettings_copy(bmain, (ParticleSettings *)id);
- return true;
case ID_GD:
if (!test) *newid = (ID *)BKE_gpencil_data_duplicate(bmain, (bGPdata *)id, false);
return true;
@@ -636,8 +629,6 @@ ListBase *which_libbase(Main *mainlib, short type)
return &(mainlib->nodetree);
case ID_BR:
return &(mainlib->brush);
- case ID_PA:
- return &(mainlib->particle);
case ID_WM:
return &(mainlib->wm);
case ID_GD:
@@ -790,7 +781,6 @@ int set_listbasepointers(Main *main, ListBase **lb)
lb[INDEX_ID_PAL] = &(main->palettes);
lb[INDEX_ID_PC] = &(main->paintcurves);
lb[INDEX_ID_BR] = &(main->brush);
- lb[INDEX_ID_PA] = &(main->particle);
lb[INDEX_ID_SPK] = &(main->speaker);
lb[INDEX_ID_WO] = &(main->world);
@@ -901,9 +891,6 @@ void *BKE_libblock_alloc_notest(short type)
case ID_BR:
id = MEM_callocN(sizeof(Brush), "brush");
break;
- case ID_PA:
- id = MEM_callocN(sizeof(ParticleSettings), "ParticleSettings");
- break;
case ID_WM:
id = MEM_callocN(sizeof(wmWindowManager), "Window manager");
break;
@@ -1039,9 +1026,6 @@ void BKE_libblock_init_empty(ID *id)
case ID_BR:
BKE_brush_init((Brush *)id);
break;
- case ID_PA:
- /* Nothing to do. */
- break;
case ID_PC:
/* Nothing to do. */
break;
@@ -1244,7 +1228,6 @@ void BKE_main_free(Main *mainvar)
case 31: BKE_libblock_free_ex(mainvar, id, false); break;
case 32: BKE_libblock_free_ex(mainvar, id, false); break;
case 33: BKE_libblock_free_ex(mainvar, id, false); break;
- case 34: BKE_libblock_free_ex(mainvar, id, false); break;
default:
BLI_assert(0);
break;
diff --git a/source/blender/blenkernel/intern/library_query.c b/source/blender/blenkernel/intern/library_query.c
index 87f9cbc9b05..44c1e1baa4d 100644
--- a/source/blender/blenkernel/intern/library_query.c
+++ b/source/blender/blenkernel/intern/library_query.c
@@ -51,6 +51,7 @@
#include "DNA_mask_types.h"
#include "DNA_node_types.h"
#include "DNA_object_force.h"
+#include "DNA_object_types.h"
#include "DNA_rigidbody_types.h"
#include "DNA_scene_types.h"
#include "DNA_sensor_types.h"
@@ -63,7 +64,6 @@
#include "DNA_world_types.h"
#include "BLI_utildefines.h"
-#include "BLI_listbase.h"
#include "BLI_ghash.h"
#include "BLI_linklist_stack.h"
@@ -74,7 +74,6 @@
#include "BKE_library_query.h"
#include "BKE_main.h"
#include "BKE_modifier.h"
-#include "BKE_particle.h"
#include "BKE_rigidbody.h"
#include "BKE_sca.h"
#include "BKE_sequencer.h"
@@ -167,15 +166,6 @@ static void library_foreach_constraintObjectLooper(bConstraint *UNUSED(con), ID
FOREACH_FINALIZE_VOID;
}
-static void library_foreach_particlesystemsObjectLooper(
- ParticleSystem *UNUSED(psys), ID **id_pointer, void *user_data, int cd_flag)
-{
- LibraryForeachIDData *data = (LibraryForeachIDData *) user_data;
- FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cd_flag);
-
- FOREACH_FINALIZE_VOID;
-}
-
static void library_foreach_sensorsObjectLooper(
bSensor *UNUSED(sensor), ID **id_pointer, void *user_data, int cd_flag)
{
@@ -402,10 +392,6 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
if (toolsett) {
CALLBACK_INVOKE(toolsett->skgen_template, IDWALK_NOP);
- CALLBACK_INVOKE(toolsett->particle.scene, IDWALK_NOP);
- CALLBACK_INVOKE(toolsett->particle.object, IDWALK_NOP);
- CALLBACK_INVOKE(toolsett->particle.shape_object, IDWALK_NOP);
-
library_foreach_paint(&data, &toolsett->imapaint.paint);
CALLBACK_INVOKE(toolsett->imapaint.stencil, IDWALK_USER);
CALLBACK_INVOKE(toolsett->imapaint.clone, IDWALK_USER);
@@ -438,7 +424,6 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
case ID_OB:
{
Object *object = (Object *) id;
- ParticleSystem *psys;
/* Object is special, proxies make things hard... */
const int data_cd_flag = data.cd_flag;
@@ -520,10 +505,6 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
modifiers_foreachIDLink(object, library_foreach_modifiersForeachIDLink, &data);
BKE_constraints_id_loop(&object->constraints, library_foreach_constraintObjectLooper, &data);
- for (psys = object->particlesystem.first; psys; psys = psys->next) {
- BKE_particlesystem_id_loop(psys, library_foreach_particlesystemsObjectLooper, &data);
- }
-
if (object->soft) {
CALLBACK_INVOKE(object->soft->collision_group, IDWALK_NOP);
@@ -738,53 +719,6 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
break;
}
- case ID_PA:
- {
- ParticleSettings *psett = (ParticleSettings *) id;
- CALLBACK_INVOKE(psett->dup_group, IDWALK_NOP);
- CALLBACK_INVOKE(psett->dup_ob, IDWALK_NOP);
- CALLBACK_INVOKE(psett->bb_ob, IDWALK_NOP);
- CALLBACK_INVOKE(psett->collision_group, IDWALK_NOP);
-
- for (i = 0; i < MAX_MTEX; i++) {
- if (psett->mtex[i]) {
- library_foreach_mtex(&data, psett->mtex[i]);
- }
- }
-
- if (psett->effector_weights) {
- CALLBACK_INVOKE(psett->effector_weights->group, IDWALK_NOP);
- }
-
- if (psett->pd) {
- CALLBACK_INVOKE(psett->pd->tex, IDWALK_USER);
- CALLBACK_INVOKE(psett->pd->f_source, IDWALK_NOP);
- }
- if (psett->pd2) {
- CALLBACK_INVOKE(psett->pd2->tex, IDWALK_USER);
- CALLBACK_INVOKE(psett->pd2->f_source, IDWALK_NOP);
- }
-
- if (psett->boids) {
- BoidState *state;
- BoidRule *rule;
-
- for (state = psett->boids->states.first; state; state = state->next) {
- for (rule = state->rules.first; rule; rule = rule->next) {
- if (rule->type == eBoidRuleType_Avoid) {
- BoidRuleGoalAvoid *gabr = (BoidRuleGoalAvoid *)rule;
- CALLBACK_INVOKE(gabr->ob, IDWALK_NOP);
- }
- else if (rule->type == eBoidRuleType_FollowLeader) {
- BoidRuleFollowLeader *flbr = (BoidRuleFollowLeader *)rule;
- CALLBACK_INVOKE(flbr->ob, IDWALK_NOP);
- }
- }
- }
- }
- break;
- }
-
case ID_MC:
{
MovieClip *clip = (MovieClip *) id;
@@ -949,7 +883,7 @@ bool BKE_library_idtype_can_use_idtype(const short id_type_owner, const short id
/* Could be the following, but simpler to just always say 'yes' here. */
#if 0
return ELEM(id_type_used, ID_ME, ID_CU, ID_MB, ID_LT, ID_SPK, ID_AR, ID_LA, ID_CA, /* obdata */
- ID_OB, ID_MA, ID_GD, ID_GR, ID_TE, ID_PA, ID_TXT, ID_SO, ID_MC, ID_IM, ID_AC
+ ID_OB, ID_MA, ID_GD, ID_GR, ID_TE, ID_TXT, ID_SO, ID_MC, ID_IM, ID_AC
/* + constraints, modifiers and game logic ID types... */);
#else
return true;
@@ -989,8 +923,6 @@ bool BKE_library_idtype_can_use_idtype(const short id_type_owner, const short id
#endif
case ID_BR:
return ELEM(id_type_used, ID_BR, ID_IM, ID_PC, ID_TE);
- case ID_PA:
- return ELEM(id_type_used, ID_OB, ID_GR, ID_TE);
case ID_MC:
return ELEM(id_type_used, ID_GD, ID_IM);
case ID_MSK:
diff --git a/source/blender/blenkernel/intern/library_remap.c b/source/blender/blenkernel/intern/library_remap.c
index b468e6436c8..b7f7f2c19cc 100644
--- a/source/blender/blenkernel/intern/library_remap.c
+++ b/source/blender/blenkernel/intern/library_remap.c
@@ -98,7 +98,6 @@
#include "BKE_node.h"
#include "BKE_object.h"
#include "BKE_paint.h"
-#include "BKE_particle.h"
#include "BKE_sca.h"
#include "BKE_speaker.h"
#include "BKE_sound.h"
@@ -797,9 +796,6 @@ void BKE_libblock_free_ex(Main *bmain, void *idv, const bool do_id_user)
case ID_BR:
BKE_brush_free((Brush *)id);
break;
- case ID_PA:
- BKE_particlesettings_free((ParticleSettings *)id);
- break;
case ID_WM:
if (free_windowmanager_cb)
free_windowmanager_cb(NULL, (wmWindowManager *)id);
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
index 41e4c21d814..936b014cca3 100644
--- a/source/blender/blenkernel/intern/modifier.c
+++ b/source/blender/blenkernel/intern/modifier.c
@@ -401,13 +401,6 @@ bool modifiers_isModifierEnabled(Object *ob, int modifierType)
return (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render));
}
-bool modifiers_isParticleEnabled(Object *ob)
-{
- ModifierData *md = modifiers_findByType(ob, eModifierType_ParticleSystem);
-
- return (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render));
-}
-
bool modifier_isEnabled(struct Scene *scene, ModifierData *md, int required_mode)
{
const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index b127ef877cc..cc5d8d9e61d 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -50,6 +50,8 @@
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_movieclip_types.h"
+#include "DNA_object_force.h"
+#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_sequence_types.h"
@@ -104,8 +106,6 @@
#include "BKE_node.h"
#include "BKE_object.h"
#include "BKE_paint.h"
-#include "BKE_particle.h"
-#include "BKE_pointcache.h"
#include "BKE_property.h"
#include "BKE_rigidbody.h"
#include "BKE_sca.h"
@@ -162,15 +162,6 @@ void BKE_object_update_base_layer(struct Scene *scene, Object *ob)
}
}
-void BKE_object_free_particlesystems(Object *ob)
-{
- ParticleSystem *psys;
-
- while ((psys = BLI_pophead(&ob->particlesystem))) {
- psys_free(ob, psys);
- }
-}
-
void BKE_object_free_softbody(Object *ob)
{
if (ob->soft) {
@@ -209,9 +200,6 @@ void BKE_object_free_modifiers(Object *ob)
modifier_free(md);
}
- /* particle modifiers were freed, so free the particlesystems as well */
- BKE_object_free_particlesystems(ob);
-
/* same for softbody */
BKE_object_free_softbody(ob);
@@ -307,8 +295,6 @@ void BKE_object_link_modifiers(struct Object *ob_dst, const struct Object *ob_sr
modifier_unique_name(&ob_dst->modifiers, nmd);
}
- BKE_object_copy_particlesystems(ob_dst, ob_src);
-
/* TODO: smoke?, cloth? */
}
@@ -352,40 +338,8 @@ void BKE_object_free_derived_caches(Object *ob)
void BKE_object_free_caches(Object *object)
{
- ModifierData *md;
short update_flag = 0;
- /* Free particle system caches holding paths. */
- if (object->particlesystem.first) {
- ParticleSystem *psys;
- for (psys = object->particlesystem.first;
- psys != NULL;
- psys = psys->next)
- {
- psys_free_path_cache(psys, psys->edit);
- update_flag |= PSYS_RECALC_REDO;
- }
- }
-
- /* Free memory used by cached derived meshes in the particle system modifiers. */
- for (md = object->modifiers.first; md != NULL; md = md->next) {
- if (md->type == eModifierType_ParticleSystem) {
- ParticleSystemModifierData *psmd = (ParticleSystemModifierData *) md;
- if (psmd->dm_final != NULL) {
- psmd->dm_final->needsFree = 1;
- psmd->dm_final->release(psmd->dm_final);
- psmd->dm_final = NULL;
- if (psmd->dm_deformed != NULL) {
- psmd->dm_deformed->needsFree = 1;
- psmd->dm_deformed->release(psmd->dm_deformed);
- psmd->dm_deformed = NULL;
- }
- psmd->flag |= eParticleSystemFlag_file_loaded;
- update_flag |= OB_RECALC_DATA;
- }
- }
- }
-
/* Tag object for update, so once memory critical operation is over and
* scene update routines are back to it's business the object will be
* guaranteed to be in a known state.
@@ -874,8 +828,6 @@ SoftBody *copy_softbody(const SoftBody *sb, bool copy_caches)
sbn->scratch = NULL;
- sbn->pointcache = BKE_ptcache_copy_list(&sbn->ptcaches, &sb->ptcaches, copy_caches);
-
if (sb->effector_weights)
sbn->effector_weights = MEM_dupallocN(sb->effector_weights);
@@ -893,119 +845,6 @@ BulletSoftBody *copy_bulletsoftbody(BulletSoftBody *bsb)
return bsbn;
}
-ParticleSystem *BKE_object_copy_particlesystem(ParticleSystem *psys)
-{
- ParticleSystem *psysn;
- ParticleData *pa;
- int p;
-
- psysn = MEM_dupallocN(psys);
- psysn->particles = MEM_dupallocN(psys->particles);
- psysn->child = MEM_dupallocN(psys->child);
-
- if (psys->part->type == PART_HAIR) {
- for (p = 0, pa = psysn->particles; p < psysn->totpart; p++, pa++)
- pa->hair = MEM_dupallocN(pa->hair);
- }
-
- if (psysn->particles && (psysn->particles->keys || psysn->particles->boid)) {
- ParticleKey *key = psysn->particles->keys;
- BoidParticle *boid = psysn->particles->boid;
-
- if (key)
- key = MEM_dupallocN(key);
-
- if (boid)
- boid = MEM_dupallocN(boid);
-
- for (p = 0, pa = psysn->particles; p < psysn->totpart; p++, pa++) {
- if (boid)
- pa->boid = boid++;
- if (key) {
- pa->keys = key;
- key += pa->totkey;
- }
- }
- }
-
- if (psys->clmd) {
- psysn->clmd = (ClothModifierData *)modifier_new(eModifierType_Cloth);
- modifier_copyData((ModifierData *)psys->clmd, (ModifierData *)psysn->clmd);
- psys->hair_in_dm = psys->hair_out_dm = NULL;
- }
-
- BLI_duplicatelist(&psysn->targets, &psys->targets);
-
- psysn->pathcache = NULL;
- psysn->childcache = NULL;
- psysn->edit = NULL;
- psysn->pdd = NULL;
- psysn->effectors = NULL;
- psysn->tree = NULL;
- psysn->bvhtree = NULL;
-
- BLI_listbase_clear(&psysn->pathcachebufs);
- BLI_listbase_clear(&psysn->childcachebufs);
- psysn->renderdata = NULL;
-
- psysn->pointcache = BKE_ptcache_copy_list(&psysn->ptcaches, &psys->ptcaches, false);
-
- /* XXX - from reading existing code this seems correct but intended usage of
- * pointcache should /w cloth should be added in 'ParticleSystem' - campbell */
- if (psysn->clmd) {
- psysn->clmd->point_cache = psysn->pointcache;
- }
-
- id_us_plus((ID *)psysn->part);
-
- return psysn;
-}
-
-void BKE_object_copy_particlesystems(Object *ob_dst, const Object *ob_src)
-{
- ParticleSystem *psys, *npsys;
- ModifierData *md;
-
- if (ob_dst->type != OB_MESH) {
- /* currently only mesh objects can have soft body */
- return;
- }
-
- BLI_listbase_clear(&ob_dst->particlesystem);
- for (psys = ob_src->particlesystem.first; psys; psys = psys->next) {
- npsys = BKE_object_copy_particlesystem(psys);
-
- BLI_addtail(&ob_dst->particlesystem, npsys);
-
- /* need to update particle modifiers too */
- for (md = ob_dst->modifiers.first; md; md = md->next) {
- if (md->type == eModifierType_ParticleSystem) {
- ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md;
- if (psmd->psys == psys)
- psmd->psys = npsys;
- }
- else if (md->type == eModifierType_DynamicPaint) {
- DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md;
- if (pmd->brush) {
- if (pmd->brush->psys == psys) {
- pmd->brush->psys = npsys;
- }
- }
- }
- else if (md->type == eModifierType_Smoke) {
- SmokeModifierData *smd = (SmokeModifierData *) md;
-
- if (smd->type == MOD_SMOKE_TYPE_FLOW) {
- if (smd->flow) {
- if (smd->flow->psys == psys)
- smd->flow->psys = npsys;
- }
- }
- }
- }
- }
-}
-
void BKE_object_copy_softbody(Object *ob_dst, const Object *ob_src)
{
if (ob_src->soft) {
@@ -1162,8 +1001,6 @@ Object *BKE_object_copy_ex(Main *bmain, Object *ob, bool copy_caches)
obn->rigidbody_object = BKE_rigidbody_copy_object(ob);
obn->rigidbody_constraint = BKE_rigidbody_copy_constraint(ob);
- BKE_object_copy_particlesystems(obn, ob);
-
obn->derivedDeform = NULL;
obn->derivedFinal = NULL;
@@ -3683,25 +3520,6 @@ bool BKE_object_modifier_use_time(Object *ob, ModifierData *md)
return false;
}
-/* set "ignore cache" flag for all caches on this object */
-static void object_cacheIgnoreClear(Object *ob, int state)
-{
- ListBase pidlist;
- PTCacheID *pid;
- BKE_ptcache_ids_from_object(&pidlist, ob, NULL, 0);
-
- for (pid = pidlist.first; pid; pid = pid->next) {
- if (pid->cache) {
- if (state)
- pid->cache->flag |= PTCACHE_IGNORE_CLEAR;
- else
- pid->cache->flag &= ~PTCACHE_IGNORE_CLEAR;
- }
- }
-
- BLI_freelistN(&pidlist);
-}
-
/* Note: this function should eventually be replaced by depsgraph functionality.
* Avoid calling this in new code unless there is a very good reason for it!
*/
@@ -3761,11 +3579,7 @@ bool BKE_object_modifier_update_subframe(Scene *scene, Object *ob, bool update_m
ob->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME;
BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, frame, ADT_RECALC_ANIM);
if (update_mesh) {
- /* ignore cache clear during subframe updates
- * to not mess up cache validity */
- object_cacheIgnoreClear(ob, 1);
BKE_object_handle_update(G.main->eval_ctx, scene, ob);
- object_cacheIgnoreClear(ob, 0);
}
else
BKE_object_where_is_calc_time(scene, ob, frame);
diff --git a/source/blender/blenkernel/intern/object_deform.c b/source/blender/blenkernel/intern/object_deform.c
index b5f63588423..72968d1964c 100644
--- a/source/blender/blenkernel/intern/object_deform.c
+++ b/source/blender/blenkernel/intern/object_deform.c
@@ -42,7 +42,6 @@
#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
#include "DNA_object_force.h"
-#include "DNA_particle_types.h"
#include "DNA_scene_types.h"
#include "BKE_action.h"
@@ -72,8 +71,6 @@ static Lattice *object_defgroup_lattice_get(ID *id)
void BKE_object_defgroup_remap_update_users(Object *ob, int *map)
{
ModifierData *md;
- ParticleSystem *psys;
- int a;
/* these cases don't use names to refer to vertex groups, so when
* they get removed the numbers get out of sync, this corrects that */
@@ -98,12 +95,6 @@ void BKE_object_defgroup_remap_update_users(Object *ob, int *map)
}
}
}
-
- for (psys = ob->particlesystem.first; psys; psys = psys->next) {
- for (a = 0; a < PSYS_TOT_VG; a++) {
- psys->vgroup[a] = map[psys->vgroup[a]];
- }
- }
}
/** \} */
diff --git a/source/blender/blenkernel/intern/object_dupli.c b/source/blender/blenkernel/intern/object_dupli.c
index 14cc5ec0849..3ec174146b1 100644
--- a/source/blender/blenkernel/intern/object_dupli.c
+++ b/source/blender/blenkernel/intern/object_dupli.c
@@ -44,6 +44,7 @@
#include "DNA_anim_types.h"
#include "DNA_group_types.h"
#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_vfont_types.h"
@@ -57,7 +58,6 @@
#include "BKE_main.h"
#include "BKE_mesh.h"
#include "BKE_object.h"
-#include "BKE_particle.h"
#include "BKE_scene.h"
#include "BKE_editmesh.h"
#include "BKE_anim.h"
@@ -825,327 +825,6 @@ const DupliGenerator gen_dupli_faces = {
make_duplis_faces /* make_duplis */
};
-/* OB_DUPLIPARTS */
-static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem *psys)
-{
- Scene *scene = ctx->scene;
- Object *par = ctx->object;
- bool for_render = ctx->eval_ctx->mode == DAG_EVAL_RENDER;
- bool use_texcoords = ELEM(ctx->eval_ctx->mode, DAG_EVAL_RENDER, DAG_EVAL_PREVIEW);
-
- GroupObject *go;
- Object *ob = NULL, **oblist = NULL, obcopy, *obcopylist = NULL;
- DupliObject *dob;
- ParticleDupliWeight *dw;
- ParticleSettings *part;
- ParticleData *pa;
- ChildParticle *cpa = NULL;
- ParticleKey state;
- ParticleCacheKey *cache;
- float ctime, pa_time, scale = 1.0f;
- float tmat[4][4], mat[4][4], pamat[4][4], vec[3], size = 0.0;
- float (*obmat)[4];
- int a, b, hair = 0;
- int totpart, totchild, totgroup = 0 /*, pa_num */;
- const bool dupli_type_hack = !BKE_scene_use_new_shading_nodes(scene);
-
- int no_draw_flag = PARS_UNEXIST;
-
- if (psys == NULL) return;
-
- part = psys->part;
-
- if (part == NULL)
- return;
-
- if (!psys_check_enabled(par, psys, (ctx->eval_ctx->mode == DAG_EVAL_RENDER)))
- return;
-
- if (!for_render)
- no_draw_flag |= PARS_NO_DISP;
-
- ctime = BKE_scene_frame_get(scene); /* NOTE: in old animsys, used parent object's timeoffset... */
-
- totpart = psys->totpart;
- totchild = psys->totchild;
-
- BLI_srandom((unsigned int)(31415926 + psys->seed));
-
- if ((psys->renderdata || part->draw_as == PART_DRAW_REND) && ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR)) {
- ParticleSimulationData sim = {NULL};
- sim.scene = scene;
- sim.ob = par;
- sim.psys = psys;
- sim.psmd = psys_get_modifier(par, psys);
- /* make sure emitter imat is in global coordinates instead of render view coordinates */
- invert_m4_m4(par->imat, par->obmat);
-
- /* first check for loops (particle system object used as dupli object) */
- if (part->ren_as == PART_DRAW_OB) {
- if (ELEM(part->dup_ob, NULL, par))
- return;
- }
- else { /*PART_DRAW_GR */
- if (part->dup_group == NULL || BLI_listbase_is_empty(&part->dup_group->gobject))
- return;
-
- if (BLI_findptr(&part->dup_group->gobject, par, offsetof(GroupObject, ob))) {
- return;
- }
- }
-
- /* if we have a hair particle system, use the path cache */
- if (part->type == PART_HAIR) {
- if (psys->flag & PSYS_HAIR_DONE)
- hair = (totchild == 0 || psys->childcache) && psys->pathcache;
- if (!hair)
- return;
-
- /* we use cache, update totchild according to cached data */
- totchild = psys->totchildcache;
- totpart = psys->totcached;
- }
-
- psys_check_group_weights(part);
-
- psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
-
- /* gather list of objects or single object */
- if (part->ren_as == PART_DRAW_GR) {
- if (ctx->do_update) {
- BKE_group_handle_recalc_and_update(ctx->eval_ctx, scene, par, part->dup_group);
- }
-
- if (part->draw & PART_DRAW_COUNT_GR) {
- for (dw = part->dupliweights.first; dw; dw = dw->next)
- totgroup += dw->count;
- }
- else {
- for (go = part->dup_group->gobject.first; go; go = go->next)
- totgroup++;
- }
-
- /* we also copy the actual objects to restore afterwards, since
- * BKE_object_where_is_calc_time will change the object which breaks transform */
- oblist = MEM_callocN((size_t)totgroup * sizeof(Object *), "dupgroup object list");
- obcopylist = MEM_callocN((size_t)totgroup * sizeof(Object), "dupgroup copy list");
-
- if (part->draw & PART_DRAW_COUNT_GR && totgroup) {
- dw = part->dupliweights.first;
-
- for (a = 0; a < totgroup; dw = dw->next) {
- for (b = 0; b < dw->count; b++, a++) {
- oblist[a] = dw->ob;
- obcopylist[a] = *dw->ob;
- }
- }
- }
- else {
- go = part->dup_group->gobject.first;
- for (a = 0; a < totgroup; a++, go = go->next) {
- oblist[a] = go->ob;
- obcopylist[a] = *go->ob;
- }
- }
- }
- else {
- ob = part->dup_ob;
- obcopy = *ob;
- }
-
- if (totchild == 0 || part->draw & PART_DRAW_PARENT)
- a = 0;
- else
- a = totpart;
-
- for (pa = psys->particles; a < totpart + totchild; a++, pa++) {
- if (a < totpart) {
- /* handle parent particle */
- if (pa->flag & no_draw_flag)
- continue;
-
- /* pa_num = pa->num; */ /* UNUSED */
- pa_time = pa->time;
- size = pa->size;
- }
- else {
- /* handle child particle */
- cpa = &psys->child[a - totpart];
-
- /* pa_num = a; */ /* UNUSED */
- pa_time = psys->particles[cpa->parent].time;
- size = psys_get_child_size(psys, cpa, ctime, NULL);
- }
-
- /* some hair paths might be non-existent so they can't be used for duplication */
- if (hair && psys->pathcache &&
- ((a < totpart && psys->pathcache[a]->segments < 0) ||
- (a >= totpart && psys->childcache[a - totpart]->segments < 0)))
- {
- continue;
- }
-
- if (part->ren_as == PART_DRAW_GR) {
- /* prevent divide by zero below [#28336] */
- if (totgroup == 0)
- continue;
-
- /* for groups, pick the object based on settings */
- if (part->draw & PART_DRAW_RAND_GR)
- b = BLI_rand() % totgroup;
- else
- b = a % totgroup;
-
- ob = oblist[b];
- obmat = oblist[b]->obmat;
- }
- else {
- obmat = ob->obmat;
- }
-
- if (hair) {
- /* hair we handle separate and compute transform based on hair keys */
- if (a < totpart) {
- cache = psys->pathcache[a];
- psys_get_dupli_path_transform(&sim, pa, NULL, cache, pamat, &scale);
- }
- else {
- cache = psys->childcache[a - totpart];
- psys_get_dupli_path_transform(&sim, NULL, cpa, cache, pamat, &scale);
- }
-
- copy_v3_v3(pamat[3], cache->co);
- pamat[3][3] = 1.0f;
-
- }
- else {
- /* first key */
- state.time = ctime;
- if (psys_get_particle_state(&sim, a, &state, 0) == 0) {
- continue;
- }
- else {
- float tquat[4];
- normalize_qt_qt(tquat, state.rot);
- quat_to_mat4(pamat, tquat);
- copy_v3_v3(pamat[3], state.co);
- pamat[3][3] = 1.0f;
- }
- }
-
- if (part->ren_as == PART_DRAW_GR && psys->part->draw & PART_DRAW_WHOLE_GR) {
- for (go = part->dup_group->gobject.first, b = 0; go; go = go->next, b++) {
-
- copy_m4_m4(tmat, oblist[b]->obmat);
- /* apply particle scale */
- mul_mat3_m4_fl(tmat, size * scale);
- mul_v3_fl(tmat[3], size * scale);
- /* group dupli offset, should apply after everything else */
- if (!is_zero_v3(part->dup_group->dupli_ofs))
- sub_v3_v3(tmat[3], part->dup_group->dupli_ofs);
- /* individual particle transform */
- mul_m4_m4m4(mat, pamat, tmat);
-
- dob = make_dupli(ctx, go->ob, mat, a, false, false);
- dob->particle_system = psys;
- if (use_texcoords)
- psys_get_dupli_texture(psys, part, sim.psmd, pa, cpa, dob->uv, dob->orco);
- }
- }
- else {
- /* to give ipos in object correct offset */
- BKE_object_where_is_calc_time(scene, ob, ctime - pa_time);
-
- copy_v3_v3(vec, obmat[3]);
- obmat[3][0] = obmat[3][1] = obmat[3][2] = 0.0f;
-
- /* particle rotation uses x-axis as the aligned axis, so pre-rotate the object accordingly */
- if ((part->draw & PART_DRAW_ROTATE_OB) == 0) {
- float xvec[3], q[4], size_mat[4][4], original_size[3];
-
- mat4_to_size(original_size, obmat);
- size_to_mat4(size_mat, original_size);
-
- xvec[0] = -1.f;
- xvec[1] = xvec[2] = 0;
- vec_to_quat(q, xvec, ob->trackflag, ob->upflag);
- quat_to_mat4(obmat, q);
- obmat[3][3] = 1.0f;
-
- /* add scaling if requested */
- if ((part->draw & PART_DRAW_NO_SCALE_OB) == 0)
- mul_m4_m4m4(obmat, obmat, size_mat);
- }
- else if (part->draw & PART_DRAW_NO_SCALE_OB) {
- /* remove scaling */
- float size_mat[4][4], original_size[3];
-
- mat4_to_size(original_size, obmat);
- size_to_mat4(size_mat, original_size);
- invert_m4(size_mat);
-
- mul_m4_m4m4(obmat, obmat, size_mat);
- }
-
- mul_m4_m4m4(tmat, pamat, obmat);
- mul_mat3_m4_fl(tmat, size * scale);
-
- copy_m4_m4(mat, tmat);
-
- if (part->draw & PART_DRAW_GLOBAL_OB)
- add_v3_v3v3(mat[3], mat[3], vec);
-
- dob = make_dupli(ctx, ob, mat, a, false, false);
- dob->particle_system = psys;
- if (use_texcoords)
- psys_get_dupli_texture(psys, part, sim.psmd, pa, cpa, dob->uv, dob->orco);
- /* XXX blender internal needs this to be set to dupligroup to render
- * groups correctly, but we don't want this hack for cycles */
- if (dupli_type_hack && ctx->group)
- dob->type = OB_DUPLIGROUP;
- }
- }
-
- /* restore objects since they were changed in BKE_object_where_is_calc_time */
- if (part->ren_as == PART_DRAW_GR) {
- for (a = 0; a < totgroup; a++)
- *(oblist[a]) = obcopylist[a];
- }
- else
- *ob = obcopy;
- }
-
- /* clean up */
- if (oblist)
- MEM_freeN(oblist);
- if (obcopylist)
- MEM_freeN(obcopylist);
-
- if (psys->lattice_deform_data) {
- end_latt_deform(psys->lattice_deform_data);
- psys->lattice_deform_data = NULL;
- }
-}
-
-static void make_duplis_particles(const DupliContext *ctx)
-{
- ParticleSystem *psys;
- int psysid;
-
- /* particle system take up one level in id, the particles another */
- for (psys = ctx->object->particlesystem.first, psysid = 0; psys; psys = psys->next, psysid++) {
- /* particles create one more level for persistent psys index */
- DupliContext pctx;
- copy_dupli_context(&pctx, ctx, ctx->object, NULL, psysid, false);
- make_duplis_particle_system(&pctx, psys);
- }
-}
-
-const DupliGenerator gen_dupli_particles = {
- OB_DUPLIPARTS, /* type */
- make_duplis_particles /* make_duplis */
-};
-
/* ------------- */
/* select dupli generator from given context */
@@ -1161,10 +840,7 @@ static const DupliGenerator *get_dupli_generator(const DupliContext *ctx)
if (ctx->eval_ctx->mode == DAG_EVAL_RENDER ? (restrictflag & OB_RESTRICT_RENDER) : (restrictflag & OB_RESTRICT_VIEW))
return NULL;
- if (transflag & OB_DUPLIPARTS) {
- return &gen_dupli_particles;
- }
- else if (transflag & OB_DUPLIVERTS) {
+ if (transflag & OB_DUPLIVERTS) {
if (ctx->object->type == OB_MESH) {
return &gen_dupli_verts;
}
@@ -1222,12 +898,8 @@ int count_duplilist(Object *ob)
if (ob->transflag & OB_DUPLIVERTS) {
if (ob->type == OB_MESH) {
if (ob->transflag & OB_DUPLIVERTS) {
- ParticleSystem *psys = ob->particlesystem.first;
int pdup = 0;
- for (; psys; psys = psys->next)
- pdup += psys->totpart;
-
if (pdup == 0) {
Mesh *me = ob->data;
return me->totvert;
diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c
index 5cb704e4737..b8cb8955672 100644
--- a/source/blender/blenkernel/intern/object_update.c
+++ b/source/blender/blenkernel/intern/object_update.c
@@ -32,6 +32,7 @@
#include "DNA_group_types.h"
#include "DNA_key_types.h"
#include "DNA_material_types.h"
+#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "BLI_blenlib.h"
@@ -53,7 +54,6 @@
#include "BKE_lattice.h"
#include "BKE_editmesh.h"
#include "BKE_object.h"
-#include "BKE_particle.h"
#include "BKE_scene.h"
#include "BKE_material.h"
#include "BKE_image.h"
@@ -257,53 +257,6 @@ void BKE_object_handle_data_update(EvaluationContext *eval_ctx,
else if (ob->type == OB_LAMP)
lamp_drivers_update(scene, ob->data, ctime);
- /* particles */
- if (ob != scene->obedit && ob->particlesystem.first) {
- ParticleSystem *tpsys, *psys;
- DerivedMesh *dm;
- ob->transflag &= ~OB_DUPLIPARTS;
- psys = ob->particlesystem.first;
- while (psys) {
- /* ensure this update always happens even if psys is disabled */
- if (psys->recalc & PSYS_RECALC_TYPE) {
- psys_changed_type(ob, psys);
- }
-
- if (psys_check_enabled(ob, psys, eval_ctx->mode == DAG_EVAL_RENDER)) {
- /* check use of dupli objects here */
- if (psys->part && (psys->part->draw_as == PART_DRAW_REND || eval_ctx->mode == DAG_EVAL_RENDER) &&
- ((psys->part->ren_as == PART_DRAW_OB && psys->part->dup_ob) ||
- (psys->part->ren_as == PART_DRAW_GR && psys->part->dup_group)))
- {
- ob->transflag |= OB_DUPLIPARTS;
- }
-
- particle_system_update(scene, ob, psys, (eval_ctx->mode == DAG_EVAL_RENDER));
- psys = psys->next;
- }
- else if (psys->flag & PSYS_DELETE) {
- tpsys = psys->next;
- BLI_remlink(&ob->particlesystem, psys);
- psys_free(ob, psys);
- psys = tpsys;
- }
- else
- psys = psys->next;
- }
-
- if (eval_ctx->mode == DAG_EVAL_RENDER && ob->transflag & OB_DUPLIPARTS) {
- /* this is to make sure we get render level duplis in groups:
- * the derivedmesh must be created before init_render_mesh,
- * since object_duplilist does dupliparticles before that */
- CustomDataMask data_mask = CD_MASK_BAREMESH | CD_MASK_MFACE | CD_MASK_MTFACE | CD_MASK_MCOL;
- dm = mesh_create_derived_render(scene, ob, data_mask);
- dm->release(dm);
-
- for (psys = ob->particlesystem.first; psys; psys = psys->next)
- psys_get_modifier(ob, psys)->flag &= ~eParticleSystemFlag_psys_updated;
- }
- }
-
/* quick cache removed */
}
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
deleted file mode 100644
index 1ea27558545..00000000000
--- a/source/blender/blenkernel/intern/particle.c
+++ /dev/null
@@ -1,4304 +0,0 @@
-/*
- * ***** 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) 2007 by Janne Karhu.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/blenkernel/intern/particle.c
- * \ingroup bke
- */
-
-
-#include <stdlib.h>
-#include <math.h>
-#include <string.h>
-
-#include "MEM_guardedalloc.h"
-
-#include "DNA_curve_types.h"
-#include "DNA_group_types.h"
-#include "DNA_key_types.h"
-#include "DNA_material_types.h"
-#include "DNA_mesh_types.h"
-#include "DNA_meshdata_types.h"
-#include "DNA_particle_types.h"
-#include "DNA_smoke_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_dynamicpaint_types.h"
-
-#include "BLI_blenlib.h"
-#include "BLI_noise.h"
-#include "BLI_math.h"
-#include "BLI_utildefines.h"
-#include "BLI_kdtree.h"
-#include "BLI_rand.h"
-#include "BLI_task.h"
-#include "BLI_threads.h"
-#include "BLI_linklist.h"
-
-#include "BLT_translation.h"
-
-#include "BKE_anim.h"
-#include "BKE_animsys.h"
-
-#include "BKE_boids.h"
-#include "BKE_cloth.h"
-#include "BKE_colortools.h"
-#include "BKE_effect.h"
-#include "BKE_global.h"
-#include "BKE_group.h"
-#include "BKE_main.h"
-#include "BKE_lattice.h"
-
-#include "BKE_displist.h"
-#include "BKE_particle.h"
-#include "BKE_material.h"
-#include "BKE_key.h"
-#include "BKE_library.h"
-#include "BKE_library_query.h"
-#include "BKE_library_remap.h"
-#include "BKE_depsgraph.h"
-#include "BKE_modifier.h"
-#include "BKE_mesh.h"
-#include "BKE_cdderivedmesh.h"
-#include "BKE_pointcache.h"
-#include "BKE_scene.h"
-#include "BKE_deform.h"
-
-#include "RE_render_ext.h"
-
-unsigned int PSYS_FRAND_SEED_OFFSET[PSYS_FRAND_COUNT];
-unsigned int PSYS_FRAND_SEED_MULTIPLIER[PSYS_FRAND_COUNT];
-float PSYS_FRAND_BASE[PSYS_FRAND_COUNT];
-
-void psys_init_rng(void)
-{
- int i;
- BLI_srandom(5831); /* arbitrary */
- for (i = 0; i < PSYS_FRAND_COUNT; ++i) {
- PSYS_FRAND_BASE[i] = BLI_frand();
- PSYS_FRAND_SEED_OFFSET[i] = (unsigned int)BLI_rand();
- PSYS_FRAND_SEED_MULTIPLIER[i] = (unsigned int)BLI_rand();
- }
-}
-
-static void get_child_modifier_parameters(ParticleSettings *part, ParticleThreadContext *ctx,
- ChildParticle *cpa, short cpa_from, int cpa_num, float *cpa_fuv, float *orco, ParticleTexture *ptex);
-static void get_cpa_texture(DerivedMesh *dm, ParticleSystem *psys, ParticleSettings *part, ParticleData *par,
- int child_index, int face_index, const float fw[4], float *orco, ParticleTexture *ptex, int event, float cfra);
-extern void do_child_modifiers(ParticleThreadContext *ctx, ParticleSimulationData *sim,
- ParticleTexture *ptex, const float par_co[3], const float par_vel[3], const float par_rot[4], const float par_orco[3],
- ChildParticle *cpa, const float orco[3], float mat[4][4], ParticleKey *state, float t);
-
-/* few helpers for countall etc. */
-int count_particles(ParticleSystem *psys)
-{
- ParticleSettings *part = psys->part;
- PARTICLE_P;
- int tot = 0;
-
- LOOP_SHOWN_PARTICLES {
- if (pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN) == 0) {}
- else if (pa->alive == PARS_DEAD && (part->flag & PART_DIED) == 0) {}
- else tot++;
- }
- return tot;
-}
-int count_particles_mod(ParticleSystem *psys, int totgr, int cur)
-{
- ParticleSettings *part = psys->part;
- PARTICLE_P;
- int tot = 0;
-
- LOOP_SHOWN_PARTICLES {
- if (pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN) == 0) {}
- else if (pa->alive == PARS_DEAD && (part->flag & PART_DIED) == 0) {}
- else if (p % totgr == cur) tot++;
- }
- return tot;
-}
-/* we allocate path cache memory in chunks instead of a big contiguous
- * chunk, windows' memory allocater fails to find big blocks of memory often */
-
-#define PATH_CACHE_BUF_SIZE 1024
-
-static ParticleCacheKey *pcache_key_segment_endpoint_safe(ParticleCacheKey *key)
-{
- return (key->segments > 0) ? (key + (key->segments - 1)) : key;
-}
-
-static ParticleCacheKey **psys_alloc_path_cache_buffers(ListBase *bufs, int tot, int totkeys)
-{
- LinkData *buf;
- ParticleCacheKey **cache;
- int i, totkey, totbufkey;
-
- tot = MAX2(tot, 1);
- totkey = 0;
- cache = MEM_callocN(tot * sizeof(void *), "PathCacheArray");
-
- while (totkey < tot) {
- totbufkey = MIN2(tot - totkey, PATH_CACHE_BUF_SIZE);
- buf = MEM_callocN(sizeof(LinkData), "PathCacheLinkData");
- buf->data = MEM_callocN(sizeof(ParticleCacheKey) * totbufkey * totkeys, "ParticleCacheKey");
-
- for (i = 0; i < totbufkey; i++)
- cache[totkey + i] = ((ParticleCacheKey *)buf->data) + i * totkeys;
-
- totkey += totbufkey;
- BLI_addtail(bufs, buf);
- }
-
- return cache;
-}
-
-static void psys_free_path_cache_buffers(ParticleCacheKey **cache, ListBase *bufs)
-{
- LinkData *buf;
-
- if (cache)
- MEM_freeN(cache);
-
- for (buf = bufs->first; buf; buf = buf->next)
- MEM_freeN(buf->data);
- BLI_freelistN(bufs);
-}
-
-/************************************************/
-/* Getting stuff */
-/************************************************/
-/* get object's active particle system safely */
-ParticleSystem *psys_get_current(Object *ob)
-{
- ParticleSystem *psys;
- if (ob == NULL) return NULL;
-
- for (psys = ob->particlesystem.first; psys; psys = psys->next) {
- if (psys->flag & PSYS_CURRENT)
- return psys;
- }
-
- return NULL;
-}
-short psys_get_current_num(Object *ob)
-{
- ParticleSystem *psys;
- short i;
-
- if (ob == NULL) return 0;
-
- for (psys = ob->particlesystem.first, i = 0; psys; psys = psys->next, i++)
- if (psys->flag & PSYS_CURRENT)
- return i;
-
- return i;
-}
-void psys_set_current_num(Object *ob, int index)
-{
- ParticleSystem *psys;
- short i;
-
- if (ob == NULL) return;
-
- for (psys = ob->particlesystem.first, i = 0; psys; psys = psys->next, i++) {
- if (i == index)
- psys->flag |= PSYS_CURRENT;
- else
- psys->flag &= ~PSYS_CURRENT;
- }
-}
-
-#if 0 /* UNUSED */
-Object *psys_find_object(Scene *scene, ParticleSystem *psys)
-{
- Base *base;
- ParticleSystem *tpsys;
-
- for (base = scene->base.first; base; base = base->next) {
- for (tpsys = base->object->particlesystem.first; psys; psys = psys->next) {
- if (tpsys == psys)
- return base->object;
- }
- }
-
- return NULL;
-}
-#endif
-
-struct LatticeDeformData *psys_create_lattice_deform_data(ParticleSimulationData *sim)
-{
- struct LatticeDeformData *lattice_deform_data = NULL;
-
- if (psys_in_edit_mode(sim->scene, sim->psys) == 0) {
- Object *lattice = NULL;
- ModifierData *md = (ModifierData *)psys_get_modifier(sim->ob, sim->psys);
-
- for (; md; md = md->next) {
- if (md->type == eModifierType_Lattice) {
- LatticeModifierData *lmd = (LatticeModifierData *)md;
- lattice = lmd->object;
- break;
- }
- }
- if (lattice)
- lattice_deform_data = init_latt_deform(lattice, NULL);
- }
-
- return lattice_deform_data;
-}
-void psys_disable_all(Object *ob)
-{
- ParticleSystem *psys = ob->particlesystem.first;
-
- for (; psys; psys = psys->next)
- psys->flag |= PSYS_DISABLED;
-}
-void psys_enable_all(Object *ob)
-{
- ParticleSystem *psys = ob->particlesystem.first;
-
- for (; psys; psys = psys->next)
- psys->flag &= ~PSYS_DISABLED;
-}
-bool psys_in_edit_mode(Scene *scene, ParticleSystem *psys)
-{
- return (scene->basact && (scene->basact->object->mode & OB_MODE_PARTICLE_EDIT) && psys == psys_get_current((scene->basact)->object) && (psys->edit || psys->pointcache->edit) && !psys->renderdata);
-}
-bool psys_check_enabled(Object *ob, ParticleSystem *psys, const bool use_render_params)
-{
- ParticleSystemModifierData *psmd;
-
- if (psys->flag & PSYS_DISABLED || psys->flag & PSYS_DELETE || !psys->part)
- return 0;
-
- psmd = psys_get_modifier(ob, psys);
- if (psys->renderdata || use_render_params) {
- if (!(psmd->modifier.mode & eModifierMode_Render))
- return 0;
- }
- else if (!(psmd->modifier.mode & eModifierMode_Realtime))
- return 0;
-
- return 1;
-}
-
-bool psys_check_edited(ParticleSystem *psys)
-{
- if (psys->part && psys->part->type == PART_HAIR)
- return (psys->flag & PSYS_EDITED || (psys->edit && psys->edit->edited));
- else
- return (psys->pointcache->edit && psys->pointcache->edit->edited);
-}
-
-void psys_check_group_weights(ParticleSettings *part)
-{
- ParticleDupliWeight *dw, *tdw;
- GroupObject *go;
- int current = 0;
-
- if (part->ren_as == PART_DRAW_GR && part->dup_group && part->dup_group->gobject.first) {
- /* First try to find NULL objects from their index,
- * and remove all weights that don't have an object in the group. */
- dw = part->dupliweights.first;
- while (dw) {
- if (dw->ob == NULL || !BKE_group_object_exists(part->dup_group, dw->ob)) {
- go = (GroupObject *)BLI_findlink(&part->dup_group->gobject, dw->index);
- if (go) {
- dw->ob = go->ob;
- }
- else {
- tdw = dw->next;
- BLI_freelinkN(&part->dupliweights, dw);
- dw = tdw;
- }
- }
- else {
- dw = dw->next;
- }
- }
-
- /* then add objects in the group to new list */
- go = part->dup_group->gobject.first;
- while (go) {
- dw = part->dupliweights.first;
- while (dw && dw->ob != go->ob)
- dw = dw->next;
-
- if (!dw) {
- dw = MEM_callocN(sizeof(ParticleDupliWeight), "ParticleDupliWeight");
- dw->ob = go->ob;
- dw->count = 1;
- BLI_addtail(&part->dupliweights, dw);
- }
-
- go = go->next;
- }
-
- dw = part->dupliweights.first;
- for (; dw; dw = dw->next) {
- if (dw->flag & PART_DUPLIW_CURRENT) {
- current = 1;
- break;
- }
- }
-
- if (!current) {
- dw = part->dupliweights.first;
- if (dw)
- dw->flag |= PART_DUPLIW_CURRENT;
- }
- }
- else {
- BLI_freelistN(&part->dupliweights);
- }
-}
-int psys_uses_gravity(ParticleSimulationData *sim)
-{
- return sim->scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY && sim->psys->part && sim->psys->part->effector_weights->global_gravity != 0.0f;
-}
-/************************************************/
-/* Freeing stuff */
-/************************************************/
-static void fluid_free_settings(SPHFluidSettings *fluid)
-{
- if (fluid)
- MEM_freeN(fluid);
-}
-
-/** Free (or release) any data used by this particle settings (does not free the partsett itself). */
-void BKE_particlesettings_free(ParticleSettings *part)
-{
- int a;
-
- BKE_animdata_free((ID *)part, false);
-
- for (a = 0; a < MAX_MTEX; a++) {
- MEM_SAFE_FREE(part->mtex[a]);
- }
-
- if (part->clumpcurve)
- curvemapping_free(part->clumpcurve);
- if (part->roughcurve)
- curvemapping_free(part->roughcurve);
-
- free_partdeflect(part->pd);
- free_partdeflect(part->pd2);
-
- MEM_SAFE_FREE(part->effector_weights);
-
- BLI_freelistN(&part->dupliweights);
-
- boid_free_settings(part->boids);
- fluid_free_settings(part->fluid);
-}
-
-void free_hair(Object *UNUSED(ob), ParticleSystem *psys, int dynamics)
-{
- PARTICLE_P;
-
- LOOP_PARTICLES {
- if (pa->hair)
- MEM_freeN(pa->hair);
- pa->hair = NULL;
- pa->totkey = 0;
- }
-
- psys->flag &= ~PSYS_HAIR_DONE;
-
- if (psys->clmd) {
- if (dynamics) {
- BKE_ptcache_free_list(&psys->ptcaches);
- psys->pointcache = NULL;
-
- modifier_free((ModifierData *)psys->clmd);
-
- psys->clmd = NULL;
- psys->pointcache = BKE_ptcache_add(&psys->ptcaches);
- }
- else {
- cloth_free_modifier(psys->clmd);
- }
- }
-
- if (psys->hair_in_dm)
- psys->hair_in_dm->release(psys->hair_in_dm);
- psys->hair_in_dm = NULL;
-
- if (psys->hair_out_dm)
- psys->hair_out_dm->release(psys->hair_out_dm);
- psys->hair_out_dm = NULL;
-}
-void free_keyed_keys(ParticleSystem *psys)
-{
- PARTICLE_P;
-
- if (psys->part->type == PART_HAIR)
- return;
-
- if (psys->particles && psys->particles->keys) {
- MEM_freeN(psys->particles->keys);
-
- LOOP_PARTICLES {
- if (pa->keys) {
- pa->keys = NULL;
- pa->totkey = 0;
- }
- }
- }
-}
-static void free_child_path_cache(ParticleSystem *psys)
-{
- psys_free_path_cache_buffers(psys->childcache, &psys->childcachebufs);
- psys->childcache = NULL;
- psys->totchildcache = 0;
-}
-void psys_free_path_cache(ParticleSystem *psys, PTCacheEdit *edit)
-{
- if (edit) {
- psys_free_path_cache_buffers(edit->pathcache, &edit->pathcachebufs);
- edit->pathcache = NULL;
- edit->totcached = 0;
- }
- if (psys) {
- psys_free_path_cache_buffers(psys->pathcache, &psys->pathcachebufs);
- psys->pathcache = NULL;
- psys->totcached = 0;
-
- free_child_path_cache(psys);
- }
-}
-void psys_free_children(ParticleSystem *psys)
-{
- if (psys->child) {
- MEM_freeN(psys->child);
- psys->child = NULL;
- psys->totchild = 0;
- }
-
- free_child_path_cache(psys);
-}
-void psys_free_particles(ParticleSystem *psys)
-{
- PARTICLE_P;
-
- if (psys->particles) {
- /* Even though psys->part should never be NULL, this can happen as an exception during deletion.
- * See ID_REMAP_SKIP/FORCE/FLAG_NEVER_NULL_USAGE in BKE_library_remap. */
- if (psys->part && psys->part->type == PART_HAIR) {
- LOOP_PARTICLES {
- if (pa->hair)
- MEM_freeN(pa->hair);
- }
- }
-
- if (psys->particles->keys)
- MEM_freeN(psys->particles->keys);
-
- if (psys->particles->boid)
- MEM_freeN(psys->particles->boid);
-
- MEM_freeN(psys->particles);
- psys->particles = NULL;
- psys->totpart = 0;
- }
-}
-void psys_free_pdd(ParticleSystem *psys)
-{
- if (psys->pdd) {
- if (psys->pdd->cdata)
- MEM_freeN(psys->pdd->cdata);
- psys->pdd->cdata = NULL;
-
- if (psys->pdd->vdata)
- MEM_freeN(psys->pdd->vdata);
- psys->pdd->vdata = NULL;
-
- if (psys->pdd->ndata)
- MEM_freeN(psys->pdd->ndata);
- psys->pdd->ndata = NULL;
-
- if (psys->pdd->vedata)
- MEM_freeN(psys->pdd->vedata);
- psys->pdd->vedata = NULL;
-
- psys->pdd->totpoint = 0;
- psys->pdd->tot_vec_size = 0;
- }
-}
-/* free everything */
-void psys_free(Object *ob, ParticleSystem *psys)
-{
- if (psys) {
- int nr = 0;
- ParticleSystem *tpsys;
-
- psys_free_path_cache(psys, NULL);
-
- free_hair(ob, psys, 1);
-
- psys_free_particles(psys);
-
- if (psys->edit && psys->free_edit)
- psys->free_edit(psys->edit);
-
- if (psys->child) {
- MEM_freeN(psys->child);
- psys->child = NULL;
- psys->totchild = 0;
- }
-
- /* check if we are last non-visible particle system */
- for (tpsys = ob->particlesystem.first; tpsys; tpsys = tpsys->next) {
- if (tpsys->part) {
- if (ELEM(tpsys->part->ren_as, PART_DRAW_OB, PART_DRAW_GR)) {
- nr++;
- break;
- }
- }
- }
- /* clear do-not-draw-flag */
- if (!nr)
- ob->transflag &= ~OB_DUPLIPARTS;
-
- psys->part = NULL;
-
- BKE_ptcache_free_list(&psys->ptcaches);
- psys->pointcache = NULL;
-
- BLI_freelistN(&psys->targets);
-
- BLI_bvhtree_free(psys->bvhtree);
- BLI_kdtree_free(psys->tree);
-
- if (psys->fluid_springs)
- MEM_freeN(psys->fluid_springs);
-
- pdEndEffectors(&psys->effectors);
-
- if (psys->pdd) {
- psys_free_pdd(psys);
- MEM_freeN(psys->pdd);
- }
-
- MEM_freeN(psys);
- }
-}
-
-/************************************************/
-/* Rendering */
-/************************************************/
-/* these functions move away particle data and bring it back after
- * rendering, to make different render settings possible without
- * removing the previous data. this should be solved properly once */
-
-void psys_render_set(Object *ob, ParticleSystem *psys, float viewmat[4][4], float winmat[4][4], int winx, int winy, int timeoffset)
-{
- ParticleRenderData *data;
- ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys);
-
- if (psys->renderdata)
- return;
-
- data = MEM_callocN(sizeof(ParticleRenderData), "ParticleRenderData");
-
- data->child = psys->child;
- data->totchild = psys->totchild;
- data->pathcache = psys->pathcache;
- data->pathcachebufs.first = psys->pathcachebufs.first;
- data->pathcachebufs.last = psys->pathcachebufs.last;
- data->totcached = psys->totcached;
- data->childcache = psys->childcache;
- data->childcachebufs.first = psys->childcachebufs.first;
- data->childcachebufs.last = psys->childcachebufs.last;
- data->totchildcache = psys->totchildcache;
-
- if (psmd->dm_final)
- data->dm = CDDM_copy(psmd->dm_final);
- data->totdmvert = psmd->totdmvert;
- data->totdmedge = psmd->totdmedge;
- data->totdmface = psmd->totdmface;
-
- psys->child = NULL;
- psys->pathcache = NULL;
- psys->childcache = NULL;
- psys->totchild = psys->totcached = psys->totchildcache = 0;
- BLI_listbase_clear(&psys->pathcachebufs);
- BLI_listbase_clear(&psys->childcachebufs);
-
- copy_m4_m4(data->winmat, winmat);
- mul_m4_m4m4(data->viewmat, viewmat, ob->obmat);
- mul_m4_m4m4(data->mat, winmat, data->viewmat);
- data->winx = winx;
- data->winy = winy;
-
- data->timeoffset = timeoffset;
-
- psys->renderdata = data;
-
- /* Hair can and has to be recalculated if everything isn't displayed. */
- if (psys->part->disp != 100 && psys->part->type == PART_HAIR)
- psys->recalc |= PSYS_RECALC_RESET;
-}
-
-void psys_render_restore(Object *ob, ParticleSystem *psys)
-{
- ParticleRenderData *data;
- ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys);
- float render_disp = psys_get_current_display_percentage(psys);
- float disp;
-
- data = psys->renderdata;
- if (!data)
- return;
-
- if (data->elems)
- MEM_freeN(data->elems);
-
- if (psmd->dm_final) {
- psmd->dm_final->needsFree = 1;
- psmd->dm_final->release(psmd->dm_final);
- }
- if (psmd->dm_deformed) {
- psmd->dm_deformed->needsFree = 1;
- psmd->dm_deformed->release(psmd->dm_deformed);
- psmd->dm_deformed = NULL;
- }
-
- psys_free_path_cache(psys, NULL);
-
- if (psys->child) {
- MEM_freeN(psys->child);
- psys->child = 0;
- psys->totchild = 0;
- }
-
- psys->child = data->child;
- psys->totchild = data->totchild;
- psys->pathcache = data->pathcache;
- psys->pathcachebufs.first = data->pathcachebufs.first;
- psys->pathcachebufs.last = data->pathcachebufs.last;
- psys->totcached = data->totcached;
- psys->childcache = data->childcache;
- psys->childcachebufs.first = data->childcachebufs.first;
- psys->childcachebufs.last = data->childcachebufs.last;
- psys->totchildcache = data->totchildcache;
-
- psmd->dm_final = data->dm;
- psmd->totdmvert = data->totdmvert;
- psmd->totdmedge = data->totdmedge;
- psmd->totdmface = data->totdmface;
- psmd->flag &= ~eParticleSystemFlag_psys_updated;
-
- if (psmd->dm_final) {
- if (!psmd->dm_final->deformedOnly) {
- if (ob->derivedDeform) {
- psmd->dm_deformed = CDDM_copy(ob->derivedDeform);
- }
- else {
- psmd->dm_deformed = CDDM_from_mesh((Mesh *)ob->data);
- }
- DM_ensure_tessface(psmd->dm_deformed);
- }
- psys_calc_dmcache(ob, psmd->dm_final, psmd->dm_deformed, psys);
- }
-
- MEM_freeN(data);
- psys->renderdata = NULL;
-
- /* restore particle display percentage */
- disp = psys_get_current_display_percentage(psys);
-
- if (disp != render_disp) {
- /* Hair can and has to be recalculated if everything isn't displayed. */
- if (psys->part->type == PART_HAIR) {
- psys->recalc |= PSYS_RECALC_RESET;
- }
- else {
- PARTICLE_P;
-
- LOOP_PARTICLES {
- if (psys_frand(psys, p) > disp)
- pa->flag |= PARS_NO_DISP;
- else
- pa->flag &= ~PARS_NO_DISP;
- }
- }
- }
-}
-
-bool psys_render_simplify_params(ParticleSystem *psys, ChildParticle *cpa, float *params)
-{
- ParticleRenderData *data;
- ParticleRenderElem *elem;
- float x, w, scale, alpha, lambda, t, scalemin, scalemax;
- int b;
-
- if (!(psys->renderdata && (psys->part->simplify_flag & PART_SIMPLIFY_ENABLE)))
- return false;
-
- data = psys->renderdata;
- if (!data->do_simplify)
- return false;
- b = (data->index_mf_to_mpoly) ? DM_origindex_mface_mpoly(data->index_mf_to_mpoly, data->index_mp_to_orig, cpa->num) : cpa->num;
- if (b == ORIGINDEX_NONE) {
- return false;
- }
-
- elem = &data->elems[b];
-
- lambda = elem->lambda;
- t = elem->t;
- scalemin = elem->scalemin;
- scalemax = elem->scalemax;
-
- if (!elem->reduce) {
- scale = scalemin;
- alpha = 1.0f;
- }
- else {
- x = (elem->curchild + 0.5f) / elem->totchild;
- if (x < lambda - t) {
- scale = scalemax;
- alpha = 1.0f;
- }
- else if (x >= lambda + t) {
- scale = scalemin;
- alpha = 0.0f;
- }
- else {
- w = (lambda + t - x) / (2.0f * t);
- scale = scalemin + (scalemax - scalemin) * w;
- alpha = w;
- }
- }
-
- params[0] = scale;
- params[1] = alpha;
-
- elem->curchild++;
-
- return 1;
-}
-
-/************************************************/
-/* Interpolation */
-/************************************************/
-static float interpolate_particle_value(float v1, float v2, float v3, float v4, const float w[4], int four)
-{
- float value;
-
- value = w[0] * v1 + w[1] * v2 + w[2] * v3;
- if (four)
- value += w[3] * v4;
-
- CLAMP(value, 0.f, 1.f);
-
- return value;
-}
-
-void psys_interpolate_particle(short type, ParticleKey keys[4], float dt, ParticleKey *result, bool velocity)
-{
- float t[4];
-
- if (type < 0) {
- interp_cubic_v3(result->co, result->vel, keys[1].co, keys[1].vel, keys[2].co, keys[2].vel, dt);
- }
- else {
- key_curve_position_weights(dt, t, type);
-
- interp_v3_v3v3v3v3(result->co, keys[0].co, keys[1].co, keys[2].co, keys[3].co, t);
-
- if (velocity) {
- float temp[3];
-
- if (dt > 0.999f) {
- key_curve_position_weights(dt - 0.001f, t, type);
- interp_v3_v3v3v3v3(temp, keys[0].co, keys[1].co, keys[2].co, keys[3].co, t);
- sub_v3_v3v3(result->vel, result->co, temp);
- }
- else {
- key_curve_position_weights(dt + 0.001f, t, type);
- interp_v3_v3v3v3v3(temp, keys[0].co, keys[1].co, keys[2].co, keys[3].co, t);
- sub_v3_v3v3(result->vel, temp, result->co);
- }
- }
- }
-}
-
-
-typedef struct ParticleInterpolationData {
- HairKey *hkey[2];
-
- DerivedMesh *dm;
- MVert *mvert[2];
-
- int keyed;
- ParticleKey *kkey[2];
-
- PointCache *cache;
- PTCacheMem *pm;
-
- PTCacheEditPoint *epoint;
- PTCacheEditKey *ekey[2];
-
- float birthtime, dietime;
- int bspline;
-} ParticleInterpolationData;
-/* Assumes pointcache->mem_cache exists, so for disk cached particles call psys_make_temp_pointcache() before use */
-/* It uses ParticleInterpolationData->pm to store the current memory cache frame so it's thread safe. */
-static void get_pointcache_keys_for_time(Object *UNUSED(ob), PointCache *cache, PTCacheMem **cur, int index, float t, ParticleKey *key1, ParticleKey *key2)
-{
- static PTCacheMem *pm = NULL;
- int index1, index2;
-
- if (index < 0) { /* initialize */
- *cur = cache->mem_cache.first;
-
- if (*cur)
- *cur = (*cur)->next;
- }
- else {
- if (*cur) {
- while (*cur && (*cur)->next && (float)(*cur)->frame < t)
- *cur = (*cur)->next;
-
- pm = *cur;
-
- index2 = BKE_ptcache_mem_index_find(pm, index);
- index1 = BKE_ptcache_mem_index_find(pm->prev, index);
- if (index2 < 0) {
- return;
- }
-
- BKE_ptcache_make_particle_key(key2, index2, pm->data, (float)pm->frame);
- if (index1 < 0)
- copy_particle_key(key1, key2, 1);
- else
- BKE_ptcache_make_particle_key(key1, index1, pm->prev->data, (float)pm->prev->frame);
- }
- else if (cache->mem_cache.first) {
- pm = cache->mem_cache.first;
- index2 = BKE_ptcache_mem_index_find(pm, index);
- if (index2 < 0) {
- return;
- }
- BKE_ptcache_make_particle_key(key2, index2, pm->data, (float)pm->frame);
- copy_particle_key(key1, key2, 1);
- }
- }
-}
-static int get_pointcache_times_for_particle(PointCache *cache, int index, float *start, float *end)
-{
- PTCacheMem *pm;
- int ret = 0;
-
- for (pm = cache->mem_cache.first; pm; pm = pm->next) {
- if (BKE_ptcache_mem_index_find(pm, index) >= 0) {
- *start = pm->frame;
- ret++;
- break;
- }
- }
-
- for (pm = cache->mem_cache.last; pm; pm = pm->prev) {
- if (BKE_ptcache_mem_index_find(pm, index) >= 0) {
- *end = pm->frame;
- ret++;
- break;
- }
- }
-
- return ret == 2;
-}
-
-float psys_get_dietime_from_cache(PointCache *cache, int index)
-{
- PTCacheMem *pm;
- int dietime = 10000000; /* some max value so that we can default to pa->time+lifetime */
-
- for (pm = cache->mem_cache.last; pm; pm = pm->prev) {
- if (BKE_ptcache_mem_index_find(pm, index) >= 0)
- return (float)pm->frame;
- }
-
- return (float)dietime;
-}
-
-static void init_particle_interpolation(Object *ob, ParticleSystem *psys, ParticleData *pa, ParticleInterpolationData *pind)
-{
-
- if (pind->epoint) {
- PTCacheEditPoint *point = pind->epoint;
-
- pind->ekey[0] = point->keys;
- pind->ekey[1] = point->totkey > 1 ? point->keys + 1 : NULL;
-
- pind->birthtime = *(point->keys->time);
- pind->dietime = *((point->keys + point->totkey - 1)->time);
- }
- else if (pind->keyed) {
- ParticleKey *key = pa->keys;
- pind->kkey[0] = key;
- pind->kkey[1] = pa->totkey > 1 ? key + 1 : NULL;
-
- pind->birthtime = key->time;
- pind->dietime = (key + pa->totkey - 1)->time;
- }
- else if (pind->cache) {
- float start = 0.0f, end = 0.0f;
- get_pointcache_keys_for_time(ob, pind->cache, &pind->pm, -1, 0.0f, NULL, NULL);
- pind->birthtime = pa ? pa->time : pind->cache->startframe;
- pind->dietime = pa ? pa->dietime : pind->cache->endframe;
-
- if (get_pointcache_times_for_particle(pind->cache, pa - psys->particles, &start, &end)) {
- pind->birthtime = MAX2(pind->birthtime, start);
- pind->dietime = MIN2(pind->dietime, end);
- }
- }
- else {
- HairKey *key = pa->hair;
- pind->hkey[0] = key;
- pind->hkey[1] = key + 1;
-
- pind->birthtime = key->time;
- pind->dietime = (key + pa->totkey - 1)->time;
-
- if (pind->dm) {
- pind->mvert[0] = CDDM_get_vert(pind->dm, pa->hair_index);
- pind->mvert[1] = pind->mvert[0] + 1;
- }
- }
-}
-static void edit_to_particle(ParticleKey *key, PTCacheEditKey *ekey)
-{
- copy_v3_v3(key->co, ekey->co);
- if (ekey->vel) {
- copy_v3_v3(key->vel, ekey->vel);
- }
- key->time = *(ekey->time);
-}
-static void hair_to_particle(ParticleKey *key, HairKey *hkey)
-{
- copy_v3_v3(key->co, hkey->co);
- key->time = hkey->time;
-}
-
-static void mvert_to_particle(ParticleKey *key, MVert *mvert, HairKey *hkey)
-{
- copy_v3_v3(key->co, mvert->co);
- key->time = hkey->time;
-}
-
-static void do_particle_interpolation(ParticleSystem *psys, int p, ParticleData *pa, float t, ParticleInterpolationData *pind, ParticleKey *result)
-{
- PTCacheEditPoint *point = pind->epoint;
- ParticleKey keys[4];
- int point_vel = (point && point->keys->vel);
- float real_t, dfra, keytime, invdt = 1.f;
-
- /* billboards wont fill in all of these, so start cleared */
- memset(keys, 0, sizeof(keys));
-
- /* interpret timing and find keys */
- if (point) {
- if (result->time < 0.0f)
- real_t = -result->time;
- else
- real_t = *(pind->ekey[0]->time) + t * (*(pind->ekey[0][point->totkey - 1].time) - *(pind->ekey[0]->time));
-
- while (*(pind->ekey[1]->time) < real_t)
- pind->ekey[1]++;
-
- pind->ekey[0] = pind->ekey[1] - 1;
- }
- else if (pind->keyed) {
- /* we have only one key, so let's use that */
- if (pind->kkey[1] == NULL) {
- copy_particle_key(result, pind->kkey[0], 1);
- return;
- }
-
- if (result->time < 0.0f)
- real_t = -result->time;
- else
- real_t = pind->kkey[0]->time + t * (pind->kkey[0][pa->totkey - 1].time - pind->kkey[0]->time);
-
- if (psys->part->phystype == PART_PHYS_KEYED && psys->flag & PSYS_KEYED_TIMING) {
- ParticleTarget *pt = psys->targets.first;
-
- pt = pt->next;
-
- while (pt && pa->time + pt->time < real_t)
- pt = pt->next;
-
- if (pt) {
- pt = pt->prev;
-
- if (pa->time + pt->time + pt->duration > real_t)
- real_t = pa->time + pt->time;
- }
- else
- real_t = pa->time + ((ParticleTarget *)psys->targets.last)->time;
- }
-
- CLAMP(real_t, pa->time, pa->dietime);
-
- while (pind->kkey[1]->time < real_t)
- pind->kkey[1]++;
-
- pind->kkey[0] = pind->kkey[1] - 1;
- }
- else if (pind->cache) {
- if (result->time < 0.0f) /* flag for time in frames */
- real_t = -result->time;
- else
- real_t = pa->time + t * (pa->dietime - pa->time);
- }
- else {
- if (result->time < 0.0f)
- real_t = -result->time;
- else
- real_t = pind->hkey[0]->time + t * (pind->hkey[0][pa->totkey - 1].time - pind->hkey[0]->time);
-
- while (pind->hkey[1]->time < real_t) {
- pind->hkey[1]++;
- pind->mvert[1]++;
- }
-
- pind->hkey[0] = pind->hkey[1] - 1;
- }
-
- /* set actual interpolation keys */
- if (point) {
- edit_to_particle(keys + 1, pind->ekey[0]);
- edit_to_particle(keys + 2, pind->ekey[1]);
- }
- else if (pind->dm) {
- pind->mvert[0] = pind->mvert[1] - 1;
- mvert_to_particle(keys + 1, pind->mvert[0], pind->hkey[0]);
- mvert_to_particle(keys + 2, pind->mvert[1], pind->hkey[1]);
- }
- else if (pind->keyed) {
- memcpy(keys + 1, pind->kkey[0], sizeof(ParticleKey));
- memcpy(keys + 2, pind->kkey[1], sizeof(ParticleKey));
- }
- else if (pind->cache) {
- get_pointcache_keys_for_time(NULL, pind->cache, &pind->pm, p, real_t, keys + 1, keys + 2);
- }
- else {
- hair_to_particle(keys + 1, pind->hkey[0]);
- hair_to_particle(keys + 2, pind->hkey[1]);
- }
-
- /* set secondary interpolation keys for hair */
- if (!pind->keyed && !pind->cache && !point_vel) {
- if (point) {
- if (pind->ekey[0] != point->keys)
- edit_to_particle(keys, pind->ekey[0] - 1);
- else
- edit_to_particle(keys, pind->ekey[0]);
- }
- else if (pind->dm) {
- if (pind->hkey[0] != pa->hair)
- mvert_to_particle(keys, pind->mvert[0] - 1, pind->hkey[0] - 1);
- else
- mvert_to_particle(keys, pind->mvert[0], pind->hkey[0]);
- }
- else {
- if (pind->hkey[0] != pa->hair)
- hair_to_particle(keys, pind->hkey[0] - 1);
- else
- hair_to_particle(keys, pind->hkey[0]);
- }
-
- if (point) {
- if (pind->ekey[1] != point->keys + point->totkey - 1)
- edit_to_particle(keys + 3, pind->ekey[1] + 1);
- else
- edit_to_particle(keys + 3, pind->ekey[1]);
- }
- else if (pind->dm) {
- if (pind->hkey[1] != pa->hair + pa->totkey - 1)
- mvert_to_particle(keys + 3, pind->mvert[1] + 1, pind->hkey[1] + 1);
- else
- mvert_to_particle(keys + 3, pind->mvert[1], pind->hkey[1]);
- }
- else {
- if (pind->hkey[1] != pa->hair + pa->totkey - 1)
- hair_to_particle(keys + 3, pind->hkey[1] + 1);
- else
- hair_to_particle(keys + 3, pind->hkey[1]);
- }
- }
-
- dfra = keys[2].time - keys[1].time;
- keytime = (real_t - keys[1].time) / dfra;
-
- /* convert velocity to timestep size */
- if (pind->keyed || pind->cache || point_vel) {
- invdt = dfra * 0.04f * (psys ? psys->part->timetweak : 1.f);
- mul_v3_fl(keys[1].vel, invdt);
- mul_v3_fl(keys[2].vel, invdt);
- interp_qt_qtqt(result->rot, keys[1].rot, keys[2].rot, keytime);
- }
-
- /* now we should have in chronologiacl order k1<=k2<=t<=k3<=k4 with keytime between [0, 1]->[k2, k3] (k1 & k4 used for cardinal & bspline interpolation)*/
- psys_interpolate_particle((pind->keyed || pind->cache || point_vel) ? -1 /* signal for cubic interpolation */
- : (pind->bspline ? KEY_BSPLINE : KEY_CARDINAL),
- keys, keytime, result, 1);
-
- /* the velocity needs to be converted back from cubic interpolation */
- if (pind->keyed || pind->cache || point_vel)
- mul_v3_fl(result->vel, 1.f / invdt);
-}
-
-static void interpolate_pathcache(ParticleCacheKey *first, float t, ParticleCacheKey *result)
-{
- int i = 0;
- ParticleCacheKey *cur = first;
-
- /* scale the requested time to fit the entire path even if the path is cut early */
- t *= (first + first->segments)->time;
-
- while (i < first->segments && cur->time < t)
- cur++;
-
- if (cur->time == t)
- *result = *cur;
- else {
- float dt = (t - (cur - 1)->time) / (cur->time - (cur - 1)->time);
- interp_v3_v3v3(result->co, (cur - 1)->co, cur->co, dt);
- interp_v3_v3v3(result->vel, (cur - 1)->vel, cur->vel, dt);
- interp_qt_qtqt(result->rot, (cur - 1)->rot, cur->rot, dt);
- result->time = t;
- }
-
- /* first is actual base rotation, others are incremental from first */
- if (cur == first || cur - 1 == first)
- copy_qt_qt(result->rot, first->rot);
- else
- mul_qt_qtqt(result->rot, first->rot, result->rot);
-}
-
-/************************************************/
-/* Particles on a dm */
-/************************************************/
-/* interpolate a location on a face based on face coordinates */
-void psys_interpolate_face(MVert *mvert, MFace *mface, MTFace *tface, float (*orcodata)[3],
- float w[4], float vec[3], float nor[3], float utan[3], float vtan[3],
- float orco[3], float ornor[3])
-{
- float *v1 = 0, *v2 = 0, *v3 = 0, *v4 = 0;
- float e1[3], e2[3], s1, s2, t1, t2;
- float *uv1, *uv2, *uv3, *uv4;
- float n1[3], n2[3], n3[3], n4[3];
- float tuv[4][2];
- float *o1, *o2, *o3, *o4;
-
- v1 = mvert[mface->v1].co;
- v2 = mvert[mface->v2].co;
- v3 = mvert[mface->v3].co;
-
- normal_short_to_float_v3(n1, mvert[mface->v1].no);
- normal_short_to_float_v3(n2, mvert[mface->v2].no);
- normal_short_to_float_v3(n3, mvert[mface->v3].no);
-
- if (mface->v4) {
- v4 = mvert[mface->v4].co;
- normal_short_to_float_v3(n4, mvert[mface->v4].no);
-
- interp_v3_v3v3v3v3(vec, v1, v2, v3, v4, w);
-
- if (nor) {
- if (mface->flag & ME_SMOOTH)
- interp_v3_v3v3v3v3(nor, n1, n2, n3, n4, w);
- else
- normal_quad_v3(nor, v1, v2, v3, v4);
- }
- }
- else {
- interp_v3_v3v3v3(vec, v1, v2, v3, w);
-
- if (nor) {
- if (mface->flag & ME_SMOOTH)
- interp_v3_v3v3v3(nor, n1, n2, n3, w);
- else
- normal_tri_v3(nor, v1, v2, v3);
- }
- }
-
- /* calculate tangent vectors */
- if (utan && vtan) {
- if (tface) {
- uv1 = tface->uv[0];
- uv2 = tface->uv[1];
- uv3 = tface->uv[2];
- uv4 = tface->uv[3];
- }
- else {
- uv1 = tuv[0]; uv2 = tuv[1]; uv3 = tuv[2]; uv4 = tuv[3];
- map_to_sphere(uv1, uv1 + 1, v1[0], v1[1], v1[2]);
- map_to_sphere(uv2, uv2 + 1, v2[0], v2[1], v2[2]);
- map_to_sphere(uv3, uv3 + 1, v3[0], v3[1], v3[2]);
- if (v4)
- map_to_sphere(uv4, uv4 + 1, v4[0], v4[1], v4[2]);
- }
-
- if (v4) {
- s1 = uv3[0] - uv1[0];
- s2 = uv4[0] - uv1[0];
-
- t1 = uv3[1] - uv1[1];
- t2 = uv4[1] - uv1[1];
-
- sub_v3_v3v3(e1, v3, v1);
- sub_v3_v3v3(e2, v4, v1);
- }
- else {
- s1 = uv2[0] - uv1[0];
- s2 = uv3[0] - uv1[0];
-
- t1 = uv2[1] - uv1[1];
- t2 = uv3[1] - uv1[1];
-
- sub_v3_v3v3(e1, v2, v1);
- sub_v3_v3v3(e2, v3, v1);
- }
-
- vtan[0] = (s1 * e2[0] - s2 * e1[0]);
- vtan[1] = (s1 * e2[1] - s2 * e1[1]);
- vtan[2] = (s1 * e2[2] - s2 * e1[2]);
-
- utan[0] = (t1 * e2[0] - t2 * e1[0]);
- utan[1] = (t1 * e2[1] - t2 * e1[1]);
- utan[2] = (t1 * e2[2] - t2 * e1[2]);
- }
-
- if (orco) {
- if (orcodata) {
- o1 = orcodata[mface->v1];
- o2 = orcodata[mface->v2];
- o3 = orcodata[mface->v3];
-
- if (mface->v4) {
- o4 = orcodata[mface->v4];
-
- interp_v3_v3v3v3v3(orco, o1, o2, o3, o4, w);
-
- if (ornor)
- normal_quad_v3(ornor, o1, o2, o3, o4);
- }
- else {
- interp_v3_v3v3v3(orco, o1, o2, o3, w);
-
- if (ornor)
- normal_tri_v3(ornor, o1, o2, o3);
- }
- }
- else {
- copy_v3_v3(orco, vec);
- if (ornor && nor)
- copy_v3_v3(ornor, nor);
- }
- }
-}
-void psys_interpolate_uvs(const MTFace *tface, int quad, const float w[4], float uvco[2])
-{
- float v10 = tface->uv[0][0];
- float v11 = tface->uv[0][1];
- float v20 = tface->uv[1][0];
- float v21 = tface->uv[1][1];
- float v30 = tface->uv[2][0];
- float v31 = tface->uv[2][1];
- float v40, v41;
-
- if (quad) {
- v40 = tface->uv[3][0];
- v41 = tface->uv[3][1];
-
- uvco[0] = w[0] * v10 + w[1] * v20 + w[2] * v30 + w[3] * v40;
- uvco[1] = w[0] * v11 + w[1] * v21 + w[2] * v31 + w[3] * v41;
- }
- else {
- uvco[0] = w[0] * v10 + w[1] * v20 + w[2] * v30;
- uvco[1] = w[0] * v11 + w[1] * v21 + w[2] * v31;
- }
-}
-
-void psys_interpolate_mcol(const MCol *mcol, int quad, const float w[4], MCol *mc)
-{
- const char *cp1, *cp2, *cp3, *cp4;
- char *cp;
-
- cp = (char *)mc;
- cp1 = (const char *)&mcol[0];
- cp2 = (const char *)&mcol[1];
- cp3 = (const char *)&mcol[2];
-
- if (quad) {
- cp4 = (char *)&mcol[3];
-
- cp[0] = (int)(w[0] * cp1[0] + w[1] * cp2[0] + w[2] * cp3[0] + w[3] * cp4[0]);
- cp[1] = (int)(w[0] * cp1[1] + w[1] * cp2[1] + w[2] * cp3[1] + w[3] * cp4[1]);
- cp[2] = (int)(w[0] * cp1[2] + w[1] * cp2[2] + w[2] * cp3[2] + w[3] * cp4[2]);
- cp[3] = (int)(w[0] * cp1[3] + w[1] * cp2[3] + w[2] * cp3[3] + w[3] * cp4[3]);
- }
- else {
- cp[0] = (int)(w[0] * cp1[0] + w[1] * cp2[0] + w[2] * cp3[0]);
- cp[1] = (int)(w[0] * cp1[1] + w[1] * cp2[1] + w[2] * cp3[1]);
- cp[2] = (int)(w[0] * cp1[2] + w[1] * cp2[2] + w[2] * cp3[2]);
- cp[3] = (int)(w[0] * cp1[3] + w[1] * cp2[3] + w[2] * cp3[3]);
- }
-}
-
-static float psys_interpolate_value_from_verts(DerivedMesh *dm, short from, int index, const float fw[4], const float *values)
-{
- if (values == 0 || index == -1)
- return 0.0;
-
- switch (from) {
- case PART_FROM_VERT:
- return values[index];
- case PART_FROM_FACE:
- case PART_FROM_VOLUME:
- {
- MFace *mf = dm->getTessFaceData(dm, index, CD_MFACE);
- return interpolate_particle_value(values[mf->v1], values[mf->v2], values[mf->v3], values[mf->v4], fw, mf->v4);
- }
-
- }
- return 0.0f;
-}
-
-/* conversion of pa->fw to origspace layer coordinates */
-static void psys_w_to_origspace(const float w[4], float uv[2])
-{
- uv[0] = w[1] + w[2];
- uv[1] = w[2] + w[3];
-}
-
-/* conversion of pa->fw to weights in face from origspace */
-static void psys_origspace_to_w(OrigSpaceFace *osface, int quad, const float w[4], float neww[4])
-{
- float v[4][3], co[3];
-
- v[0][0] = osface->uv[0][0]; v[0][1] = osface->uv[0][1]; v[0][2] = 0.0f;
- v[1][0] = osface->uv[1][0]; v[1][1] = osface->uv[1][1]; v[1][2] = 0.0f;
- v[2][0] = osface->uv[2][0]; v[2][1] = osface->uv[2][1]; v[2][2] = 0.0f;
-
- psys_w_to_origspace(w, co);
- co[2] = 0.0f;
-
- if (quad) {
- v[3][0] = osface->uv[3][0]; v[3][1] = osface->uv[3][1]; v[3][2] = 0.0f;
- interp_weights_poly_v3(neww, v, 4, co);
- }
- else {
- interp_weights_poly_v3(neww, v, 3, co);
- neww[3] = 0.0f;
- }
-}
-
-/**
- * Find the final derived mesh tessface for a particle, from its original tessface index.
- * This is slow and can be optimized but only for many lookups.
- *
- * \param dm_final final DM, it may not have the same topology as original mesh.
- * \param dm_deformed deformed-only DM, it has the exact same topology as original mesh.
- * \param findex_orig the input tessface index.
- * \param fw face weights (position of the particle inside the \a findex_orig tessface).
- * \param poly_nodes may be NULL, otherwise an array of linked list, one for each final DM polygon, containing all
- * its tessfaces indices.
- * \return the DM tessface index.
- */
-int psys_particle_dm_face_lookup(
- DerivedMesh *dm_final, DerivedMesh *dm_deformed,
- int findex_orig, const float fw[4], struct LinkNode **poly_nodes)
-{
- MFace *mtessface_final;
- OrigSpaceFace *osface_final;
- int pindex_orig;
- float uv[2], (*faceuv)[2];
-
- const int *index_mf_to_mpoly_deformed = NULL;
- const int *index_mf_to_mpoly = NULL;
- const int *index_mp_to_orig = NULL;
-
- const int totface_final = dm_final->getNumTessFaces(dm_final);
- const int totface_deformed = dm_deformed ? dm_deformed->getNumTessFaces(dm_deformed) : totface_final;
-
- if (ELEM(0, totface_final, totface_deformed)) {
- return DMCACHE_NOTFOUND;
- }
-
- index_mf_to_mpoly = dm_final->getTessFaceDataArray(dm_final, CD_ORIGINDEX);
- index_mp_to_orig = dm_final->getPolyDataArray(dm_final, CD_ORIGINDEX);
- BLI_assert(index_mf_to_mpoly);
-
- if (dm_deformed) {
- index_mf_to_mpoly_deformed = dm_deformed->getTessFaceDataArray(dm_deformed, CD_ORIGINDEX);
- }
- else {
- BLI_assert(dm_final->deformedOnly);
- index_mf_to_mpoly_deformed = index_mf_to_mpoly;
- }
- BLI_assert(index_mf_to_mpoly_deformed);
-
- pindex_orig = index_mf_to_mpoly_deformed[findex_orig];
-
- if (dm_deformed == NULL) {
- dm_deformed = dm_final;
- }
-
- index_mf_to_mpoly_deformed = NULL;
-
- mtessface_final = dm_final->getTessFaceArray(dm_final);
- osface_final = dm_final->getTessFaceDataArray(dm_final, CD_ORIGSPACE);
-
- if (osface_final == NULL) {
- /* Assume we don't need osface_final data, and we get a direct 1-1 mapping... */
- if (findex_orig < totface_final) {
- //printf("\tNO CD_ORIGSPACE, assuming not needed\n");
- return findex_orig;
- }
- else {
- printf("\tNO CD_ORIGSPACE, error out of range\n");
- return DMCACHE_NOTFOUND;
- }
- }
- else if (findex_orig >= dm_deformed->getNumTessFaces(dm_deformed)) {
- return DMCACHE_NOTFOUND; /* index not in the original mesh */
- }
-
- psys_w_to_origspace(fw, uv);
-
- if (poly_nodes) {
- /* we can have a restricted linked list of faces to check, faster! */
- LinkNode *tessface_node = poly_nodes[pindex_orig];
-
- for (; tessface_node; tessface_node = tessface_node->next) {
- int findex_dst = GET_INT_FROM_POINTER(tessface_node->link);
- faceuv = osface_final[findex_dst].uv;
-
- /* check that this intersects - Its possible this misses :/ -
- * could also check its not between */
- if (mtessface_final[findex_dst].v4) {
- if (isect_point_quad_v2(uv, faceuv[0], faceuv[1], faceuv[2], faceuv[3])) {
- return findex_dst;
- }
- }
- else if (isect_point_tri_v2(uv, faceuv[0], faceuv[1], faceuv[2])) {
- return findex_dst;
- }
- }
- }
- else { /* if we have no node, try every face */
- for (int findex_dst = 0; findex_dst < totface_final; findex_dst++) {
- /* If current tessface from 'final' DM and orig tessface (given by index) map to the same orig poly... */
- if (DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, findex_dst) == pindex_orig) {
- faceuv = osface_final[findex_dst].uv;
-
- /* check that this intersects - Its possible this misses :/ -
- * could also check its not between */
- if (mtessface_final[findex_dst].v4) {
- if (isect_point_quad_v2(uv, faceuv[0], faceuv[1], faceuv[2], faceuv[3])) {
- return findex_dst;
- }
- }
- else if (isect_point_tri_v2(uv, faceuv[0], faceuv[1], faceuv[2])) {
- return findex_dst;
- }
- }
- }
- }
-
- return DMCACHE_NOTFOUND;
-}
-
-static int psys_map_index_on_dm(DerivedMesh *dm, int from, int index, int index_dmcache, const float fw[4], float UNUSED(foffset), int *mapindex, float mapfw[4])
-{
- if (index < 0)
- return 0;
-
- if (dm->deformedOnly || index_dmcache == DMCACHE_ISCHILD) {
- /* for meshes that are either only deformed or for child particles, the
- * index and fw do not require any mapping, so we can directly use it */
- if (from == PART_FROM_VERT) {
- if (index >= dm->getNumVerts(dm))
- return 0;
-
- *mapindex = index;
- }
- else { /* FROM_FACE/FROM_VOLUME */
- if (index >= dm->getNumTessFaces(dm))
- return 0;
-
- *mapindex = index;
- copy_v4_v4(mapfw, fw);
- }
- }
- else {
- /* for other meshes that have been modified, we try to map the particle
- * to their new location, which means a different index, and for faces
- * also a new face interpolation weights */
- if (from == PART_FROM_VERT) {
- if (index_dmcache == DMCACHE_NOTFOUND || index_dmcache > dm->getNumVerts(dm))
- return 0;
-
- *mapindex = index_dmcache;
- }
- else { /* FROM_FACE/FROM_VOLUME */
- /* find a face on the derived mesh that uses this face */
- MFace *mface;
- OrigSpaceFace *osface;
- int i;
-
- i = index_dmcache;
-
- if (i == DMCACHE_NOTFOUND || i >= dm->getNumTessFaces(dm))
- return 0;
-
- *mapindex = i;
-
- /* modify the original weights to become
- * weights for the derived mesh face */
- osface = dm->getTessFaceDataArray(dm, CD_ORIGSPACE);
- mface = dm->getTessFaceData(dm, i, CD_MFACE);
-
- if (osface == NULL)
- mapfw[0] = mapfw[1] = mapfw[2] = mapfw[3] = 0.0f;
- else
- psys_origspace_to_w(&osface[i], mface->v4, fw, mapfw);
- }
- }
-
- return 1;
-}
-
-/* interprets particle data to get a point on a mesh in object space */
-void psys_particle_on_dm(DerivedMesh *dm_final, int from, int index, int index_dmcache,
- const float fw[4], float foffset, float vec[3], float nor[3], float utan[3], float vtan[3],
- float orco[3], float ornor[3])
-{
- float tmpnor[3], mapfw[4];
- float (*orcodata)[3];
- int mapindex;
-
- if (!psys_map_index_on_dm(dm_final, from, index, index_dmcache, fw, foffset, &mapindex, mapfw)) {
- if (vec) { vec[0] = vec[1] = vec[2] = 0.0; }
- if (nor) { nor[0] = nor[1] = 0.0; nor[2] = 1.0; }
- if (orco) { orco[0] = orco[1] = orco[2] = 0.0; }
- if (ornor) { ornor[0] = ornor[1] = 0.0; ornor[2] = 1.0; }
- if (utan) { utan[0] = utan[1] = utan[2] = 0.0; }
- if (vtan) { vtan[0] = vtan[1] = vtan[2] = 0.0; }
-
- return;
- }
-
- orcodata = dm_final->getVertDataArray(dm_final, CD_ORCO);
-
- if (from == PART_FROM_VERT) {
- dm_final->getVertCo(dm_final, mapindex, vec);
-
- if (nor) {
- dm_final->getVertNo(dm_final, mapindex, nor);
- normalize_v3(nor);
- }
-
- if (orco) {
- if (orcodata) {
- copy_v3_v3(orco, orcodata[mapindex]);
- }
- else {
- copy_v3_v3(orco, vec);
- }
- }
-
- if (ornor) {
- dm_final->getVertNo(dm_final, mapindex, ornor);
- normalize_v3(ornor);
- }
-
- if (utan && vtan) {
- utan[0] = utan[1] = utan[2] = 0.0f;
- vtan[0] = vtan[1] = vtan[2] = 0.0f;
- }
- }
- else { /* PART_FROM_FACE / PART_FROM_VOLUME */
- MFace *mface;
- MTFace *mtface;
- MVert *mvert;
-
- mface = dm_final->getTessFaceData(dm_final, mapindex, CD_MFACE);
- mvert = dm_final->getVertDataArray(dm_final, CD_MVERT);
- mtface = CustomData_get_layer(&dm_final->faceData, CD_MTFACE);
-
- if (mtface)
- mtface += mapindex;
-
- if (from == PART_FROM_VOLUME) {
- psys_interpolate_face(mvert, mface, mtface, orcodata, mapfw, vec, tmpnor, utan, vtan, orco, ornor);
- if (nor)
- copy_v3_v3(nor, tmpnor);
-
- normalize_v3(tmpnor); /* XXX Why not normalize tmpnor before copying it into nor??? -- mont29 */
- mul_v3_fl(tmpnor, -foffset);
- add_v3_v3(vec, tmpnor);
- }
- else
- psys_interpolate_face(mvert, mface, mtface, orcodata, mapfw, vec, nor, utan, vtan, orco, ornor);
- }
-}
-
-float psys_particle_value_from_verts(DerivedMesh *dm, short from, ParticleData *pa, float *values)
-{
- float mapfw[4];
- int mapindex;
-
- if (!psys_map_index_on_dm(dm, from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, &mapindex, mapfw))
- return 0.0f;
-
- return psys_interpolate_value_from_verts(dm, from, mapindex, mapfw, values);
-}
-
-ParticleSystemModifierData *psys_get_modifier(Object *ob, ParticleSystem *psys)
-{
- ModifierData *md;
- ParticleSystemModifierData *psmd;
-
- for (md = ob->modifiers.first; md; md = md->next) {
- if (md->type == eModifierType_ParticleSystem) {
- psmd = (ParticleSystemModifierData *) md;
- if (psmd->psys == psys) {
- return psmd;
- }
- }
- }
- return NULL;
-}
-/************************************************/
-/* Particles on a shape */
-/************************************************/
-/* ready for future use */
-static void psys_particle_on_shape(int UNUSED(distr), int UNUSED(index),
- float *UNUSED(fuv), float vec[3], float nor[3], float utan[3], float vtan[3],
- float orco[3], float ornor[3])
-{
- /* TODO */
- float zerovec[3] = {0.0f, 0.0f, 0.0f};
- if (vec) {
- copy_v3_v3(vec, zerovec);
- }
- if (nor) {
- copy_v3_v3(nor, zerovec);
- }
- if (utan) {
- copy_v3_v3(utan, zerovec);
- }
- if (vtan) {
- copy_v3_v3(vtan, zerovec);
- }
- if (orco) {
- copy_v3_v3(orco, zerovec);
- }
- if (ornor) {
- copy_v3_v3(ornor, zerovec);
- }
-}
-/************************************************/
-/* Particles on emitter */
-/************************************************/
-
-CustomDataMask psys_emitter_customdata_mask(ParticleSystem *psys)
-{
- CustomDataMask dataMask = 0;
- MTex *mtex;
- int i;
-
- if (!psys->part)
- return 0;
-
- for (i = 0; i < MAX_MTEX; i++) {
- mtex = psys->part->mtex[i];
- if (mtex && mtex->mapto && (mtex->texco & TEXCO_UV))
- dataMask |= CD_MASK_MTFACE;
- }
-
- if (psys->part->tanfac != 0.0f)
- dataMask |= CD_MASK_MTFACE;
-
- /* ask for vertexgroups if we need them */
- for (i = 0; i < PSYS_TOT_VG; i++) {
- if (psys->vgroup[i]) {
- dataMask |= CD_MASK_MDEFORMVERT;
- break;
- }
- }
-
- /* particles only need this if they are after a non deform modifier, and
- * the modifier stack will only create them in that case. */
- dataMask |= CD_MASK_ORIGSPACE_MLOOP | CD_MASK_ORIGINDEX;
-
- dataMask |= CD_MASK_ORCO;
-
- return dataMask;
-}
-
-void psys_particle_on_emitter(ParticleSystemModifierData *psmd, int from, int index, int index_dmcache,
- float fuv[4], float foffset, float vec[3], float nor[3], float utan[3], float vtan[3],
- float orco[3], float ornor[3])
-{
- if (psmd && psmd->dm_final) {
- if (psmd->psys->part->distr == PART_DISTR_GRID && psmd->psys->part->from != PART_FROM_VERT) {
- if (vec)
- copy_v3_v3(vec, fuv);
-
- if (orco)
- copy_v3_v3(orco, fuv);
- return;
- }
- /* we cant use the num_dmcache */
- psys_particle_on_dm(psmd->dm_final, from, index, index_dmcache, fuv, foffset, vec, nor, utan, vtan, orco, ornor);
- }
- else
- psys_particle_on_shape(from, index, fuv, vec, nor, utan, vtan, orco, ornor);
-
-}
-/************************************************/
-/* Path Cache */
-/************************************************/
-
-extern void do_kink(ParticleKey *state, const float par_co[3], const float par_vel[3], const float par_rot[4], float time, float freq, float shape, float amplitude, float flat,
- short type, short axis, float obmat[4][4], int smooth_start);
-extern float do_clump(ParticleKey *state, const float par_co[3], float time, const float orco_offset[3], float clumpfac, float clumppow, float pa_clump,
- bool use_clump_noise, float clump_noise_size, CurveMapping *clumpcurve);
-
-void precalc_guides(ParticleSimulationData *sim, ListBase *effectors)
-{
- EffectedPoint point;
- ParticleKey state;
- EffectorData efd;
- EffectorCache *eff;
- ParticleSystem *psys = sim->psys;
- EffectorWeights *weights = sim->psys->part->effector_weights;
- GuideEffectorData *data;
- PARTICLE_P;
-
- if (!effectors)
- return;
-
- LOOP_PARTICLES {
- psys_particle_on_emitter(sim->psmd, sim->psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, state.co, 0, 0, 0, 0, 0);
-
- mul_m4_v3(sim->ob->obmat, state.co);
- mul_mat3_m4_v3(sim->ob->obmat, state.vel);
-
- pd_point_from_particle(sim, pa, &state, &point);
-
- for (eff = effectors->first; eff; eff = eff->next) {
- if (eff->pd->forcefield != PFIELD_GUIDE)
- continue;
-
- if (!eff->guide_data)
- eff->guide_data = MEM_callocN(sizeof(GuideEffectorData) * psys->totpart, "GuideEffectorData");
-
- data = eff->guide_data + p;
-
- sub_v3_v3v3(efd.vec_to_point, state.co, eff->guide_loc);
- copy_v3_v3(efd.nor, eff->guide_dir);
- efd.distance = len_v3(efd.vec_to_point);
-
- copy_v3_v3(data->vec_to_point, efd.vec_to_point);
- data->strength = effector_falloff(eff, &efd, &point, weights);
- }
- }
-}
-
-int do_guides(ParticleSettings *part, ListBase *effectors, ParticleKey *state, int index, float time)
-{
- CurveMapping *clumpcurve = (part->child_flag & PART_CHILD_USE_CLUMP_CURVE) ? part->clumpcurve : NULL;
- CurveMapping *roughcurve = (part->child_flag & PART_CHILD_USE_ROUGH_CURVE) ? part->roughcurve : NULL;
- EffectorCache *eff;
- PartDeflect *pd;
- Curve *cu;
- GuideEffectorData *data;
-
- float effect[3] = {0.0f, 0.0f, 0.0f}, veffect[3] = {0.0f, 0.0f, 0.0f};
- float guidevec[4], guidedir[3], rot2[4], temp[3];
- float guidetime, radius, weight, angle, totstrength = 0.0f;
- float vec_to_point[3];
-
- if (effectors) for (eff = effectors->first; eff; eff = eff->next) {
- pd = eff->pd;
-
- if (pd->forcefield != PFIELD_GUIDE)
- continue;
-
- data = eff->guide_data + index;
-
- if (data->strength <= 0.0f)
- continue;
-
- guidetime = time / (1.0f - pd->free_end);
-
- if (guidetime > 1.0f)
- continue;
-
- cu = (Curve *)eff->ob->data;
-
- if (pd->flag & PFIELD_GUIDE_PATH_ADD) {
- if (where_on_path(eff->ob, data->strength * guidetime, guidevec, guidedir, NULL, &radius, &weight) == 0)
- return 0;
- }
- else {
- if (where_on_path(eff->ob, guidetime, guidevec, guidedir, NULL, &radius, &weight) == 0)
- return 0;
- }
-
- mul_m4_v3(eff->ob->obmat, guidevec);
- mul_mat3_m4_v3(eff->ob->obmat, guidedir);
-
- normalize_v3(guidedir);
-
- copy_v3_v3(vec_to_point, data->vec_to_point);
-
- if (guidetime != 0.0f) {
- /* curve direction */
- cross_v3_v3v3(temp, eff->guide_dir, guidedir);
- angle = dot_v3v3(eff->guide_dir, guidedir) / (len_v3(eff->guide_dir));
- angle = saacos(angle);
- axis_angle_to_quat(rot2, temp, angle);
- mul_qt_v3(rot2, vec_to_point);
-
- /* curve tilt */
- axis_angle_to_quat(rot2, guidedir, guidevec[3] - eff->guide_loc[3]);
- mul_qt_v3(rot2, vec_to_point);
- }
-
- /* curve taper */
- if (cu->taperobj)
- mul_v3_fl(vec_to_point, BKE_displist_calc_taper(eff->scene, cu->taperobj, (int)(data->strength * guidetime * 100.0f), 100));
-
- else { /* curve size*/
- if (cu->flag & CU_PATH_RADIUS) {
- mul_v3_fl(vec_to_point, radius);
- }
- }
-
- if (clumpcurve)
- curvemapping_changed_all(clumpcurve);
- if (roughcurve)
- curvemapping_changed_all(roughcurve);
-
- {
- ParticleKey key;
- float par_co[3] = {0.0f, 0.0f, 0.0f};
- float par_vel[3] = {0.0f, 0.0f, 0.0f};
- float par_rot[4] = {1.0f, 0.0f, 0.0f, 0.0f};
- float orco_offset[3] = {0.0f, 0.0f, 0.0f};
-
- copy_v3_v3(key.co, vec_to_point);
- do_kink(&key, par_co, par_vel, par_rot, guidetime, pd->kink_freq, pd->kink_shape, pd->kink_amp, 0.f, pd->kink, pd->kink_axis, 0, 0);
- do_clump(&key, par_co, guidetime, orco_offset, pd->clump_fac, pd->clump_pow, 1.0f,
- part->child_flag & PART_CHILD_USE_CLUMP_NOISE, part->clump_noise_size, clumpcurve);
- copy_v3_v3(vec_to_point, key.co);
- }
-
- add_v3_v3(vec_to_point, guidevec);
-
- //sub_v3_v3v3(pa_loc, pa_loc, pa_zero);
- madd_v3_v3fl(effect, vec_to_point, data->strength);
- madd_v3_v3fl(veffect, guidedir, data->strength);
- totstrength += data->strength;
-
- if (pd->flag & PFIELD_GUIDE_PATH_WEIGHT)
- totstrength *= weight;
- }
-
- if (totstrength != 0.0f) {
- if (totstrength > 1.0f)
- mul_v3_fl(effect, 1.0f / totstrength);
- CLAMP(totstrength, 0.0f, 1.0f);
- //add_v3_v3(effect, pa_zero);
- interp_v3_v3v3(state->co, state->co, effect, totstrength);
-
- normalize_v3(veffect);
- mul_v3_fl(veffect, len_v3(state->vel));
- copy_v3_v3(state->vel, veffect);
- return 1;
- }
- return 0;
-}
-
-static void do_path_effectors(ParticleSimulationData *sim, int i, ParticleCacheKey *ca, int k, int steps, float *UNUSED(rootco), float effector, float UNUSED(dfra), float UNUSED(cfra), float *length, float *vec)
-{
- float force[3] = {0.0f, 0.0f, 0.0f};
- ParticleKey eff_key;
- EffectedPoint epoint;
-
- /* Don't apply effectors for dynamic hair, otherwise the effectors don't get applied twice. */
- if (sim->psys->flag & PSYS_HAIR_DYNAMICS)
- return;
-
- copy_v3_v3(eff_key.co, (ca - 1)->co);
- copy_v3_v3(eff_key.vel, (ca - 1)->vel);
- copy_qt_qt(eff_key.rot, (ca - 1)->rot);
-
- pd_point_from_particle(sim, sim->psys->particles + i, &eff_key, &epoint);
- pdDoEffectors(sim->psys->effectors, sim->colliders, sim->psys->part->effector_weights, &epoint, force, NULL);
-
- mul_v3_fl(force, effector * powf((float)k / (float)steps, 100.0f * sim->psys->part->eff_hair) / (float)steps);
-
- add_v3_v3(force, vec);
-
- normalize_v3(force);
-
- if (k < steps)
- sub_v3_v3v3(vec, (ca + 1)->co, ca->co);
-
- madd_v3_v3v3fl(ca->co, (ca - 1)->co, force, *length);
-
- if (k < steps)
- *length = len_v3(vec);
-}
-static void offset_child(ChildParticle *cpa, ParticleKey *par, float *par_rot, ParticleKey *child, float flat, float radius)
-{
- copy_v3_v3(child->co, cpa->fuv);
- mul_v3_fl(child->co, radius);
-
- child->co[0] *= flat;
-
- copy_v3_v3(child->vel, par->vel);
-
- if (par_rot) {
- mul_qt_v3(par_rot, child->co);
- copy_qt_qt(child->rot, par_rot);
- }
- else
- unit_qt(child->rot);
-
- add_v3_v3(child->co, par->co);
-}
-float *psys_cache_vgroup(DerivedMesh *dm, ParticleSystem *psys, int vgroup)
-{
- float *vg = 0;
-
- if (vgroup < 0) {
- /* hair dynamics pinning vgroup */
-
- }
- else if (psys->vgroup[vgroup]) {
- MDeformVert *dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
- if (dvert) {
- int totvert = dm->getNumVerts(dm), i;
- vg = MEM_callocN(sizeof(float) * totvert, "vg_cache");
- if (psys->vg_neg & (1 << vgroup)) {
- for (i = 0; i < totvert; i++)
- vg[i] = 1.0f - defvert_find_weight(&dvert[i], psys->vgroup[vgroup] - 1);
- }
- else {
- for (i = 0; i < totvert; i++)
- vg[i] = defvert_find_weight(&dvert[i], psys->vgroup[vgroup] - 1);
- }
- }
- }
- return vg;
-}
-void psys_find_parents(ParticleSimulationData *sim, const bool use_render_params)
-{
- ParticleSystem *psys = sim->psys;
- ParticleSettings *part = sim->psys->part;
- KDTree *tree;
- ChildParticle *cpa;
- ParticleTexture ptex;
- int p, totparent, totchild = sim->psys->totchild;
- float co[3], orco[3];
- int from = PART_FROM_FACE;
- totparent = (int)(totchild * part->parents * 0.3f);
-
- if ((sim->psys->renderdata || use_render_params) && part->child_nbr && part->ren_child_nbr)
- totparent *= (float)part->child_nbr / (float)part->ren_child_nbr;
-
- /* hard limit, workaround for it being ignored above */
- if (sim->psys->totpart < totparent) {
- totparent = sim->psys->totpart;
- }
-
- tree = BLI_kdtree_new(totparent);
-
- for (p = 0, cpa = sim->psys->child; p < totparent; p++, cpa++) {
- psys_particle_on_emitter(sim->psmd, from, cpa->num, DMCACHE_ISCHILD, cpa->fuv, cpa->foffset, co, 0, 0, 0, orco, 0);
-
- /* Check if particle doesn't exist because of texture influence. Insert only existing particles into kdtree. */
- get_cpa_texture(sim->psmd->dm_final, psys, part, psys->particles + cpa->pa[0], p, cpa->num, cpa->fuv, orco, &ptex, PAMAP_DENS | PAMAP_CHILD, psys->cfra);
-
- if (ptex.exist >= psys_frand(psys, p + 24)) {
- BLI_kdtree_insert(tree, p, orco);
- }
- }
-
- BLI_kdtree_balance(tree);
-
- for (; p < totchild; p++, cpa++) {
- psys_particle_on_emitter(sim->psmd, from, cpa->num, DMCACHE_ISCHILD, cpa->fuv, cpa->foffset, co, 0, 0, 0, orco, 0);
- cpa->parent = BLI_kdtree_find_nearest(tree, orco, NULL);
- }
-
- BLI_kdtree_free(tree);
-}
-
-static bool psys_thread_context_init_path(
- ParticleThreadContext *ctx, ParticleSimulationData *sim, Scene *scene,
- float cfra, const bool editupdate, const bool use_render_params)
-{
- ParticleSystem *psys = sim->psys;
- ParticleSettings *part = psys->part;
- int totparent = 0, between = 0;
- int segments = 1 << part->draw_step;
- int totchild = psys->totchild;
-
- psys_thread_context_init(ctx, sim);
-
- /*---start figuring out what is actually wanted---*/
- if (psys_in_edit_mode(scene, psys)) {
- ParticleEditSettings *pset = &scene->toolsettings->particle;
-
- if ((psys->renderdata == 0 && use_render_params == 0) && (psys->edit == NULL || pset->flag & PE_DRAW_PART) == 0)
- totchild = 0;
-
- segments = 1 << pset->draw_step;
- }
-
- if (totchild && part->childtype == PART_CHILD_FACES) {
- totparent = (int)(totchild * part->parents * 0.3f);
-
- if ((psys->renderdata || use_render_params) && part->child_nbr && part->ren_child_nbr)
- totparent *= (float)part->child_nbr / (float)part->ren_child_nbr;
-
- /* part->parents could still be 0 so we can't test with totparent */
- between = 1;
- }
-
- if (psys->renderdata || use_render_params)
- segments = 1 << part->ren_step;
- else {
- totchild = (int)((float)totchild * (float)part->disp / 100.0f);
- totparent = MIN2(totparent, totchild);
- }
-
- if (totchild == 0)
- return false;
-
- /* fill context values */
- ctx->between = between;
- ctx->segments = segments;
- if (ELEM(part->kink, PART_KINK_SPIRAL))
- ctx->extra_segments = max_ii(part->kink_extra_steps, 1);
- else
- ctx->extra_segments = 0;
- ctx->totchild = totchild;
- ctx->totparent = totparent;
- ctx->parent_pass = 0;
- ctx->cfra = cfra;
- ctx->editupdate = editupdate;
-
- psys->lattice_deform_data = psys_create_lattice_deform_data(&ctx->sim);
-
- /* cache all relevant vertex groups if they exist */
- ctx->vg_length = psys_cache_vgroup(ctx->dm, psys, PSYS_VG_LENGTH);
- ctx->vg_clump = psys_cache_vgroup(ctx->dm, psys, PSYS_VG_CLUMP);
- ctx->vg_kink = psys_cache_vgroup(ctx->dm, psys, PSYS_VG_KINK);
- ctx->vg_rough1 = psys_cache_vgroup(ctx->dm, psys, PSYS_VG_ROUGH1);
- ctx->vg_rough2 = psys_cache_vgroup(ctx->dm, psys, PSYS_VG_ROUGH2);
- ctx->vg_roughe = psys_cache_vgroup(ctx->dm, psys, PSYS_VG_ROUGHE);
- if (psys->part->flag & PART_CHILD_EFFECT)
- ctx->vg_effector = psys_cache_vgroup(ctx->dm, psys, PSYS_VG_EFFECTOR);
-
- /* prepare curvemapping tables */
- if ((part->child_flag & PART_CHILD_USE_CLUMP_CURVE) && part->clumpcurve) {
- ctx->clumpcurve = curvemapping_copy(part->clumpcurve);
- curvemapping_changed_all(ctx->clumpcurve);
- }
- else {
- ctx->clumpcurve = NULL;
- }
- if ((part->child_flag & PART_CHILD_USE_ROUGH_CURVE) && part->roughcurve) {
- ctx->roughcurve = curvemapping_copy(part->roughcurve);
- curvemapping_changed_all(ctx->roughcurve);
- }
- else {
- ctx->roughcurve = NULL;
- }
-
- return true;
-}
-
-static void psys_task_init_path(ParticleTask *task, ParticleSimulationData *sim)
-{
- /* init random number generator */
- int seed = 31415926 + sim->psys->seed;
-
- task->rng_path = BLI_rng_new(seed);
-}
-
-/* note: this function must be thread safe, except for branching! */
-static void psys_thread_create_path(ParticleTask *task, struct ChildParticle *cpa, ParticleCacheKey *child_keys, int i)
-{
- ParticleThreadContext *ctx = task->ctx;
- Object *ob = ctx->sim.ob;
- ParticleSystem *psys = ctx->sim.psys;
- ParticleSettings *part = psys->part;
- ParticleCacheKey **cache = psys->childcache;
- ParticleCacheKey **pcache = psys_in_edit_mode(ctx->sim.scene, psys) && psys->edit ? psys->edit->pathcache : psys->pathcache;
- ParticleCacheKey *child, *key[4];
- ParticleTexture ptex;
- float *cpa_fuv = 0, *par_rot = 0, rot[4];
- float orco[3], ornor[3], hairmat[4][4], dvec[3], off1[4][3], off2[4][3];
- float eff_length, eff_vec[3], weight[4];
- int k, cpa_num;
- short cpa_from;
-
- if (!pcache)
- return;
-
- if (ctx->between) {
- ParticleData *pa = psys->particles + cpa->pa[0];
- int w, needupdate;
- float foffset, wsum = 0.f;
- float co[3];
- float p_min = part->parting_min;
- float p_max = part->parting_max;
- /* Virtual parents don't work nicely with parting. */
- float p_fac = part->parents > 0.f ? 0.f : part->parting_fac;
-
- if (ctx->editupdate) {
- needupdate = 0;
- w = 0;
- while (w < 4 && cpa->pa[w] >= 0) {
- if (psys->edit->points[cpa->pa[w]].flag & PEP_EDIT_RECALC) {
- needupdate = 1;
- break;
- }
- w++;
- }
-
- if (!needupdate)
- return;
- else
- memset(child_keys, 0, sizeof(*child_keys) * (ctx->segments + 1));
- }
-
- /* get parent paths */
- for (w = 0; w < 4; w++) {
- if (cpa->pa[w] >= 0) {
- key[w] = pcache[cpa->pa[w]];
- weight[w] = cpa->w[w];
- }
- else {
- key[w] = pcache[0];
- weight[w] = 0.f;
- }
- }
-
- /* modify weights to create parting */
- if (p_fac > 0.f) {
- const ParticleCacheKey *key_0_last = pcache_key_segment_endpoint_safe(key[0]);
- for (w = 0; w < 4; w++) {
- if (w && (weight[w] > 0.f)) {
- const ParticleCacheKey *key_w_last = pcache_key_segment_endpoint_safe(key[w]);
- float d;
- if (part->flag & PART_CHILD_LONG_HAIR) {
- /* For long hair use tip distance/root distance as parting factor instead of root to tip angle. */
- float d1 = len_v3v3(key[0]->co, key[w]->co);
- float d2 = len_v3v3(key_0_last->co, key_w_last->co);
-
- d = d1 > 0.f ? d2 / d1 - 1.f : 10000.f;
- }
- else {
- float v1[3], v2[3];
- sub_v3_v3v3(v1, key_0_last->co, key[0]->co);
- sub_v3_v3v3(v2, key_w_last->co, key[w]->co);
- normalize_v3(v1);
- normalize_v3(v2);
-
- d = RAD2DEGF(saacos(dot_v3v3(v1, v2)));
- }
-
- if (p_max > p_min)
- d = (d - p_min) / (p_max - p_min);
- else
- d = (d - p_min) <= 0.f ? 0.f : 1.f;
-
- CLAMP(d, 0.f, 1.f);
-
- if (d > 0.f)
- weight[w] *= (1.f - d);
- }
- wsum += weight[w];
- }
- for (w = 0; w < 4; w++)
- weight[w] /= wsum;
-
- interp_v4_v4v4(weight, cpa->w, weight, p_fac);
- }
-
- /* get the original coordinates (orco) for texture usage */
- cpa_num = cpa->num;
-
- foffset = cpa->foffset;
- cpa_fuv = cpa->fuv;
- cpa_from = PART_FROM_FACE;
-
- psys_particle_on_emitter(ctx->sim.psmd, cpa_from, cpa_num, DMCACHE_ISCHILD, cpa->fuv, foffset, co, ornor, 0, 0, orco, 0);
-
- mul_m4_v3(ob->obmat, co);
-
- for (w = 0; w < 4; w++)
- sub_v3_v3v3(off1[w], co, key[w]->co);
-
- psys_mat_hair_to_global(ob, ctx->sim.psmd->dm_final, psys->part->from, pa, hairmat);
- }
- else {
- ParticleData *pa = psys->particles + cpa->parent;
- float co[3];
- if (ctx->editupdate) {
- if (!(psys->edit->points[cpa->parent].flag & PEP_EDIT_RECALC))
- return;
-
- memset(child_keys, 0, sizeof(*child_keys) * (ctx->segments + 1));
- }
-
- /* get the parent path */
- key[0] = pcache[cpa->parent];
-
- /* get the original coordinates (orco) for texture usage */
- cpa_from = part->from;
- cpa_num = pa->num;
- /* XXX hack to avoid messed up particle num and subsequent crash (#40733) */
- if (cpa_num > ctx->sim.psmd->dm_final->getNumTessFaces(ctx->sim.psmd->dm_final))
- cpa_num = 0;
- cpa_fuv = pa->fuv;
-
- psys_particle_on_emitter(ctx->sim.psmd, cpa_from, cpa_num, DMCACHE_ISCHILD, cpa_fuv, pa->foffset, co, ornor, 0, 0, orco, 0);
-
- psys_mat_hair_to_global(ob, ctx->sim.psmd->dm_final, psys->part->from, pa, hairmat);
- }
-
- child_keys->segments = ctx->segments;
-
- /* get different child parameters from textures & vgroups */
- get_child_modifier_parameters(part, ctx, cpa, cpa_from, cpa_num, cpa_fuv, orco, &ptex);
-
- if (ptex.exist < psys_frand(psys, i + 24)) {
- child_keys->segments = -1;
- return;
- }
-
- /* create the child path */
- for (k = 0, child = child_keys; k <= ctx->segments; k++, child++) {
- if (ctx->between) {
- int w = 0;
-
- zero_v3(child->co);
- zero_v3(child->vel);
- unit_qt(child->rot);
-
- for (w = 0; w < 4; w++) {
- copy_v3_v3(off2[w], off1[w]);
-
- if (part->flag & PART_CHILD_LONG_HAIR) {
- /* Use parent rotation (in addition to emission location) to determine child offset. */
- if (k)
- mul_qt_v3((key[w] + k)->rot, off2[w]);
-
- /* Fade the effect of rotation for even lengths in the end */
- project_v3_v3v3(dvec, off2[w], (key[w] + k)->vel);
- madd_v3_v3fl(off2[w], dvec, -(float)k / (float)ctx->segments);
- }
-
- add_v3_v3(off2[w], (key[w] + k)->co);
- }
-
- /* child position is the weighted sum of parent positions */
- interp_v3_v3v3v3v3(child->co, off2[0], off2[1], off2[2], off2[3], weight);
- interp_v3_v3v3v3v3(child->vel, (key[0] + k)->vel, (key[1] + k)->vel, (key[2] + k)->vel, (key[3] + k)->vel, weight);
-
- copy_qt_qt(child->rot, (key[0] + k)->rot);
- }
- else {
- if (k) {
- mul_qt_qtqt(rot, (key[0] + k)->rot, key[0]->rot);
- par_rot = rot;
- }
- else {
- par_rot = key[0]->rot;
- }
- /* offset the child from the parent position */
- offset_child(cpa, (ParticleKey *)(key[0] + k), par_rot, (ParticleKey *)child, part->childflat, part->childrad);
- }
-
- child->time = (float)k / (float)ctx->segments;
- }
-
- /* apply effectors */
- if (part->flag & PART_CHILD_EFFECT) {
- for (k = 0, child = child_keys; k <= ctx->segments; k++, child++) {
- if (k) {
- do_path_effectors(&ctx->sim, cpa->pa[0], child, k, ctx->segments, child_keys->co, ptex.effector, 0.0f, ctx->cfra, &eff_length, eff_vec);
- }
- else {
- sub_v3_v3v3(eff_vec, (child + 1)->co, child->co);
- eff_length = len_v3(eff_vec);
- }
- }
- }
-
- {
- ParticleData *pa = NULL;
- ParticleCacheKey *par = NULL;
- float par_co[3];
- float par_orco[3];
-
- if (ctx->totparent) {
- if (i >= ctx->totparent) {
- pa = &psys->particles[cpa->parent];
- /* this is now threadsafe, virtual parents are calculated before rest of children */
- BLI_assert(cpa->parent < psys->totchildcache);
- par = cache[cpa->parent];
- }
- }
- else if (cpa->parent >= 0) {
- pa = &psys->particles[cpa->parent];
- par = pcache[cpa->parent];
-
- /* If particle is unexisting, try to pick a viable parent from particles used for interpolation. */
- for (k = 0; k < 4 && pa && (pa->flag & PARS_UNEXIST); k++) {
- if (cpa->pa[k] >= 0) {
- pa = &psys->particles[cpa->pa[k]];
- par = pcache[cpa->pa[k]];
- }
- }
-
- if (pa->flag & PARS_UNEXIST) pa = NULL;
- }
-
- if (pa) {
- ListBase modifiers;
- BLI_listbase_clear(&modifiers);
-
- psys_particle_on_emitter(ctx->sim.psmd, part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset,
- par_co, NULL, NULL, NULL, par_orco, NULL);
-
- psys_apply_child_modifiers(ctx, &modifiers, cpa, &ptex, orco, ornor, hairmat, child_keys, par, par_orco);
- }
- else
- zero_v3(par_orco);
- }
-
- /* Hide virtual parents */
- if (i < ctx->totparent)
- child_keys->segments = -1;
-}
-
-static void exec_child_path_cache(TaskPool * __restrict UNUSED(pool), void *taskdata, int UNUSED(threadid))
-{
- ParticleTask *task = taskdata;
- ParticleThreadContext *ctx = task->ctx;
- ParticleSystem *psys = ctx->sim.psys;
- ParticleCacheKey **cache = psys->childcache;
- ChildParticle *cpa;
- int i;
-
- cpa = psys->child + task->begin;
- for (i = task->begin; i < task->end; ++i, ++cpa) {
- BLI_assert(i < psys->totchildcache);
- psys_thread_create_path(task, cpa, cache[i], i);
- }
-}
-
-void psys_cache_child_paths(
- ParticleSimulationData *sim, float cfra,
- const bool editupdate, const bool use_render_params)
-{
- TaskScheduler *task_scheduler;
- TaskPool *task_pool;
- ParticleThreadContext ctx;
- ParticleTask *tasks_parent, *tasks_child;
- int numtasks_parent, numtasks_child;
- int i, totchild, totparent;
-
- if (sim->psys->flag & PSYS_GLOBAL_HAIR)
- return;
-
- /* create a task pool for child path tasks */
- if (!psys_thread_context_init_path(&ctx, sim, sim->scene, cfra, editupdate, use_render_params))
- return;
-
- task_scheduler = BLI_task_scheduler_get();
- task_pool = BLI_task_pool_create(task_scheduler, &ctx);
- totchild = ctx.totchild;
- totparent = ctx.totparent;
-
- if (editupdate && sim->psys->childcache && totchild == sim->psys->totchildcache) {
- ; /* just overwrite the existing cache */
- }
- else {
- /* clear out old and create new empty path cache */
- free_child_path_cache(sim->psys);
-
- sim->psys->childcache = psys_alloc_path_cache_buffers(&sim->psys->childcachebufs, totchild, ctx.segments + ctx.extra_segments + 1);
- sim->psys->totchildcache = totchild;
- }
-
- /* cache parent paths */
- ctx.parent_pass = 1;
- psys_tasks_create(&ctx, 0, totparent, &tasks_parent, &numtasks_parent);
- for (i = 0; i < numtasks_parent; ++i) {
- ParticleTask *task = &tasks_parent[i];
-
- psys_task_init_path(task, sim);
- BLI_task_pool_push(task_pool, exec_child_path_cache, task, false, TASK_PRIORITY_LOW);
- }
- BLI_task_pool_work_and_wait(task_pool);
-
- /* cache child paths */
- ctx.parent_pass = 0;
- psys_tasks_create(&ctx, totparent, totchild, &tasks_child, &numtasks_child);
- for (i = 0; i < numtasks_child; ++i) {
- ParticleTask *task = &tasks_child[i];
-
- psys_task_init_path(task, sim);
- BLI_task_pool_push(task_pool, exec_child_path_cache, task, false, TASK_PRIORITY_LOW);
- }
- BLI_task_pool_work_and_wait(task_pool);
-
- BLI_task_pool_free(task_pool);
-
- psys_tasks_free(tasks_parent, numtasks_parent);
- psys_tasks_free(tasks_child, numtasks_child);
-
- psys_thread_context_free(&ctx);
-}
-
-/* figure out incremental rotations along path starting from unit quat */
-static void cache_key_incremental_rotation(ParticleCacheKey *key0, ParticleCacheKey *key1, ParticleCacheKey *key2, float *prev_tangent, int i)
-{
- float cosangle, angle, tangent[3], normal[3], q[4];
-
- switch (i) {
- case 0:
- /* start from second key */
- break;
- case 1:
- /* calculate initial tangent for incremental rotations */
- sub_v3_v3v3(prev_tangent, key0->co, key1->co);
- normalize_v3(prev_tangent);
- unit_qt(key1->rot);
- break;
- default:
- sub_v3_v3v3(tangent, key0->co, key1->co);
- normalize_v3(tangent);
-
- cosangle = dot_v3v3(tangent, prev_tangent);
-
- /* note we do the comparison on cosangle instead of
- * angle, since floating point accuracy makes it give
- * different results across platforms */
- if (cosangle > 0.999999f) {
- copy_v4_v4(key1->rot, key2->rot);
- }
- else {
- angle = saacos(cosangle);
- cross_v3_v3v3(normal, prev_tangent, tangent);
- axis_angle_to_quat(q, normal, angle);
- mul_qt_qtqt(key1->rot, q, key2->rot);
- }
-
- copy_v3_v3(prev_tangent, tangent);
- }
-}
-
-/**
- * Calculates paths ready for drawing/rendering
- * - Useful for making use of opengl vertex arrays for super fast strand drawing.
- * - Makes child strands possible and creates them too into the cache.
- * - Cached path data is also used to determine cut position for the editmode tool. */
-void psys_cache_paths(ParticleSimulationData *sim, float cfra, const bool use_render_params)
-{
- PARTICLE_PSMD;
- ParticleEditSettings *pset = &sim->scene->toolsettings->particle;
- ParticleSystem *psys = sim->psys;
- ParticleSettings *part = psys->part;
- ParticleCacheKey *ca, **cache;
-
- DerivedMesh *hair_dm = (psys->part->type == PART_HAIR && psys->flag & PSYS_HAIR_DYNAMICS) ? psys->hair_out_dm : NULL;
-
- ParticleKey result;
-
- Material *ma;
- ParticleInterpolationData pind;
- ParticleTexture ptex;
-
- PARTICLE_P;
-
- float birthtime = 0.0, dietime = 0.0;
- float t, time = 0.0, dfra = 1.0 /* , frs_sec = sim->scene->r.frs_sec*/ /*UNUSED*/;
- float col[4] = {0.5f, 0.5f, 0.5f, 1.0f};
- float prev_tangent[3] = {0.0f, 0.0f, 0.0f}, hairmat[4][4];
- float rotmat[3][3];
- int k;
- int segments = (int)pow(2.0, (double)((psys->renderdata || use_render_params) ? part->ren_step : part->draw_step));
- int totpart = psys->totpart;
- float length, vec[3];
- float *vg_effector = NULL;
- float *vg_length = NULL, pa_length = 1.0f;
- int keyed, baked;
-
- /* we don't have anything valid to create paths from so let's quit here */
- if ((psys->flag & PSYS_HAIR_DONE || psys->flag & PSYS_KEYED || psys->pointcache) == 0)
- return;
-
- if (psys_in_edit_mode(sim->scene, psys))
- if (psys->renderdata == 0 && (psys->edit == NULL || pset->flag & PE_DRAW_PART) == 0)
- return;
-
- keyed = psys->flag & PSYS_KEYED;
- baked = psys->pointcache->mem_cache.first && psys->part->type != PART_HAIR;
-
- /* clear out old and create new empty path cache */
- psys_free_path_cache(psys, psys->edit);
- cache = psys->pathcache = psys_alloc_path_cache_buffers(&psys->pathcachebufs, totpart, segments + 1);
-
- psys->lattice_deform_data = psys_create_lattice_deform_data(sim);
- ma = give_current_material(sim->ob, psys->part->omat);
- if (ma && (psys->part->draw_col == PART_DRAW_COL_MAT))
- copy_v3_v3(col, &ma->r);
-
- if ((psys->flag & PSYS_GLOBAL_HAIR) == 0) {
- if ((psys->part->flag & PART_CHILD_EFFECT) == 0)
- vg_effector = psys_cache_vgroup(psmd->dm_final, psys, PSYS_VG_EFFECTOR);
-
- if (!psys->totchild)
- vg_length = psys_cache_vgroup(psmd->dm_final, psys, PSYS_VG_LENGTH);
- }
-
- /* ensure we have tessfaces to be used for mapping */
- if (part->from != PART_FROM_VERT) {
- DM_ensure_tessface(psmd->dm_final);
- }
-
- /*---first main loop: create all actual particles' paths---*/
- LOOP_PARTICLES {
- if (!psys->totchild) {
- psys_get_texture(sim, pa, &ptex, PAMAP_LENGTH, 0.f);
- pa_length = ptex.length * (1.0f - part->randlength * psys_frand(psys, psys->seed + p));
- if (vg_length)
- pa_length *= psys_particle_value_from_verts(psmd->dm_final, part->from, pa, vg_length);
- }
-
- pind.keyed = keyed;
- pind.cache = baked ? psys->pointcache : NULL;
- pind.epoint = NULL;
- pind.bspline = (psys->part->flag & PART_HAIR_BSPLINE);
- pind.dm = hair_dm;
-
- memset(cache[p], 0, sizeof(*cache[p]) * (segments + 1));
-
- cache[p]->segments = segments;
-
- /*--get the first data points--*/
- init_particle_interpolation(sim->ob, sim->psys, pa, &pind);
-
- /* hairmat is needed for for non-hair particle too so we get proper rotations */
- psys_mat_hair_to_global(sim->ob, psmd->dm_final, psys->part->from, pa, hairmat);
- copy_v3_v3(rotmat[0], hairmat[2]);
- copy_v3_v3(rotmat[1], hairmat[1]);
- copy_v3_v3(rotmat[2], hairmat[0]);
-
- if (part->draw & PART_ABS_PATH_TIME) {
- birthtime = MAX2(pind.birthtime, part->path_start);
- dietime = MIN2(pind.dietime, part->path_end);
- }
- else {
- float tb = pind.birthtime;
- birthtime = tb + part->path_start * (pind.dietime - tb);
- dietime = tb + part->path_end * (pind.dietime - tb);
- }
-
- if (birthtime >= dietime) {
- cache[p]->segments = -1;
- continue;
- }
-
- dietime = birthtime + pa_length * (dietime - birthtime);
-
- /*--interpolate actual path from data points--*/
- for (k = 0, ca = cache[p]; k <= segments; k++, ca++) {
- time = (float)k / (float)segments;
- t = birthtime + time * (dietime - birthtime);
- result.time = -t;
- do_particle_interpolation(psys, p, pa, t, &pind, &result);
- copy_v3_v3(ca->co, result.co);
-
- /* dynamic hair is in object space */
- /* keyed and baked are already in global space */
- if (hair_dm)
- mul_m4_v3(sim->ob->obmat, ca->co);
- else if (!keyed && !baked && !(psys->flag & PSYS_GLOBAL_HAIR))
- mul_m4_v3(hairmat, ca->co);
-
- copy_v3_v3(ca->col, col);
- }
-
- if (part->type == PART_HAIR) {
- HairKey *hkey;
-
- for (k = 0, hkey = pa->hair; k < pa->totkey; ++k, ++hkey) {
- mul_v3_m4v3(hkey->world_co, hairmat, hkey->co);
- }
- }
-
- /*--modify paths and calculate rotation & velocity--*/
-
- if (!(psys->flag & PSYS_GLOBAL_HAIR)) {
- /* apply effectors */
- if ((psys->part->flag & PART_CHILD_EFFECT) == 0) {
- float effector = 1.0f;
- if (vg_effector)
- effector *= psys_particle_value_from_verts(psmd->dm_final, psys->part->from, pa, vg_effector);
-
- sub_v3_v3v3(vec, (cache[p] + 1)->co, cache[p]->co);
- length = len_v3(vec);
-
- for (k = 1, ca = cache[p] + 1; k <= segments; k++, ca++)
- do_path_effectors(sim, p, ca, k, segments, cache[p]->co, effector, dfra, cfra, &length, vec);
- }
-
- /* apply guide curves to path data */
- if (sim->psys->effectors && (psys->part->flag & PART_CHILD_EFFECT) == 0) {
- for (k = 0, ca = cache[p]; k <= segments; k++, ca++)
- /* ca is safe to cast, since only co and vel are used */
- do_guides(sim->psys->part, sim->psys->effectors, (ParticleKey *)ca, p, (float)k / (float)segments);
- }
-
- /* lattices have to be calculated separately to avoid mixups between effector calculations */
- if (psys->lattice_deform_data) {
- for (k = 0, ca = cache[p]; k <= segments; k++, ca++)
- calc_latt_deform(psys->lattice_deform_data, ca->co, 1.0f);
- }
- }
-
- /* finally do rotation & velocity */
- for (k = 1, ca = cache[p] + 1; k <= segments; k++, ca++) {
- cache_key_incremental_rotation(ca, ca - 1, ca - 2, prev_tangent, k);
-
- if (k == segments)
- copy_qt_qt(ca->rot, (ca - 1)->rot);
-
- /* set velocity */
- sub_v3_v3v3(ca->vel, ca->co, (ca - 1)->co);
-
- if (k == 1)
- copy_v3_v3((ca - 1)->vel, ca->vel);
-
- ca->time = (float)k / (float)segments;
- }
- /* First rotation is based on emitting face orientation.
- * This is way better than having flipping rotations resulting
- * from using a global axis as a rotation pole (vec_to_quat()).
- * It's not an ideal solution though since it disregards the
- * initial tangent, but taking that in to account will allow
- * the possibility of flipping again. -jahka
- */
- mat3_to_quat_is_ok(cache[p]->rot, rotmat);
- }
-
- psys->totcached = totpart;
-
- if (psys->lattice_deform_data) {
- end_latt_deform(psys->lattice_deform_data);
- psys->lattice_deform_data = NULL;
- }
-
- if (vg_effector)
- MEM_freeN(vg_effector);
-
- if (vg_length)
- MEM_freeN(vg_length);
-}
-void psys_cache_edit_paths(Scene *scene, Object *ob, PTCacheEdit *edit, float cfra, const bool use_render_params)
-{
- ParticleCacheKey *ca, **cache = edit->pathcache;
- ParticleEditSettings *pset = &scene->toolsettings->particle;
-
- PTCacheEditPoint *point = NULL;
- PTCacheEditKey *ekey = NULL;
-
- ParticleSystem *psys = edit->psys;
- ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys);
- ParticleData *pa = psys ? psys->particles : NULL;
-
- ParticleInterpolationData pind;
- ParticleKey result;
-
- float birthtime = 0.0f, dietime = 0.0f;
- float t, time = 0.0f, keytime = 0.0f /*, frs_sec */;
- float hairmat[4][4], rotmat[3][3], prev_tangent[3] = {0.0f, 0.0f, 0.0f};
- int k, i;
- int segments = 1 << pset->draw_step;
- int totpart = edit->totpoint, recalc_set = 0;
- float sel_col[3];
- float nosel_col[3];
-
- segments = MAX2(segments, 4);
-
- if (!cache || edit->totpoint != edit->totcached) {
- /* clear out old and create new empty path cache */
- psys_free_path_cache(edit->psys, edit);
- cache = edit->pathcache = psys_alloc_path_cache_buffers(&edit->pathcachebufs, totpart, segments + 1);
-
- /* set flag for update (child particles check this too) */
- for (i = 0, point = edit->points; i < totpart; i++, point++)
- point->flag |= PEP_EDIT_RECALC;
- recalc_set = 1;
- }
-
- /* frs_sec = (psys || edit->pid.flag & PTCACHE_VEL_PER_SEC) ? 25.0f : 1.0f; */ /* UNUSED */
-
- if (pset->brushtype == PE_BRUSH_WEIGHT) {
- ; /* use weight painting colors now... */
- }
- else {
- sel_col[0] = (float)edit->sel_col[0] / 255.0f;
- sel_col[1] = (float)edit->sel_col[1] / 255.0f;
- sel_col[2] = (float)edit->sel_col[2] / 255.0f;
- nosel_col[0] = (float)edit->nosel_col[0] / 255.0f;
- nosel_col[1] = (float)edit->nosel_col[1] / 255.0f;
- nosel_col[2] = (float)edit->nosel_col[2] / 255.0f;
- }
-
- /*---first main loop: create all actual particles' paths---*/
- for (i = 0, point = edit->points; i < totpart; i++, pa += pa ? 1 : 0, point++) {
- if (edit->totcached && !(point->flag & PEP_EDIT_RECALC))
- continue;
-
- if (point->totkey == 0)
- continue;
-
- ekey = point->keys;
-
- pind.keyed = 0;
- pind.cache = NULL;
- pind.epoint = point;
- pind.bspline = psys ? (psys->part->flag & PART_HAIR_BSPLINE) : 0;
- pind.dm = NULL;
-
-
- /* should init_particle_interpolation set this ? */
- if (pset->brushtype == PE_BRUSH_WEIGHT) {
- pind.hkey[0] = NULL;
- /* pa != NULL since the weight brush is only available for hair */
- pind.hkey[1] = pa->hair;
- }
-
-
- memset(cache[i], 0, sizeof(*cache[i]) * (segments + 1));
-
- cache[i]->segments = segments;
-
- /*--get the first data points--*/
- init_particle_interpolation(ob, psys, pa, &pind);
-
- if (psys) {
- psys_mat_hair_to_global(ob, psmd->dm_final, psys->part->from, pa, hairmat);
- copy_v3_v3(rotmat[0], hairmat[2]);
- copy_v3_v3(rotmat[1], hairmat[1]);
- copy_v3_v3(rotmat[2], hairmat[0]);
- }
-
- birthtime = pind.birthtime;
- dietime = pind.dietime;
-
- if (birthtime >= dietime) {
- cache[i]->segments = -1;
- continue;
- }
-
- /*--interpolate actual path from data points--*/
- for (k = 0, ca = cache[i]; k <= segments; k++, ca++) {
- time = (float)k / (float)segments;
- t = birthtime + time * (dietime - birthtime);
- result.time = -t;
- do_particle_interpolation(psys, i, pa, t, &pind, &result);
- copy_v3_v3(ca->co, result.co);
-
- /* non-hair points are already in global space */
- if (psys && !(psys->flag & PSYS_GLOBAL_HAIR)) {
- mul_m4_v3(hairmat, ca->co);
-
- if (k) {
- cache_key_incremental_rotation(ca, ca - 1, ca - 2, prev_tangent, k);
-
- if (k == segments)
- copy_qt_qt(ca->rot, (ca - 1)->rot);
-
- /* set velocity */
- sub_v3_v3v3(ca->vel, ca->co, (ca - 1)->co);
-
- if (k == 1)
- copy_v3_v3((ca - 1)->vel, ca->vel);
- }
- }
- else {
- ca->vel[0] = ca->vel[1] = 0.0f;
- ca->vel[2] = 1.0f;
- }
-
- /* selection coloring in edit mode */
- if (pset->brushtype == PE_BRUSH_WEIGHT) {
- float t2;
-
- if (k == 0) {
- weight_to_rgb(ca->col, pind.hkey[1]->weight);
- }
- else {
- float w1[3], w2[3];
- keytime = (t - (*pind.ekey[0]->time)) / ((*pind.ekey[1]->time) - (*pind.ekey[0]->time));
-
- weight_to_rgb(w1, pind.hkey[0]->weight);
- weight_to_rgb(w2, pind.hkey[1]->weight);
-
- interp_v3_v3v3(ca->col, w1, w2, keytime);
- }
-
- /* at the moment this is only used for weight painting.
- * will need to move out of this check if its used elsewhere. */
- t2 = birthtime + ((float)k / (float)segments) * (dietime - birthtime);
-
- while (pind.hkey[1]->time < t2) pind.hkey[1]++;
- pind.hkey[0] = pind.hkey[1] - 1;
- }
- else {
- if ((ekey + (pind.ekey[0] - point->keys))->flag & PEK_SELECT) {
- if ((ekey + (pind.ekey[1] - point->keys))->flag & PEK_SELECT) {
- copy_v3_v3(ca->col, sel_col);
- }
- else {
- keytime = (t - (*pind.ekey[0]->time)) / ((*pind.ekey[1]->time) - (*pind.ekey[0]->time));
- interp_v3_v3v3(ca->col, sel_col, nosel_col, keytime);
- }
- }
- else {
- if ((ekey + (pind.ekey[1] - point->keys))->flag & PEK_SELECT) {
- keytime = (t - (*pind.ekey[0]->time)) / ((*pind.ekey[1]->time) - (*pind.ekey[0]->time));
- interp_v3_v3v3(ca->col, nosel_col, sel_col, keytime);
- }
- else {
- copy_v3_v3(ca->col, nosel_col);
- }
- }
- }
-
- ca->time = t;
- }
- if (psys && !(psys->flag & PSYS_GLOBAL_HAIR)) {
- /* First rotation is based on emitting face orientation.
- * This is way better than having flipping rotations resulting
- * from using a global axis as a rotation pole (vec_to_quat()).
- * It's not an ideal solution though since it disregards the
- * initial tangent, but taking that in to account will allow
- * the possibility of flipping again. -jahka
- */
- mat3_to_quat_is_ok(cache[i]->rot, rotmat);
- }
- }
-
- edit->totcached = totpart;
-
- if (psys) {
- ParticleSimulationData sim = {0};
- sim.scene = scene;
- sim.ob = ob;
- sim.psys = psys;
- sim.psmd = psys_get_modifier(ob, psys);
-
- psys_cache_child_paths(&sim, cfra, true, use_render_params);
- }
-
- /* clear recalc flag if set here */
- if (recalc_set) {
- for (i = 0, point = edit->points; i < totpart; i++, point++)
- point->flag &= ~PEP_EDIT_RECALC;
- }
-}
-/************************************************/
-/* Particle Key handling */
-/************************************************/
-void copy_particle_key(ParticleKey *to, ParticleKey *from, int time)
-{
- if (time) {
- memcpy(to, from, sizeof(ParticleKey));
- }
- else {
- float to_time = to->time;
- memcpy(to, from, sizeof(ParticleKey));
- to->time = to_time;
- }
-}
-void psys_get_from_key(ParticleKey *key, float loc[3], float vel[3], float rot[4], float *time)
-{
- if (loc) copy_v3_v3(loc, key->co);
- if (vel) copy_v3_v3(vel, key->vel);
- if (rot) copy_qt_qt(rot, key->rot);
- if (time) *time = key->time;
-}
-/*-------changing particle keys from space to another-------*/
-#if 0
-static void key_from_object(Object *ob, ParticleKey *key)
-{
- float q[4];
-
- add_v3_v3(key->vel, key->co);
-
- mul_m4_v3(ob->obmat, key->co);
- mul_m4_v3(ob->obmat, key->vel);
- mat4_to_quat(q, ob->obmat);
-
- sub_v3_v3v3(key->vel, key->vel, key->co);
- mul_qt_qtqt(key->rot, q, key->rot);
-}
-#endif
-
-static void triatomat(float *v1, float *v2, float *v3, float (*uv)[2], float mat[4][4])
-{
- float det, w1, w2, d1[2], d2[2];
-
- memset(mat, 0, sizeof(float) * 4 * 4);
- mat[3][3] = 1.0f;
-
- /* first axis is the normal */
- normal_tri_v3(mat[2], v1, v2, v3);
-
- /* second axis along (1, 0) in uv space */
- if (uv) {
- d1[0] = uv[1][0] - uv[0][0];
- d1[1] = uv[1][1] - uv[0][1];
- d2[0] = uv[2][0] - uv[0][0];
- d2[1] = uv[2][1] - uv[0][1];
-
- det = d2[0] * d1[1] - d2[1] * d1[0];
-
- if (det != 0.0f) {
- det = 1.0f / det;
- w1 = -d2[1] * det;
- w2 = d1[1] * det;
-
- mat[1][0] = w1 * (v2[0] - v1[0]) + w2 * (v3[0] - v1[0]);
- mat[1][1] = w1 * (v2[1] - v1[1]) + w2 * (v3[1] - v1[1]);
- mat[1][2] = w1 * (v2[2] - v1[2]) + w2 * (v3[2] - v1[2]);
- normalize_v3(mat[1]);
- }
- else
- mat[1][0] = mat[1][1] = mat[1][2] = 0.0f;
- }
- else {
- sub_v3_v3v3(mat[1], v2, v1);
- normalize_v3(mat[1]);
- }
-
- /* third as a cross product */
- cross_v3_v3v3(mat[0], mat[1], mat[2]);
-}
-
-static void psys_face_mat(Object *ob, DerivedMesh *dm, ParticleData *pa, float mat[4][4], int orco)
-{
- float v[3][3];
- MFace *mface;
- OrigSpaceFace *osface;
- float (*orcodata)[3];
-
- int i = (ELEM(pa->num_dmcache, DMCACHE_ISCHILD, DMCACHE_NOTFOUND)) ? pa->num : pa->num_dmcache;
- if (i == -1 || i >= dm->getNumTessFaces(dm)) { unit_m4(mat); return; }
-
- mface = dm->getTessFaceData(dm, i, CD_MFACE);
- osface = dm->getTessFaceData(dm, i, CD_ORIGSPACE);
-
- if (orco && (orcodata = dm->getVertDataArray(dm, CD_ORCO))) {
- copy_v3_v3(v[0], orcodata[mface->v1]);
- copy_v3_v3(v[1], orcodata[mface->v2]);
- copy_v3_v3(v[2], orcodata[mface->v3]);
-
- /* ugly hack to use non-transformed orcos, since only those
- * give symmetric results for mirroring in particle mode */
- if (DM_get_vert_data_layer(dm, CD_ORIGINDEX))
- BKE_mesh_orco_verts_transform(ob->data, v, 3, 1);
- }
- else {
- dm->getVertCo(dm, mface->v1, v[0]);
- dm->getVertCo(dm, mface->v2, v[1]);
- dm->getVertCo(dm, mface->v3, v[2]);
- }
-
- triatomat(v[0], v[1], v[2], (osface) ? osface->uv : NULL, mat);
-}
-
-void psys_mat_hair_to_object(Object *UNUSED(ob), DerivedMesh *dm, short from, ParticleData *pa, float hairmat[4][4])
-{
- float vec[3];
-
- /* can happen when called from a different object's modifier */
- if (!dm) {
- unit_m4(hairmat);
- return;
- }
-
- psys_face_mat(0, dm, pa, hairmat, 0);
- psys_particle_on_dm(dm, from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, vec, 0, 0, 0, 0, 0);
- copy_v3_v3(hairmat[3], vec);
-}
-
-void psys_mat_hair_to_orco(Object *ob, DerivedMesh *dm, short from, ParticleData *pa, float hairmat[4][4])
-{
- float vec[3], orco[3];
-
- psys_face_mat(ob, dm, pa, hairmat, 1);
- psys_particle_on_dm(dm, from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, vec, 0, 0, 0, orco, 0);
-
- /* see psys_face_mat for why this function is called */
- if (DM_get_vert_data_layer(dm, CD_ORIGINDEX))
- BKE_mesh_orco_verts_transform(ob->data, &orco, 1, 1);
- copy_v3_v3(hairmat[3], orco);
-}
-
-void psys_vec_rot_to_face(DerivedMesh *dm, ParticleData *pa, float vec[3])
-{
- float mat[4][4];
-
- psys_face_mat(0, dm, pa, mat, 0);
- transpose_m4(mat); /* cheap inverse for rotation matrix */
- mul_mat3_m4_v3(mat, vec);
-}
-
-void psys_mat_hair_to_global(Object *ob, DerivedMesh *dm, short from, ParticleData *pa, float hairmat[4][4])
-{
- float facemat[4][4];
-
- psys_mat_hair_to_object(ob, dm, from, pa, facemat);
-
- mul_m4_m4m4(hairmat, ob->obmat, facemat);
-}
-
-/************************************************/
-/* ParticleSettings handling */
-/************************************************/
-ModifierData *object_add_particle_system(Scene *scene, Object *ob, const char *name)
-{
- ParticleSystem *psys;
- ModifierData *md;
- ParticleSystemModifierData *psmd;
-
- if (!ob || ob->type != OB_MESH)
- return NULL;
-
- psys = ob->particlesystem.first;
- for (; psys; psys = psys->next)
- psys->flag &= ~PSYS_CURRENT;
-
- psys = MEM_callocN(sizeof(ParticleSystem), "particle_system");
- psys->pointcache = BKE_ptcache_add(&psys->ptcaches);
- BLI_addtail(&ob->particlesystem, psys);
-
- psys->part = psys_new_settings(DATA_("ParticleSettings"), NULL);
-
- if (BLI_listbase_count_ex(&ob->particlesystem, 2) > 1)
- BLI_snprintf(psys->name, sizeof(psys->name), DATA_("ParticleSystem %i"), BLI_listbase_count(&ob->particlesystem));
- else
- BLI_strncpy(psys->name, DATA_("ParticleSystem"), sizeof(psys->name));
-
- md = modifier_new(eModifierType_ParticleSystem);
-
- if (name)
- BLI_strncpy_utf8(md->name, name, sizeof(md->name));
- else
- BLI_snprintf(md->name, sizeof(md->name), DATA_("ParticleSystem %i"), BLI_listbase_count(&ob->particlesystem));
- modifier_unique_name(&ob->modifiers, md);
-
- psmd = (ParticleSystemModifierData *) md;
- psmd->psys = psys;
- BLI_addtail(&ob->modifiers, md);
-
- psys->totpart = 0;
- psys->flag = PSYS_CURRENT;
- psys->cfra = BKE_scene_frame_get_from_ctime(scene, CFRA + 1);
-
- DAG_relations_tag_update(G.main);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
-
- return md;
-}
-void object_remove_particle_system(Scene *UNUSED(scene), Object *ob)
-{
- ParticleSystem *psys = psys_get_current(ob);
- ParticleSystemModifierData *psmd;
- ModifierData *md;
-
- if (!psys)
- return;
-
- /* clear all other appearances of this pointer (like on smoke flow modifier) */
- if ((md = modifiers_findByType(ob, eModifierType_Smoke))) {
- SmokeModifierData *smd = (SmokeModifierData *)md;
- if ((smd->type == MOD_SMOKE_TYPE_FLOW) && smd->flow && smd->flow->psys)
- if (smd->flow->psys == psys)
- smd->flow->psys = NULL;
- }
-
- if ((md = modifiers_findByType(ob, eModifierType_DynamicPaint))) {
- DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md;
- if (pmd->brush && pmd->brush->psys)
- if (pmd->brush->psys == psys)
- pmd->brush->psys = NULL;
- }
-
- /* clear modifier */
- psmd = psys_get_modifier(ob, psys);
- BLI_remlink(&ob->modifiers, psmd);
- modifier_free((ModifierData *)psmd);
-
- /* clear particle system */
- BLI_remlink(&ob->particlesystem, psys);
- if (psys->part) {
- id_us_min(&psys->part->id);
- }
- psys_free(ob, psys);
-
- if (ob->particlesystem.first)
- ((ParticleSystem *) ob->particlesystem.first)->flag |= PSYS_CURRENT;
- else
- ob->mode &= ~OB_MODE_PARTICLE_EDIT;
-
- DAG_relations_tag_update(G.main);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
-}
-
-static void default_particle_settings(ParticleSettings *part)
-{
- part->type = PART_EMITTER;
- part->distr = PART_DISTR_JIT;
- part->draw_as = PART_DRAW_REND;
- part->ren_as = PART_DRAW_HALO;
- part->bb_uv_split = 1;
- part->bb_align = PART_BB_VIEW;
- part->bb_split_offset = PART_BB_OFF_LINEAR;
- part->flag = PART_EDISTR | PART_TRAND | PART_HIDE_ADVANCED_HAIR;
-
- part->sta = 1.0;
- part->end = 200.0;
- part->lifetime = 50.0;
- part->jitfac = 1.0;
- part->totpart = 1000;
- part->grid_res = 10;
- part->timetweak = 1.0;
- part->courant_target = 0.2;
-
- part->integrator = PART_INT_MIDPOINT;
- part->phystype = PART_PHYS_NEWTON;
- part->hair_step = 5;
- part->keys_step = 5;
- part->draw_step = 2;
- part->ren_step = 3;
- part->adapt_angle = 5;
- part->adapt_pix = 3;
- part->kink_axis = 2;
- part->kink_amp_clump = 1.f;
- part->kink_extra_steps = 4;
- part->clump_noise_size = 1.0f;
- part->reactevent = PART_EVENT_DEATH;
- part->disp = 100;
- part->from = PART_FROM_FACE;
-
- part->normfac = 1.0f;
-
- part->mass = 1.0;
- part->size = 0.05;
- part->childsize = 1.0;
-
- part->rotmode = PART_ROT_VEL;
- part->avemode = PART_AVE_VELOCITY;
-
- part->child_nbr = 10;
- part->ren_child_nbr = 100;
- part->childrad = 0.2f;
- part->childflat = 0.0f;
- part->clumppow = 0.0f;
- part->kink_amp = 0.2f;
- part->kink_freq = 2.0;
-
- part->rough1_size = 1.0;
- part->rough2_size = 1.0;
- part->rough_end_shape = 1.0;
-
- part->clength = 1.0f;
- part->clength_thres = 0.0f;
-
- part->draw = PART_DRAW_EMITTER;
- part->draw_line[0] = 0.5;
- part->path_start = 0.0f;
- part->path_end = 1.0f;
-
- part->bb_size[0] = part->bb_size[1] = 1.0f;
-
- part->keyed_loops = 1;
-
- part->color_vec_max = 1.f;
- part->draw_col = PART_DRAW_COL_MAT;
-
- part->simplify_refsize = 1920;
- part->simplify_rate = 1.0f;
- part->simplify_transition = 0.1f;
- part->simplify_viewport = 0.8;
-
- if (!part->effector_weights)
- part->effector_weights = BKE_add_effector_weights(NULL);
-
- part->omat = 1;
- part->use_modifier_stack = false;
-}
-
-
-ParticleSettings *psys_new_settings(const char *name, Main *main)
-{
- ParticleSettings *part;
-
- if (main == NULL)
- main = G.main;
-
- part = BKE_libblock_alloc(main, ID_PA, name);
-
- default_particle_settings(part);
-
- return part;
-}
-
-void BKE_particlesettings_clump_curve_init(ParticleSettings *part)
-{
- CurveMapping *cumap = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
-
- cumap->cm[0].curve[0].x = 0.0f;
- cumap->cm[0].curve[0].y = 1.0f;
- cumap->cm[0].curve[1].x = 1.0f;
- cumap->cm[0].curve[1].y = 1.0f;
-
- part->clumpcurve = cumap;
-}
-
-void BKE_particlesettings_rough_curve_init(ParticleSettings *part)
-{
- CurveMapping *cumap = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
-
- cumap->cm[0].curve[0].x = 0.0f;
- cumap->cm[0].curve[0].y = 1.0f;
- cumap->cm[0].curve[1].x = 1.0f;
- cumap->cm[0].curve[1].y = 1.0f;
-
- part->roughcurve = cumap;
-}
-
-ParticleSettings *BKE_particlesettings_copy(Main *bmain, ParticleSettings *part)
-{
- ParticleSettings *partn;
- int a;
-
- partn = BKE_libblock_copy(bmain, &part->id);
-
- partn->pd = MEM_dupallocN(part->pd);
- partn->pd2 = MEM_dupallocN(part->pd2);
- partn->effector_weights = MEM_dupallocN(part->effector_weights);
- partn->fluid = MEM_dupallocN(part->fluid);
-
- if (part->clumpcurve)
- partn->clumpcurve = curvemapping_copy(part->clumpcurve);
- if (part->roughcurve)
- partn->roughcurve = curvemapping_copy(part->roughcurve);
-
- partn->boids = boid_copy_settings(part->boids);
-
- for (a = 0; a < MAX_MTEX; a++) {
- if (part->mtex[a]) {
- partn->mtex[a] = MEM_mallocN(sizeof(MTex), "psys_copy_tex");
- memcpy(partn->mtex[a], part->mtex[a], sizeof(MTex));
- id_us_plus((ID *)partn->mtex[a]->tex);
- }
- }
-
- BLI_duplicatelist(&partn->dupliweights, &part->dupliweights);
-
- BKE_id_copy_ensure_local(bmain, &part->id, &partn->id);
-
- return partn;
-}
-
-void BKE_particlesettings_make_local(Main *bmain, ParticleSettings *part, const bool lib_local)
-{
- BKE_id_make_local_generic(bmain, &part->id, true, lib_local);
-}
-
-/************************************************/
-/* Textures */
-/************************************************/
-
-static int get_particle_uv(DerivedMesh *dm, ParticleData *pa, int face_index, const float fuv[4], char *name, float *texco)
-{
- MFace *mf;
- MTFace *tf;
- int i;
-
- tf = CustomData_get_layer_named(&dm->faceData, CD_MTFACE, name);
-
- if (tf == NULL)
- tf = CustomData_get_layer(&dm->faceData, CD_MTFACE);
-
- if (tf == NULL)
- return 0;
-
- if (pa) {
- i = ELEM(pa->num_dmcache, DMCACHE_NOTFOUND, DMCACHE_ISCHILD) ? pa->num : pa->num_dmcache;
- if (i >= dm->getNumTessFaces(dm))
- i = -1;
- }
- else
- i = face_index;
-
- if (i == -1) {
- texco[0] = 0.0f;
- texco[1] = 0.0f;
- texco[2] = 0.0f;
- }
- else {
- mf = dm->getTessFaceData(dm, i, CD_MFACE);
-
- psys_interpolate_uvs(&tf[i], mf->v4, fuv, texco);
-
- texco[0] = texco[0] * 2.0f - 1.0f;
- texco[1] = texco[1] * 2.0f - 1.0f;
- texco[2] = 0.0f;
- }
-
- return 1;
-}
-
-#define SET_PARTICLE_TEXTURE(type, pvalue, texfac) \
- if ((event & mtex->mapto) & type) { \
- pvalue = texture_value_blend(def, pvalue, value, texfac, blend); \
- } (void)0
-
-#define CLAMP_PARTICLE_TEXTURE_POS(type, pvalue) \
- if (event & type) { \
- CLAMP(pvalue, 0.0f, 1.0f); \
- } (void)0
-
-#define CLAMP_WARP_PARTICLE_TEXTURE_POS(type, pvalue) \
- if (event & type) { \
- if (pvalue < 0.0f) \
- pvalue = 1.0f + pvalue; \
- CLAMP(pvalue, 0.0f, 1.0f); \
- } (void)0
-
-#define CLAMP_PARTICLE_TEXTURE_POSNEG(type, pvalue) \
- if (event & type) { \
- CLAMP(pvalue, -1.0f, 1.0f); \
- } (void)0
-
-static void get_cpa_texture(DerivedMesh *dm, ParticleSystem *psys, ParticleSettings *part, ParticleData *par, int child_index, int face_index, const float fw[4], float *orco, ParticleTexture *ptex, int event, float cfra)
-{
- MTex *mtex, **mtexp = part->mtex;
- int m;
- float value, rgba[4], texvec[3];
-
- ptex->ivel = ptex->life = ptex->exist = ptex->size = ptex->damp =
- ptex->gravity = ptex->field = ptex->time = ptex->clump = ptex->kink_freq = ptex->kink_amp =
- ptex->effector = ptex->rough1 = ptex->rough2 = ptex->roughe = 1.0f;
-
- ptex->length = 1.0f - part->randlength * psys_frand(psys, child_index + 26);
- ptex->length *= part->clength_thres < psys_frand(psys, child_index + 27) ? part->clength : 1.0f;
-
- for (m = 0; m < MAX_MTEX; m++, mtexp++) {
- mtex = *mtexp;
- if (mtex && mtex->tex && mtex->mapto) {
- float def = mtex->def_var;
- short blend = mtex->blendtype;
- short texco = mtex->texco;
-
- if (ELEM(texco, TEXCO_UV, TEXCO_ORCO) && (ELEM(part->from, PART_FROM_FACE, PART_FROM_VOLUME) == 0 || part->distr == PART_DISTR_GRID))
- texco = TEXCO_GLOB;
-
- switch (texco) {
- case TEXCO_GLOB:
- copy_v3_v3(texvec, par->state.co);
- break;
- case TEXCO_OBJECT:
- copy_v3_v3(texvec, par->state.co);
- if (mtex->object)
- mul_m4_v3(mtex->object->imat, texvec);
- break;
- case TEXCO_UV:
- if (fw && get_particle_uv(dm, NULL, face_index, fw, mtex->uvname, texvec))
- break;
- /* no break, failed to get uv's, so let's try orco's */
- case TEXCO_ORCO:
- copy_v3_v3(texvec, orco);
- break;
- case TEXCO_PARTICLE:
- /* texture coordinates in range [-1, 1] */
- texvec[0] = 2.f * (cfra - par->time) / (par->dietime - par->time) - 1.f;
- texvec[1] = 0.f;
- texvec[2] = 0.f;
- break;
- }
-
- externtex(mtex, texvec, &value, rgba, rgba + 1, rgba + 2, rgba + 3, 0, NULL, false, false);
-
- if ((event & mtex->mapto) & PAMAP_ROUGH)
- ptex->rough1 = ptex->rough2 = ptex->roughe = texture_value_blend(def, ptex->rough1, value, mtex->roughfac, blend);
-
- SET_PARTICLE_TEXTURE(PAMAP_LENGTH, ptex->length, mtex->lengthfac);
- SET_PARTICLE_TEXTURE(PAMAP_CLUMP, ptex->clump, mtex->clumpfac);
- SET_PARTICLE_TEXTURE(PAMAP_KINK_AMP, ptex->kink_amp, mtex->kinkampfac);
- SET_PARTICLE_TEXTURE(PAMAP_KINK_FREQ, ptex->kink_freq, mtex->kinkfac);
- SET_PARTICLE_TEXTURE(PAMAP_DENS, ptex->exist, mtex->padensfac);
- }
- }
-
- CLAMP_PARTICLE_TEXTURE_POS(PAMAP_LENGTH, ptex->length);
- CLAMP_WARP_PARTICLE_TEXTURE_POS(PAMAP_CLUMP, ptex->clump);
- CLAMP_WARP_PARTICLE_TEXTURE_POS(PAMAP_KINK_AMP, ptex->kink_amp);
- CLAMP_WARP_PARTICLE_TEXTURE_POS(PAMAP_KINK_FREQ, ptex->kink_freq);
- CLAMP_WARP_PARTICLE_TEXTURE_POS(PAMAP_ROUGH, ptex->rough1);
- CLAMP_WARP_PARTICLE_TEXTURE_POS(PAMAP_DENS, ptex->exist);
-}
-void psys_get_texture(ParticleSimulationData *sim, ParticleData *pa, ParticleTexture *ptex, int event, float cfra)
-{
- Object *ob = sim->ob;
- Mesh *me = (Mesh *)ob->data;
- ParticleSettings *part = sim->psys->part;
- MTex **mtexp = part->mtex;
- MTex *mtex;
- int m;
- float value, rgba[4], co[3], texvec[3];
- int setvars = 0;
-
- /* initialize ptex */
- ptex->ivel = ptex->life = ptex->exist = ptex->size = ptex->damp =
- ptex->gravity = ptex->field = ptex->length = ptex->clump = ptex->kink_freq = ptex->kink_amp =
- ptex->effector = ptex->rough1 = ptex->rough2 = ptex->roughe = 1.0f;
-
- ptex->time = (float)(pa - sim->psys->particles) / (float)sim->psys->totpart;
-
- for (m = 0; m < MAX_MTEX; m++, mtexp++) {
- mtex = *mtexp;
- if (mtex && mtex->tex && mtex->mapto) {
- float def = mtex->def_var;
- short blend = mtex->blendtype;
- short texco = mtex->texco;
-
- if (texco == TEXCO_UV && (ELEM(part->from, PART_FROM_FACE, PART_FROM_VOLUME) == 0 || part->distr == PART_DISTR_GRID))
- texco = TEXCO_GLOB;
-
- switch (texco) {
- case TEXCO_GLOB:
- copy_v3_v3(texvec, pa->state.co);
- break;
- case TEXCO_OBJECT:
- copy_v3_v3(texvec, pa->state.co);
- if (mtex->object)
- mul_m4_v3(mtex->object->imat, texvec);
- break;
- case TEXCO_UV:
- if (get_particle_uv(sim->psmd->dm_final, pa, 0, pa->fuv, mtex->uvname, texvec))
- break;
- /* no break, failed to get uv's, so let's try orco's */
- case TEXCO_ORCO:
- psys_particle_on_emitter(sim->psmd, sim->psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, co, 0, 0, 0, texvec, 0);
-
- if (me->bb == NULL || (me->bb->flag & BOUNDBOX_DIRTY)) {
- BKE_mesh_texspace_calc(me);
- }
- sub_v3_v3(texvec, me->loc);
- if (me->size[0] != 0.0f) texvec[0] /= me->size[0];
- if (me->size[1] != 0.0f) texvec[1] /= me->size[1];
- if (me->size[2] != 0.0f) texvec[2] /= me->size[2];
- break;
- case TEXCO_PARTICLE:
- /* texture coordinates in range [-1, 1] */
- texvec[0] = 2.f * (cfra - pa->time) / (pa->dietime - pa->time) - 1.f;
- if (sim->psys->totpart > 0)
- texvec[1] = 2.f * (float)(pa - sim->psys->particles) / (float)sim->psys->totpart - 1.f;
- else
- texvec[1] = 0.0f;
- texvec[2] = 0.f;
- break;
- }
-
- externtex(mtex, texvec, &value, rgba, rgba + 1, rgba + 2, rgba + 3, 0, NULL, false, false);
-
- if ((event & mtex->mapto) & PAMAP_TIME) {
- /* the first time has to set the base value for time regardless of blend mode */
- if ((setvars & MAP_PA_TIME) == 0) {
- int flip = (mtex->timefac < 0.0f);
- float timefac = fabsf(mtex->timefac);
- ptex->time *= 1.0f - timefac;
- ptex->time += timefac * ((flip) ? 1.0f - value : value);
- setvars |= MAP_PA_TIME;
- }
- else
- ptex->time = texture_value_blend(def, ptex->time, value, mtex->timefac, blend);
- }
- SET_PARTICLE_TEXTURE(PAMAP_LIFE, ptex->life, mtex->lifefac);
- SET_PARTICLE_TEXTURE(PAMAP_DENS, ptex->exist, mtex->padensfac);
- SET_PARTICLE_TEXTURE(PAMAP_SIZE, ptex->size, mtex->sizefac);
- SET_PARTICLE_TEXTURE(PAMAP_IVEL, ptex->ivel, mtex->ivelfac);
- SET_PARTICLE_TEXTURE(PAMAP_FIELD, ptex->field, mtex->fieldfac);
- SET_PARTICLE_TEXTURE(PAMAP_GRAVITY, ptex->gravity, mtex->gravityfac);
- SET_PARTICLE_TEXTURE(PAMAP_DAMP, ptex->damp, mtex->dampfac);
- SET_PARTICLE_TEXTURE(PAMAP_LENGTH, ptex->length, mtex->lengthfac);
- }
- }
-
- CLAMP_WARP_PARTICLE_TEXTURE_POS(PAMAP_TIME, ptex->time);
- CLAMP_WARP_PARTICLE_TEXTURE_POS(PAMAP_LIFE, ptex->life);
- CLAMP_WARP_PARTICLE_TEXTURE_POS(PAMAP_DENS, ptex->exist);
- CLAMP_PARTICLE_TEXTURE_POS(PAMAP_SIZE, ptex->size);
- CLAMP_PARTICLE_TEXTURE_POSNEG(PAMAP_IVEL, ptex->ivel);
- CLAMP_PARTICLE_TEXTURE_POSNEG(PAMAP_FIELD, ptex->field);
- CLAMP_PARTICLE_TEXTURE_POSNEG(PAMAP_GRAVITY, ptex->gravity);
- CLAMP_WARP_PARTICLE_TEXTURE_POS(PAMAP_DAMP, ptex->damp);
- CLAMP_PARTICLE_TEXTURE_POS(PAMAP_LENGTH, ptex->length);
-}
-/************************************************/
-/* Particle State */
-/************************************************/
-float psys_get_timestep(ParticleSimulationData *sim)
-{
- return 0.04f * sim->psys->part->timetweak;
-}
-float psys_get_child_time(ParticleSystem *psys, ChildParticle *cpa, float cfra, float *birthtime, float *dietime)
-{
- ParticleSettings *part = psys->part;
- float time, life;
-
- if (part->childtype == PART_CHILD_FACES) {
- int w = 0;
- time = 0.0;
- while (w < 4 && cpa->pa[w] >= 0) {
- time += cpa->w[w] * (psys->particles + cpa->pa[w])->time;
- w++;
- }
-
- life = part->lifetime * (1.0f - part->randlife * psys_frand(psys, cpa - psys->child + 25));
- }
- else {
- ParticleData *pa = psys->particles + cpa->parent;
-
- time = pa->time;
- life = pa->lifetime;
- }
-
- if (birthtime)
- *birthtime = time;
- if (dietime)
- *dietime = time + life;
-
- return (cfra - time) / life;
-}
-float psys_get_child_size(ParticleSystem *psys, ChildParticle *cpa, float UNUSED(cfra), float *UNUSED(pa_time))
-{
- ParticleSettings *part = psys->part;
- float size; // time XXX
-
- if (part->childtype == PART_CHILD_FACES)
- size = part->size;
- else
- size = psys->particles[cpa->parent].size;
-
- size *= part->childsize;
-
- if (part->childrandsize != 0.0f)
- size *= 1.0f - part->childrandsize * psys_frand(psys, cpa - psys->child + 26);
-
- return size;
-}
-static void get_child_modifier_parameters(ParticleSettings *part, ParticleThreadContext *ctx, ChildParticle *cpa, short cpa_from, int cpa_num, float *cpa_fuv, float *orco, ParticleTexture *ptex)
-{
- ParticleSystem *psys = ctx->sim.psys;
- int i = cpa - psys->child;
-
- get_cpa_texture(ctx->dm, psys, part, psys->particles + cpa->pa[0], i, cpa_num, cpa_fuv, orco, ptex, PAMAP_DENS | PAMAP_CHILD, psys->cfra);
-
-
- if (ptex->exist < psys_frand(psys, i + 24))
- return;
-
- if (ctx->vg_length)
- ptex->length *= psys_interpolate_value_from_verts(ctx->dm, cpa_from, cpa_num, cpa_fuv, ctx->vg_length);
- if (ctx->vg_clump)
- ptex->clump *= psys_interpolate_value_from_verts(ctx->dm, cpa_from, cpa_num, cpa_fuv, ctx->vg_clump);
- if (ctx->vg_kink)
- ptex->kink_freq *= psys_interpolate_value_from_verts(ctx->dm, cpa_from, cpa_num, cpa_fuv, ctx->vg_kink);
- if (ctx->vg_rough1)
- ptex->rough1 *= psys_interpolate_value_from_verts(ctx->dm, cpa_from, cpa_num, cpa_fuv, ctx->vg_rough1);
- if (ctx->vg_rough2)
- ptex->rough2 *= psys_interpolate_value_from_verts(ctx->dm, cpa_from, cpa_num, cpa_fuv, ctx->vg_rough2);
- if (ctx->vg_roughe)
- ptex->roughe *= psys_interpolate_value_from_verts(ctx->dm, cpa_from, cpa_num, cpa_fuv, ctx->vg_roughe);
- if (ctx->vg_effector)
- ptex->effector *= psys_interpolate_value_from_verts(ctx->dm, cpa_from, cpa_num, cpa_fuv, ctx->vg_effector);
-}
-/* get's hair (or keyed) particles state at the "path time" specified in state->time */
-void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey *state, const bool vel)
-{
- PARTICLE_PSMD;
- ParticleSystem *psys = sim->psys;
- ParticleSettings *part = sim->psys->part;
- Material *ma = give_current_material(sim->ob, part->omat);
- ParticleData *pa;
- ChildParticle *cpa;
- ParticleTexture ptex;
- ParticleKey *par = 0, keys[4], tstate;
- ParticleThreadContext ctx; /* fake thread context for child modifiers */
- ParticleInterpolationData pind;
-
- float t;
- float co[3], orco[3];
- float hairmat[4][4];
- int totpart = psys->totpart;
- int totchild = psys->totchild;
- short between = 0, edit = 0;
-
- int keyed = part->phystype & PART_PHYS_KEYED && psys->flag & PSYS_KEYED;
- int cached = !keyed && part->type != PART_HAIR;
-
- float *cpa_fuv; int cpa_num; short cpa_from;
-
- /* initialize keys to zero */
- memset(keys, 0, 4 * sizeof(ParticleKey));
-
- t = state->time;
- CLAMP(t, 0.0f, 1.0f);
-
- if (p < totpart) {
- /* interpolate pathcache directly if it exist */
- if (psys->pathcache) {
- ParticleCacheKey result;
- interpolate_pathcache(psys->pathcache[p], t, &result);
- copy_v3_v3(state->co, result.co);
- copy_v3_v3(state->vel, result.vel);
- copy_qt_qt(state->rot, result.rot);
- }
- /* otherwise interpolate with other means */
- else {
- pa = psys->particles + p;
-
- pind.keyed = keyed;
- pind.cache = cached ? psys->pointcache : NULL;
- pind.epoint = NULL;
- pind.bspline = (psys->part->flag & PART_HAIR_BSPLINE);
- /* pind.dm disabled in editmode means we don't get effectors taken into
- * account when subdividing for instance */
- pind.dm = psys_in_edit_mode(sim->scene, psys) ? NULL : psys->hair_out_dm;
- init_particle_interpolation(sim->ob, psys, pa, &pind);
- do_particle_interpolation(psys, p, pa, t, &pind, state);
-
- if (pind.dm) {
- mul_m4_v3(sim->ob->obmat, state->co);
- mul_mat3_m4_v3(sim->ob->obmat, state->vel);
- }
- else if (!keyed && !cached && !(psys->flag & PSYS_GLOBAL_HAIR)) {
- if ((pa->flag & PARS_REKEY) == 0) {
- psys_mat_hair_to_global(sim->ob, sim->psmd->dm_final, part->from, pa, hairmat);
- mul_m4_v3(hairmat, state->co);
- mul_mat3_m4_v3(hairmat, state->vel);
-
- if (sim->psys->effectors && (part->flag & PART_CHILD_GUIDE) == 0) {
- do_guides(sim->psys->part, sim->psys->effectors, state, p, state->time);
- /* TODO: proper velocity handling */
- }
-
- if (psys->lattice_deform_data && edit == 0)
- calc_latt_deform(psys->lattice_deform_data, state->co, 1.0f);
- }
- }
- }
- }
- else if (totchild) {
- //invert_m4_m4(imat, ob->obmat);
-
- /* interpolate childcache directly if it exists */
- if (psys->childcache) {
- ParticleCacheKey result;
- interpolate_pathcache(psys->childcache[p - totpart], t, &result);
- copy_v3_v3(state->co, result.co);
- copy_v3_v3(state->vel, result.vel);
- copy_qt_qt(state->rot, result.rot);
- }
- else {
- float par_co[3], par_orco[3];
-
- cpa = psys->child + p - totpart;
-
- if (state->time < 0.0f)
- t = psys_get_child_time(psys, cpa, -state->time, NULL, NULL);
-
- if (totchild && part->childtype == PART_CHILD_FACES) {
- /* part->parents could still be 0 so we can't test with totparent */
- between = 1;
- }
- if (between) {
- int w = 0;
- float foffset;
-
- /* get parent states */
- while (w < 4 && cpa->pa[w] >= 0) {
- keys[w].time = state->time;
- psys_get_particle_on_path(sim, cpa->pa[w], keys + w, 1);
- w++;
- }
-
- /* get the original coordinates (orco) for texture usage */
- cpa_num = cpa->num;
-
- foffset = cpa->foffset;
- cpa_fuv = cpa->fuv;
- cpa_from = PART_FROM_FACE;
-
- psys_particle_on_emitter(psmd, cpa_from, cpa_num, DMCACHE_ISCHILD, cpa->fuv, foffset, co, 0, 0, 0, orco, 0);
-
- /* we need to save the actual root position of the child for positioning it accurately to the surface of the emitter */
- //copy_v3_v3(cpa_1st, co);
-
- //mul_m4_v3(ob->obmat, cpa_1st);
-
- pa = psys->particles + cpa->parent;
-
- psys_particle_on_emitter(psmd, part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, par_co, 0, 0, 0, par_orco, 0);
- if (part->type == PART_HAIR)
- psys_mat_hair_to_global(sim->ob, sim->psmd->dm_final, psys->part->from, pa, hairmat);
- else
- unit_m4(hairmat);
-
- pa = 0;
- }
- else {
- /* get the parent state */
- keys->time = state->time;
- psys_get_particle_on_path(sim, cpa->parent, keys, 1);
-
- /* get the original coordinates (orco) for texture usage */
- pa = psys->particles + cpa->parent;
-
- cpa_from = part->from;
- cpa_num = pa->num;
- cpa_fuv = pa->fuv;
-
- psys_particle_on_emitter(psmd, part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, par_co, 0, 0, 0, par_orco, 0);
- if (part->type == PART_HAIR) {
- psys_particle_on_emitter(psmd, cpa_from, cpa_num, DMCACHE_ISCHILD, cpa_fuv, pa->foffset, co, 0, 0, 0, orco, 0);
- psys_mat_hair_to_global(sim->ob, sim->psmd->dm_final, psys->part->from, pa, hairmat);
- }
- else {
- copy_v3_v3(orco, cpa->fuv);
- unit_m4(hairmat);
- }
- }
-
- /* correct child ipo timing */
-#if 0 // XXX old animation system
- if ((part->flag & PART_ABS_TIME) == 0 && part->ipo) {
- calc_ipo(part->ipo, 100.0f * t);
- execute_ipo((ID *)part, part->ipo);
- }
-#endif // XXX old animation system
-
- /* get different child parameters from textures & vgroups */
- memset(&ctx, 0, sizeof(ParticleThreadContext));
- ctx.sim = *sim;
- ctx.dm = psmd->dm_final;
- ctx.ma = ma;
- /* TODO: assign vertex groups */
- get_child_modifier_parameters(part, &ctx, cpa, cpa_from, cpa_num, cpa_fuv, orco, &ptex);
-
- if (between) {
- int w = 0;
-
- state->co[0] = state->co[1] = state->co[2] = 0.0f;
- state->vel[0] = state->vel[1] = state->vel[2] = 0.0f;
-
- /* child position is the weighted sum of parent positions */
- while (w < 4 && cpa->pa[w] >= 0) {
- state->co[0] += cpa->w[w] * keys[w].co[0];
- state->co[1] += cpa->w[w] * keys[w].co[1];
- state->co[2] += cpa->w[w] * keys[w].co[2];
-
- state->vel[0] += cpa->w[w] * keys[w].vel[0];
- state->vel[1] += cpa->w[w] * keys[w].vel[1];
- state->vel[2] += cpa->w[w] * keys[w].vel[2];
- w++;
- }
- /* apply offset for correct positioning */
- //add_v3_v3(state->co, cpa_1st);
- }
- else {
- /* offset the child from the parent position */
- offset_child(cpa, keys, keys->rot, state, part->childflat, part->childrad);
- }
-
- par = keys;
-
- if (vel)
- copy_particle_key(&tstate, state, 1);
-
- /* apply different deformations to the child path */
- do_child_modifiers(NULL, sim, &ptex, par->co, par->vel, par->rot, par_orco, cpa, orco, hairmat, state, t);
-
- /* try to estimate correct velocity */
- if (vel) {
- ParticleKey tstate_tmp;
- float length = len_v3(state->vel);
-
- if (t >= 0.001f) {
- tstate_tmp.time = t - 0.001f;
- psys_get_particle_on_path(sim, p, &tstate_tmp, 0);
- sub_v3_v3v3(state->vel, state->co, tstate_tmp.co);
- normalize_v3(state->vel);
- }
- else {
- tstate_tmp.time = t + 0.001f;
- psys_get_particle_on_path(sim, p, &tstate_tmp, 0);
- sub_v3_v3v3(state->vel, tstate_tmp.co, state->co);
- normalize_v3(state->vel);
- }
-
- mul_v3_fl(state->vel, length);
- }
- }
- }
-}
-/* gets particle's state at a time, returns 1 if particle exists and can be seen and 0 if not */
-int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *state, int always)
-{
- ParticleSystem *psys = sim->psys;
- ParticleSettings *part = psys->part;
- ParticleData *pa = NULL;
- ChildParticle *cpa = NULL;
- float cfra;
- int totpart = psys->totpart;
- float timestep = psys_get_timestep(sim);
-
- /* negative time means "use current time" */
- cfra = state->time > 0 ? state->time : BKE_scene_frame_get(sim->scene);
-
- if (p >= totpart) {
- if (!psys->totchild)
- return 0;
-
- if (part->childtype == PART_CHILD_FACES) {
- if (!(psys->flag & PSYS_KEYED))
- return 0;
-
- cpa = psys->child + p - totpart;
-
- state->time = psys_get_child_time(psys, cpa, cfra, NULL, NULL);
-
- if (!always) {
- if ((state->time < 0.0f && !(part->flag & PART_UNBORN)) ||
- (state->time > 1.0f && !(part->flag & PART_DIED)))
- {
- return 0;
- }
- }
-
- state->time = (cfra - (part->sta + (part->end - part->sta) * psys_frand(psys, p + 23))) / (part->lifetime * psys_frand(psys, p + 24));
-
- psys_get_particle_on_path(sim, p, state, 1);
- return 1;
- }
- else {
- cpa = sim->psys->child + p - totpart;
- pa = sim->psys->particles + cpa->parent;
- }
- }
- else {
- pa = sim->psys->particles + p;
- }
-
- if (pa) {
- if (!always) {
- if ((cfra < pa->time && (part->flag & PART_UNBORN) == 0) ||
- (cfra >= pa->dietime && (part->flag & PART_DIED) == 0))
- {
- return 0;
- }
- }
-
- cfra = MIN2(cfra, pa->dietime);
- }
-
- if (sim->psys->flag & PSYS_KEYED) {
- state->time = -cfra;
- psys_get_particle_on_path(sim, p, state, 1);
- return 1;
- }
- else {
- if (cpa) {
- float mat[4][4];
- ParticleKey *key1;
- float t = (cfra - pa->time) / pa->lifetime;
- float par_orco[3] = {0.0f, 0.0f, 0.0f};
-
- key1 = &pa->state;
- offset_child(cpa, key1, key1->rot, state, part->childflat, part->childrad);
-
- CLAMP(t, 0.0f, 1.0f);
-
- unit_m4(mat);
- do_child_modifiers(NULL, sim, NULL, key1->co, key1->vel, key1->rot, par_orco, cpa, cpa->fuv, mat, state, t);
-
- if (psys->lattice_deform_data)
- calc_latt_deform(psys->lattice_deform_data, state->co, 1.0f);
- }
- else {
- if (pa->state.time == cfra || ELEM(part->phystype, PART_PHYS_NO, PART_PHYS_KEYED))
- copy_particle_key(state, &pa->state, 1);
- else if (pa->prev_state.time == cfra)
- copy_particle_key(state, &pa->prev_state, 1);
- else {
- float dfra, frs_sec = sim->scene->r.frs_sec;
- /* let's interpolate to try to be as accurate as possible */
- if (pa->state.time + 2.f >= state->time && pa->prev_state.time - 2.f <= state->time) {
- if (pa->prev_state.time >= pa->state.time || pa->prev_state.time < 0.f) {
- /* prev_state is wrong so let's not use it, this can happen at frames 1, 0 or particle birth */
- dfra = state->time - pa->state.time;
-
- copy_particle_key(state, &pa->state, 1);
-
- madd_v3_v3v3fl(state->co, state->co, state->vel, dfra / frs_sec);
- }
- else {
- ParticleKey keys[4];
- float keytime;
-
- copy_particle_key(keys + 1, &pa->prev_state, 1);
- copy_particle_key(keys + 2, &pa->state, 1);
-
- dfra = keys[2].time - keys[1].time;
-
- keytime = (state->time - keys[1].time) / dfra;
-
- /* convert velocity to timestep size */
- mul_v3_fl(keys[1].vel, dfra * timestep);
- mul_v3_fl(keys[2].vel, dfra * timestep);
-
- psys_interpolate_particle(-1, keys, keytime, state, 1);
-
- /* convert back to real velocity */
- mul_v3_fl(state->vel, 1.f / (dfra * timestep));
-
- interp_v3_v3v3(state->ave, keys[1].ave, keys[2].ave, keytime);
- interp_qt_qtqt(state->rot, keys[1].rot, keys[2].rot, keytime);
- }
- }
- else if (pa->state.time + 1.f >= state->time && pa->state.time - 1.f <= state->time) {
- /* linear interpolation using only pa->state */
-
- dfra = state->time - pa->state.time;
-
- copy_particle_key(state, &pa->state, 1);
-
- madd_v3_v3v3fl(state->co, state->co, state->vel, dfra / frs_sec);
- }
- else {
- /* extrapolating over big ranges is not accurate so let's just give something close to reasonable back */
- copy_particle_key(state, &pa->state, 0);
- }
- }
-
- if (sim->psys->lattice_deform_data)
- calc_latt_deform(sim->psys->lattice_deform_data, state->co, 1.0f);
- }
-
- return 1;
- }
-}
-
-void psys_get_dupli_texture(ParticleSystem *psys, ParticleSettings *part,
- ParticleSystemModifierData *psmd, ParticleData *pa, ChildParticle *cpa,
- float uv[2], float orco[3])
-{
- MFace *mface;
- MTFace *mtface;
- float loc[3];
- int num;
-
- /* XXX: on checking '(psmd->dm != NULL)'
- * This is incorrect but needed for metaball evaluation.
- * Ideally this would be calculated via the depsgraph, however with metaballs,
- * the entire scenes dupli's are scanned, which also looks into uncalculated data.
- *
- * For now just include this workaround as an alternative to crashing,
- * but longer term metaballs should behave in a more manageable way, see: T46622. */
-
- uv[0] = uv[1] = 0.f;
-
- /* Grid distribution doesn't support UV or emit from vertex mode */
- bool is_grid = (part->distr == PART_DISTR_GRID && part->from != PART_FROM_VERT);
-
- if (cpa) {
- if ((part->childtype == PART_CHILD_FACES) && (psmd->dm_final != NULL)) {
- CustomData *mtf_data = psmd->dm_final->getTessFaceDataLayout(psmd->dm_final);
- const int uv_idx = CustomData_get_render_layer(mtf_data, CD_MTFACE);
- mtface = CustomData_get_layer_n(mtf_data, CD_MTFACE, uv_idx);
-
- if (mtface && !is_grid) {
- mface = psmd->dm_final->getTessFaceData(psmd->dm_final, cpa->num, CD_MFACE);
- mtface += cpa->num;
- psys_interpolate_uvs(mtface, mface->v4, cpa->fuv, uv);
- }
-
- psys_particle_on_emitter(psmd, PART_FROM_FACE, cpa->num, DMCACHE_ISCHILD, cpa->fuv, cpa->foffset, loc, 0, 0, 0, orco, 0);
- return;
- }
- else {
- pa = psys->particles + cpa->pa[0];
- }
- }
-
- if ((part->from == PART_FROM_FACE) && (psmd->dm_final != NULL) && !is_grid) {
- CustomData *mtf_data = psmd->dm_final->getTessFaceDataLayout(psmd->dm_final);
- const int uv_idx = CustomData_get_render_layer(mtf_data, CD_MTFACE);
- mtface = CustomData_get_layer_n(mtf_data, CD_MTFACE, uv_idx);
-
- num = pa->num_dmcache;
-
- if (num == DMCACHE_NOTFOUND)
- num = pa->num;
-
- if (num >= psmd->dm_final->getNumTessFaces(psmd->dm_final)) {
- /* happens when simplify is enabled
- * gives invalid coords but would crash otherwise */
- num = DMCACHE_NOTFOUND;
- }
-
- if (mtface && !ELEM(num, DMCACHE_NOTFOUND, DMCACHE_ISCHILD)) {
- mface = psmd->dm_final->getTessFaceData(psmd->dm_final, num, CD_MFACE);
- mtface += num;
- psys_interpolate_uvs(mtface, mface->v4, pa->fuv, uv);
- }
- }
-
- psys_particle_on_emitter(psmd, part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, loc, 0, 0, 0, orco, 0);
-}
-
-void psys_get_dupli_path_transform(ParticleSimulationData *sim, ParticleData *pa, ChildParticle *cpa, ParticleCacheKey *cache, float mat[4][4], float *scale)
-{
- Object *ob = sim->ob;
- ParticleSystem *psys = sim->psys;
- ParticleSystemModifierData *psmd = sim->psmd;
- float loc[3], nor[3], vec[3], side[3], len;
- float xvec[3] = {-1.0, 0.0, 0.0}, nmat[3][3];
-
- sub_v3_v3v3(vec, (cache + cache->segments)->co, cache->co);
- len = normalize_v3(vec);
-
- if (pa == NULL && psys->part->childflat != PART_CHILD_FACES)
- pa = psys->particles + cpa->pa[0];
-
- if (pa)
- psys_particle_on_emitter(psmd, sim->psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, loc, nor, 0, 0, 0, 0);
- else
- psys_particle_on_emitter(psmd, PART_FROM_FACE, cpa->num, DMCACHE_ISCHILD, cpa->fuv, cpa->foffset, loc, nor, 0, 0, 0, 0);
-
- if (psys->part->rotmode == PART_ROT_VEL) {
- transpose_m3_m4(nmat, ob->imat);
- mul_m3_v3(nmat, nor);
- normalize_v3(nor);
-
- /* make sure that we get a proper side vector */
- if (fabsf(dot_v3v3(nor, vec)) > 0.999999f) {
- if (fabsf(dot_v3v3(nor, xvec)) > 0.999999f) {
- nor[0] = 0.0f;
- nor[1] = 1.0f;
- nor[2] = 0.0f;
- }
- else {
- nor[0] = 1.0f;
- nor[1] = 0.0f;
- nor[2] = 0.0f;
- }
- }
- cross_v3_v3v3(side, nor, vec);
- normalize_v3(side);
-
- /* rotate side vector around vec */
- if (psys->part->phasefac != 0) {
- float q_phase[4];
- float phasefac = psys->part->phasefac;
- if (psys->part->randphasefac != 0.0f)
- phasefac += psys->part->randphasefac * psys_frand(psys, (pa - psys->particles) + 20);
- axis_angle_to_quat(q_phase, vec, phasefac * (float)M_PI);
-
- mul_qt_v3(q_phase, side);
- }
-
- cross_v3_v3v3(nor, vec, side);
-
- unit_m4(mat);
- copy_v3_v3(mat[0], vec);
- copy_v3_v3(mat[1], side);
- copy_v3_v3(mat[2], nor);
- }
- else {
- quat_to_mat4(mat, pa->state.rot);
- }
-
- *scale = len;
-}
-
-void psys_make_billboard(ParticleBillboardData *bb, float xvec[3], float yvec[3], float zvec[3], float center[3])
-{
- float onevec[3] = {0.0f, 0.0f, 0.0f}, tvec[3], tvec2[3];
-
- xvec[0] = 1.0f; xvec[1] = 0.0f; xvec[2] = 0.0f;
- yvec[0] = 0.0f; yvec[1] = 1.0f; yvec[2] = 0.0f;
-
- /* can happen with bad pointcache or physics calculation
- * since this becomes geometry, nan's and inf's crash raytrace code.
- * better not allow this. */
- if ((!isfinite(bb->vec[0])) || (!isfinite(bb->vec[1])) || (!isfinite(bb->vec[2])) ||
- (!isfinite(bb->vel[0])) || (!isfinite(bb->vel[1])) || (!isfinite(bb->vel[2])) )
- {
- zero_v3(bb->vec);
- zero_v3(bb->vel);
-
- zero_v3(xvec);
- zero_v3(yvec);
- zero_v3(zvec);
- zero_v3(center);
-
- return;
- }
-
- if (bb->align < PART_BB_VIEW)
- onevec[bb->align] = 1.0f;
-
- if (bb->lock && (bb->align == PART_BB_VIEW)) {
- normalize_v3_v3(xvec, bb->ob->obmat[0]);
- normalize_v3_v3(yvec, bb->ob->obmat[1]);
- normalize_v3_v3(zvec, bb->ob->obmat[2]);
- }
- else if (bb->align == PART_BB_VEL) {
- float temp[3];
-
- normalize_v3_v3(temp, bb->vel);
-
- sub_v3_v3v3(zvec, bb->ob->obmat[3], bb->vec);
-
- if (bb->lock) {
- float fac = -dot_v3v3(zvec, temp);
-
- madd_v3_v3fl(zvec, temp, fac);
- }
- normalize_v3(zvec);
-
- cross_v3_v3v3(xvec, temp, zvec);
- normalize_v3(xvec);
-
- cross_v3_v3v3(yvec, zvec, xvec);
- }
- else {
- sub_v3_v3v3(zvec, bb->ob->obmat[3], bb->vec);
- if (bb->lock)
- zvec[bb->align] = 0.0f;
- normalize_v3(zvec);
-
- if (bb->align < PART_BB_VIEW)
- cross_v3_v3v3(xvec, onevec, zvec);
- else
- cross_v3_v3v3(xvec, bb->ob->obmat[1], zvec);
- normalize_v3(xvec);
-
- cross_v3_v3v3(yvec, zvec, xvec);
- }
-
- copy_v3_v3(tvec, xvec);
- copy_v3_v3(tvec2, yvec);
-
- mul_v3_fl(xvec, cosf(bb->tilt * (float)M_PI));
- mul_v3_fl(tvec2, sinf(bb->tilt * (float)M_PI));
- add_v3_v3(xvec, tvec2);
-
- mul_v3_fl(yvec, cosf(bb->tilt * (float)M_PI));
- mul_v3_fl(tvec, -sinf(bb->tilt * (float)M_PI));
- add_v3_v3(yvec, tvec);
-
- mul_v3_fl(xvec, bb->size[0]);
- mul_v3_fl(yvec, bb->size[1]);
-
- madd_v3_v3v3fl(center, bb->vec, xvec, bb->offset[0]);
- madd_v3_v3fl(center, yvec, bb->offset[1]);
-}
-
-void psys_apply_hair_lattice(Scene *scene, Object *ob, ParticleSystem *psys)
-{
- ParticleSimulationData sim = {0};
- sim.scene = scene;
- sim.ob = ob;
- sim.psys = psys;
- sim.psmd = psys_get_modifier(ob, psys);
-
- psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
-
- if (psys->lattice_deform_data) {
- ParticleData *pa = psys->particles;
- HairKey *hkey;
- int p, h;
- float hairmat[4][4], imat[4][4];
-
- for (p = 0; p < psys->totpart; p++, pa++) {
- psys_mat_hair_to_global(sim.ob, sim.psmd->dm_final, psys->part->from, pa, hairmat);
- invert_m4_m4(imat, hairmat);
-
- hkey = pa->hair;
- for (h = 0; h < pa->totkey; h++, hkey++) {
- mul_m4_v3(hairmat, hkey->co);
- calc_latt_deform(psys->lattice_deform_data, hkey->co, 1.0f);
- mul_m4_v3(imat, hkey->co);
- }
- }
-
- end_latt_deform(psys->lattice_deform_data);
- psys->lattice_deform_data = NULL;
-
- /* protect the applied shape */
- psys->flag |= PSYS_EDITED;
- }
-}
diff --git a/source/blender/blenkernel/intern/particle_child.c b/source/blender/blenkernel/intern/particle_child.c
deleted file mode 100644
index ec5f73f87ce..00000000000
--- a/source/blender/blenkernel/intern/particle_child.c
+++ /dev/null
@@ -1,739 +0,0 @@
-/*
- * ***** 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) Blender Foundation
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): Lukas Toenne
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/blenkernel/intern/particle_child.c
- * \ingroup bke
- */
-
-#include "BLI_math.h"
-#include "BLI_noise.h"
-
-#include "DNA_material_types.h"
-
-#include "BKE_colortools.h"
-#include "BKE_particle.h"
-
-struct Material;
-
-void do_kink(ParticleKey *state, const float par_co[3], const float par_vel[3], const float par_rot[4], float time, float freq, float shape, float amplitude, float flat,
- short type, short axis, float obmat[4][4], int smooth_start);
-float do_clump(ParticleKey *state, const float par_co[3], float time, const float orco_offset[3], float clumpfac, float clumppow, float pa_clump,
- bool use_clump_noise, float clump_noise_size, CurveMapping *clumpcurve);
-void do_child_modifiers(ParticleThreadContext *ctx, ParticleSimulationData *sim,
- ParticleTexture *ptex, const float par_co[3], const float par_vel[3], const float par_rot[4], const float par_orco[3],
- ChildParticle *cpa, const float orco[3], float mat[4][4], ParticleKey *state, float t);
-
-static void get_strand_normal(Material *ma, const float surfnor[3], float surfdist, float nor[3])
-{
- float cross[3], nstrand[3], vnor[3], blend;
-
- if (!((ma->mode & MA_STR_SURFDIFF) || (ma->strand_surfnor > 0.0f)))
- return;
-
- if (ma->mode & MA_STR_SURFDIFF) {
- cross_v3_v3v3(cross, surfnor, nor);
- cross_v3_v3v3(nstrand, nor, cross);
-
- blend = dot_v3v3(nstrand, surfnor);
- CLAMP(blend, 0.0f, 1.0f);
-
- interp_v3_v3v3(vnor, nstrand, surfnor, blend);
- normalize_v3(vnor);
- }
- else {
- copy_v3_v3(vnor, nor);
- }
-
- if (ma->strand_surfnor > 0.0f) {
- if (ma->strand_surfnor > surfdist) {
- blend = (ma->strand_surfnor - surfdist) / ma->strand_surfnor;
- interp_v3_v3v3(vnor, vnor, surfnor, blend);
- normalize_v3(vnor);
- }
- }
-
- copy_v3_v3(nor, vnor);
-}
-
-/* ------------------------------------------------------------------------- */
-
-typedef struct ParticlePathIterator {
- ParticleCacheKey *key;
- int index;
- float time;
-
- ParticleCacheKey *parent_key;
- float parent_rotation[4];
-} ParticlePathIterator;
-
-static void psys_path_iter_get(ParticlePathIterator *iter, ParticleCacheKey *keys, int totkeys,
- ParticleCacheKey *parent, int index)
-{
- BLI_assert(index >= 0 && index < totkeys);
-
- iter->key = keys + index;
- iter->index = index;
- iter->time = (float)index / (float)(totkeys - 1);
-
- if (parent) {
- iter->parent_key = parent + index;
- if (index > 0)
- mul_qt_qtqt(iter->parent_rotation, iter->parent_key->rot, parent->rot);
- else
- copy_qt_qt(iter->parent_rotation, parent->rot);
- }
- else {
- iter->parent_key = NULL;
- unit_qt(iter->parent_rotation);
- }
-}
-
-typedef struct ParticlePathModifier {
- struct ParticlePathModifier *next, *prev;
-
- void (*apply)(ParticleCacheKey *keys, int totkeys, ParticleCacheKey *parent_keys);
-} ParticlePathModifier;
-
-/* ------------------------------------------------------------------------- */
-
-static void do_kink_spiral_deform(ParticleKey *state, const float dir[3], const float kink[3],
- float time, float freq, float shape, float amplitude,
- const float spiral_start[3])
-{
- float result[3];
-
- CLAMP(time, 0.f, 1.f);
-
- copy_v3_v3(result, state->co);
-
- {
- /* Creates a logarithmic spiral:
- * r(theta) = a * exp(b * theta)
- *
- * The "density" parameter b is defined by the shape parameter
- * and goes up to the Golden Spiral for 1.0
- * http://en.wikipedia.org/wiki/Golden_spiral
- */
- const float b = shape * (1.0f + sqrtf(5.0f)) / (float)M_PI * 0.25f;
- /* angle of the spiral against the curve (rotated opposite to make a smooth transition) */
- const float start_angle = ((b != 0.0f) ? atanf(1.0f / b) :
- (float)-M_PI_2) + (b > 0.0f ? -(float)M_PI_2 : (float)M_PI_2);
-
- float spiral_axis[3], rot[3][3];
- float vec[3];
-
- float theta = freq * time * 2.0f * (float)M_PI;
- float radius = amplitude * expf(b * theta);
-
- /* a bit more intuitive than using negative frequency for this */
- if (amplitude < 0.0f)
- theta = -theta;
-
- cross_v3_v3v3(spiral_axis, dir, kink);
- normalize_v3(spiral_axis);
-
- mul_v3_v3fl(vec, kink, -radius);
-
- axis_angle_normalized_to_mat3(rot, spiral_axis, theta);
- mul_m3_v3(rot, vec);
-
- madd_v3_v3fl(vec, kink, amplitude);
-
- axis_angle_normalized_to_mat3(rot, spiral_axis, -start_angle);
- mul_m3_v3(rot, vec);
-
- add_v3_v3v3(result, spiral_start, vec);
- }
-
- copy_v3_v3(state->co, result);
-}
-
-static void do_kink_spiral(ParticleThreadContext *ctx, ParticleTexture *ptex, const float parent_orco[3],
- ChildParticle *cpa, const float orco[3], float hairmat[4][4],
- ParticleCacheKey *keys, ParticleCacheKey *parent_keys, int *r_totkeys, float *r_max_length)
-{
- struct ParticleSettings *part = ctx->sim.psys->part;
- const int seed = ctx->sim.psys->child_seed + (int)(cpa - ctx->sim.psys->child);
- const int totkeys = ctx->segments + 1;
- const int extrakeys = ctx->extra_segments;
-
- float kink_amp_random = part->kink_amp_random;
- float kink_amp = part->kink_amp * (1.0f - kink_amp_random * psys_frand(ctx->sim.psys, 93541 + seed));
- float kink_freq = part->kink_freq;
- float kink_shape = part->kink_shape;
- float kink_axis_random = part->kink_axis_random;
- float rough1 = part->rough1;
- float rough2 = part->rough2;
- float rough_end = part->rough_end;
-
- ParticlePathIterator iter;
- ParticleCacheKey *key;
- int k;
-
- float dir[3];
- float spiral_start[3] = {0.0f, 0.0f, 0.0f};
- float spiral_start_time = 0.0f;
- float spiral_par_co[3] = {0.0f, 0.0f, 0.0f};
- float spiral_par_vel[3] = {0.0f, 0.0f, 0.0f};
- float spiral_par_rot[4] = {1.0f, 0.0f, 0.0f, 0.0f};
- float totlen;
- float cut_time;
- int start_index = 0, end_index = 0;
- float kink_base[3];
-
- if (ptex) {
- kink_amp *= ptex->kink_amp;
- kink_freq *= ptex->kink_freq;
- rough1 *= ptex->rough1;
- rough2 *= ptex->rough2;
- rough_end *= ptex->roughe;
- }
-
- cut_time = (totkeys - 1) * ptex->length;
- zero_v3(spiral_start);
-
- for (k = 0, key = keys; k < totkeys-1; k++, key++) {
- if ((float)(k + 1) >= cut_time) {
- float fac = cut_time - (float)k;
- ParticleCacheKey *par = parent_keys + k;
-
- start_index = k + 1;
- end_index = start_index + extrakeys;
-
- spiral_start_time = ((float)k + fac) / (float)(totkeys - 1);
- interp_v3_v3v3(spiral_start, key->co, (key+1)->co, fac);
-
- interp_v3_v3v3(spiral_par_co, par->co, (par+1)->co, fac);
- interp_v3_v3v3(spiral_par_vel, par->vel, (par+1)->vel, fac);
- interp_qt_qtqt(spiral_par_rot, par->rot, (par+1)->rot, fac);
-
- break;
- }
- }
-
- zero_v3(dir);
-
- zero_v3(kink_base);
- kink_base[part->kink_axis] = 1.0f;
- mul_mat3_m4_v3(ctx->sim.ob->obmat, kink_base);
-
- for (k = 0, key = keys; k < end_index; k++, key++) {
- float par_time;
- float *par_co, *par_vel, *par_rot;
-
- psys_path_iter_get(&iter, keys, end_index, NULL, k);
- if (k < start_index) {
- sub_v3_v3v3(dir, (key+1)->co, key->co);
- normalize_v3(dir);
-
- par_time = (float)k / (float)(totkeys - 1);
- par_co = parent_keys[k].co;
- par_vel = parent_keys[k].vel;
- par_rot = parent_keys[k].rot;
- }
- else {
- float spiral_time = (float)(k - start_index) / (float)(extrakeys-1);
- float kink[3], tmp[3];
-
- /* use same time value for every point on the spiral */
- par_time = spiral_start_time;
- par_co = spiral_par_co;
- par_vel = spiral_par_vel;
- par_rot = spiral_par_rot;
-
- project_v3_v3v3(tmp, kink_base, dir);
- sub_v3_v3v3(kink, kink_base, tmp);
- normalize_v3(kink);
-
- if (kink_axis_random > 0.0f) {
- float a = kink_axis_random * (psys_frand(ctx->sim.psys, 7112 + seed) * 2.0f - 1.0f) * (float)M_PI;
- float rot[3][3];
-
- axis_angle_normalized_to_mat3(rot, dir, a);
- mul_m3_v3(rot, kink);
- }
-
- do_kink_spiral_deform((ParticleKey *)key, dir, kink, spiral_time, kink_freq, kink_shape, kink_amp, spiral_start);
- }
-
- /* apply different deformations to the child path */
- do_child_modifiers(ctx, &ctx->sim, ptex, par_co, par_vel, par_rot, parent_orco, cpa, orco, hairmat, (ParticleKey *)key, par_time);
- }
-
- totlen = 0.0f;
- for (k = 0, key = keys; k < end_index-1; k++, key++)
- totlen += len_v3v3((key+1)->co, key->co);
-
- *r_totkeys = end_index;
- *r_max_length = totlen;
-}
-
-/* ------------------------------------------------------------------------- */
-
-static bool check_path_length(int k, ParticleCacheKey *keys, ParticleCacheKey *key, float max_length, float step_length, float *cur_length, float dvec[3])
-{
- if (*cur_length + step_length > max_length) {
- sub_v3_v3v3(dvec, key->co, (key-1)->co);
- mul_v3_fl(dvec, (max_length - *cur_length) / step_length);
- add_v3_v3v3(key->co, (key-1)->co, dvec);
- keys->segments = k;
- /* something over the maximum step value */
- return false;
- }
- else {
- *cur_length += step_length;
- return true;
- }
-}
-
-void psys_apply_child_modifiers(ParticleThreadContext *ctx, struct ListBase *modifiers,
- ChildParticle *cpa, ParticleTexture *ptex, const float orco[3], const float ornor[3], float hairmat[4][4],
- ParticleCacheKey *keys, ParticleCacheKey *parent_keys, const float parent_orco[3])
-{
- struct ParticleSettings *part = ctx->sim.psys->part;
- struct Material *ma = ctx->ma;
- const bool draw_col_ma = (part->draw_col == PART_DRAW_COL_MAT);
- const bool use_length_check = !ELEM(part->kink, PART_KINK_SPIRAL);
-
- ParticlePathModifier *mod;
- ParticleCacheKey *key;
- int totkeys, k;
- float max_length;
-
-#if 0 /* TODO for the future: use true particle modifiers that work on the whole curve */
- for (mod = modifiers->first; mod; mod = mod->next) {
- mod->apply(keys, totkeys, parent_keys);
- }
-#else
- (void)modifiers;
- (void)mod;
-
- if (part->kink == PART_KINK_SPIRAL) {
- do_kink_spiral(ctx, ptex, parent_orco, cpa, orco, hairmat, keys, parent_keys, &totkeys, &max_length);
- keys->segments = totkeys - 1;
- }
- else {
- ParticlePathIterator iter;
-
- totkeys = ctx->segments + 1;
- max_length = ptex->length;
-
- for (k = 0, key = keys; k < totkeys; k++, key++) {
- ParticleKey *par;
-
- psys_path_iter_get(&iter, keys, totkeys, parent_keys, k);
- par = (ParticleKey *)iter.parent_key;
-
- /* apply different deformations to the child path */
- do_child_modifiers(ctx, &ctx->sim, ptex, par->co, par->vel, iter.parent_rotation, parent_orco, cpa, orco, hairmat, (ParticleKey *)key, iter.time);
- }
- }
-
- {
- const float step_length = 1.0f / (float)(totkeys - 1);
-
- float cur_length = 0.0f;
-
- /* we have to correct velocity because of kink & clump */
- for (k = 0, key = keys; k < totkeys; ++k, ++key) {
- if (k >= 2) {
- sub_v3_v3v3((key-1)->vel, key->co, (key-2)->co);
- mul_v3_fl((key-1)->vel, 0.5);
-
- if (ma && draw_col_ma)
- get_strand_normal(ma, ornor, cur_length, (key-1)->vel);
- }
-
- if (use_length_check && k > 1) {
- float dvec[3];
- /* check if path needs to be cut before actual end of data points */
- if (!check_path_length(k, keys, key, max_length, step_length, &cur_length, dvec)) {
- /* last key */
- sub_v3_v3v3(key->vel, key->co, (key-1)->co);
- if (ma && draw_col_ma) {
- copy_v3_v3(key->col, &ma->r);
- }
- break;
- }
- }
- if (k == totkeys-1) {
- /* last key */
- sub_v3_v3v3(key->vel, key->co, (key-1)->co);
- }
-
- if (ma && draw_col_ma) {
- copy_v3_v3(key->col, &ma->r);
- get_strand_normal(ma, ornor, cur_length, key->vel);
- }
- }
- }
-#endif
-}
-
-/* ------------------------------------------------------------------------- */
-
-void do_kink(ParticleKey *state, const float par_co[3], const float par_vel[3], const float par_rot[4], float time, float freq, float shape,
- float amplitude, float flat, short type, short axis, float obmat[4][4], int smooth_start)
-{
- float kink[3] = {1.f, 0.f, 0.f}, par_vec[3], q1[4] = {1.f, 0.f, 0.f, 0.f};
- float t, dt = 1.f, result[3];
-
- if (ELEM(type, PART_KINK_NO, PART_KINK_SPIRAL))
- return;
-
- CLAMP(time, 0.f, 1.f);
-
- if (shape != 0.0f && !ELEM(type, PART_KINK_BRAID)) {
- if (shape < 0.0f)
- time = (float)pow(time, 1.f + shape);
- else
- time = (float)pow(time, 1.f / (1.f - shape));
- }
-
- t = time * freq * (float)M_PI;
-
- if (smooth_start) {
- dt = fabsf(t);
- /* smooth the beginning of kink */
- CLAMP(dt, 0.f, (float)M_PI);
- dt = sinf(dt / 2.f);
- }
-
- if (!ELEM(type, PART_KINK_RADIAL)) {
- float temp[3];
-
- kink[axis] = 1.f;
-
- if (obmat)
- mul_mat3_m4_v3(obmat, kink);
-
- mul_qt_v3(par_rot, kink);
-
- /* make sure kink is normal to strand */
- project_v3_v3v3(temp, kink, par_vel);
- sub_v3_v3(kink, temp);
- normalize_v3(kink);
- }
-
- copy_v3_v3(result, state->co);
- sub_v3_v3v3(par_vec, par_co, state->co);
-
- switch (type) {
- case PART_KINK_CURL:
- {
- float curl_offset[3];
-
- /* rotate kink vector around strand tangent */
- mul_v3_v3fl(curl_offset, kink, amplitude);
- axis_angle_to_quat(q1, par_vel, t);
- mul_qt_v3(q1, curl_offset);
-
- interp_v3_v3v3(par_vec, state->co, par_co, flat);
- add_v3_v3v3(result, par_vec, curl_offset);
- break;
- }
- case PART_KINK_RADIAL:
- {
- if (flat > 0.f) {
- float proj[3];
- /* flatten along strand */
- project_v3_v3v3(proj, par_vec, par_vel);
- madd_v3_v3fl(result, proj, flat);
- }
-
- madd_v3_v3fl(result, par_vec, -amplitude * sinf(t));
- break;
- }
- case PART_KINK_WAVE:
- {
- madd_v3_v3fl(result, kink, amplitude * sinf(t));
-
- if (flat > 0.f) {
- float proj[3];
- /* flatten along wave */
- project_v3_v3v3(proj, par_vec, kink);
- madd_v3_v3fl(result, proj, flat);
-
- /* flatten along strand */
- project_v3_v3v3(proj, par_vec, par_vel);
- madd_v3_v3fl(result, proj, flat);
- }
- break;
- }
- case PART_KINK_BRAID:
- {
- float y_vec[3] = {0.f, 1.f, 0.f};
- float z_vec[3] = {0.f, 0.f, 1.f};
- float vec_one[3], state_co[3];
- float inp_y, inp_z, length;
-
- if (par_rot) {
- mul_qt_v3(par_rot, y_vec);
- mul_qt_v3(par_rot, z_vec);
- }
-
- negate_v3(par_vec);
- normalize_v3_v3(vec_one, par_vec);
-
- inp_y = dot_v3v3(y_vec, vec_one);
- inp_z = dot_v3v3(z_vec, vec_one);
-
- if (inp_y > 0.5f) {
- copy_v3_v3(state_co, y_vec);
-
- mul_v3_fl(y_vec, amplitude * cosf(t));
- mul_v3_fl(z_vec, amplitude / 2.f * sinf(2.f * t));
- }
- else if (inp_z > 0.0f) {
- mul_v3_v3fl(state_co, z_vec, sinf((float)M_PI / 3.f));
- madd_v3_v3fl(state_co, y_vec, -0.5f);
-
- mul_v3_fl(y_vec, -amplitude * cosf(t + (float)M_PI / 3.f));
- mul_v3_fl(z_vec, amplitude / 2.f * cosf(2.f * t + (float)M_PI / 6.f));
- }
- else {
- mul_v3_v3fl(state_co, z_vec, -sinf((float)M_PI / 3.f));
- madd_v3_v3fl(state_co, y_vec, -0.5f);
-
- mul_v3_fl(y_vec, amplitude * -sinf(t + (float)M_PI / 6.f));
- mul_v3_fl(z_vec, amplitude / 2.f * -sinf(2.f * t + (float)M_PI / 3.f));
- }
-
- mul_v3_fl(state_co, amplitude);
- add_v3_v3(state_co, par_co);
- sub_v3_v3v3(par_vec, state->co, state_co);
-
- length = normalize_v3(par_vec);
- mul_v3_fl(par_vec, MIN2(length, amplitude / 2.f));
-
- add_v3_v3v3(state_co, par_co, y_vec);
- add_v3_v3(state_co, z_vec);
- add_v3_v3(state_co, par_vec);
-
- shape = 2.f * (float)M_PI * (1.f + shape);
-
- if (t < shape) {
- shape = t / shape;
- shape = (float)sqrt((double)shape);
- interp_v3_v3v3(result, result, state_co, shape);
- }
- else {
- copy_v3_v3(result, state_co);
- }
- break;
- }
- }
-
- /* blend the start of the kink */
- if (dt < 1.f)
- interp_v3_v3v3(state->co, state->co, result, dt);
- else
- copy_v3_v3(state->co, result);
-}
-
-static float do_clump_level(float result[3], const float co[3], const float par_co[3], float time,
- float clumpfac, float clumppow, float pa_clump, CurveMapping *clumpcurve)
-{
- float clump = 0.0f;
-
- if (clumpcurve) {
- clump = pa_clump * (1.0f - CLAMPIS(curvemapping_evaluateF(clumpcurve, 0, time), 0.0f, 1.0f));
-
- interp_v3_v3v3(result, co, par_co, clump);
- }
- else if (clumpfac != 0.0f) {
- float cpow;
-
- if (clumppow < 0.0f)
- cpow = 1.0f + clumppow;
- else
- cpow = 1.0f + 9.0f * clumppow;
-
- if (clumpfac < 0.0f) /* clump roots instead of tips */
- clump = -clumpfac * pa_clump * (float)pow(1.0 - (double)time, (double)cpow);
- else
- clump = clumpfac * pa_clump * (float)pow((double)time, (double)cpow);
-
- interp_v3_v3v3(result, co, par_co, clump);
- }
-
- return clump;
-}
-
-float do_clump(ParticleKey *state, const float par_co[3], float time, const float orco_offset[3], float clumpfac, float clumppow, float pa_clump,
- bool use_clump_noise, float clump_noise_size, CurveMapping *clumpcurve)
-{
- float clump;
-
- if (use_clump_noise && clump_noise_size != 0.0f) {
- float center[3], noisevec[3];
- float da[4], pa[12];
-
- mul_v3_v3fl(noisevec, orco_offset, 1.0f / clump_noise_size);
- voronoi(noisevec[0], noisevec[1], noisevec[2], da, pa, 1.0f, 0);
- mul_v3_fl(&pa[0], clump_noise_size);
- add_v3_v3v3(center, par_co, &pa[0]);
-
- do_clump_level(state->co, state->co, center, time, clumpfac, clumppow, pa_clump, clumpcurve);
- }
-
- clump = do_clump_level(state->co, state->co, par_co, time, clumpfac, clumppow, pa_clump, clumpcurve);
-
- return clump;
-}
-
-static void do_rough(const float loc[3], float mat[4][4], float t, float fac, float size, float thres, ParticleKey *state)
-{
- float rough[3];
- float rco[3];
-
- if (thres != 0.0f) {
- if (fabsf((float)(-1.5f + loc[0] + loc[1] + loc[2])) < 1.5f * thres) {
- return;
- }
- }
-
- copy_v3_v3(rco, loc);
- mul_v3_fl(rco, t);
- rough[0] = -1.0f + 2.0f * BLI_gTurbulence(size, rco[0], rco[1], rco[2], 2, 0, 2);
- rough[1] = -1.0f + 2.0f * BLI_gTurbulence(size, rco[1], rco[2], rco[0], 2, 0, 2);
- rough[2] = -1.0f + 2.0f * BLI_gTurbulence(size, rco[2], rco[0], rco[1], 2, 0, 2);
-
- madd_v3_v3fl(state->co, mat[0], fac * rough[0]);
- madd_v3_v3fl(state->co, mat[1], fac * rough[1]);
- madd_v3_v3fl(state->co, mat[2], fac * rough[2]);
-}
-
-static void do_rough_end(const float loc[3], float mat[4][4], float t, float fac, float shape, ParticleKey *state)
-{
- float rough[2];
- float roughfac;
-
- roughfac = fac * (float)pow((double)t, shape);
- copy_v2_v2(rough, loc);
- rough[0] = -1.0f + 2.0f * rough[0];
- rough[1] = -1.0f + 2.0f * rough[1];
- mul_v2_fl(rough, roughfac);
-
- madd_v3_v3fl(state->co, mat[0], rough[0]);
- madd_v3_v3fl(state->co, mat[1], rough[1]);
-}
-
-static void do_rough_curve(const float loc[3], float mat[4][4], float time, float fac, float size, CurveMapping *roughcurve, ParticleKey *state)
-{
- float rough[3];
- float rco[3];
-
- if (!roughcurve)
- return;
-
- fac *= CLAMPIS(curvemapping_evaluateF(roughcurve, 0, time), 0.0f, 1.0f);
-
- copy_v3_v3(rco, loc);
- mul_v3_fl(rco, time);
- rough[0] = -1.0f + 2.0f * BLI_gTurbulence(size, rco[0], rco[1], rco[2], 2, 0, 2);
- rough[1] = -1.0f + 2.0f * BLI_gTurbulence(size, rco[1], rco[2], rco[0], 2, 0, 2);
- rough[2] = -1.0f + 2.0f * BLI_gTurbulence(size, rco[2], rco[0], rco[1], 2, 0, 2);
-
- madd_v3_v3fl(state->co, mat[0], fac * rough[0]);
- madd_v3_v3fl(state->co, mat[1], fac * rough[1]);
- madd_v3_v3fl(state->co, mat[2], fac * rough[2]);
-}
-
-void do_child_modifiers(ParticleThreadContext *ctx, ParticleSimulationData *sim, ParticleTexture *ptex,
- const float par_co[3], const float par_vel[3], const float par_rot[4], const float par_orco[3],
- ChildParticle *cpa, const float orco[3], float mat[4][4], ParticleKey *state, float t)
-{
- ParticleSettings *part = sim->psys->part;
- CurveMapping *clumpcurve = NULL, *roughcurve = NULL;
- int i = cpa - sim->psys->child;
- int guided = 0;
-
- if (part->child_flag & PART_CHILD_USE_CLUMP_CURVE) {
- clumpcurve = (ctx != NULL) ? ctx->clumpcurve : part->clumpcurve;
- }
- if (part->child_flag & PART_CHILD_USE_ROUGH_CURVE) {
- roughcurve = (ctx != NULL) ? ctx->roughcurve : part->roughcurve;
- }
-
- float kink_amp = part->kink_amp;
- float kink_amp_clump = part->kink_amp_clump;
- float kink_freq = part->kink_freq;
- float rough1 = part->rough1;
- float rough2 = part->rough2;
- float rough_end = part->rough_end;
- const bool smooth_start = (sim->psys->part->childtype == PART_CHILD_FACES);
-
- if (ptex) {
- kink_amp *= ptex->kink_amp;
- kink_freq *= ptex->kink_freq;
- rough1 *= ptex->rough1;
- rough2 *= ptex->rough2;
- rough_end *= ptex->roughe;
- }
-
- if (part->flag & PART_CHILD_EFFECT)
- /* state is safe to cast, since only co and vel are used */
- guided = do_guides(sim->psys->part, sim->psys->effectors, (ParticleKey *)state, cpa->parent, t);
-
- if (guided == 0) {
- float orco_offset[3];
- float clump;
-
- sub_v3_v3v3(orco_offset, orco, par_orco);
- clump = do_clump(state, par_co, t, orco_offset, part->clumpfac, part->clumppow, ptex ? ptex->clump : 1.f,
- part->child_flag & PART_CHILD_USE_CLUMP_NOISE, part->clump_noise_size, clumpcurve);
-
- if (kink_freq != 0.f) {
- kink_amp *= (1.f - kink_amp_clump * clump);
-
- do_kink(state, par_co, par_vel, par_rot, t, kink_freq, part->kink_shape,
- kink_amp, part->kink_flat, part->kink, part->kink_axis,
- sim->ob->obmat, smooth_start);
- }
- }
-
- if (roughcurve) {
- do_rough_curve(orco, mat, t, rough1, part->rough1_size, roughcurve, state);
- }
- else {
- if (rough1 > 0.f)
- do_rough(orco, mat, t, rough1, part->rough1_size, 0.0, state);
-
- if (rough2 > 0.f) {
- float vec[3];
- psys_frand_vec(sim->psys, i + 27, vec);
- do_rough(vec, mat, t, rough2, part->rough2_size, part->rough2_thres, state);
- }
-
- if (rough_end > 0.f) {
- float vec[3];
- psys_frand_vec(sim->psys, i + 27, vec);
- do_rough_end(vec, mat, t, rough_end, part->rough_end_shape, state);
- }
- }
-}
diff --git a/source/blender/blenkernel/intern/particle_distribute.c b/source/blender/blenkernel/intern/particle_distribute.c
deleted file mode 100644
index 44cf5b119c1..00000000000
--- a/source/blender/blenkernel/intern/particle_distribute.c
+++ /dev/null
@@ -1,1476 +0,0 @@
-/*
- * ***** 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) 2007 by Janne Karhu.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): Raul Fernandez Hernandez (Farsthary),
- * Stephen Swhitehorn,
- * Lukas Toenne
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/blenkernel/intern/particle_distribute.c
- * \ingroup bke
- */
-
-#include <string.h>
-
-#include "MEM_guardedalloc.h"
-
-#include "BLI_utildefines.h"
-#include "BLI_jitter.h"
-#include "BLI_kdtree.h"
-#include "BLI_math.h"
-#include "BLI_rand.h"
-#include "BLI_sort.h"
-#include "BLI_task.h"
-
-#include "DNA_mesh_types.h"
-#include "DNA_meshdata_types.h"
-#include "DNA_modifier_types.h"
-#include "DNA_particle_types.h"
-#include "DNA_scene_types.h"
-
-#include "BKE_cdderivedmesh.h"
-#include "BKE_DerivedMesh.h"
-#include "BKE_global.h"
-#include "BKE_mesh.h"
-#include "BKE_object.h"
-#include "BKE_particle.h"
-
-static int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot);
-
-static void alloc_child_particles(ParticleSystem *psys, int tot)
-{
- if (psys->child) {
- /* only re-allocate if we have to */
- if (psys->part->childtype && psys->totchild == tot) {
- memset(psys->child, 0, tot*sizeof(ChildParticle));
- return;
- }
-
- MEM_freeN(psys->child);
- psys->child=NULL;
- psys->totchild=0;
- }
-
- if (psys->part->childtype) {
- psys->totchild= tot;
- if (psys->totchild)
- psys->child= MEM_callocN(psys->totchild*sizeof(ChildParticle), "child_particles");
- }
-}
-
-static void distribute_simple_children(Scene *scene, Object *ob, DerivedMesh *finaldm, DerivedMesh *deformdm, ParticleSystem *psys)
-{
- ChildParticle *cpa = NULL;
- int i, p;
- int child_nbr= psys_get_child_number(scene, psys);
- int totpart= psys_get_tot_child(scene, psys);
-
- alloc_child_particles(psys, totpart);
-
- cpa = psys->child;
- for (i=0; i<child_nbr; i++) {
- for (p=0; p<psys->totpart; p++,cpa++) {
- float length=2.0;
- cpa->parent=p;
-
- /* create even spherical distribution inside unit sphere */
- while (length>=1.0f) {
- cpa->fuv[0]=2.0f*BLI_frand()-1.0f;
- cpa->fuv[1]=2.0f*BLI_frand()-1.0f;
- cpa->fuv[2]=2.0f*BLI_frand()-1.0f;
- length=len_v3(cpa->fuv);
- }
-
- cpa->num=-1;
- }
- }
- /* dmcache must be updated for parent particles if children from faces is used */
- psys_calc_dmcache(ob, finaldm, deformdm, psys);
-}
-static void distribute_grid(DerivedMesh *dm, ParticleSystem *psys)
-{
- ParticleData *pa=NULL;
- float min[3], max[3], delta[3], d;
- MVert *mv, *mvert = dm->getVertDataArray(dm,0);
- int totvert=dm->getNumVerts(dm), from=psys->part->from;
- int i, j, k, p, res=psys->part->grid_res, size[3], axis;
-
- /* find bounding box of dm */
- if (totvert > 0) {
- mv=mvert;
- copy_v3_v3(min, mv->co);
- copy_v3_v3(max, mv->co);
- mv++;
- for (i = 1; i < totvert; i++, mv++) {
- minmax_v3v3_v3(min, max, mv->co);
- }
- }
- else {
- zero_v3(min);
- zero_v3(max);
- }
-
- sub_v3_v3v3(delta, max, min);
-
- /* determine major axis */
- axis = axis_dominant_v3_single(delta);
-
- d = delta[axis]/(float)res;
-
- size[axis] = res;
- size[(axis+1)%3] = (int)ceil(delta[(axis+1)%3]/d);
- size[(axis+2)%3] = (int)ceil(delta[(axis+2)%3]/d);
-
- /* float errors grrr.. */
- size[(axis+1)%3] = MIN2(size[(axis+1)%3],res);
- size[(axis+2)%3] = MIN2(size[(axis+2)%3],res);
-
- size[0] = MAX2(size[0], 1);
- size[1] = MAX2(size[1], 1);
- size[2] = MAX2(size[2], 1);
-
- /* no full offset for flat/thin objects */
- min[0]+= d < delta[0] ? d/2.f : delta[0]/2.f;
- min[1]+= d < delta[1] ? d/2.f : delta[1]/2.f;
- min[2]+= d < delta[2] ? d/2.f : delta[2]/2.f;
-
- for (i=0,p=0,pa=psys->particles; i<res; i++) {
- for (j=0; j<res; j++) {
- for (k=0; k<res; k++,p++,pa++) {
- pa->fuv[0] = min[0] + (float)i*d;
- pa->fuv[1] = min[1] + (float)j*d;
- pa->fuv[2] = min[2] + (float)k*d;
- pa->flag |= PARS_UNEXIST;
- pa->hair_index = 0; /* abused in volume calculation */
- }
- }
- }
-
- /* enable particles near verts/edges/faces/inside surface */
- if (from==PART_FROM_VERT) {
- float vec[3];
-
- pa=psys->particles;
-
- min[0] -= d/2.0f;
- min[1] -= d/2.0f;
- min[2] -= d/2.0f;
-
- for (i=0,mv=mvert; i<totvert; i++,mv++) {
- sub_v3_v3v3(vec,mv->co,min);
- vec[0]/=delta[0];
- vec[1]/=delta[1];
- vec[2]/=delta[2];
- pa[((int)(vec[0] * (size[0] - 1)) * res +
- (int)(vec[1] * (size[1] - 1))) * res +
- (int)(vec[2] * (size[2] - 1))].flag &= ~PARS_UNEXIST;
- }
- }
- else if (ELEM(from,PART_FROM_FACE,PART_FROM_VOLUME)) {
- float co1[3], co2[3];
-
- MFace *mface= NULL, *mface_array;
- float v1[3], v2[3], v3[3], v4[4], lambda;
- int a, a1, a2, a0mul, a1mul, a2mul, totface;
- int amax= from==PART_FROM_FACE ? 3 : 1;
-
- totface=dm->getNumTessFaces(dm);
- mface=mface_array=dm->getTessFaceDataArray(dm,CD_MFACE);
-
- for (a=0; a<amax; a++) {
- if (a==0) { a0mul=res*res; a1mul=res; a2mul=1; }
- else if (a==1) { a0mul=res; a1mul=1; a2mul=res*res; }
- else { a0mul=1; a1mul=res*res; a2mul=res; }
-
- for (a1=0; a1<size[(a+1)%3]; a1++) {
- for (a2=0; a2<size[(a+2)%3]; a2++) {
- mface= mface_array;
-
- pa = psys->particles + a1*a1mul + a2*a2mul;
- copy_v3_v3(co1, pa->fuv);
- co1[a] -= d < delta[a] ? d/2.f : delta[a]/2.f;
- copy_v3_v3(co2, co1);
- co2[a] += delta[a] + 0.001f*d;
- co1[a] -= 0.001f*d;
-
- /* lets intersect the faces */
- for (i=0; i<totface; i++,mface++) {
- copy_v3_v3(v1, mvert[mface->v1].co);
- copy_v3_v3(v2, mvert[mface->v2].co);
- copy_v3_v3(v3, mvert[mface->v3].co);
-
- bool intersects_tri = isect_axial_line_segment_tri_v3(a, co1, co2, v2, v3, v1, &lambda);
- if (intersects_tri) {
- if (from==PART_FROM_FACE)
- (pa+(int)(lambda*size[a])*a0mul)->flag &= ~PARS_UNEXIST;
- else /* store number of intersections */
- (pa+(int)(lambda*size[a])*a0mul)->hair_index++;
- }
-
- if (mface->v4 && (!intersects_tri || from==PART_FROM_VOLUME)) {
- copy_v3_v3(v4, mvert[mface->v4].co);
-
- if (isect_axial_line_segment_tri_v3(a, co1, co2, v4, v1, v3, &lambda)) {
- if (from==PART_FROM_FACE)
- (pa+(int)(lambda*size[a])*a0mul)->flag &= ~PARS_UNEXIST;
- else
- (pa+(int)(lambda*size[a])*a0mul)->hair_index++;
- }
- }
- }
-
- if (from==PART_FROM_VOLUME) {
- int in=pa->hair_index%2;
- if (in) pa->hair_index++;
- for (i=0; i<size[0]; i++) {
- if (in || (pa+i*a0mul)->hair_index%2)
- (pa+i*a0mul)->flag &= ~PARS_UNEXIST;
- /* odd intersections == in->out / out->in */
- /* even intersections -> in stays same */
- in=(in + (pa+i*a0mul)->hair_index) % 2;
- }
- }
- }
- }
- }
- }
-
- if (psys->part->flag & PART_GRID_HEXAGONAL) {
- for (i=0,p=0,pa=psys->particles; i<res; i++) {
- for (j=0; j<res; j++) {
- for (k=0; k<res; k++,p++,pa++) {
- if (j%2)
- pa->fuv[0] += d/2.f;
-
- if (k%2) {
- pa->fuv[0] += d/2.f;
- pa->fuv[1] += d/2.f;
- }
- }
- }
- }
- }
-
- if (psys->part->flag & PART_GRID_INVERT) {
- for (i=0; i<size[0]; i++) {
- for (j=0; j<size[1]; j++) {
- pa=psys->particles + res*(i*res + j);
- for (k=0; k<size[2]; k++, pa++) {
- pa->flag ^= PARS_UNEXIST;
- }
- }
- }
- }
-
- if (psys->part->grid_rand > 0.f) {
- float rfac = d * psys->part->grid_rand;
- for (p=0,pa=psys->particles; p<psys->totpart; p++,pa++) {
- if (pa->flag & PARS_UNEXIST)
- continue;
-
- pa->fuv[0] += rfac * (psys_frand(psys, p + 31) - 0.5f);
- pa->fuv[1] += rfac * (psys_frand(psys, p + 32) - 0.5f);
- pa->fuv[2] += rfac * (psys_frand(psys, p + 33) - 0.5f);
- }
- }
-}
-
-/* modified copy from rayshade.c */
-static void hammersley_create(float *out, int n, int seed, float amount)
-{
- RNG *rng;
- double p, t, offs[2];
- int k, kk;
-
- rng = BLI_rng_new(31415926 + n + seed);
- offs[0] = BLI_rng_get_double(rng) + (double)amount;
- offs[1] = BLI_rng_get_double(rng) + (double)amount;
- BLI_rng_free(rng);
-
- for (k = 0; k < n; k++) {
- t = 0;
- for (p = 0.5, kk = k; kk; p *= 0.5, kk >>= 1)
- if (kk & 1) /* kk mod 2 = 1 */
- t += p;
-
- out[2*k + 0] = fmod((double)k/(double)n + offs[0], 1.0);
- out[2*k + 1] = fmod(t + offs[1], 1.0);
- }
-}
-
-/* almost exact copy of BLI_jitter_init */
-static void init_mv_jit(float *jit, int num, int seed2, float amount)
-{
- RNG *rng;
- float *jit2, x, rad1, rad2, rad3;
- int i, num2;
-
- if (num==0) return;
-
- rad1= (float)(1.0f/sqrtf((float)num));
- rad2= (float)(1.0f/((float)num));
- rad3= (float)sqrtf((float)num)/((float)num);
-
- rng = BLI_rng_new(31415926 + num + seed2);
- x= 0;
- num2 = 2 * num;
- for (i=0; i<num2; i+=2) {
-
- jit[i] = x + amount*rad1*(0.5f - BLI_rng_get_float(rng));
- jit[i+1] = i/(2.0f*num) + amount*rad1*(0.5f - BLI_rng_get_float(rng));
-
- jit[i]-= (float)floor(jit[i]);
- jit[i+1]-= (float)floor(jit[i+1]);
-
- x+= rad3;
- x -= (float)floor(x);
- }
-
- jit2= MEM_mallocN(12 + 2*sizeof(float)*num, "initjit");
-
- for (i=0 ; i<4 ; i++) {
- BLI_jitterate1((float (*)[2])jit, (float (*)[2])jit2, num, rad1);
- BLI_jitterate1((float (*)[2])jit, (float (*)[2])jit2, num, rad1);
- BLI_jitterate2((float (*)[2])jit, (float (*)[2])jit2, num, rad2);
- }
- MEM_freeN(jit2);
- BLI_rng_free(rng);
-}
-
-static void psys_uv_to_w(float u, float v, int quad, float *w)
-{
- float vert[4][3], co[3];
-
- if (!quad) {
- if (u+v > 1.0f)
- v= 1.0f-v;
- else
- u= 1.0f-u;
- }
-
- vert[0][0] = 0.0f; vert[0][1] = 0.0f; vert[0][2] = 0.0f;
- vert[1][0] = 1.0f; vert[1][1] = 0.0f; vert[1][2] = 0.0f;
- vert[2][0] = 1.0f; vert[2][1] = 1.0f; vert[2][2] = 0.0f;
-
- co[0] = u;
- co[1] = v;
- co[2] = 0.0f;
-
- if (quad) {
- vert[3][0] = 0.0f; vert[3][1] = 1.0f; vert[3][2] = 0.0f;
- interp_weights_poly_v3( w,vert, 4, co);
- }
- else {
- interp_weights_poly_v3( w,vert, 3, co);
- w[3] = 0.0f;
- }
-}
-
-/* Find the index in "sum" array before "value" is crossed. */
-static int distribute_binary_search(float *sum, int n, float value)
-{
- int mid, low = 0, high = n - 1;
-
- if (high == low)
- return low;
-
- if (sum[low] >= value)
- return low;
-
- if (sum[high - 1] < value)
- return high;
-
- while (low < high) {
- mid = (low + high) / 2;
-
- if ((sum[mid] >= value) && (sum[mid - 1] < value))
- return mid;
-
- if (sum[mid] > value) {
- high = mid - 1;
- }
- else {
- low = mid + 1;
- }
- }
-
- return low;
-}
-
-/* the max number if calls to rng_* funcs within psys_thread_distribute_particle
- * be sure to keep up to date if this changes */
-#define PSYS_RND_DIST_SKIP 2
-
-/* note: this function must be thread safe, for from == PART_FROM_CHILD */
-#define ONLY_WORKING_WITH_PA_VERTS 0
-static void distribute_from_verts_exec(ParticleTask *thread, ParticleData *pa, int p)
-{
- ParticleThreadContext *ctx= thread->ctx;
- int rng_skip_tot= PSYS_RND_DIST_SKIP; /* count how many rng_* calls wont need skipping */
-
- /* TODO_PARTICLE - use original index */
- pa->num= ctx->index[p];
- pa->fuv[0] = 1.0f;
- pa->fuv[1] = pa->fuv[2] = pa->fuv[3] = 0.0;
-
-#if ONLY_WORKING_WITH_PA_VERTS
- if (ctx->tree) {
- KDTreeNearest ptn[3];
- int w, maxw;
-
- psys_particle_on_dm(ctx->dm,from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co1,0,0,0,orco1,0);
- BKE_mesh_orco_verts_transform((Mesh*)ob->data, &orco1, 1, 1);
- maxw = BLI_kdtree_find_nearest_n(ctx->tree,orco1,ptn,3);
-
- for (w=0; w<maxw; w++) {
- pa->verts[w]=ptn->num;
- }
- }
-#endif
-
- if (rng_skip_tot > 0) /* should never be below zero */
- BLI_rng_skip(thread->rng, rng_skip_tot);
-}
-
-static void distribute_from_faces_exec(ParticleTask *thread, ParticleData *pa, int p) {
- ParticleThreadContext *ctx= thread->ctx;
- DerivedMesh *dm= ctx->dm;
- float randu, randv;
- int distr= ctx->distr;
- int i;
- int rng_skip_tot= PSYS_RND_DIST_SKIP; /* count how many rng_* calls wont need skipping */
-
- MFace *mface;
-
- pa->num = i = ctx->index[p];
- mface = dm->getTessFaceData(dm,i,CD_MFACE);
-
- switch (distr) {
- case PART_DISTR_JIT:
- if (ctx->jitlevel == 1) {
- if (mface->v4)
- psys_uv_to_w(0.5f, 0.5f, mface->v4, pa->fuv);
- else
- psys_uv_to_w(1.0f / 3.0f, 1.0f / 3.0f, mface->v4, pa->fuv);
- }
- else {
- float offset = fmod(ctx->jitoff[i] + (float)p, (float)ctx->jitlevel);
- if (!isnan(offset)) {
- psys_uv_to_w(ctx->jit[2*(int)offset], ctx->jit[2*(int)offset+1], mface->v4, pa->fuv);
- }
- }
- break;
- case PART_DISTR_RAND:
- randu= BLI_rng_get_float(thread->rng);
- randv= BLI_rng_get_float(thread->rng);
- rng_skip_tot -= 2;
-
- psys_uv_to_w(randu, randv, mface->v4, pa->fuv);
- break;
- }
- pa->foffset= 0.0f;
-
- if (rng_skip_tot > 0) /* should never be below zero */
- BLI_rng_skip(thread->rng, rng_skip_tot);
-}
-
-static void distribute_from_volume_exec(ParticleTask *thread, ParticleData *pa, int p) {
- ParticleThreadContext *ctx= thread->ctx;
- DerivedMesh *dm= ctx->dm;
- float *v1, *v2, *v3, *v4, nor[3], co[3];
- float cur_d, min_d, randu, randv;
- int distr= ctx->distr;
- int i, intersect, tot;
- int rng_skip_tot= PSYS_RND_DIST_SKIP; /* count how many rng_* calls wont need skipping */
-
- MFace *mface;
- MVert *mvert=dm->getVertDataArray(dm,CD_MVERT);
-
- pa->num = i = ctx->index[p];
- mface = dm->getTessFaceData(dm,i,CD_MFACE);
-
- switch (distr) {
- case PART_DISTR_JIT:
- if (ctx->jitlevel == 1) {
- if (mface->v4)
- psys_uv_to_w(0.5f, 0.5f, mface->v4, pa->fuv);
- else
- psys_uv_to_w(1.0f / 3.0f, 1.0f / 3.0f, mface->v4, pa->fuv);
- }
- else {
- float offset = fmod(ctx->jitoff[i] + (float)p, (float)ctx->jitlevel);
- if (!isnan(offset)) {
- psys_uv_to_w(ctx->jit[2*(int)offset], ctx->jit[2*(int)offset+1], mface->v4, pa->fuv);
- }
- }
- break;
- case PART_DISTR_RAND:
- randu= BLI_rng_get_float(thread->rng);
- randv= BLI_rng_get_float(thread->rng);
- rng_skip_tot -= 2;
-
- psys_uv_to_w(randu, randv, mface->v4, pa->fuv);
- break;
- }
- pa->foffset= 0.0f;
-
- /* experimental */
- tot=dm->getNumTessFaces(dm);
-
- psys_interpolate_face(mvert,mface,0,0,pa->fuv,co,nor,0,0,0,0);
-
- normalize_v3(nor);
- negate_v3(nor);
-
- min_d=FLT_MAX;
- intersect=0;
-
- for (i=0,mface=dm->getTessFaceDataArray(dm,CD_MFACE); i<tot; i++,mface++) {
- if (i==pa->num) continue;
-
- v1=mvert[mface->v1].co;
- v2=mvert[mface->v2].co;
- v3=mvert[mface->v3].co;
-
- if (isect_ray_tri_v3(co, nor, v2, v3, v1, &cur_d, NULL)) {
- if (cur_d<min_d) {
- min_d=cur_d;
- pa->foffset=cur_d*0.5f; /* to the middle of volume */
- intersect=1;
- }
- }
- if (mface->v4) {
- v4=mvert[mface->v4].co;
-
- if (isect_ray_tri_v3(co, nor, v4, v1, v3, &cur_d, NULL)) {
- if (cur_d<min_d) {
- min_d=cur_d;
- pa->foffset=cur_d*0.5f; /* to the middle of volume */
- intersect=1;
- }
- }
- }
- }
- if (intersect==0)
- pa->foffset=0.0;
- else {
- switch (distr) {
- case PART_DISTR_JIT:
- pa->foffset *= ctx->jit[p % (2 * ctx->jitlevel)];
- break;
- case PART_DISTR_RAND:
- pa->foffset *= BLI_frand();
- break;
- }
- }
-
- if (rng_skip_tot > 0) /* should never be below zero */
- BLI_rng_skip(thread->rng, rng_skip_tot);
-}
-
-static void distribute_children_exec(ParticleTask *thread, ChildParticle *cpa, int p) {
- ParticleThreadContext *ctx= thread->ctx;
- Object *ob= ctx->sim.ob;
- DerivedMesh *dm= ctx->dm;
- float orco1[3], co1[3], nor1[3];
- float randu, randv;
- int cfrom= ctx->cfrom;
- int i;
- int rng_skip_tot= PSYS_RND_DIST_SKIP; /* count how many rng_* calls wont need skipping */
-
- MFace *mf;
-
- if (ctx->index[p] < 0) {
- cpa->num=0;
- cpa->fuv[0]=cpa->fuv[1]=cpa->fuv[2]=cpa->fuv[3]=0.0f;
- cpa->pa[0]=cpa->pa[1]=cpa->pa[2]=cpa->pa[3]=0;
- return;
- }
-
- mf= dm->getTessFaceData(dm, ctx->index[p], CD_MFACE);
-
- randu= BLI_rng_get_float(thread->rng);
- randv= BLI_rng_get_float(thread->rng);
- rng_skip_tot -= 2;
-
- psys_uv_to_w(randu, randv, mf->v4, cpa->fuv);
-
- cpa->num = ctx->index[p];
-
- if (ctx->tree) {
- KDTreeNearest ptn[10];
- int w,maxw;//, do_seams;
- float maxd /*, mind,dd */, totw= 0.0f;
- int parent[10];
- float pweight[10];
-
- psys_particle_on_dm(dm,cfrom,cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,co1,nor1,NULL,NULL,orco1,NULL);
- BKE_mesh_orco_verts_transform((Mesh*)ob->data, &orco1, 1, 1);
- maxw = BLI_kdtree_find_nearest_n(ctx->tree,orco1,ptn,3);
-
- maxd=ptn[maxw-1].dist;
- /* mind=ptn[0].dist; */ /* UNUSED */
-
- /* the weights here could be done better */
- for (w=0; w<maxw; w++) {
- parent[w]=ptn[w].index;
- pweight[w]=(float)pow(2.0,(double)(-6.0f*ptn[w].dist/maxd));
- }
- for (;w<10; w++) {
- parent[w]=-1;
- pweight[w]=0.0f;
- }
-
- for (w=0,i=0; w<maxw && i<4; w++) {
- if (parent[w]>=0) {
- cpa->pa[i]=parent[w];
- cpa->w[i]=pweight[w];
- totw+=pweight[w];
- i++;
- }
- }
- for (;i<4; i++) {
- cpa->pa[i]=-1;
- cpa->w[i]=0.0f;
- }
-
- if (totw > 0.0f) {
- for (w = 0; w < 4; w++) {
- cpa->w[w] /= totw;
- }
- }
-
- cpa->parent=cpa->pa[0];
- }
-
- if (rng_skip_tot > 0) /* should never be below zero */
- BLI_rng_skip(thread->rng, rng_skip_tot);
-}
-
-static void exec_distribute_parent(TaskPool * __restrict UNUSED(pool), void *taskdata, int UNUSED(threadid))
-{
- ParticleTask *task = taskdata;
- ParticleSystem *psys= task->ctx->sim.psys;
- ParticleData *pa;
- int p;
-
- BLI_rng_skip(task->rng, PSYS_RND_DIST_SKIP * task->begin);
-
- pa= psys->particles + task->begin;
- switch (psys->part->from) {
- case PART_FROM_FACE:
- for (p = task->begin; p < task->end; ++p, ++pa)
- distribute_from_faces_exec(task, pa, p);
- break;
- case PART_FROM_VOLUME:
- for (p = task->begin; p < task->end; ++p, ++pa)
- distribute_from_volume_exec(task, pa, p);
- break;
- case PART_FROM_VERT:
- for (p = task->begin; p < task->end; ++p, ++pa)
- distribute_from_verts_exec(task, pa, p);
- break;
- }
-}
-
-static void exec_distribute_child(TaskPool * __restrict UNUSED(pool), void *taskdata, int UNUSED(threadid))
-{
- ParticleTask *task = taskdata;
- ParticleSystem *psys = task->ctx->sim.psys;
- ChildParticle *cpa;
- int p;
-
- /* RNG skipping at the beginning */
- cpa = psys->child;
- for (p = 0; p < task->begin; ++p, ++cpa) {
- if (task->ctx->skip) /* simplification skip */
- BLI_rng_skip(task->rng, PSYS_RND_DIST_SKIP * task->ctx->skip[p]);
-
- BLI_rng_skip(task->rng, PSYS_RND_DIST_SKIP);
- }
-
- for (; p < task->end; ++p, ++cpa) {
- if (task->ctx->skip) /* simplification skip */
- BLI_rng_skip(task->rng, PSYS_RND_DIST_SKIP * task->ctx->skip[p]);
-
- distribute_children_exec(task, cpa, p);
- }
-}
-
-static int distribute_compare_orig_index(const void *p1, const void *p2, void *user_data)
-{
- int *orig_index = (int *) user_data;
- int index1 = orig_index[*(const int *)p1];
- int index2 = orig_index[*(const int *)p2];
-
- if (index1 < index2)
- return -1;
- else if (index1 == index2) {
- /* this pointer comparison appears to make qsort stable for glibc,
- * and apparently on solaris too, makes the renders reproducible */
- if (p1 < p2)
- return -1;
- else if (p1 == p2)
- return 0;
- else
- return 1;
- }
- else
- return 1;
-}
-
-static void distribute_invalid(Scene *scene, ParticleSystem *psys, int from)
-{
- if (from == PART_FROM_CHILD) {
- ChildParticle *cpa;
- int p, totchild = psys_get_tot_child(scene, psys);
-
- if (psys->child && totchild) {
- for (p=0,cpa=psys->child; p<totchild; p++,cpa++) {
- cpa->fuv[0]=cpa->fuv[1]=cpa->fuv[2]=cpa->fuv[3] = 0.0;
- cpa->foffset= 0.0f;
- cpa->parent=0;
- cpa->pa[0]=cpa->pa[1]=cpa->pa[2]=cpa->pa[3]=0;
- cpa->num= -1;
- }
- }
- }
- else {
- PARTICLE_P;
- LOOP_PARTICLES {
- pa->fuv[0] = pa->fuv[1] = pa->fuv[2] = pa->fuv[3] = 0.0;
- pa->foffset= 0.0f;
- pa->num= -1;
- }
- }
-}
-
-/* Creates a distribution of coordinates on a DerivedMesh */
-/* This is to denote functionality that does not yet work with mesh - only derived mesh */
-static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, ParticleSimulationData *sim, int from)
-{
- Scene *scene = sim->scene;
- DerivedMesh *finaldm = sim->psmd->dm_final;
- Object *ob = sim->ob;
- ParticleSystem *psys= sim->psys;
- ParticleData *pa=0, *tpars= 0;
- ParticleSettings *part;
- ParticleSeam *seams= 0;
- KDTree *tree=0;
- DerivedMesh *dm= NULL;
- float *jit= NULL;
- int i, p=0;
- int cfrom=0;
- int totelem=0, totpart, *particle_element=0, children=0, totseam=0;
- int jitlevel= 1, distr;
- float *element_weight=NULL,*jitter_offset=NULL, *vweight=NULL;
- float cur, maxweight=0.0, tweight, totweight, inv_totweight, co[3], nor[3], orco[3];
-
- if (ELEM(NULL, ob, psys, psys->part))
- return 0;
-
- part=psys->part;
- totpart=psys->totpart;
- if (totpart==0)
- return 0;
-
- if (!finaldm->deformedOnly && !finaldm->getTessFaceDataArray(finaldm, CD_ORIGINDEX)) {
- printf("Can't create particles with the current modifier stack, disable destructive modifiers\n");
-// XXX error("Can't paint with the current modifier stack, disable destructive modifiers");
- return 0;
- }
-
- /* XXX This distribution code is totally broken in case from == PART_FROM_CHILD, it's always using finaldm
- * even if use_modifier_stack is unset... But making things consistent here break all existing edited
- * hair systems, so better wait for complete rewrite.
- */
-
- psys_thread_context_init(ctx, sim);
-
- /* First handle special cases */
- if (from == PART_FROM_CHILD) {
- /* Simple children */
- if (part->childtype != PART_CHILD_FACES) {
- BLI_srandom(31415926 + psys->seed + psys->child_seed);
- distribute_simple_children(scene, ob, finaldm, sim->psmd->dm_deformed, psys);
- return 0;
- }
- }
- else {
- /* Grid distribution */
- if (part->distr==PART_DISTR_GRID && from != PART_FROM_VERT) {
- BLI_srandom(31415926 + psys->seed);
-
- if (psys->part->use_modifier_stack) {
- dm = finaldm;
- }
- else {
- dm = CDDM_from_mesh((Mesh*)ob->data);
- }
- DM_ensure_tessface(dm);
-
- distribute_grid(dm,psys);
-
- if (dm != finaldm) {
- dm->release(dm);
- }
-
- return 0;
- }
- }
-
- /* Create trees and original coordinates if needed */
- if (from == PART_FROM_CHILD) {
- distr=PART_DISTR_RAND;
- BLI_srandom(31415926 + psys->seed + psys->child_seed);
- dm= finaldm;
-
- /* BMESH ONLY */
- DM_ensure_tessface(dm);
-
- children=1;
-
- tree=BLI_kdtree_new(totpart);
-
- for (p=0,pa=psys->particles; p<totpart; p++,pa++) {
- psys_particle_on_dm(dm,part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co,nor,0,0,orco,NULL);
- BKE_mesh_orco_verts_transform((Mesh*)ob->data, &orco, 1, 1);
- BLI_kdtree_insert(tree, p, orco);
- }
-
- BLI_kdtree_balance(tree);
-
- totpart = psys_get_tot_child(scene, psys);
- cfrom = from = PART_FROM_FACE;
- }
- else {
- distr = part->distr;
- BLI_srandom(31415926 + psys->seed);
-
- if (psys->part->use_modifier_stack)
- dm = finaldm;
- else
- dm= CDDM_from_mesh((Mesh*)ob->data);
-
- /* BMESH ONLY, for verts we don't care about tessfaces */
- if (from != PART_FROM_VERT) {
- DM_ensure_tessface(dm);
- }
-
- /* we need orco for consistent distributions */
- if (!CustomData_has_layer(&dm->vertData, CD_ORCO))
- DM_add_vert_layer(dm, CD_ORCO, CD_ASSIGN, BKE_mesh_orco_verts_get(ob));
-
- if (from == PART_FROM_VERT) {
- MVert *mv= dm->getVertDataArray(dm, CD_MVERT);
- float (*orcodata)[3] = dm->getVertDataArray(dm, CD_ORCO);
- int totvert = dm->getNumVerts(dm);
-
- tree=BLI_kdtree_new(totvert);
-
- for (p=0; p<totvert; p++) {
- if (orcodata) {
- copy_v3_v3(co,orcodata[p]);
- BKE_mesh_orco_verts_transform((Mesh*)ob->data, &co, 1, 1);
- }
- else
- copy_v3_v3(co,mv[p].co);
- BLI_kdtree_insert(tree, p, co);
- }
-
- BLI_kdtree_balance(tree);
- }
- }
-
- /* Get total number of emission elements and allocate needed arrays */
- totelem = (from == PART_FROM_VERT) ? dm->getNumVerts(dm) : dm->getNumTessFaces(dm);
-
- if (totelem == 0) {
- distribute_invalid(scene, psys, children ? PART_FROM_CHILD : 0);
-
- if (G.debug & G_DEBUG)
- fprintf(stderr,"Particle distribution error: Nothing to emit from!\n");
-
- if (dm != finaldm) dm->release(dm);
-
- BLI_kdtree_free(tree);
-
- return 0;
- }
-
- element_weight = MEM_callocN(sizeof(float)*totelem, "particle_distribution_weights");
- particle_element= MEM_callocN(sizeof(int)*totpart, "particle_distribution_indexes");
- jitter_offset = MEM_callocN(sizeof(float)*totelem, "particle_distribution_jitoff");
-
- /* Calculate weights from face areas */
- if ((part->flag&PART_EDISTR || children) && from != PART_FROM_VERT) {
- MVert *v1, *v2, *v3, *v4;
- float totarea=0.f, co1[3], co2[3], co3[3], co4[3];
- float (*orcodata)[3];
-
- orcodata= dm->getVertDataArray(dm, CD_ORCO);
-
- for (i=0; i<totelem; i++) {
- MFace *mf=dm->getTessFaceData(dm,i,CD_MFACE);
-
- if (orcodata) {
- copy_v3_v3(co1, orcodata[mf->v1]);
- copy_v3_v3(co2, orcodata[mf->v2]);
- copy_v3_v3(co3, orcodata[mf->v3]);
- BKE_mesh_orco_verts_transform((Mesh*)ob->data, &co1, 1, 1);
- BKE_mesh_orco_verts_transform((Mesh*)ob->data, &co2, 1, 1);
- BKE_mesh_orco_verts_transform((Mesh*)ob->data, &co3, 1, 1);
- if (mf->v4) {
- copy_v3_v3(co4, orcodata[mf->v4]);
- BKE_mesh_orco_verts_transform((Mesh*)ob->data, &co4, 1, 1);
- }
- }
- else {
- v1= (MVert*)dm->getVertData(dm,mf->v1,CD_MVERT);
- v2= (MVert*)dm->getVertData(dm,mf->v2,CD_MVERT);
- v3= (MVert*)dm->getVertData(dm,mf->v3,CD_MVERT);
- copy_v3_v3(co1, v1->co);
- copy_v3_v3(co2, v2->co);
- copy_v3_v3(co3, v3->co);
- if (mf->v4) {
- v4= (MVert*)dm->getVertData(dm,mf->v4,CD_MVERT);
- copy_v3_v3(co4, v4->co);
- }
- }
-
- cur = mf->v4 ? area_quad_v3(co1, co2, co3, co4) : area_tri_v3(co1, co2, co3);
-
- if (cur > maxweight)
- maxweight = cur;
-
- element_weight[i] = cur;
- totarea += cur;
- }
-
- for (i=0; i<totelem; i++)
- element_weight[i] /= totarea;
-
- maxweight /= totarea;
- }
- else {
- float min=1.0f/(float)(MIN2(totelem,totpart));
- for (i=0; i<totelem; i++)
- element_weight[i]=min;
- maxweight=min;
- }
-
- /* Calculate weights from vgroup */
- vweight = psys_cache_vgroup(dm,psys,PSYS_VG_DENSITY);
-
- if (vweight) {
- if (from==PART_FROM_VERT) {
- for (i=0;i<totelem; i++)
- element_weight[i]*=vweight[i];
- }
- else { /* PART_FROM_FACE / PART_FROM_VOLUME */
- for (i=0;i<totelem; i++) {
- MFace *mf=dm->getTessFaceData(dm,i,CD_MFACE);
- tweight = vweight[mf->v1] + vweight[mf->v2] + vweight[mf->v3];
-
- if (mf->v4) {
- tweight += vweight[mf->v4];
- tweight /= 4.0f;
- }
- else {
- tweight /= 3.0f;
- }
-
- element_weight[i]*=tweight;
- }
- }
- MEM_freeN(vweight);
- }
-
- /* Calculate total weight of all elements */
- int totmapped = 0;
- totweight = 0.0f;
- for (i = 0; i < totelem; i++) {
- if (element_weight[i] > 0.0f) {
- totmapped++;
- totweight += element_weight[i];
- }
- }
-
- if (totmapped == 0) {
- /* We are not allowed to distribute particles anywhere... */
- return 0;
- }
-
- inv_totweight = 1.0f / totweight;
-
- /* Calculate cumulative weights.
- * We remove all null-weighted elements from element_sum, and create a new mapping
- * 'activ'_elem_index -> orig_elem_index.
- * This simplifies greatly the filtering of zero-weighted items - and can be much more efficient
- * especially in random case (reducing a lot the size of binary-searched array)...
- */
- float *element_sum = MEM_mallocN(sizeof(*element_sum) * totmapped, __func__);
- int *element_map = MEM_mallocN(sizeof(*element_map) * totmapped, __func__);
- int i_mapped = 0;
-
- for (i = 0; i < totelem && element_weight[i] == 0.0f; i++);
- element_sum[i_mapped] = element_weight[i] * inv_totweight;
- element_map[i_mapped] = i;
- i_mapped++;
- for (i++; i < totelem; i++) {
- if (element_weight[i] > 0.0f) {
- element_sum[i_mapped] = element_sum[i_mapped - 1] + element_weight[i] * inv_totweight;
- /* Skip elements which weight is so small that it does not affect the sum. */
- if (element_sum[i_mapped] > element_sum[i_mapped - 1]) {
- element_map[i_mapped] = i;
- i_mapped++;
- }
- }
- }
- totmapped = i_mapped;
-
- /* Finally assign elements to particles */
- if ((part->flag & PART_TRAND) || (part->simplify_flag & PART_SIMPLIFY_ENABLE)) {
- for (p = 0; p < totpart; p++) {
- /* In theory element_sum[totmapped - 1] should be 1.0,
- * but due to float errors this is not necessarily always true, so scale pos accordingly. */
- const float pos = BLI_frand() * element_sum[totmapped - 1];
- const int eidx = distribute_binary_search(element_sum, totmapped, pos);
- particle_element[p] = element_map[eidx];
- BLI_assert(pos <= element_sum[eidx]);
- BLI_assert(eidx ? (pos > element_sum[eidx - 1]) : (pos >= 0.0f));
- jitter_offset[particle_element[p]] = pos;
- }
- }
- else {
- double step, pos;
-
- step = (totpart < 2) ? 0.5 : 1.0 / (double)totpart;
- /* This is to address tricky issues with vertex-emitting when user tries (and expects) exact 1-1 vert/part
- * distribution (see T47983 and its two example files). It allows us to consider pos as
- * 'midpoint between v and v+1' (or 'p and p+1', depending whether we have more vertices than particles or not),
- * and avoid stumbling over float imprecisions in element_sum. */
- if (from == PART_FROM_VERT) {
- pos = (totpart < totmapped) ? 0.5 / (double)totmapped : step * 0.5; /* We choose the smaller step. */
- }
- else {
- pos = 0.0;
- }
-
- for (i = 0, p = 0; p < totpart; p++, pos += step) {
- for ( ; (i < totmapped - 1) && (pos > (double)element_sum[i]); i++);
-
- particle_element[p] = element_map[i];
-
- jitter_offset[particle_element[p]] = pos;
- }
- }
-
- MEM_freeN(element_sum);
- MEM_freeN(element_map);
-
- /* For hair, sort by origindex (allows optimization's in rendering), */
- /* however with virtual parents the children need to be in random order. */
- if (part->type == PART_HAIR && !(part->childtype==PART_CHILD_FACES && part->parents!=0.0f)) {
- int *orig_index = NULL;
-
- if (from == PART_FROM_VERT) {
- if (dm->numVertData)
- orig_index = dm->getVertDataArray(dm, CD_ORIGINDEX);
- }
- else {
- if (dm->numTessFaceData)
- orig_index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
- }
-
- if (orig_index) {
- BLI_qsort_r(particle_element, totpart, sizeof(int), distribute_compare_orig_index, orig_index);
- }
- }
-
- /* Create jittering if needed */
- if (distr==PART_DISTR_JIT && ELEM(from,PART_FROM_FACE,PART_FROM_VOLUME)) {
- jitlevel= part->userjit;
-
- if (jitlevel == 0) {
- jitlevel= totpart/totelem;
- if (part->flag & PART_EDISTR) jitlevel*= 2; /* looks better in general, not very scietific */
- if (jitlevel<3) jitlevel= 3;
- }
-
- jit= MEM_callocN((2+ jitlevel*2)*sizeof(float), "jit");
-
- /* for small amounts of particles we use regular jitter since it looks
- * a bit better, for larger amounts we switch to hammersley sequence
- * because it is much faster */
- if (jitlevel < 25)
- init_mv_jit(jit, jitlevel, psys->seed, part->jitfac);
- else
- hammersley_create(jit, jitlevel+1, psys->seed, part->jitfac);
- BLI_array_randomize(jit, 2*sizeof(float), jitlevel, psys->seed); /* for custom jit or even distribution */
- }
-
- /* Setup things for threaded distribution */
- ctx->tree= tree;
- ctx->seams= seams;
- ctx->totseam= totseam;
- ctx->sim.psys= psys;
- ctx->index= particle_element;
- ctx->jit= jit;
- ctx->jitlevel= jitlevel;
- ctx->jitoff= jitter_offset;
- ctx->weight= element_weight;
- ctx->maxweight= maxweight;
- ctx->cfrom= cfrom;
- ctx->distr= distr;
- ctx->dm= dm;
- ctx->tpars= tpars;
-
- if (children) {
- totpart= psys_render_simplify_distribution(ctx, totpart);
- alloc_child_particles(psys, totpart);
- }
-
- return 1;
-}
-
-static void psys_task_init_distribute(ParticleTask *task, ParticleSimulationData *sim)
-{
- /* init random number generator */
- int seed = 31415926 + sim->psys->seed;
-
- task->rng = BLI_rng_new(seed);
-}
-
-static void distribute_particles_on_dm(ParticleSimulationData *sim, int from)
-{
- TaskScheduler *task_scheduler;
- TaskPool *task_pool;
- ParticleThreadContext ctx;
- ParticleTask *tasks;
- DerivedMesh *finaldm = sim->psmd->dm_final;
- int i, totpart, numtasks;
-
- /* create a task pool for distribution tasks */
- if (!psys_thread_context_init_distribute(&ctx, sim, from))
- return;
-
- task_scheduler = BLI_task_scheduler_get();
- task_pool = BLI_task_pool_create(task_scheduler, &ctx);
-
- totpart = (from == PART_FROM_CHILD ? sim->psys->totchild : sim->psys->totpart);
- psys_tasks_create(&ctx, 0, totpart, &tasks, &numtasks);
- for (i = 0; i < numtasks; ++i) {
- ParticleTask *task = &tasks[i];
-
- psys_task_init_distribute(task, sim);
- if (from == PART_FROM_CHILD)
- BLI_task_pool_push(task_pool, exec_distribute_child, task, false, TASK_PRIORITY_LOW);
- else
- BLI_task_pool_push(task_pool, exec_distribute_parent, task, false, TASK_PRIORITY_LOW);
- }
- BLI_task_pool_work_and_wait(task_pool);
-
- BLI_task_pool_free(task_pool);
-
- psys_calc_dmcache(sim->ob, finaldm, sim->psmd->dm_deformed, sim->psys);
-
- if (ctx.dm != finaldm)
- ctx.dm->release(ctx.dm);
-
- psys_tasks_free(tasks, numtasks);
-
- psys_thread_context_free(&ctx);
-}
-
-/* ready for future use, to emit particles without geometry */
-static void distribute_particles_on_shape(ParticleSimulationData *sim, int UNUSED(from))
-{
- distribute_invalid(sim->scene, sim->psys, 0);
-
- fprintf(stderr,"Shape emission not yet possible!\n");
-}
-
-void distribute_particles(ParticleSimulationData *sim, int from)
-{
- PARTICLE_PSMD;
- int distr_error=0;
-
- if (psmd) {
- if (psmd->dm_final)
- distribute_particles_on_dm(sim, from);
- else
- distr_error=1;
- }
- else
- distribute_particles_on_shape(sim, from);
-
- if (distr_error) {
- distribute_invalid(sim->scene, sim->psys, from);
-
- fprintf(stderr,"Particle distribution error!\n");
- }
-}
-
-/* ======== Simplify ======== */
-
-static float psys_render_viewport_falloff(double rate, float dist, float width)
-{
- return pow(rate, dist / width);
-}
-
-static float psys_render_projected_area(ParticleSystem *psys, const float center[3], float area, double vprate, float *viewport)
-{
- ParticleRenderData *data = psys->renderdata;
- float co[4], view[3], ortho1[3], ortho2[3], w, dx, dy, radius;
-
- /* transform to view space */
- copy_v3_v3(co, center);
- co[3] = 1.0f;
- mul_m4_v4(data->viewmat, co);
-
- /* compute two vectors orthogonal to view vector */
- normalize_v3_v3(view, co);
- ortho_basis_v3v3_v3(ortho1, ortho2, view);
-
- /* compute on screen minification */
- w = co[2] * data->winmat[2][3] + data->winmat[3][3];
- dx = data->winx * ortho2[0] * data->winmat[0][0];
- dy = data->winy * ortho2[1] * data->winmat[1][1];
- w = sqrtf(dx * dx + dy * dy) / w;
-
- /* w squared because we are working with area */
- area = area * w * w;
-
- /* viewport of the screen test */
-
- /* project point on screen */
- mul_m4_v4(data->winmat, co);
- if (co[3] != 0.0f) {
- co[0] = 0.5f * data->winx * (1.0f + co[0] / co[3]);
- co[1] = 0.5f * data->winy * (1.0f + co[1] / co[3]);
- }
-
- /* screen space radius */
- radius = sqrtf(area / (float)M_PI);
-
- /* make smaller using fallof once over screen edge */
- *viewport = 1.0f;
-
- if (co[0] + radius < 0.0f)
- *viewport *= psys_render_viewport_falloff(vprate, -(co[0] + radius), data->winx);
- else if (co[0] - radius > data->winx)
- *viewport *= psys_render_viewport_falloff(vprate, (co[0] - radius) - data->winx, data->winx);
-
- if (co[1] + radius < 0.0f)
- *viewport *= psys_render_viewport_falloff(vprate, -(co[1] + radius), data->winy);
- else if (co[1] - radius > data->winy)
- *viewport *= psys_render_viewport_falloff(vprate, (co[1] - radius) - data->winy, data->winy);
-
- return area;
-}
-
-/* BMESH_TODO, for orig face data, we need to use MPoly */
-static int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot)
-{
- DerivedMesh *dm = ctx->dm;
- Mesh *me = (Mesh *)(ctx->sim.ob->data);
- MFace *mf, *mface;
- MVert *mvert;
- ParticleRenderData *data;
- ParticleRenderElem *elems, *elem;
- ParticleSettings *part = ctx->sim.psys->part;
- float *facearea, (*facecenter)[3], size[3], fac, powrate, scaleclamp;
- float co1[3], co2[3], co3[3], co4[3], lambda, arearatio, t, area, viewport;
- double vprate;
- int *facetotvert;
- int a, b, totorigface, totface, newtot, skipped;
-
- /* double lookup */
- const int *index_mf_to_mpoly;
- const int *index_mp_to_orig;
-
- if (part->ren_as != PART_DRAW_PATH || !(part->draw & PART_DRAW_REN_STRAND))
- return tot;
- if (!ctx->sim.psys->renderdata)
- return tot;
-
- data = ctx->sim.psys->renderdata;
- if (data->timeoffset)
- return 0;
- if (!(part->simplify_flag & PART_SIMPLIFY_ENABLE))
- return tot;
-
- mvert = dm->getVertArray(dm);
- mface = dm->getTessFaceArray(dm);
- totface = dm->getNumTessFaces(dm);
- totorigface = me->totpoly;
-
- if (totface == 0 || totorigface == 0)
- return tot;
-
- index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
- index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX);
- if (index_mf_to_mpoly == NULL) {
- index_mp_to_orig = NULL;
- }
-
- facearea = MEM_callocN(sizeof(float) * totorigface, "SimplifyFaceArea");
- facecenter = MEM_callocN(sizeof(float[3]) * totorigface, "SimplifyFaceCenter");
- facetotvert = MEM_callocN(sizeof(int) * totorigface, "SimplifyFaceArea");
- elems = MEM_callocN(sizeof(ParticleRenderElem) * totorigface, "SimplifyFaceElem");
-
- if (data->elems)
- MEM_freeN(data->elems);
-
- data->do_simplify = true;
- data->elems = elems;
- data->index_mf_to_mpoly = index_mf_to_mpoly;
- data->index_mp_to_orig = index_mp_to_orig;
-
- /* compute number of children per original face */
- for (a = 0; a < tot; a++) {
- b = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, ctx->index[a]) : ctx->index[a];
- if (b != ORIGINDEX_NONE) {
- elems[b].totchild++;
- }
- }
-
- /* compute areas and centers of original faces */
- for (mf = mface, a = 0; a < totface; a++, mf++) {
- b = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, a) : a;
-
- if (b != ORIGINDEX_NONE) {
- copy_v3_v3(co1, mvert[mf->v1].co);
- copy_v3_v3(co2, mvert[mf->v2].co);
- copy_v3_v3(co3, mvert[mf->v3].co);
-
- add_v3_v3(facecenter[b], co1);
- add_v3_v3(facecenter[b], co2);
- add_v3_v3(facecenter[b], co3);
-
- if (mf->v4) {
- copy_v3_v3(co4, mvert[mf->v4].co);
- add_v3_v3(facecenter[b], co4);
- facearea[b] += area_quad_v3(co1, co2, co3, co4);
- facetotvert[b] += 4;
- }
- else {
- facearea[b] += area_tri_v3(co1, co2, co3);
- facetotvert[b] += 3;
- }
- }
- }
-
- for (a = 0; a < totorigface; a++)
- if (facetotvert[a] > 0)
- mul_v3_fl(facecenter[a], 1.0f / facetotvert[a]);
-
- /* for conversion from BU area / pixel area to reference screen size */
- BKE_mesh_texspace_get(me, 0, 0, size);
- fac = ((size[0] + size[1] + size[2]) / 3.0f) / part->simplify_refsize;
- fac = fac * fac;
-
- powrate = log(0.5f) / log(part->simplify_rate * 0.5f);
- if (part->simplify_flag & PART_SIMPLIFY_VIEWPORT)
- vprate = pow(1.0f - part->simplify_viewport, 5.0);
- else
- vprate = 1.0;
-
- /* set simplification parameters per original face */
- for (a = 0, elem = elems; a < totorigface; a++, elem++) {
- area = psys_render_projected_area(ctx->sim.psys, facecenter[a], facearea[a], vprate, &viewport);
- arearatio = fac * area / facearea[a];
-
- if ((arearatio < 1.0f || viewport < 1.0f) && elem->totchild) {
- /* lambda is percentage of elements to keep */
- lambda = (arearatio < 1.0f) ? powf(arearatio, powrate) : 1.0f;
- lambda *= viewport;
-
- lambda = MAX2(lambda, 1.0f / elem->totchild);
-
- /* compute transition region */
- t = part->simplify_transition;
- elem->t = (lambda - t < 0.0f) ? lambda : (lambda + t > 1.0f) ? 1.0f - lambda : t;
- elem->reduce = 1;
-
- /* scale at end and beginning of the transition region */
- elem->scalemax = (lambda + t < 1.0f) ? 1.0f / lambda : 1.0f / (1.0f - elem->t * elem->t / t);
- elem->scalemin = (lambda + t < 1.0f) ? 0.0f : elem->scalemax * (1.0f - elem->t / t);
-
- elem->scalemin = sqrtf(elem->scalemin);
- elem->scalemax = sqrtf(elem->scalemax);
-
- /* clamp scaling */
- scaleclamp = (float)min_ii(elem->totchild, 10);
- elem->scalemin = MIN2(scaleclamp, elem->scalemin);
- elem->scalemax = MIN2(scaleclamp, elem->scalemax);
-
- /* extend lambda to include transition */
- lambda = lambda + elem->t;
- if (lambda > 1.0f)
- lambda = 1.0f;
- }
- else {
- lambda = arearatio;
-
- elem->scalemax = 1.0f; //sqrt(lambda);
- elem->scalemin = 1.0f; //sqrt(lambda);
- elem->reduce = 0;
- }
-
- elem->lambda = lambda;
- elem->scalemin = sqrtf(elem->scalemin);
- elem->scalemax = sqrtf(elem->scalemax);
- elem->curchild = 0;
- }
-
- MEM_freeN(facearea);
- MEM_freeN(facecenter);
- MEM_freeN(facetotvert);
-
- /* move indices and set random number skipping */
- ctx->skip = MEM_callocN(sizeof(int) * tot, "SimplificationSkip");
-
- skipped = 0;
- for (a = 0, newtot = 0; a < tot; a++) {
- b = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, ctx->index[a]) : ctx->index[a];
-
- if (b != ORIGINDEX_NONE) {
- if (elems[b].curchild++ < ceil(elems[b].lambda * elems[b].totchild)) {
- ctx->index[newtot] = ctx->index[a];
- ctx->skip[newtot] = skipped;
- skipped = 0;
- newtot++;
- }
- else skipped++;
- }
- else skipped++;
- }
-
- for (a = 0, elem = elems; a < totorigface; a++, elem++)
- elem->curchild = 0;
-
- return newtot;
-}
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
deleted file mode 100644
index efaf1f9df2b..00000000000
--- a/source/blender/blenkernel/intern/particle_system.c
+++ /dev/null
@@ -1,4362 +0,0 @@
-/*
- * ***** 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) 2007 by Janne Karhu.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): Raul Fernandez Hernandez (Farsthary), Stephen Swhitehorn.
- *
- * Adaptive time step
- * Classical SPH
- * Copyright 2011-2012 AutoCRC
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/blenkernel/intern/particle_system.c
- * \ingroup bke
- */
-
-
-#include <stddef.h>
-
-#include <stdlib.h>
-#include <math.h>
-#include <string.h>
-
-#include "MEM_guardedalloc.h"
-
-#include "DNA_anim_types.h"
-#include "DNA_boid_types.h"
-#include "DNA_particle_types.h"
-#include "DNA_mesh_types.h"
-#include "DNA_meshdata_types.h"
-#include "DNA_modifier_types.h"
-#include "DNA_object_force.h"
-#include "DNA_object_types.h"
-#include "DNA_curve_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_texture_types.h"
-#include "DNA_listBase.h"
-
-#include "BLI_utildefines.h"
-#include "BLI_edgehash.h"
-#include "BLI_rand.h"
-#include "BLI_jitter.h"
-#include "BLI_math.h"
-#include "BLI_blenlib.h"
-#include "BLI_kdtree.h"
-#include "BLI_kdopbvh.h"
-#include "BLI_sort.h"
-#include "BLI_task.h"
-#include "BLI_threads.h"
-#include "BLI_linklist.h"
-
-#include "BKE_animsys.h"
-#include "BKE_boids.h"
-#include "BKE_cdderivedmesh.h"
-#include "BKE_collision.h"
-#include "BKE_colortools.h"
-#include "BKE_effect.h"
-#include "BKE_library_query.h"
-#include "BKE_particle.h"
-#include "BKE_global.h"
-
-#include "BKE_DerivedMesh.h"
-#include "BKE_object.h"
-#include "BKE_material.h"
-#include "BKE_cloth.h"
-#include "BKE_lattice.h"
-#include "BKE_pointcache.h"
-#include "BKE_mesh.h"
-#include "BKE_modifier.h"
-#include "BKE_scene.h"
-#include "BKE_bvhutils.h"
-#include "BKE_depsgraph.h"
-
-#include "PIL_time.h"
-
-#include "RE_shader_ext.h"
-
-/* fluid sim particle import */
-#ifdef WITH_MOD_FLUID
-#include "DNA_object_fluidsim.h"
-#include "LBM_fluidsim.h"
-#include <zlib.h>
-#include <string.h>
-
-#endif // WITH_MOD_FLUID
-
-static ThreadRWMutex psys_bvhtree_rwlock = BLI_RWLOCK_INITIALIZER;
-
-/************************************************/
-/* Reacting to system events */
-/************************************************/
-
-static int particles_are_dynamic(ParticleSystem *psys)
-{
- if (psys->pointcache->flag & PTCACHE_BAKED)
- return 0;
-
- if (psys->part->type == PART_HAIR)
- return psys->flag & PSYS_HAIR_DYNAMICS;
- else
- return ELEM(psys->part->phystype, PART_PHYS_NEWTON, PART_PHYS_BOIDS, PART_PHYS_FLUID);
-}
-
-float psys_get_current_display_percentage(ParticleSystem *psys)
-{
- ParticleSettings *part=psys->part;
-
- if ((psys->renderdata && !particles_are_dynamic(psys)) || /* non-dynamic particles can be rendered fully */
- (part->child_nbr && part->childtype) || /* display percentage applies to children */
- (psys->pointcache->flag & PTCACHE_BAKING)) /* baking is always done with full amount */
- {
- return 1.0f;
- }
-
- return psys->part->disp/100.0f;
-}
-
-static int tot_particles(ParticleSystem *psys, PTCacheID *pid)
-{
- if (pid && psys->pointcache->flag & PTCACHE_EXTERNAL)
- return pid->cache->totpoint;
- else if (psys->part->distr == PART_DISTR_GRID && psys->part->from != PART_FROM_VERT)
- return psys->part->grid_res * psys->part->grid_res * psys->part->grid_res - psys->totunexist;
- else
- return psys->part->totpart - psys->totunexist;
-}
-
-void psys_reset(ParticleSystem *psys, int mode)
-{
- PARTICLE_P;
-
- if (ELEM(mode, PSYS_RESET_ALL, PSYS_RESET_DEPSGRAPH)) {
- if (mode == PSYS_RESET_ALL || !(psys->flag & PSYS_EDITED)) {
- /* don't free if not absolutely necessary */
- if (psys->totpart != tot_particles(psys, NULL)) {
- psys_free_particles(psys);
- psys->totpart= 0;
- }
-
- psys->totkeyed= 0;
- psys->flag &= ~(PSYS_HAIR_DONE|PSYS_KEYED);
-
- if (psys->edit && psys->free_edit) {
- psys->free_edit(psys->edit);
- psys->edit = NULL;
- psys->free_edit = NULL;
- }
- }
- }
- else if (mode == PSYS_RESET_CACHE_MISS) {
- /* set all particles to be skipped */
- LOOP_PARTICLES
- pa->flag |= PARS_NO_DISP;
- }
-
- /* reset children */
- if (psys->child) {
- MEM_freeN(psys->child);
- psys->child= NULL;
- }
-
- psys->totchild= 0;
-
- /* reset path cache */
- psys_free_path_cache(psys, psys->edit);
-
- /* reset point cache */
- BKE_ptcache_invalidate(psys->pointcache);
-
- if (psys->fluid_springs) {
- MEM_freeN(psys->fluid_springs);
- psys->fluid_springs = NULL;
- }
-
- psys->tot_fluidsprings = psys->alloc_fluidsprings = 0;
-}
-
-static void realloc_particles(ParticleSimulationData *sim, int new_totpart)
-{
- ParticleSystem *psys = sim->psys;
- ParticleSettings *part = psys->part;
- ParticleData *newpars = NULL;
- BoidParticle *newboids = NULL;
- PARTICLE_P;
- int totpart, totsaved = 0;
-
- if (new_totpart<0) {
- if ((part->distr == PART_DISTR_GRID) && (part->from != PART_FROM_VERT)) {
- totpart= part->grid_res;
- totpart*=totpart*totpart;
- }
- else
- totpart=part->totpart;
- }
- else
- totpart=new_totpart;
-
- if (totpart != psys->totpart) {
- if (psys->edit && psys->free_edit) {
- psys->free_edit(psys->edit);
- psys->edit = NULL;
- psys->free_edit = NULL;
- }
-
- if (totpart) {
- newpars= MEM_callocN(totpart*sizeof(ParticleData), "particles");
- if (newpars == NULL)
- return;
-
- if (psys->part->phystype == PART_PHYS_BOIDS) {
- newboids= MEM_callocN(totpart*sizeof(BoidParticle), "boid particles");
-
- if (newboids == NULL) {
- /* allocation error! */
- if (newpars)
- MEM_freeN(newpars);
- return;
- }
- }
- }
-
- if (psys->particles) {
- totsaved=MIN2(psys->totpart,totpart);
- /*save old pars*/
- if (totsaved) {
- memcpy(newpars,psys->particles,totsaved*sizeof(ParticleData));
-
- if (psys->particles->boid)
- memcpy(newboids, psys->particles->boid, totsaved*sizeof(BoidParticle));
- }
-
- if (psys->particles->keys)
- MEM_freeN(psys->particles->keys);
-
- if (psys->particles->boid)
- MEM_freeN(psys->particles->boid);
-
- for (p=0, pa=newpars; p<totsaved; p++, pa++) {
- if (pa->keys) {
- pa->keys= NULL;
- pa->totkey= 0;
- }
- }
-
- for (p=totsaved, pa=psys->particles+totsaved; p<psys->totpart; p++, pa++)
- if (pa->hair) MEM_freeN(pa->hair);
-
- MEM_freeN(psys->particles);
- psys_free_pdd(psys);
- }
-
- psys->particles=newpars;
- psys->totpart=totpart;
-
- if (newboids) {
- LOOP_PARTICLES
- pa->boid = newboids++;
- }
- }
-
- if (psys->child) {
- MEM_freeN(psys->child);
- psys->child=NULL;
- psys->totchild=0;
- }
-}
-
-int psys_get_child_number(Scene *scene, ParticleSystem *psys)
-{
- int nbr;
-
- if (!psys->part->childtype)
- return 0;
-
- if (psys->renderdata)
- nbr= psys->part->ren_child_nbr;
- else
- nbr= psys->part->child_nbr;
-
- return get_render_child_particle_number(&scene->r, nbr, psys->renderdata != NULL);
-}
-
-int psys_get_tot_child(Scene *scene, ParticleSystem *psys)
-{
- return psys->totpart*psys_get_child_number(scene, psys);
-}
-
-/************************************************/
-/* Distribution */
-/************************************************/
-
-void psys_calc_dmcache(Object *ob, DerivedMesh *dm_final, DerivedMesh *dm_deformed, ParticleSystem *psys)
-{
- /* use for building derived mesh mapping info:
- *
- * node: the allocated links - total derived mesh element count
- * nodearray: the array of nodes aligned with the base mesh's elements, so
- * each original elements can reference its derived elements
- */
- Mesh *me= (Mesh*)ob->data;
- bool use_modifier_stack= psys->part->use_modifier_stack;
- PARTICLE_P;
-
- /* CACHE LOCATIONS */
- if (!dm_final->deformedOnly) {
- /* Will use later to speed up subsurf/derivedmesh */
- LinkNode *node, *nodedmelem, **nodearray;
- int totdmelem, totelem, i, *origindex, *origindex_poly = NULL;
-
- if (psys->part->from == PART_FROM_VERT) {
- totdmelem= dm_final->getNumVerts(dm_final);
-
- if (use_modifier_stack) {
- totelem= totdmelem;
- origindex= NULL;
- }
- else {
- totelem= me->totvert;
- origindex= dm_final->getVertDataArray(dm_final, CD_ORIGINDEX);
- }
- }
- else { /* FROM_FACE/FROM_VOLUME */
- totdmelem= dm_final->getNumTessFaces(dm_final);
-
- if (use_modifier_stack) {
- totelem= totdmelem;
- origindex= NULL;
- origindex_poly= NULL;
- }
- else {
- totelem = dm_deformed->getNumTessFaces(dm_deformed);
- origindex = dm_final->getTessFaceDataArray(dm_final, CD_ORIGINDEX);
-
- /* for face lookups we need the poly origindex too */
- origindex_poly= dm_final->getPolyDataArray(dm_final, CD_ORIGINDEX);
- if (origindex_poly == NULL) {
- origindex= NULL;
- }
- }
- }
-
- nodedmelem= MEM_callocN(sizeof(LinkNode)*totdmelem, "psys node elems");
- nodearray= MEM_callocN(sizeof(LinkNode *)*totelem, "psys node array");
-
- for (i=0, node=nodedmelem; i<totdmelem; i++, node++) {
- int origindex_final;
- node->link = SET_INT_IN_POINTER(i);
-
- /* may be vertex or face origindex */
- if (use_modifier_stack) {
- origindex_final = i;
- }
- else {
- origindex_final = origindex ? origindex[i] : ORIGINDEX_NONE;
-
- /* if we have a poly source, do an index lookup */
- if (origindex_poly && origindex_final != ORIGINDEX_NONE) {
- origindex_final = origindex_poly[origindex_final];
- }
- }
-
- if (origindex_final != ORIGINDEX_NONE && origindex_final < totelem) {
- if (nodearray[origindex_final]) {
- /* prepend */
- node->next = nodearray[origindex_final];
- nodearray[origindex_final] = node;
- }
- else {
- nodearray[origindex_final] = node;
- }
- }
- }
-
- /* cache the verts/faces! */
- LOOP_PARTICLES {
- if (pa->num < 0) {
- pa->num_dmcache = DMCACHE_NOTFOUND;
- continue;
- }
-
- if (use_modifier_stack) {
- if (pa->num < totelem)
- pa->num_dmcache = DMCACHE_ISCHILD;
- else
- pa->num_dmcache = DMCACHE_NOTFOUND;
- }
- else {
- if (psys->part->from == PART_FROM_VERT) {
- if (pa->num < totelem && nodearray[pa->num])
- pa->num_dmcache= GET_INT_FROM_POINTER(nodearray[pa->num]->link);
- else
- pa->num_dmcache = DMCACHE_NOTFOUND;
- }
- else { /* FROM_FACE/FROM_VOLUME */
- pa->num_dmcache = psys_particle_dm_face_lookup(dm_final, dm_deformed, pa->num, pa->fuv, nodearray);
- }
- }
- }
-
- MEM_freeN(nodearray);
- MEM_freeN(nodedmelem);
- }
- else {
- /* TODO PARTICLE, make the following line unnecessary, each function
- * should know to use the num or num_dmcache, set the num_dmcache to
- * an invalid value, just in case */
-
- LOOP_PARTICLES {
- pa->num_dmcache = DMCACHE_NOTFOUND;
- }
- }
-}
-
-/* threaded child particle distribution and path caching */
-void psys_thread_context_init(ParticleThreadContext *ctx, ParticleSimulationData *sim)
-{
- memset(ctx, 0, sizeof(ParticleThreadContext));
- ctx->sim = *sim;
- ctx->dm = ctx->sim.psmd->dm_final;
- ctx->ma = give_current_material(sim->ob, sim->psys->part->omat);
-}
-
-#define MAX_PARTICLES_PER_TASK 256 /* XXX arbitrary - maybe use at least number of points instead for better balancing? */
-
-BLI_INLINE int ceil_ii(int a, int b)
-{
- return (a + b - 1) / b;
-}
-
-void psys_tasks_create(ParticleThreadContext *ctx, int startpart, int endpart, ParticleTask **r_tasks, int *r_numtasks)
-{
- ParticleTask *tasks;
- int numtasks = ceil_ii((endpart - startpart), MAX_PARTICLES_PER_TASK);
- float particles_per_task = (float)(endpart - startpart) / (float)numtasks, p, pnext;
- int i;
-
- tasks = MEM_callocN(sizeof(ParticleTask) * numtasks, "ParticleThread");
- *r_numtasks = numtasks;
- *r_tasks = tasks;
-
- p = (float)startpart;
- for (i = 0; i < numtasks; i++, p = pnext) {
- pnext = p + particles_per_task;
-
- tasks[i].ctx = ctx;
- tasks[i].begin = (int)p;
- tasks[i].end = min_ii((int)pnext, endpart);
- }
-}
-
-void psys_tasks_free(ParticleTask *tasks, int numtasks)
-{
- int i;
-
- /* threads */
- for (i = 0; i < numtasks; ++i) {
- if (tasks[i].rng)
- BLI_rng_free(tasks[i].rng);
- if (tasks[i].rng_path)
- BLI_rng_free(tasks[i].rng_path);
- }
-
- MEM_freeN(tasks);
-}
-
-void psys_thread_context_free(ParticleThreadContext *ctx)
-{
- /* path caching */
- if (ctx->vg_length)
- MEM_freeN(ctx->vg_length);
- if (ctx->vg_clump)
- MEM_freeN(ctx->vg_clump);
- if (ctx->vg_kink)
- MEM_freeN(ctx->vg_kink);
- if (ctx->vg_rough1)
- MEM_freeN(ctx->vg_rough1);
- if (ctx->vg_rough2)
- MEM_freeN(ctx->vg_rough2);
- if (ctx->vg_roughe)
- MEM_freeN(ctx->vg_roughe);
-
- if (ctx->sim.psys->lattice_deform_data) {
- end_latt_deform(ctx->sim.psys->lattice_deform_data);
- ctx->sim.psys->lattice_deform_data = NULL;
- }
-
- /* distribution */
- if (ctx->jit) MEM_freeN(ctx->jit);
- if (ctx->jitoff) MEM_freeN(ctx->jitoff);
- if (ctx->weight) MEM_freeN(ctx->weight);
- if (ctx->index) MEM_freeN(ctx->index);
- if (ctx->skip) MEM_freeN(ctx->skip);
- if (ctx->seams) MEM_freeN(ctx->seams);
- //if (ctx->vertpart) MEM_freeN(ctx->vertpart);
- BLI_kdtree_free(ctx->tree);
-
- if (ctx->clumpcurve != NULL) {
- curvemapping_free(ctx->clumpcurve);
- }
- if (ctx->roughcurve != NULL) {
- curvemapping_free(ctx->roughcurve);
- }
-}
-
-static void initialize_particle_texture(ParticleSimulationData *sim, ParticleData *pa, int p)
-{
- ParticleSystem *psys = sim->psys;
- ParticleSettings *part = psys->part;
- ParticleTexture ptex;
-
- psys_get_texture(sim, pa, &ptex, PAMAP_INIT, 0.f);
-
- switch (part->type) {
- case PART_EMITTER:
- if (ptex.exist < psys_frand(psys, p+125))
- pa->flag |= PARS_UNEXIST;
- pa->time = part->sta + (part->end - part->sta)*ptex.time;
- break;
- case PART_HAIR:
- if (ptex.exist < psys_frand(psys, p+125))
- pa->flag |= PARS_UNEXIST;
- pa->time = 0.f;
- break;
- case PART_FLUID:
- break;
- }
-}
-
-/* set particle parameters that don't change during particle's life */
-void initialize_particle(ParticleSimulationData *sim, ParticleData *pa)
-{
- ParticleSettings *part = sim->psys->part;
- float birth_time = (float)(pa - sim->psys->particles) / (float)sim->psys->totpart;
-
- pa->flag &= ~PARS_UNEXIST;
- pa->time = part->sta + (part->end - part->sta) * birth_time;
-
- pa->hair_index = 0;
- /* we can't reset to -1 anymore since we've figured out correct index in distribute_particles */
- /* usage other than straight after distribute has to handle this index by itself - jahka*/
- //pa->num_dmcache = DMCACHE_NOTFOUND; /* assume we don't have a derived mesh face */
-}
-
-static void initialize_all_particles(ParticleSimulationData *sim)
-{
- ParticleSystem *psys = sim->psys;
- ParticleSettings *part = psys->part;
- /* Grid distributionsets UNEXIST flag, need to take care of
- * it here because later this flag is being reset.
- *
- * We can't do it for any distribution, because it'll then
- * conflict with texture influence, which does not free
- * unexisting particles and only sets flag.
- *
- * It's not so bad, because only grid distribution sets
- * UNEXIST flag.
- */
- const bool emit_from_volume_grid = (part->distr == PART_DISTR_GRID) &&
- (!ELEM(part->from, PART_FROM_VERT, PART_FROM_CHILD));
- PARTICLE_P;
- LOOP_PARTICLES {
- if (!(emit_from_volume_grid && (pa->flag & PARS_UNEXIST) != 0)) {
- initialize_particle(sim, pa);
- }
- }
-}
-
-static void free_unexisting_particles(ParticleSimulationData *sim)
-{
- ParticleSystem *psys = sim->psys;
- PARTICLE_P;
-
- psys->totunexist = 0;
-
- LOOP_PARTICLES {
- if (pa->flag & PARS_UNEXIST) {
- psys->totunexist++;
- }
- }
-
- if (psys->totpart && psys->totunexist == psys->totpart) {
- if (psys->particles->boid)
- MEM_freeN(psys->particles->boid);
-
- MEM_freeN(psys->particles);
- psys->particles = NULL;
- psys->totpart = psys->totunexist = 0;
- }
-
- if (psys->totunexist) {
- int newtotpart = psys->totpart - psys->totunexist;
- ParticleData *npa, *newpars;
-
- npa = newpars = MEM_callocN(newtotpart * sizeof(ParticleData), "particles");
-
- for (p=0, pa=psys->particles; p<newtotpart; p++, pa++, npa++) {
- while (pa->flag & PARS_UNEXIST)
- pa++;
-
- memcpy(npa, pa, sizeof(ParticleData));
- }
-
- if (psys->particles->boid)
- MEM_freeN(psys->particles->boid);
- MEM_freeN(psys->particles);
- psys->particles = newpars;
- psys->totpart -= psys->totunexist;
-
- if (psys->particles->boid) {
- BoidParticle *newboids = MEM_callocN(psys->totpart * sizeof(BoidParticle), "boid particles");
-
- LOOP_PARTICLES {
- pa->boid = newboids++;
- }
-
- }
- }
-}
-
-static void get_angular_velocity_vector(short avemode, ParticleKey *state, float vec[3])
-{
- switch (avemode) {
- case PART_AVE_VELOCITY:
- copy_v3_v3(vec, state->vel);
- break;
- case PART_AVE_HORIZONTAL:
- {
- float zvec[3];
- zvec[0] = zvec[1] = 0;
- zvec[2] = 1.f;
- cross_v3_v3v3(vec, state->vel, zvec);
- break;
- }
- case PART_AVE_VERTICAL:
- {
- float zvec[3], temp[3];
- zvec[0] = zvec[1] = 0;
- zvec[2] = 1.f;
- cross_v3_v3v3(temp, state->vel, zvec);
- cross_v3_v3v3(vec, temp, state->vel);
- break;
- }
- case PART_AVE_GLOBAL_X:
- vec[0] = 1.f;
- vec[1] = vec[2] = 0;
- break;
- case PART_AVE_GLOBAL_Y:
- vec[1] = 1.f;
- vec[0] = vec[2] = 0;
- break;
- case PART_AVE_GLOBAL_Z:
- vec[2] = 1.f;
- vec[0] = vec[1] = 0;
- break;
- }
-}
-
-void psys_get_birth_coords(ParticleSimulationData *sim, ParticleData *pa, ParticleKey *state, float dtime, float cfra)
-{
- Object *ob = sim->ob;
- ParticleSystem *psys = sim->psys;
- ParticleSettings *part = psys->part;
- ParticleTexture ptex;
- float fac, phasefac, nor[3] = {0,0,0},loc[3],vel[3] = {0.0,0.0,0.0},rot[4],q2[4];
- float r_vel[3],r_ave[3],r_rot[4],vec[3],p_vel[3] = {0.0,0.0,0.0};
- float x_vec[3] = {1.0,0.0,0.0}, utan[3] = {0.0,1.0,0.0}, vtan[3] = {0.0,0.0,1.0}, rot_vec[3] = {0.0,0.0,0.0};
- float q_phase[4];
-
- const bool use_boids = ((part->phystype == PART_PHYS_BOIDS) &&
- (pa->boid != NULL));
- const bool use_tangents = ((use_boids == false) &&
- ((part->tanfac != 0.0f) || (part->rotmode == PART_ROT_NOR_TAN)));
-
- int p = pa - psys->particles;
-
- /* get birth location from object */
- if (use_tangents)
- psys_particle_on_emitter(sim->psmd, part->from,pa->num, pa->num_dmcache, pa->fuv,pa->foffset,loc,nor,utan,vtan,0,0);
- else
- psys_particle_on_emitter(sim->psmd, part->from,pa->num, pa->num_dmcache, pa->fuv,pa->foffset,loc,nor,0,0,0,0);
-
- /* get possible textural influence */
- psys_get_texture(sim, pa, &ptex, PAMAP_IVEL, cfra);
-
- /* particles live in global space so */
- /* let's convert: */
- /* -location */
- mul_m4_v3(ob->obmat, loc);
-
- /* -normal */
- mul_mat3_m4_v3(ob->obmat, nor);
- normalize_v3(nor);
-
- /* -tangent */
- if (use_tangents) {
- //float phase=vg_rot?2.0f*(psys_particle_value_from_verts(sim->psmd->dm,part->from,pa,vg_rot)-0.5f):0.0f;
- float phase=0.0f;
- mul_v3_fl(vtan,-cosf((float)M_PI*(part->tanphase+phase)));
- fac= -sinf((float)M_PI*(part->tanphase+phase));
- madd_v3_v3fl(vtan, utan, fac);
-
- mul_mat3_m4_v3(ob->obmat,vtan);
-
- copy_v3_v3(utan, nor);
- mul_v3_fl(utan,dot_v3v3(vtan,nor));
- sub_v3_v3(vtan, utan);
-
- normalize_v3(vtan);
- }
-
-
- /* -velocity (boids need this even if there's no random velocity) */
- if (part->randfac != 0.0f || (part->phystype==PART_PHYS_BOIDS && pa->boid)) {
- r_vel[0] = 2.0f * (psys_frand(psys, p + 10) - 0.5f);
- r_vel[1] = 2.0f * (psys_frand(psys, p + 11) - 0.5f);
- r_vel[2] = 2.0f * (psys_frand(psys, p + 12) - 0.5f);
-
- mul_mat3_m4_v3(ob->obmat, r_vel);
- normalize_v3(r_vel);
- }
-
- /* -angular velocity */
- if (part->avemode==PART_AVE_RAND) {
- r_ave[0] = 2.0f * (psys_frand(psys, p + 13) - 0.5f);
- r_ave[1] = 2.0f * (psys_frand(psys, p + 14) - 0.5f);
- r_ave[2] = 2.0f * (psys_frand(psys, p + 15) - 0.5f);
-
- mul_mat3_m4_v3(ob->obmat,r_ave);
- normalize_v3(r_ave);
- }
-
- /* -rotation */
- if (part->randrotfac != 0.0f) {
- r_rot[0] = 2.0f * (psys_frand(psys, p + 16) - 0.5f);
- r_rot[1] = 2.0f * (psys_frand(psys, p + 17) - 0.5f);
- r_rot[2] = 2.0f * (psys_frand(psys, p + 18) - 0.5f);
- r_rot[3] = 2.0f * (psys_frand(psys, p + 19) - 0.5f);
- normalize_qt(r_rot);
-
- mat4_to_quat(rot,ob->obmat);
- mul_qt_qtqt(r_rot,r_rot,rot);
- }
-
- if (use_boids) {
- float dvec[3], q[4], mat[3][3];
-
- copy_v3_v3(state->co,loc);
-
- /* boids don't get any initial velocity */
- zero_v3(state->vel);
-
- /* boids store direction in ave */
- if (fabsf(nor[2])==1.0f) {
- sub_v3_v3v3(state->ave, loc, ob->obmat[3]);
- normalize_v3(state->ave);
- }
- else {
- copy_v3_v3(state->ave, nor);
- }
-
- /* calculate rotation matrix */
- project_v3_v3v3(dvec, r_vel, state->ave);
- sub_v3_v3v3(mat[0], state->ave, dvec);
- normalize_v3(mat[0]);
- negate_v3_v3(mat[2], r_vel);
- normalize_v3(mat[2]);
- cross_v3_v3v3(mat[1], mat[2], mat[0]);
-
- /* apply rotation */
- mat3_to_quat_is_ok( q,mat);
- copy_qt_qt(state->rot, q);
- }
- else {
- /* conversion done so now we apply new: */
- /* -velocity from: */
-
- /* *reactions */
- if (dtime > 0.f) {
- sub_v3_v3v3(vel, pa->state.vel, pa->prev_state.vel);
- }
-
- /* *emitter velocity */
- if (dtime != 0.f && part->obfac != 0.f) {
- sub_v3_v3v3(vel, loc, state->co);
- mul_v3_fl(vel, part->obfac/dtime);
- }
-
- /* *emitter normal */
- if (part->normfac != 0.f)
- madd_v3_v3fl(vel, nor, part->normfac);
-
- /* *emitter tangent */
- if (sim->psmd && part->tanfac != 0.f)
- madd_v3_v3fl(vel, vtan, part->tanfac);
-
- /* *emitter object orientation */
- if (part->ob_vel[0] != 0.f) {
- normalize_v3_v3(vec, ob->obmat[0]);
- madd_v3_v3fl(vel, vec, part->ob_vel[0]);
- }
- if (part->ob_vel[1] != 0.f) {
- normalize_v3_v3(vec, ob->obmat[1]);
- madd_v3_v3fl(vel, vec, part->ob_vel[1]);
- }
- if (part->ob_vel[2] != 0.f) {
- normalize_v3_v3(vec, ob->obmat[2]);
- madd_v3_v3fl(vel, vec, part->ob_vel[2]);
- }
-
- /* *texture */
- /* TODO */
-
- /* *random */
- if (part->randfac != 0.f)
- madd_v3_v3fl(vel, r_vel, part->randfac);
-
- /* *particle */
- if (part->partfac != 0.f)
- madd_v3_v3fl(vel, p_vel, part->partfac);
-
- mul_v3_v3fl(state->vel, vel, ptex.ivel);
-
- /* -location from emitter */
- copy_v3_v3(state->co,loc);
-
- /* -rotation */
- unit_qt(state->rot);
-
- if (part->rotmode) {
- bool use_global_space;
-
- /* create vector into which rotation is aligned */
- switch (part->rotmode) {
- case PART_ROT_NOR:
- case PART_ROT_NOR_TAN:
- copy_v3_v3(rot_vec, nor);
- use_global_space = false;
- break;
- case PART_ROT_VEL:
- copy_v3_v3(rot_vec, vel);
- use_global_space = true;
- break;
- case PART_ROT_GLOB_X:
- case PART_ROT_GLOB_Y:
- case PART_ROT_GLOB_Z:
- rot_vec[part->rotmode - PART_ROT_GLOB_X] = 1.0f;
- use_global_space = true;
- break;
- case PART_ROT_OB_X:
- case PART_ROT_OB_Y:
- case PART_ROT_OB_Z:
- copy_v3_v3(rot_vec, ob->obmat[part->rotmode - PART_ROT_OB_X]);
- use_global_space = false;
- break;
- default:
- use_global_space = true;
- break;
- }
-
- /* create rotation quat */
-
-
- if (use_global_space) {
- negate_v3(rot_vec);
- vec_to_quat(q2, rot_vec, OB_POSX, OB_POSZ);
-
- /* randomize rotation quat */
- if (part->randrotfac != 0.0f) {
- interp_qt_qtqt(rot, q2, r_rot, part->randrotfac);
- }
- else {
- copy_qt_qt(rot, q2);
- }
- }
- else {
- /* calculate rotation in local-space */
- float q_obmat[4];
- float q_imat[4];
-
- mat4_to_quat(q_obmat, ob->obmat);
- invert_qt_qt_normalized(q_imat, q_obmat);
-
-
- if (part->rotmode != PART_ROT_NOR_TAN) {
- float rot_vec_local[3];
-
- /* rot_vec */
- negate_v3(rot_vec);
- copy_v3_v3(rot_vec_local, rot_vec);
- mul_qt_v3(q_imat, rot_vec_local);
- normalize_v3(rot_vec_local);
-
- vec_to_quat(q2, rot_vec_local, OB_POSX, OB_POSZ);
- }
- else {
- /* (part->rotmode == PART_ROT_NOR_TAN) */
- float tmat[3][3];
-
- /* note: utan_local is not taken from 'utan', we calculate from rot_vec/vtan */
- /* note: it looks like rotation phase may be applied twice (once with vtan, again below)
- * however this isn't the case - campbell */
- float *rot_vec_local = tmat[0];
- float *vtan_local = tmat[1];
- float *utan_local = tmat[2];
-
- /* use tangents */
- BLI_assert(use_tangents == true);
-
- /* rot_vec */
- copy_v3_v3(rot_vec_local, rot_vec);
- mul_qt_v3(q_imat, rot_vec_local);
-
- /* vtan_local */
- copy_v3_v3(vtan_local, vtan); /* flips, cant use */
- mul_qt_v3(q_imat, vtan_local);
-
- /* ensure orthogonal matrix (rot_vec aligned) */
- cross_v3_v3v3(utan_local, vtan_local, rot_vec_local);
- cross_v3_v3v3(vtan_local, utan_local, rot_vec_local);
-
- /* note: no need to normalize */
- mat3_to_quat(q2, tmat);
- }
-
- /* randomize rotation quat */
- if (part->randrotfac != 0.0f) {
- mul_qt_qtqt(r_rot, r_rot, q_imat);
- interp_qt_qtqt(rot, q2, r_rot, part->randrotfac);
- }
- else {
- copy_qt_qt(rot, q2);
- }
-
- mul_qt_qtqt(rot, q_obmat, rot);
- }
-
- /* rotation phase */
- phasefac = part->phasefac;
- if (part->randphasefac != 0.0f)
- phasefac += part->randphasefac * psys_frand(psys, p + 20);
- axis_angle_to_quat( q_phase,x_vec, phasefac*(float)M_PI);
-
- /* combine base rotation & phase */
- mul_qt_qtqt(state->rot, rot, q_phase);
- }
-
- /* -angular velocity */
-
- zero_v3(state->ave);
-
- if (part->avemode) {
- if (part->avemode == PART_AVE_RAND)
- copy_v3_v3(state->ave, r_ave);
- else
- get_angular_velocity_vector(part->avemode, state, state->ave);
-
- normalize_v3(state->ave);
- mul_v3_fl(state->ave, part->avefac);
- }
- }
-}
-
-/* recursively evaluate emitter parent anim at cfra */
-static void evaluate_emitter_anim(Scene *scene, Object *ob, float cfra)
-{
- if (ob->parent)
- evaluate_emitter_anim(scene, ob->parent, cfra);
-
- /* we have to force RECALC_ANIM here since where_is_objec_time only does drivers */
- BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, cfra, ADT_RECALC_ANIM);
- BKE_object_where_is_calc_time(scene, ob, cfra);
-}
-
-/* sets particle to the emitter surface with initial velocity & rotation */
-void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime, float cfra)
-{
- ParticleSystem *psys = sim->psys;
- ParticleSettings *part;
- ParticleTexture ptex;
- int p = pa - psys->particles;
- part=psys->part;
-
- /* get precise emitter matrix if particle is born */
- if (part->type!=PART_HAIR && dtime > 0.f && pa->time < cfra && pa->time >= sim->psys->cfra) {
- evaluate_emitter_anim(sim->scene, sim->ob, pa->time);
-
- psys->flag |= PSYS_OB_ANIM_RESTORE;
- }
-
- psys_get_birth_coords(sim, pa, &pa->state, dtime, cfra);
-
- /* Initialize particle settings which depends on texture.
- *
- * We could only do it now because we'll need to know coordinate
- * before sampling the texture.
- */
- initialize_particle_texture(sim, pa, p);
-
- if (part->phystype==PART_PHYS_BOIDS && pa->boid) {
- BoidParticle *bpa = pa->boid;
-
- /* and gravity in r_ve */
- bpa->gravity[0] = bpa->gravity[1] = 0.0f;
- bpa->gravity[2] = -1.0f;
- if ((sim->scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) &&
- (sim->scene->physics_settings.gravity[2] != 0.0f))
- {
- bpa->gravity[2] = sim->scene->physics_settings.gravity[2];
- }
-
- bpa->data.health = part->boids->health;
- bpa->data.mode = eBoidMode_InAir;
- bpa->data.state_id = ((BoidState*)part->boids->states.first)->id;
- bpa->data.acc[0]=bpa->data.acc[1]=bpa->data.acc[2]=0.0f;
- }
-
- if (part->type == PART_HAIR) {
- pa->lifetime = 100.0f;
- }
- else {
- /* initialize the lifetime, in case the texture coordinates
- * are from Particles/Strands, which would cause undefined values
- */
- pa->lifetime = part->lifetime * (1.0f - part->randlife * psys_frand(psys, p + 21));
- pa->dietime = pa->time + pa->lifetime;
-
- /* get possible textural influence */
- psys_get_texture(sim, pa, &ptex, PAMAP_LIFE, cfra);
-
- pa->lifetime = part->lifetime * ptex.life;
-
- if (part->randlife != 0.0f)
- pa->lifetime *= 1.0f - part->randlife * psys_frand(psys, p + 21);
- }
-
- pa->dietime = pa->time + pa->lifetime;
-
- if (sim->psys->pointcache && sim->psys->pointcache->flag & PTCACHE_BAKED &&
- sim->psys->pointcache->mem_cache.first) {
- float dietime = psys_get_dietime_from_cache(sim->psys->pointcache, p);
- pa->dietime = MIN2(pa->dietime, dietime);
- }
-
- if (pa->time > cfra)
- pa->alive = PARS_UNBORN;
- else if (pa->dietime <= cfra)
- pa->alive = PARS_DEAD;
- else
- pa->alive = PARS_ALIVE;
-
- pa->state.time = cfra;
-}
-static void reset_all_particles(ParticleSimulationData *sim, float dtime, float cfra, int from)
-{
- ParticleData *pa;
- int p, totpart=sim->psys->totpart;
-
- for (p=from, pa=sim->psys->particles+from; p<totpart; p++, pa++)
- reset_particle(sim, pa, dtime, cfra);
-}
-/************************************************/
-/* Particle targets */
-/************************************************/
-ParticleSystem *psys_get_target_system(Object *ob, ParticleTarget *pt)
-{
- ParticleSystem *psys = NULL;
-
- if (pt->ob == NULL || pt->ob == ob)
- psys = BLI_findlink(&ob->particlesystem, pt->psys-1);
- else
- psys = BLI_findlink(&pt->ob->particlesystem, pt->psys-1);
-
- if (psys)
- pt->flag |= PTARGET_VALID;
- else
- pt->flag &= ~PTARGET_VALID;
-
- return psys;
-}
-/************************************************/
-/* Keyed particles */
-/************************************************/
-/* Counts valid keyed targets */
-void psys_count_keyed_targets(ParticleSimulationData *sim)
-{
- ParticleSystem *psys = sim->psys, *kpsys;
- ParticleTarget *pt = psys->targets.first;
- int keys_valid = 1;
- psys->totkeyed = 0;
-
- for (; pt; pt=pt->next) {
- kpsys = psys_get_target_system(sim->ob, pt);
-
- if (kpsys && kpsys->totpart) {
- psys->totkeyed += keys_valid;
- if (psys->flag & PSYS_KEYED_TIMING && pt->duration != 0.0f)
- psys->totkeyed += 1;
- }
- else {
- keys_valid = 0;
- }
- }
-
- psys->totkeyed *= psys->flag & PSYS_KEYED_TIMING ? 1 : psys->part->keyed_loops;
-}
-
-static void set_keyed_keys(ParticleSimulationData *sim)
-{
- ParticleSystem *psys = sim->psys;
- ParticleSimulationData ksim= {0};
- ParticleTarget *pt;
- PARTICLE_P;
- ParticleKey *key;
- int totpart = psys->totpart, k, totkeys = psys->totkeyed;
- int keyed_flag = 0;
-
- ksim.scene= sim->scene;
-
- /* no proper targets so let's clear and bail out */
- if (psys->totkeyed==0) {
- free_keyed_keys(psys);
- psys->flag &= ~PSYS_KEYED;
- return;
- }
-
- if (totpart && psys->particles->totkey != totkeys) {
- free_keyed_keys(psys);
-
- key = MEM_callocN(totpart*totkeys*sizeof(ParticleKey), "Keyed keys");
-
- LOOP_PARTICLES {
- pa->keys = key;
- pa->totkey = totkeys;
- key += totkeys;
- }
- }
-
- psys->flag &= ~PSYS_KEYED;
-
-
- pt = psys->targets.first;
- for (k=0; k<totkeys; k++) {
- ksim.ob = pt->ob ? pt->ob : sim->ob;
- ksim.psys = BLI_findlink(&ksim.ob->particlesystem, pt->psys - 1);
- keyed_flag = (ksim.psys->flag & PSYS_KEYED);
- ksim.psys->flag &= ~PSYS_KEYED;
-
- LOOP_PARTICLES {
- key = pa->keys + k;
- key->time = -1.0; /* use current time */
-
- psys_get_particle_state(&ksim, p%ksim.psys->totpart, key, 1);
-
- if (psys->flag & PSYS_KEYED_TIMING) {
- key->time = pa->time + pt->time;
- if (pt->duration != 0.0f && k+1 < totkeys) {
- copy_particle_key(key+1, key, 1);
- (key+1)->time = pa->time + pt->time + pt->duration;
- }
- }
- else if (totkeys > 1)
- key->time = pa->time + (float)k / (float)(totkeys - 1) * pa->lifetime;
- else
- key->time = pa->time;
- }
-
- if (psys->flag & PSYS_KEYED_TIMING && pt->duration!=0.0f)
- k++;
-
- ksim.psys->flag |= keyed_flag;
-
- pt = (pt->next && pt->next->flag & PTARGET_VALID) ? pt->next : psys->targets.first;
- }
-
- psys->flag |= PSYS_KEYED;
-}
-
-/************************************************/
-/* Point Cache */
-/************************************************/
-void psys_make_temp_pointcache(Object *ob, ParticleSystem *psys)
-{
- PointCache *cache = psys->pointcache;
-
- if (cache->flag & PTCACHE_DISK_CACHE && BLI_listbase_is_empty(&cache->mem_cache)) {
- PTCacheID pid;
- BKE_ptcache_id_from_particles(&pid, ob, psys);
- cache->flag &= ~PTCACHE_DISK_CACHE;
- BKE_ptcache_disk_to_mem(&pid);
- cache->flag |= PTCACHE_DISK_CACHE;
- }
-}
-static void psys_clear_temp_pointcache(ParticleSystem *psys)
-{
- if (psys->pointcache->flag & PTCACHE_DISK_CACHE)
- BKE_ptcache_free_mem(&psys->pointcache->mem_cache);
-}
-void psys_get_pointcache_start_end(Scene *scene, ParticleSystem *psys, int *sfra, int *efra)
-{
- ParticleSettings *part = psys->part;
-
- *sfra = max_ii(1, (int)part->sta);
- *efra = min_ii((int)(part->end + part->lifetime + 1.0f), max_ii(scene->r.pefra, scene->r.efra));
-}
-
-/************************************************/
-/* Effectors */
-/************************************************/
-static void psys_update_particle_bvhtree(ParticleSystem *psys, float cfra)
-{
- if (psys) {
- PARTICLE_P;
- int totpart = 0;
- bool need_rebuild;
-
- BLI_rw_mutex_lock(&psys_bvhtree_rwlock, THREAD_LOCK_READ);
- need_rebuild = !psys->bvhtree || psys->bvhtree_frame != cfra;
- BLI_rw_mutex_unlock(&psys_bvhtree_rwlock);
-
- if (need_rebuild) {
- LOOP_SHOWN_PARTICLES {
- totpart++;
- }
-
- BLI_rw_mutex_lock(&psys_bvhtree_rwlock, THREAD_LOCK_WRITE);
-
- BLI_bvhtree_free(psys->bvhtree);
- psys->bvhtree = BLI_bvhtree_new(totpart, 0.0, 4, 6);
-
- LOOP_SHOWN_PARTICLES {
- if (pa->alive == PARS_ALIVE) {
- if (pa->state.time == cfra)
- BLI_bvhtree_insert(psys->bvhtree, p, pa->prev_state.co, 1);
- else
- BLI_bvhtree_insert(psys->bvhtree, p, pa->state.co, 1);
- }
- }
- BLI_bvhtree_balance(psys->bvhtree);
-
- psys->bvhtree_frame = cfra;
-
- BLI_rw_mutex_unlock(&psys_bvhtree_rwlock);
- }
- }
-}
-void psys_update_particle_tree(ParticleSystem *psys, float cfra)
-{
- if (psys) {
- PARTICLE_P;
- int totpart = 0;
-
- if (!psys->tree || psys->tree_frame != cfra) {
- LOOP_SHOWN_PARTICLES {
- totpart++;
- }
-
- BLI_kdtree_free(psys->tree);
- psys->tree = BLI_kdtree_new(psys->totpart);
-
- LOOP_SHOWN_PARTICLES {
- if (pa->alive == PARS_ALIVE) {
- if (pa->state.time == cfra)
- BLI_kdtree_insert(psys->tree, p, pa->prev_state.co);
- else
- BLI_kdtree_insert(psys->tree, p, pa->state.co);
- }
- }
- BLI_kdtree_balance(psys->tree);
-
- psys->tree_frame = cfra;
- }
- }
-}
-
-static void psys_update_effectors(ParticleSimulationData *sim)
-{
- pdEndEffectors(&sim->psys->effectors);
- sim->psys->effectors = pdInitEffectors(sim->scene, sim->ob, sim->psys,
- sim->psys->part->effector_weights, true);
- precalc_guides(sim, sim->psys->effectors);
-}
-
-static void integrate_particle(ParticleSettings *part, ParticleData *pa, float dtime, float *external_acceleration,
- void (*force_func)(void *forcedata, ParticleKey *state, float *force, float *impulse),
- void *forcedata)
-{
-#define ZERO_F43 {{0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f}}
-
- ParticleKey states[5];
- float force[3], acceleration[3], impulse[3], dx[4][3] = ZERO_F43, dv[4][3] = ZERO_F43, oldpos[3];
- float pa_mass= (part->flag & PART_SIZEMASS ? part->mass * pa->size : part->mass);
- int i, steps=1;
- int integrator = part->integrator;
-
-#undef ZERO_F43
-
- copy_v3_v3(oldpos, pa->state.co);
-
- /* Verlet integration behaves strangely with moving emitters, so do first step with euler. */
- if (pa->prev_state.time < 0.f && integrator == PART_INT_VERLET)
- integrator = PART_INT_EULER;
-
- switch (integrator) {
- case PART_INT_EULER:
- steps=1;
- break;
- case PART_INT_MIDPOINT:
- steps=2;
- break;
- case PART_INT_RK4:
- steps=4;
- break;
- case PART_INT_VERLET:
- steps=1;
- break;
- }
-
- for (i=0; i<steps; i++) {
- copy_particle_key(states + i, &pa->state, 1);
- }
-
- states->time = 0.f;
-
- for (i=0; i<steps; i++) {
- zero_v3(force);
- zero_v3(impulse);
-
- force_func(forcedata, states+i, force, impulse);
-
- /* force to acceleration*/
- mul_v3_v3fl(acceleration, force, 1.0f/pa_mass);
-
- if (external_acceleration)
- add_v3_v3(acceleration, external_acceleration);
-
- /* calculate next state */
- add_v3_v3(states[i].vel, impulse);
-
- switch (integrator) {
- case PART_INT_EULER:
- madd_v3_v3v3fl(pa->state.co, states->co, states->vel, dtime);
- madd_v3_v3v3fl(pa->state.vel, states->vel, acceleration, dtime);
- break;
- case PART_INT_MIDPOINT:
- if (i==0) {
- madd_v3_v3v3fl(states[1].co, states->co, states->vel, dtime*0.5f);
- madd_v3_v3v3fl(states[1].vel, states->vel, acceleration, dtime*0.5f);
- states[1].time = dtime*0.5f;
- /*fra=sim->psys->cfra+0.5f*dfra;*/
- }
- else {
- madd_v3_v3v3fl(pa->state.co, states->co, states[1].vel, dtime);
- madd_v3_v3v3fl(pa->state.vel, states->vel, acceleration, dtime);
- }
- break;
- case PART_INT_RK4:
- switch (i) {
- case 0:
- copy_v3_v3(dx[0], states->vel);
- mul_v3_fl(dx[0], dtime);
- copy_v3_v3(dv[0], acceleration);
- mul_v3_fl(dv[0], dtime);
-
- madd_v3_v3v3fl(states[1].co, states->co, dx[0], 0.5f);
- madd_v3_v3v3fl(states[1].vel, states->vel, dv[0], 0.5f);
- states[1].time = dtime*0.5f;
- /*fra=sim->psys->cfra+0.5f*dfra;*/
- break;
- case 1:
- madd_v3_v3v3fl(dx[1], states->vel, dv[0], 0.5f);
- mul_v3_fl(dx[1], dtime);
- copy_v3_v3(dv[1], acceleration);
- mul_v3_fl(dv[1], dtime);
-
- madd_v3_v3v3fl(states[2].co, states->co, dx[1], 0.5f);
- madd_v3_v3v3fl(states[2].vel, states->vel, dv[1], 0.5f);
- states[2].time = dtime*0.5f;
- break;
- case 2:
- madd_v3_v3v3fl(dx[2], states->vel, dv[1], 0.5f);
- mul_v3_fl(dx[2], dtime);
- copy_v3_v3(dv[2], acceleration);
- mul_v3_fl(dv[2], dtime);
-
- add_v3_v3v3(states[3].co, states->co, dx[2]);
- add_v3_v3v3(states[3].vel, states->vel, dv[2]);
- states[3].time = dtime;
- /*fra=cfra;*/
- break;
- case 3:
- add_v3_v3v3(dx[3], states->vel, dv[2]);
- mul_v3_fl(dx[3], dtime);
- copy_v3_v3(dv[3], acceleration);
- mul_v3_fl(dv[3], dtime);
-
- madd_v3_v3v3fl(pa->state.co, states->co, dx[0], 1.0f/6.0f);
- madd_v3_v3fl(pa->state.co, dx[1], 1.0f/3.0f);
- madd_v3_v3fl(pa->state.co, dx[2], 1.0f/3.0f);
- madd_v3_v3fl(pa->state.co, dx[3], 1.0f/6.0f);
-
- madd_v3_v3v3fl(pa->state.vel, states->vel, dv[0], 1.0f/6.0f);
- madd_v3_v3fl(pa->state.vel, dv[1], 1.0f/3.0f);
- madd_v3_v3fl(pa->state.vel, dv[2], 1.0f/3.0f);
- madd_v3_v3fl(pa->state.vel, dv[3], 1.0f/6.0f);
- }
- break;
- case PART_INT_VERLET: /* Verlet integration */
- madd_v3_v3v3fl(pa->state.vel, pa->prev_state.vel, acceleration, dtime);
- madd_v3_v3v3fl(pa->state.co, pa->prev_state.co, pa->state.vel, dtime);
-
- sub_v3_v3v3(pa->state.vel, pa->state.co, oldpos);
- mul_v3_fl(pa->state.vel, 1.0f/dtime);
- break;
- }
- }
-}
-
-/*********************************************************************************************************
- * SPH fluid physics
- *
- * In theory, there could be unlimited implementation of SPH simulators
- *
- * This code uses in some parts adapted algorithms from the pseudo code as outlined in the Research paper:
- *
- * Titled: Particle-based Viscoelastic Fluid Simulation.
- * Authors: Simon Clavet, Philippe Beaudoin and Pierre Poulin
- * Website: http://www.iro.umontreal.ca/labs/infographie/papers/Clavet-2005-PVFS/
- *
- * Presented at Siggraph, (2005)
- *
- * ********************************************************************************************************/
-#define PSYS_FLUID_SPRINGS_INITIAL_SIZE 256
-static ParticleSpring *sph_spring_add(ParticleSystem *psys, ParticleSpring *spring)
-{
- /* Are more refs required? */
- if (psys->alloc_fluidsprings == 0 || psys->fluid_springs == NULL) {
- psys->alloc_fluidsprings = PSYS_FLUID_SPRINGS_INITIAL_SIZE;
- psys->fluid_springs = (ParticleSpring*)MEM_callocN(psys->alloc_fluidsprings * sizeof(ParticleSpring), "Particle Fluid Springs");
- }
- else if (psys->tot_fluidsprings == psys->alloc_fluidsprings) {
- /* Double the number of refs allocated */
- psys->alloc_fluidsprings *= 2;
- psys->fluid_springs = (ParticleSpring*)MEM_reallocN(psys->fluid_springs, psys->alloc_fluidsprings * sizeof(ParticleSpring));
- }
-
- memcpy(psys->fluid_springs + psys->tot_fluidsprings, spring, sizeof(ParticleSpring));
- psys->tot_fluidsprings++;
-
- return psys->fluid_springs + psys->tot_fluidsprings - 1;
-}
-static void sph_spring_delete(ParticleSystem *psys, int j)
-{
- if (j != psys->tot_fluidsprings - 1)
- psys->fluid_springs[j] = psys->fluid_springs[psys->tot_fluidsprings - 1];
-
- psys->tot_fluidsprings--;
-
- if (psys->tot_fluidsprings < psys->alloc_fluidsprings/2 && psys->alloc_fluidsprings > PSYS_FLUID_SPRINGS_INITIAL_SIZE) {
- psys->alloc_fluidsprings /= 2;
- psys->fluid_springs = (ParticleSpring*)MEM_reallocN(psys->fluid_springs, psys->alloc_fluidsprings * sizeof(ParticleSpring));
- }
-}
-static void sph_springs_modify(ParticleSystem *psys, float dtime)
-{
- SPHFluidSettings *fluid = psys->part->fluid;
- ParticleData *pa1, *pa2;
- ParticleSpring *spring = psys->fluid_springs;
-
- float h, d, Rij[3], rij, Lij;
- int i;
-
- float yield_ratio = fluid->yield_ratio;
- float plasticity = fluid->plasticity_constant;
- /* scale things according to dtime */
- float timefix = 25.f * dtime;
-
- if ((fluid->flag & SPH_VISCOELASTIC_SPRINGS)==0 || fluid->spring_k == 0.f)
- return;
-
- /* Loop through the springs */
- for (i=0; i<psys->tot_fluidsprings; i++, spring++) {
- pa1 = psys->particles + spring->particle_index[0];
- pa2 = psys->particles + spring->particle_index[1];
-
- sub_v3_v3v3(Rij, pa2->prev_state.co, pa1->prev_state.co);
- rij = normalize_v3(Rij);
-
- /* adjust rest length */
- Lij = spring->rest_length;
- d = yield_ratio * timefix * Lij;
-
- if (rij > Lij + d) // Stretch
- spring->rest_length += plasticity * (rij - Lij - d) * timefix;
- else if (rij < Lij - d) // Compress
- spring->rest_length -= plasticity * (Lij - d - rij) * timefix;
-
- h = 4.f*pa1->size;
-
- if (spring->rest_length > h)
- spring->delete_flag = 1;
- }
-
- /* Loop through springs backwaqrds - for efficient delete function */
- for (i=psys->tot_fluidsprings-1; i >= 0; i--) {
- if (psys->fluid_springs[i].delete_flag)
- sph_spring_delete(psys, i);
- }
-}
-static EdgeHash *sph_springhash_build(ParticleSystem *psys)
-{
- EdgeHash *springhash = NULL;
- ParticleSpring *spring;
- int i = 0;
-
- springhash = BLI_edgehash_new_ex(__func__, psys->tot_fluidsprings);
-
- for (i=0, spring=psys->fluid_springs; i<psys->tot_fluidsprings; i++, spring++)
- BLI_edgehash_insert(springhash, spring->particle_index[0], spring->particle_index[1], SET_INT_IN_POINTER(i+1));
-
- return springhash;
-}
-
-#define SPH_NEIGHBORS 512
-typedef struct SPHNeighbor {
- ParticleSystem *psys;
- int index;
-} SPHNeighbor;
-
-typedef struct SPHRangeData {
- SPHNeighbor neighbors[SPH_NEIGHBORS];
- int tot_neighbors;
-
- float* data;
-
- ParticleSystem *npsys;
- ParticleData *pa;
-
- float h;
- float mass;
- float massfac;
- int use_size;
-} SPHRangeData;
-
-static void sph_evaluate_func(BVHTree *tree, ParticleSystem **psys, float co[3], SPHRangeData *pfr, float interaction_radius, BVHTree_RangeQuery callback)
-{
- int i;
-
- pfr->tot_neighbors = 0;
-
- for (i=0; i < 10 && psys[i]; i++) {
- pfr->npsys = psys[i];
- pfr->massfac = psys[i]->part->mass / pfr->mass;
- pfr->use_size = psys[i]->part->flag & PART_SIZEMASS;
-
- if (tree) {
- BLI_bvhtree_range_query(tree, co, interaction_radius, callback, pfr);
- break;
- }
- else {
- BLI_rw_mutex_lock(&psys_bvhtree_rwlock, THREAD_LOCK_READ);
-
- BLI_bvhtree_range_query(psys[i]->bvhtree, co, interaction_radius, callback, pfr);
-
- BLI_rw_mutex_unlock(&psys_bvhtree_rwlock);
- }
- }
-}
-static void sph_density_accum_cb(void *userdata, int index, const float co[3], float squared_dist)
-{
- SPHRangeData *pfr = (SPHRangeData *)userdata;
- ParticleData *npa = pfr->npsys->particles + index;
- float q;
- float dist;
-
- UNUSED_VARS(co);
-
- if (npa == pfr->pa || squared_dist < FLT_EPSILON)
- return;
-
- /* Ugh! One particle has too many neighbors! If some aren't taken into
- * account, the forces will be biased by the tree search order. This
- * effectively adds enery to the system, and results in a churning motion.
- * But, we have to stop somewhere, and it's not the end of the world.
- * - jahka and z0r
- */
- if (pfr->tot_neighbors >= SPH_NEIGHBORS)
- return;
-
- pfr->neighbors[pfr->tot_neighbors].index = index;
- pfr->neighbors[pfr->tot_neighbors].psys = pfr->npsys;
- pfr->tot_neighbors++;
-
- dist = sqrtf(squared_dist);
- q = (1.f - dist/pfr->h) * pfr->massfac;
-
- if (pfr->use_size)
- q *= npa->size;
-
- pfr->data[0] += q*q;
- pfr->data[1] += q*q*q;
-}
-
-/*
- * Find the Courant number for an SPH particle (used for adaptive time step).
- */
-static void sph_particle_courant(SPHData *sphdata, SPHRangeData *pfr)
-{
- ParticleData *pa, *npa;
- int i;
- float flow[3], offset[3], dist;
-
- zero_v3(flow);
-
- dist = 0.0f;
- if (pfr->tot_neighbors > 0) {
- pa = pfr->pa;
- for (i=0; i < pfr->tot_neighbors; i++) {
- npa = pfr->neighbors[i].psys->particles + pfr->neighbors[i].index;
- sub_v3_v3v3(offset, pa->prev_state.co, npa->prev_state.co);
- dist += len_v3(offset);
- add_v3_v3(flow, npa->prev_state.vel);
- }
- dist += sphdata->psys[0]->part->fluid->radius; // TODO: remove this? - z0r
- sphdata->element_size = dist / pfr->tot_neighbors;
- mul_v3_v3fl(sphdata->flow, flow, 1.0f / pfr->tot_neighbors);
- }
- else {
- sphdata->element_size = FLT_MAX;
- copy_v3_v3(sphdata->flow, flow);
- }
-}
-static void sph_force_cb(void *sphdata_v, ParticleKey *state, float *force, float *UNUSED(impulse))
-{
- SPHData *sphdata = (SPHData *)sphdata_v;
- ParticleSystem **psys = sphdata->psys;
- ParticleData *pa = sphdata->pa;
- SPHFluidSettings *fluid = psys[0]->part->fluid;
- ParticleSpring *spring = NULL;
- SPHRangeData pfr;
- SPHNeighbor *pfn;
- float *gravity = sphdata->gravity;
- EdgeHash *springhash = sphdata->eh;
-
- float q, u, rij, dv[3];
- float pressure, near_pressure;
-
- float visc = fluid->viscosity_omega;
- float stiff_visc = fluid->viscosity_beta * (fluid->flag & SPH_FAC_VISCOSITY ? fluid->viscosity_omega : 1.f);
-
- float inv_mass = 1.0f / sphdata->mass;
- float spring_constant = fluid->spring_k;
-
- /* 4.0 seems to be a pretty good value */
- float interaction_radius = fluid->radius * (fluid->flag & SPH_FAC_RADIUS ? 4.0f * pa->size : 1.0f);
- float h = interaction_radius * sphdata->hfac;
- float rest_density = fluid->rest_density * (fluid->flag & SPH_FAC_DENSITY ? 4.77f : 1.f); /* 4.77 is an experimentally determined density factor */
- float rest_length = fluid->rest_length * (fluid->flag & SPH_FAC_REST_LENGTH ? 2.588f * pa->size : 1.f);
-
- float stiffness = fluid->stiffness_k;
- float stiffness_near_fac = fluid->stiffness_knear * (fluid->flag & SPH_FAC_REPULSION ? fluid->stiffness_k : 1.f);
-
- ParticleData *npa;
- float vec[3];
- float vel[3];
- float co[3];
- float data[2];
- float density, near_density;
-
- int i, spring_index, index = pa - psys[0]->particles;
-
- data[0] = data[1] = 0;
- pfr.data = data;
- pfr.h = h;
- pfr.pa = pa;
- pfr.mass = sphdata->mass;
-
- sph_evaluate_func( NULL, psys, state->co, &pfr, interaction_radius, sph_density_accum_cb);
-
- density = data[0];
- near_density = data[1];
-
- pressure = stiffness * (density - rest_density);
- near_pressure = stiffness_near_fac * near_density;
-
- pfn = pfr.neighbors;
- for (i=0; i<pfr.tot_neighbors; i++, pfn++) {
- npa = pfn->psys->particles + pfn->index;
-
- madd_v3_v3v3fl(co, npa->prev_state.co, npa->prev_state.vel, state->time);
-
- sub_v3_v3v3(vec, co, state->co);
- rij = normalize_v3(vec);
-
- q = (1.f - rij/h) * pfn->psys->part->mass * inv_mass;
-
- if (pfn->psys->part->flag & PART_SIZEMASS)
- q *= npa->size;
-
- copy_v3_v3(vel, npa->prev_state.vel);
-
- /* Double Density Relaxation */
- madd_v3_v3fl(force, vec, -(pressure + near_pressure*q)*q);
-
- /* Viscosity */
- if (visc > 0.f || stiff_visc > 0.f) {
- sub_v3_v3v3(dv, vel, state->vel);
- u = dot_v3v3(vec, dv);
-
- if (u < 0.f && visc > 0.f)
- madd_v3_v3fl(force, vec, 0.5f * q * visc * u );
-
- if (u > 0.f && stiff_visc > 0.f)
- madd_v3_v3fl(force, vec, 0.5f * q * stiff_visc * u );
- }
-
- if (spring_constant > 0.f) {
- /* Viscoelastic spring force */
- if (pfn->psys == psys[0] && fluid->flag & SPH_VISCOELASTIC_SPRINGS && springhash) {
- /* BLI_edgehash_lookup appears to be thread-safe. - z0r */
- spring_index = GET_INT_FROM_POINTER(BLI_edgehash_lookup(springhash, index, pfn->index));
-
- if (spring_index) {
- spring = psys[0]->fluid_springs + spring_index - 1;
-
- madd_v3_v3fl(force, vec, -10.f * spring_constant * (1.f - rij/h) * (spring->rest_length - rij));
- }
- else if (fluid->spring_frames == 0 || (pa->prev_state.time-pa->time) <= fluid->spring_frames) {
- ParticleSpring temp_spring;
- temp_spring.particle_index[0] = index;
- temp_spring.particle_index[1] = pfn->index;
- temp_spring.rest_length = (fluid->flag & SPH_CURRENT_REST_LENGTH) ? rij : rest_length;
- temp_spring.delete_flag = 0;
-
- /* sph_spring_add is not thread-safe. - z0r */
- sph_spring_add(psys[0], &temp_spring);
- }
- }
- else {/* PART_SPRING_HOOKES - Hooke's spring force */
- madd_v3_v3fl(force, vec, -10.f * spring_constant * (1.f - rij/h) * (rest_length - rij));
- }
- }
- }
-
- /* Artificial buoyancy force in negative gravity direction */
- if (fluid->buoyancy > 0.f && gravity)
- madd_v3_v3fl(force, gravity, fluid->buoyancy * (density-rest_density));
-
- if (sphdata->pass == 0 && psys[0]->part->time_flag & PART_TIME_AUTOSF)
- sph_particle_courant(sphdata, &pfr);
- sphdata->pass++;
-}
-
-static void sphclassical_density_accum_cb(void *userdata, int index, const float co[3], float UNUSED(squared_dist))
-{
- SPHRangeData *pfr = (SPHRangeData *)userdata;
- ParticleData *npa = pfr->npsys->particles + index;
- float q;
- float qfac = 21.0f / (256.f * (float)M_PI);
- float rij, rij_h;
- float vec[3];
-
- /* Exclude particles that are more than 2h away. Can't use squared_dist here
- * because it is not accurate enough. Use current state, i.e. the output of
- * basic_integrate() - z0r */
- sub_v3_v3v3(vec, npa->state.co, co);
- rij = len_v3(vec);
- rij_h = rij / pfr->h;
- if (rij_h > 2.0f)
- return;
-
- /* Smoothing factor. Utilise the Wendland kernel. gnuplot:
- * q1(x) = (2.0 - x)**4 * ( 1.0 + 2.0 * x)
- * plot [0:2] q1(x) */
- q = qfac / pow3f(pfr->h) * pow4f(2.0f - rij_h) * ( 1.0f + 2.0f * rij_h);
- q *= pfr->npsys->part->mass;
-
- if (pfr->use_size)
- q *= pfr->pa->size;
-
- pfr->data[0] += q;
- pfr->data[1] += q / npa->sphdensity;
-}
-
-static void sphclassical_neighbour_accum_cb(void *userdata, int index, const float co[3], float UNUSED(squared_dist))
-{
- SPHRangeData *pfr = (SPHRangeData *)userdata;
- ParticleData *npa = pfr->npsys->particles + index;
- float rij, rij_h;
- float vec[3];
-
- if (pfr->tot_neighbors >= SPH_NEIGHBORS)
- return;
-
- /* Exclude particles that are more than 2h away. Can't use squared_dist here
- * because it is not accurate enough. Use current state, i.e. the output of
- * basic_integrate() - z0r */
- sub_v3_v3v3(vec, npa->state.co, co);
- rij = len_v3(vec);
- rij_h = rij / pfr->h;
- if (rij_h > 2.0f)
- return;
-
- pfr->neighbors[pfr->tot_neighbors].index = index;
- pfr->neighbors[pfr->tot_neighbors].psys = pfr->npsys;
- pfr->tot_neighbors++;
-}
-static void sphclassical_force_cb(void *sphdata_v, ParticleKey *state, float *force, float *UNUSED(impulse))
-{
- SPHData *sphdata = (SPHData *)sphdata_v;
- ParticleSystem **psys = sphdata->psys;
- ParticleData *pa = sphdata->pa;
- SPHFluidSettings *fluid = psys[0]->part->fluid;
- SPHRangeData pfr;
- SPHNeighbor *pfn;
- float *gravity = sphdata->gravity;
-
- float dq, u, rij, dv[3];
- float pressure, npressure;
-
- float visc = fluid->viscosity_omega;
-
- float interaction_radius;
- float h, hinv;
- /* 4.77 is an experimentally determined density factor */
- float rest_density = fluid->rest_density * (fluid->flag & SPH_FAC_DENSITY ? 4.77f : 1.0f);
-
- // Use speed of sound squared
- float stiffness = pow2f(fluid->stiffness_k);
-
- ParticleData *npa;
- float vec[3];
- float co[3];
- float pressureTerm;
-
- int i;
-
- float qfac2 = 42.0f / (256.0f * (float)M_PI);
- float rij_h;
-
- /* 4.0 here is to be consistent with previous formulation/interface */
- interaction_radius = fluid->radius * (fluid->flag & SPH_FAC_RADIUS ? 4.0f * pa->size : 1.0f);
- h = interaction_radius * sphdata->hfac;
- hinv = 1.0f / h;
-
- pfr.h = h;
- pfr.pa = pa;
-
- sph_evaluate_func(NULL, psys, state->co, &pfr, interaction_radius, sphclassical_neighbour_accum_cb);
- pressure = stiffness * (pow7f(pa->sphdensity / rest_density) - 1.0f);
-
- /* multiply by mass so that we return a force, not accel */
- qfac2 *= sphdata->mass / pow3f(pfr.h);
-
- pfn = pfr.neighbors;
- for (i = 0; i < pfr.tot_neighbors; i++, pfn++) {
- npa = pfn->psys->particles + pfn->index;
- if (npa == pa) {
- /* we do not contribute to ourselves */
- continue;
- }
-
- /* Find vector to neighbor. Exclude particles that are more than 2h
- * away. Can't use current state here because it may have changed on
- * another thread - so do own mini integration. Unlike basic_integrate,
- * SPH integration depends on neighboring particles. - z0r */
- madd_v3_v3v3fl(co, npa->prev_state.co, npa->prev_state.vel, state->time);
- sub_v3_v3v3(vec, co, state->co);
- rij = normalize_v3(vec);
- rij_h = rij / pfr.h;
- if (rij_h > 2.0f)
- continue;
-
- npressure = stiffness * (pow7f(npa->sphdensity / rest_density) - 1.0f);
-
- /* First derivative of smoothing factor. Utilise the Wendland kernel.
- * gnuplot:
- * q2(x) = 2.0 * (2.0 - x)**4 - 4.0 * (2.0 - x)**3 * (1.0 + 2.0 * x)
- * plot [0:2] q2(x)
- * Particles > 2h away are excluded above. */
- dq = qfac2 * (2.0f * pow4f(2.0f - rij_h) - 4.0f * pow3f(2.0f - rij_h) * (1.0f + 2.0f * rij_h) );
-
- if (pfn->psys->part->flag & PART_SIZEMASS)
- dq *= npa->size;
-
- pressureTerm = pressure / pow2f(pa->sphdensity) + npressure / pow2f(npa->sphdensity);
-
- /* Note that 'minus' is removed, because vec = vecBA, not vecAB.
- * This applies to the viscosity calculation below, too. */
- madd_v3_v3fl(force, vec, pressureTerm * dq);
-
- /* Viscosity */
- if (visc > 0.0f) {
- sub_v3_v3v3(dv, npa->prev_state.vel, pa->prev_state.vel);
- u = dot_v3v3(vec, dv);
- /* Apply parameters */
- u *= -dq * hinv * visc / (0.5f * npa->sphdensity + 0.5f * pa->sphdensity);
- madd_v3_v3fl(force, vec, u);
- }
- }
-
- /* Artificial buoyancy force in negative gravity direction */
- if (fluid->buoyancy > 0.f && gravity)
- madd_v3_v3fl(force, gravity, fluid->buoyancy * (pa->sphdensity - rest_density));
-
- if (sphdata->pass == 0 && psys[0]->part->time_flag & PART_TIME_AUTOSF)
- sph_particle_courant(sphdata, &pfr);
- sphdata->pass++;
-}
-
-static void sphclassical_calc_dens(ParticleData *pa, float UNUSED(dfra), SPHData *sphdata)
-{
- ParticleSystem **psys = sphdata->psys;
- SPHFluidSettings *fluid = psys[0]->part->fluid;
- /* 4.0 seems to be a pretty good value */
- float interaction_radius = fluid->radius * (fluid->flag & SPH_FAC_RADIUS ? 4.0f * psys[0]->part->size : 1.0f);
- SPHRangeData pfr;
- float data[2];
-
- data[0] = 0;
- data[1] = 0;
- pfr.data = data;
- pfr.h = interaction_radius * sphdata->hfac;
- pfr.pa = pa;
- pfr.mass = sphdata->mass;
-
- sph_evaluate_func( NULL, psys, pa->state.co, &pfr, interaction_radius, sphclassical_density_accum_cb);
- pa->sphdensity = min_ff(max_ff(data[0], fluid->rest_density * 0.9f), fluid->rest_density * 1.1f);
-}
-
-void psys_sph_init(ParticleSimulationData *sim, SPHData *sphdata)
-{
- ParticleTarget *pt;
- int i;
-
- // Add other coupled particle systems.
- sphdata->psys[0] = sim->psys;
- for (i=1, pt=sim->psys->targets.first; i<10; i++, pt=(pt?pt->next:NULL))
- sphdata->psys[i] = pt ? psys_get_target_system(sim->ob, pt) : NULL;
-
- if (psys_uses_gravity(sim))
- sphdata->gravity = sim->scene->physics_settings.gravity;
- else
- sphdata->gravity = NULL;
- sphdata->eh = sph_springhash_build(sim->psys);
-
- // These per-particle values should be overridden later, but just for
- // completeness we give them default values now.
- sphdata->pa = NULL;
- sphdata->mass = 1.0f;
-
- if (sim->psys->part->fluid->solver == SPH_SOLVER_DDR) {
- sphdata->force_cb = sph_force_cb;
- sphdata->density_cb = sph_density_accum_cb;
- sphdata->hfac = 1.0f;
- }
- else {
- /* SPH_SOLVER_CLASSICAL */
- sphdata->force_cb = sphclassical_force_cb;
- sphdata->density_cb = sphclassical_density_accum_cb;
- sphdata->hfac = 0.5f;
- }
-
-}
-
-void psys_sph_finalise(SPHData *sphdata)
-{
- if (sphdata->eh) {
- BLI_edgehash_free(sphdata->eh, NULL);
- sphdata->eh = NULL;
- }
-}
-/* Sample the density field at a point in space. */
-void psys_sph_density(BVHTree *tree, SPHData *sphdata, float co[3], float vars[2])
-{
- ParticleSystem **psys = sphdata->psys;
- SPHFluidSettings *fluid = psys[0]->part->fluid;
- /* 4.0 seems to be a pretty good value */
- float interaction_radius = fluid->radius * (fluid->flag & SPH_FAC_RADIUS ? 4.0f * psys[0]->part->size : 1.0f);
- SPHRangeData pfr;
- float density[2];
-
- density[0] = density[1] = 0.0f;
- pfr.data = density;
- pfr.h = interaction_radius * sphdata->hfac;
- pfr.mass = sphdata->mass;
-
- sph_evaluate_func(tree, psys, co, &pfr, interaction_radius, sphdata->density_cb);
-
- vars[0] = pfr.data[0];
- vars[1] = pfr.data[1];
-}
-
-static void sph_integrate(ParticleSimulationData *sim, ParticleData *pa, float dfra, SPHData *sphdata)
-{
- ParticleSettings *part = sim->psys->part;
- // float timestep = psys_get_timestep(sim); // UNUSED
- float pa_mass = part->mass * (part->flag & PART_SIZEMASS ? pa->size : 1.f);
- float dtime = dfra*psys_get_timestep(sim);
- // int steps = 1; // UNUSED
- float effector_acceleration[3];
-
- sphdata->pa = pa;
- sphdata->mass = pa_mass;
- sphdata->pass = 0;
- //sphdata.element_size and sphdata.flow are set in the callback.
-
- /* restore previous state and treat gravity & effectors as external acceleration*/
- sub_v3_v3v3(effector_acceleration, pa->state.vel, pa->prev_state.vel);
- mul_v3_fl(effector_acceleration, 1.f/dtime);
-
- copy_particle_key(&pa->state, &pa->prev_state, 0);
-
- integrate_particle(part, pa, dtime, effector_acceleration, sphdata->force_cb, sphdata);
-}
-
-/************************************************/
-/* Basic physics */
-/************************************************/
-typedef struct EfData {
- ParticleTexture ptex;
- ParticleSimulationData *sim;
- ParticleData *pa;
-} EfData;
-static void basic_force_cb(void *efdata_v, ParticleKey *state, float *force, float *impulse)
-{
- EfData *efdata = (EfData *)efdata_v;
- ParticleSimulationData *sim = efdata->sim;
- ParticleSettings *part = sim->psys->part;
- ParticleData *pa = efdata->pa;
- EffectedPoint epoint;
-
- /* add effectors */
- pd_point_from_particle(efdata->sim, efdata->pa, state, &epoint);
- if (part->type != PART_HAIR || part->effector_weights->flag & EFF_WEIGHT_DO_HAIR)
- pdDoEffectors(sim->psys->effectors, sim->colliders, part->effector_weights, &epoint, force, impulse);
-
- mul_v3_fl(force, efdata->ptex.field);
- mul_v3_fl(impulse, efdata->ptex.field);
-
- /* calculate air-particle interaction */
- if (part->dragfac != 0.0f)
- madd_v3_v3fl(force, state->vel, -part->dragfac * pa->size * pa->size * len_v3(state->vel));
-
- /* brownian force */
- if (part->brownfac != 0.0f) {
- force[0] += (BLI_frand()-0.5f) * part->brownfac;
- force[1] += (BLI_frand()-0.5f) * part->brownfac;
- force[2] += (BLI_frand()-0.5f) * part->brownfac;
- }
-
- if (part->flag & PART_ROT_DYN && epoint.ave)
- copy_v3_v3(pa->state.ave, epoint.ave);
-}
-/* gathers all forces that effect particles and calculates a new state for the particle */
-static void basic_integrate(ParticleSimulationData *sim, int p, float dfra, float cfra)
-{
- ParticleSettings *part = sim->psys->part;
- ParticleData *pa = sim->psys->particles + p;
- ParticleKey tkey;
- float dtime=dfra*psys_get_timestep(sim), time;
- float *gravity = NULL, gr[3];
- EfData efdata;
-
- psys_get_texture(sim, pa, &efdata.ptex, PAMAP_PHYSICS, cfra);
-
- efdata.pa = pa;
- efdata.sim = sim;
-
- /* add global acceleration (gravitation) */
- if (psys_uses_gravity(sim) &&
- /* normal gravity is too strong for hair so it's disabled by default */
- (part->type != PART_HAIR || part->effector_weights->flag & EFF_WEIGHT_DO_HAIR))
- {
- zero_v3(gr);
- madd_v3_v3fl(gr, sim->scene->physics_settings.gravity, part->effector_weights->global_gravity * efdata.ptex.gravity);
- gravity = gr;
- }
-
- /* maintain angular velocity */
- copy_v3_v3(pa->state.ave, pa->prev_state.ave);
-
- integrate_particle(part, pa, dtime, gravity, basic_force_cb, &efdata);
-
- /* damp affects final velocity */
- if (part->dampfac != 0.f)
- mul_v3_fl(pa->state.vel, 1.f - part->dampfac * efdata.ptex.damp * 25.f * dtime);
-
- //copy_v3_v3(pa->state.ave, states->ave);
-
- /* finally we do guides */
- time=(cfra-pa->time)/pa->lifetime;
- CLAMP(time, 0.0f, 1.0f);
-
- copy_v3_v3(tkey.co,pa->state.co);
- copy_v3_v3(tkey.vel,pa->state.vel);
- tkey.time=pa->state.time;
-
- if (part->type != PART_HAIR) {
- if (do_guides(sim->psys->part, sim->psys->effectors, &tkey, p, time)) {
- copy_v3_v3(pa->state.co,tkey.co);
- /* guides don't produce valid velocity */
- sub_v3_v3v3(pa->state.vel, tkey.co, pa->prev_state.co);
- mul_v3_fl(pa->state.vel,1.0f/dtime);
- pa->state.time=tkey.time;
- }
- }
-}
-static void basic_rotate(ParticleSettings *part, ParticleData *pa, float dfra, float timestep)
-{
- float rotfac, rot1[4], rot2[4] = {1.0,0.0,0.0,0.0}, dtime=dfra*timestep, extrotfac;
-
- if ((part->flag & PART_ROTATIONS) == 0) {
- unit_qt(pa->state.rot);
- return;
- }
-
- if (part->flag & PART_ROT_DYN) {
- extrotfac = len_v3(pa->state.ave);
- }
- else {
- extrotfac = 0.0f;
- }
-
- if ((part->flag & PART_ROT_DYN) && ELEM(part->avemode, PART_AVE_VELOCITY, PART_AVE_HORIZONTAL, PART_AVE_VERTICAL)) {
- float angle;
- float len1 = len_v3(pa->prev_state.vel);
- float len2 = len_v3(pa->state.vel);
- float vec[3];
-
- if (len1 == 0.0f || len2 == 0.0f) {
- zero_v3(pa->state.ave);
- }
- else {
- cross_v3_v3v3(pa->state.ave, pa->prev_state.vel, pa->state.vel);
- normalize_v3(pa->state.ave);
- angle = dot_v3v3(pa->prev_state.vel, pa->state.vel) / (len1 * len2);
- mul_v3_fl(pa->state.ave, saacos(angle) / dtime);
- }
-
- get_angular_velocity_vector(part->avemode, &pa->state, vec);
- axis_angle_to_quat(rot2, vec, dtime*part->avefac);
- }
-
- rotfac = len_v3(pa->state.ave);
- if (rotfac == 0.0f || (part->flag & PART_ROT_DYN)==0 || extrotfac == 0.0f) {
- unit_qt(rot1);
- }
- else {
- axis_angle_to_quat(rot1,pa->state.ave,rotfac*dtime);
- }
- mul_qt_qtqt(pa->state.rot,rot1,pa->prev_state.rot);
- mul_qt_qtqt(pa->state.rot,rot2,pa->state.rot);
-
- /* keep rotation quat in good health */
- normalize_qt(pa->state.rot);
-}
-
-/************************************************
- * Collisions
- *
- * The algorithm is roughly:
- * 1. Use a BVH tree to search for faces that a particle may collide with.
- * 2. Use Newton's method to find the exact time at which the collision occurs.
- * http://en.wikipedia.org/wiki/Newton's_method
- *
- ************************************************/
-#define COLLISION_MIN_RADIUS 0.001f
-#define COLLISION_MIN_DISTANCE 0.0001f
-#define COLLISION_ZERO 0.00001f
-#define COLLISION_INIT_STEP 0.00008f
-typedef float (*NRDistanceFunc)(float *p, float radius, ParticleCollisionElement *pce, float *nor);
-static float nr_signed_distance_to_plane(float *p, float radius, ParticleCollisionElement *pce, float *nor)
-{
- float p0[3], e1[3], e2[3], d;
-
- sub_v3_v3v3(e1, pce->x1, pce->x0);
- sub_v3_v3v3(e2, pce->x2, pce->x0);
- sub_v3_v3v3(p0, p, pce->x0);
-
- cross_v3_v3v3(nor, e1, e2);
- normalize_v3(nor);
-
- d = dot_v3v3(p0, nor);
-
- if (pce->inv_nor == -1) {
- if (d < 0.f)
- pce->inv_nor = 1;
- else
- pce->inv_nor = 0;
- }
-
- if (pce->inv_nor == 1) {
- negate_v3(nor);
- d = -d;
- }
-
- return d - radius;
-}
-static float nr_distance_to_edge(float *p, float radius, ParticleCollisionElement *pce, float *UNUSED(nor))
-{
- float v0[3], v1[3], v2[3], c[3];
-
- sub_v3_v3v3(v0, pce->x1, pce->x0);
- sub_v3_v3v3(v1, p, pce->x0);
- sub_v3_v3v3(v2, p, pce->x1);
-
- cross_v3_v3v3(c, v1, v2);
-
- return fabsf(len_v3(c)/len_v3(v0)) - radius;
-}
-static float nr_distance_to_vert(float *p, float radius, ParticleCollisionElement *pce, float *UNUSED(nor))
-{
- return len_v3v3(p, pce->x0) - radius;
-}
-static void collision_interpolate_element(ParticleCollisionElement *pce, float t, float fac, ParticleCollision *col)
-{
- /* t is the current time for newton rhapson */
- /* fac is the starting factor for current collision iteration */
- /* the col->fac's are factors for the particle subframe step start and end during collision modifier step */
- float f = fac + t*(1.f-fac);
- float mul = col->fac1 + f * (col->fac2-col->fac1);
- if (pce->tot > 0) {
- madd_v3_v3v3fl(pce->x0, pce->x[0], pce->v[0], mul);
-
- if (pce->tot > 1) {
- madd_v3_v3v3fl(pce->x1, pce->x[1], pce->v[1], mul);
-
- if (pce->tot > 2)
- madd_v3_v3v3fl(pce->x2, pce->x[2], pce->v[2], mul);
- }
- }
-}
-static void collision_point_velocity(ParticleCollisionElement *pce)
-{
- float v[3];
-
- copy_v3_v3(pce->vel, pce->v[0]);
-
- if (pce->tot > 1) {
- sub_v3_v3v3(v, pce->v[1], pce->v[0]);
- madd_v3_v3fl(pce->vel, v, pce->uv[0]);
-
- if (pce->tot > 2) {
- sub_v3_v3v3(v, pce->v[2], pce->v[0]);
- madd_v3_v3fl(pce->vel, v, pce->uv[1]);
- }
- }
-}
-static float collision_point_distance_with_normal(float p[3], ParticleCollisionElement *pce, float fac, ParticleCollision *col, float *nor)
-{
- if (fac >= 0.f)
- collision_interpolate_element(pce, 0.f, fac, col);
-
- switch (pce->tot) {
- case 1:
- {
- sub_v3_v3v3(nor, p, pce->x0);
- return normalize_v3(nor);
- }
- case 2:
- {
- float u, e[3], vec[3];
- sub_v3_v3v3(e, pce->x1, pce->x0);
- sub_v3_v3v3(vec, p, pce->x0);
- u = dot_v3v3(vec, e) / dot_v3v3(e, e);
-
- madd_v3_v3v3fl(nor, vec, e, -u);
- return normalize_v3(nor);
- }
- case 3:
- return nr_signed_distance_to_plane(p, 0.f, pce, nor);
- }
- return 0;
-}
-static void collision_point_on_surface(float p[3], ParticleCollisionElement *pce, float fac, ParticleCollision *col, float *co)
-{
- collision_interpolate_element(pce, 0.f, fac, col);
-
- switch (pce->tot) {
- case 1:
- {
- sub_v3_v3v3(co, p, pce->x0);
- normalize_v3(co);
- madd_v3_v3v3fl(co, pce->x0, co, col->radius);
- break;
- }
- case 2:
- {
- float u, e[3], vec[3], nor[3];
- sub_v3_v3v3(e, pce->x1, pce->x0);
- sub_v3_v3v3(vec, p, pce->x0);
- u = dot_v3v3(vec, e) / dot_v3v3(e, e);
-
- madd_v3_v3v3fl(nor, vec, e, -u);
- normalize_v3(nor);
-
- madd_v3_v3v3fl(co, pce->x0, e, pce->uv[0]);
- madd_v3_v3fl(co, nor, col->radius);
- break;
- }
- case 3:
- {
- float p0[3], e1[3], e2[3], nor[3];
-
- sub_v3_v3v3(e1, pce->x1, pce->x0);
- sub_v3_v3v3(e2, pce->x2, pce->x0);
- sub_v3_v3v3(p0, p, pce->x0);
-
- cross_v3_v3v3(nor, e1, e2);
- normalize_v3(nor);
-
- if (pce->inv_nor == 1)
- negate_v3(nor);
-
- madd_v3_v3v3fl(co, pce->x0, nor, col->radius);
- madd_v3_v3fl(co, e1, pce->uv[0]);
- madd_v3_v3fl(co, e2, pce->uv[1]);
- break;
- }
- }
-}
-/* find first root in range [0-1] starting from 0 */
-static float collision_newton_rhapson(ParticleCollision *col, float radius, ParticleCollisionElement *pce, NRDistanceFunc distance_func)
-{
- float t0, t1, dt_init, d0, d1, dd, n[3];
- int iter;
-
- pce->inv_nor = -1;
-
- if (col->inv_total_time > 0.0f) {
- /* Initial step size should be small, but not too small or floating point
- * precision errors will appear. - z0r */
- dt_init = COLLISION_INIT_STEP * col->inv_total_time;
- }
- else {
- dt_init = 0.001f;
- }
-
- /* start from the beginning */
- t0 = 0.f;
- collision_interpolate_element(pce, t0, col->f, col);
- d0 = distance_func(col->co1, radius, pce, n);
- t1 = dt_init;
- d1 = 0.f;
-
- for (iter=0; iter<10; iter++) {//, itersum++) {
- /* get current location */
- collision_interpolate_element(pce, t1, col->f, col);
- interp_v3_v3v3(pce->p, col->co1, col->co2, t1);
-
- d1 = distance_func(pce->p, radius, pce, n);
-
- /* particle already inside face, so report collision */
- if (iter == 0 && d0 < 0.f && d0 > -radius) {
- copy_v3_v3(pce->p, col->co1);
- copy_v3_v3(pce->nor, n);
- pce->inside = 1;
- return 0.f;
- }
-
- /* Zero gradient (no movement relative to element). Can't step from
- * here. */
- if (d1 == d0) {
- /* If first iteration, try from other end where the gradient may be
- * greater. Note: code duplicated below. */
- if (iter == 0) {
- t0 = 1.f;
- collision_interpolate_element(pce, t0, col->f, col);
- d0 = distance_func(col->co2, radius, pce, n);
- t1 = 1.0f - dt_init;
- d1 = 0.f;
- continue;
- }
- else
- return -1.f;
- }
-
- dd = (t1-t0)/(d1-d0);
-
- t0 = t1;
- d0 = d1;
-
- t1 -= d1*dd;
-
- /* Particle moving away from plane could also mean a strangely rotating
- * face, so check from end. Note: code duplicated above. */
- if (iter == 0 && t1 < 0.f) {
- t0 = 1.f;
- collision_interpolate_element(pce, t0, col->f, col);
- d0 = distance_func(col->co2, radius, pce, n);
- t1 = 1.0f - dt_init;
- d1 = 0.f;
- continue;
- }
- else if (iter == 1 && (t1 < -COLLISION_ZERO || t1 > 1.f))
- return -1.f;
-
- if (d1 <= COLLISION_ZERO && d1 >= -COLLISION_ZERO) {
- if (t1 >= -COLLISION_ZERO && t1 <= 1.f) {
- if (distance_func == nr_signed_distance_to_plane)
- copy_v3_v3(pce->nor, n);
-
- CLAMP(t1, 0.f, 1.f);
-
- return t1;
- }
- else
- return -1.f;
- }
- }
- return -1.0;
-}
-static int collision_sphere_to_tri(ParticleCollision *col, float radius, ParticleCollisionElement *pce, float *t)
-{
- ParticleCollisionElement *result = &col->pce;
- float ct, u, v;
-
- pce->inv_nor = -1;
- pce->inside = 0;
-
- ct = collision_newton_rhapson(col, radius, pce, nr_signed_distance_to_plane);
-
- if (ct >= 0.f && ct < *t && (result->inside==0 || pce->inside==1) ) {
- float e1[3], e2[3], p0[3];
- float e1e1, e1e2, e1p0, e2e2, e2p0, inv;
-
- sub_v3_v3v3(e1, pce->x1, pce->x0);
- sub_v3_v3v3(e2, pce->x2, pce->x0);
- /* XXX: add radius correction here? */
- sub_v3_v3v3(p0, pce->p, pce->x0);
-
- e1e1 = dot_v3v3(e1, e1);
- e1e2 = dot_v3v3(e1, e2);
- e1p0 = dot_v3v3(e1, p0);
- e2e2 = dot_v3v3(e2, e2);
- e2p0 = dot_v3v3(e2, p0);
-
- inv = 1.f/(e1e1 * e2e2 - e1e2 * e1e2);
- u = (e2e2 * e1p0 - e1e2 * e2p0) * inv;
- v = (e1e1 * e2p0 - e1e2 * e1p0) * inv;
-
- if (u>=0.f && u<=1.f && v>=0.f && u+v<=1.f) {
- *result = *pce;
-
- /* normal already calculated in pce */
-
- result->uv[0] = u;
- result->uv[1] = v;
-
- *t = ct;
- return 1;
- }
- }
- return 0;
-}
-static int collision_sphere_to_edges(ParticleCollision *col, float radius, ParticleCollisionElement *pce, float *t)
-{
- ParticleCollisionElement edge[3], *cur = NULL, *hit = NULL;
- ParticleCollisionElement *result = &col->pce;
-
- float ct;
- int i;
-
- for (i=0; i<3; i++) {
- cur = edge+i;
- cur->x[0] = pce->x[i]; cur->x[1] = pce->x[(i+1)%3];
- cur->v[0] = pce->v[i]; cur->v[1] = pce->v[(i+1)%3];
- cur->tot = 2;
- cur->inside = 0;
-
- ct = collision_newton_rhapson(col, radius, cur, nr_distance_to_edge);
-
- if (ct >= 0.f && ct < *t) {
- float u, e[3], vec[3];
-
- sub_v3_v3v3(e, cur->x1, cur->x0);
- sub_v3_v3v3(vec, cur->p, cur->x0);
- u = dot_v3v3(vec, e) / dot_v3v3(e, e);
-
- if (u < 0.f || u > 1.f)
- break;
-
- *result = *cur;
-
- madd_v3_v3v3fl(result->nor, vec, e, -u);
- normalize_v3(result->nor);
-
- result->uv[0] = u;
-
-
- hit = cur;
- *t = ct;
- }
-
- }
-
- return hit != NULL;
-}
-static int collision_sphere_to_verts(ParticleCollision *col, float radius, ParticleCollisionElement *pce, float *t)
-{
- ParticleCollisionElement vert[3], *cur = NULL, *hit = NULL;
- ParticleCollisionElement *result = &col->pce;
-
- float ct;
- int i;
-
- for (i=0; i<3; i++) {
- cur = vert+i;
- cur->x[0] = pce->x[i];
- cur->v[0] = pce->v[i];
- cur->tot = 1;
- cur->inside = 0;
-
- ct = collision_newton_rhapson(col, radius, cur, nr_distance_to_vert);
-
- if (ct >= 0.f && ct < *t) {
- *result = *cur;
-
- sub_v3_v3v3(result->nor, cur->p, cur->x0);
- normalize_v3(result->nor);
-
- hit = cur;
- *t = ct;
- }
-
- }
-
- return hit != NULL;
-}
-/* Callback for BVHTree near test */
-void BKE_psys_collision_neartest_cb(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
-{
- ParticleCollision *col = (ParticleCollision *) userdata;
- ParticleCollisionElement pce;
- const MVertTri *vt = &col->md->tri[index];
- MVert *x = col->md->x;
- MVert *v = col->md->current_v;
- float t = hit->dist/col->original_ray_length;
- int collision = 0;
-
- pce.x[0] = x[vt->tri[0]].co;
- pce.x[1] = x[vt->tri[1]].co;
- pce.x[2] = x[vt->tri[2]].co;
-
- pce.v[0] = v[vt->tri[0]].co;
- pce.v[1] = v[vt->tri[1]].co;
- pce.v[2] = v[vt->tri[2]].co;
-
- pce.tot = 3;
- pce.inside = 0;
- pce.index = index;
-
- collision = collision_sphere_to_tri(col, ray->radius, &pce, &t);
- if (col->pce.inside == 0) {
- collision += collision_sphere_to_edges(col, ray->radius, &pce, &t);
- collision += collision_sphere_to_verts(col, ray->radius, &pce, &t);
- }
-
- if (collision) {
- hit->dist = col->original_ray_length * t;
- hit->index = index;
-
- collision_point_velocity(&col->pce);
-
- col->hit = col->current;
- }
-}
-static int collision_detect(ParticleData *pa, ParticleCollision *col, BVHTreeRayHit *hit, ListBase *colliders)
-{
- const int raycast_flag = BVH_RAYCAST_DEFAULT & ~(BVH_RAYCAST_WATERTIGHT);
- ColliderCache *coll;
- float ray_dir[3];
-
- if (BLI_listbase_is_empty(colliders))
- return 0;
-
- sub_v3_v3v3(ray_dir, col->co2, col->co1);
- hit->index = -1;
- hit->dist = col->original_ray_length = normalize_v3(ray_dir);
- col->pce.inside = 0;
-
- /* even if particle is stationary we want to check for moving colliders */
- /* if hit.dist is zero the bvhtree_ray_cast will just ignore everything */
- if (hit->dist == 0.0f)
- hit->dist = col->original_ray_length = 0.000001f;
-
- for (coll = colliders->first; coll; coll=coll->next) {
- /* for boids: don't check with current ground object; also skip if permeated */
- bool skip = false;
-
- for (int i = 0; i < col->skip_count; i++) {
- if (coll->ob == col->skip[i]) {
- skip = true;
- break;
- }
- }
-
- if (skip)
- continue;
-
- /* particles should not collide with emitter at birth */
- if (coll->ob == col->emitter && pa->time < col->cfra && pa->time >= col->old_cfra)
- continue;
-
- col->current = coll->ob;
- col->md = coll->collmd;
- col->fac1 = (col->old_cfra - coll->collmd->time_x) / (coll->collmd->time_xnew - coll->collmd->time_x);
- col->fac2 = (col->cfra - coll->collmd->time_x) / (coll->collmd->time_xnew - coll->collmd->time_x);
-
- if (col->md && col->md->bvhtree) {
- BLI_bvhtree_ray_cast_ex(
- col->md->bvhtree, col->co1, ray_dir, col->radius, hit,
- BKE_psys_collision_neartest_cb, col, raycast_flag);
- }
- }
-
- return hit->index >= 0;
-}
-static int collision_response(ParticleData *pa, ParticleCollision *col, BVHTreeRayHit *hit, int kill, int dynamic_rotation)
-{
- ParticleCollisionElement *pce = &col->pce;
- PartDeflect *pd = col->hit->pd;
- float co[3]; /* point of collision */
- float x = hit->dist/col->original_ray_length; /* location factor of collision between this iteration */
- float f = col->f + x * (1.0f - col->f); /* time factor of collision between timestep */
- float dt1 = (f - col->f) * col->total_time; /* time since previous collision (in seconds) */
- float dt2 = (1.0f - f) * col->total_time; /* time left after collision (in seconds) */
- int through = (BLI_frand() < pd->pdef_perm) ? 1 : 0; /* did particle pass through the collision surface? */
-
- /* calculate exact collision location */
- interp_v3_v3v3(co, col->co1, col->co2, x);
-
- /* particle dies in collision */
- if (through == 0 && (kill || pd->flag & PDEFLE_KILL_PART)) {
- pa->alive = PARS_DYING;
- pa->dietime = col->old_cfra + (col->cfra - col->old_cfra) * f;
-
- copy_v3_v3(pa->state.co, co);
- interp_v3_v3v3(pa->state.vel, pa->prev_state.vel, pa->state.vel, f);
- interp_qt_qtqt(pa->state.rot, pa->prev_state.rot, pa->state.rot, f);
- interp_v3_v3v3(pa->state.ave, pa->prev_state.ave, pa->state.ave, f);
-
- /* particle is dead so we don't need to calculate further */
- return 0;
- }
- /* figure out velocity and other data after collision */
- else {
- float v0[3]; /* velocity directly before collision to be modified into velocity directly after collision */
- float v0_nor[3];/* normal component of v0 */
- float v0_tan[3];/* tangential component of v0 */
- float vc_tan[3];/* tangential component of collision surface velocity */
- float v0_dot, vc_dot;
- float damp = pd->pdef_damp + pd->pdef_rdamp * 2 * (BLI_frand() - 0.5f);
- float frict = pd->pdef_frict + pd->pdef_rfrict * 2 * (BLI_frand() - 0.5f);
- float distance, nor[3], dot;
-
- CLAMP(damp,0.0f, 1.0f);
- CLAMP(frict,0.0f, 1.0f);
-
- /* get exact velocity right before collision */
- madd_v3_v3v3fl(v0, col->ve1, col->acc, dt1);
-
- /* convert collider velocity from 1/framestep to 1/s TODO: here we assume 1 frame step for collision modifier */
- mul_v3_fl(pce->vel, col->inv_timestep);
-
- /* calculate tangential particle velocity */
- v0_dot = dot_v3v3(pce->nor, v0);
- madd_v3_v3v3fl(v0_tan, v0, pce->nor, -v0_dot);
-
- /* calculate tangential collider velocity */
- vc_dot = dot_v3v3(pce->nor, pce->vel);
- madd_v3_v3v3fl(vc_tan, pce->vel, pce->nor, -vc_dot);
-
- /* handle friction effects (tangential and angular velocity) */
- if (frict > 0.0f) {
- /* angular <-> linear velocity */
- if (dynamic_rotation) {
- float vr_tan[3], v1_tan[3], ave[3];
-
- /* linear velocity of particle surface */
- cross_v3_v3v3(vr_tan, pce->nor, pa->state.ave);
- mul_v3_fl(vr_tan, pa->size);
-
- /* change to coordinates that move with the collision plane */
- sub_v3_v3v3(v1_tan, v0_tan, vc_tan);
-
- /* The resulting velocity is a weighted average of particle cm & surface
- * velocity. This weight (related to particle's moment of inertia) could
- * be made a parameter for angular <-> linear conversion.
- */
- madd_v3_v3fl(v1_tan, vr_tan, -0.4);
- mul_v3_fl(v1_tan, 1.0f/1.4f); /* 1/(1+0.4) */
-
- /* rolling friction is around 0.01 of sliding friction (could be made a parameter) */
- mul_v3_fl(v1_tan, 1.0f - 0.01f * frict);
-
- /* surface_velocity is opposite to cm velocity */
- negate_v3_v3(vr_tan, v1_tan);
-
- /* get back to global coordinates */
- add_v3_v3(v1_tan, vc_tan);
-
- /* convert to angular velocity*/
- cross_v3_v3v3(ave, vr_tan, pce->nor);
- mul_v3_fl(ave, 1.0f/MAX2(pa->size, 0.001f));
-
- /* only friction will cause change in linear & angular velocity */
- interp_v3_v3v3(pa->state.ave, pa->state.ave, ave, frict);
- interp_v3_v3v3(v0_tan, v0_tan, v1_tan, frict);
- }
- else {
- /* just basic friction (unphysical due to the friction model used in Blender) */
- interp_v3_v3v3(v0_tan, v0_tan, vc_tan, frict);
- }
- }
-
- /* stickiness was possibly added before, so cancel that before calculating new normal velocity */
- /* otherwise particles go flying out of the surface because of high reversed sticky velocity */
- if (v0_dot < 0.0f) {
- v0_dot += pd->pdef_stickness;
- if (v0_dot > 0.0f)
- v0_dot = 0.0f;
- }
-
- /* damping and flipping of velocity around normal */
- v0_dot *= 1.0f - damp;
- vc_dot *= through ? damp : 1.0f;
-
- /* calculate normal particle velocity */
- /* special case for object hitting the particle from behind */
- if (through==0 && ((vc_dot>0.0f && v0_dot>0.0f && vc_dot>v0_dot) || (vc_dot<0.0f && v0_dot<0.0f && vc_dot<v0_dot)))
- mul_v3_v3fl(v0_nor, pce->nor, vc_dot);
- else if (v0_dot > 0.f)
- mul_v3_v3fl(v0_nor, pce->nor, vc_dot + v0_dot);
- else
- mul_v3_v3fl(v0_nor, pce->nor, vc_dot + (through ? 1.0f : -1.0f) * v0_dot);
-
- /* combine components together again */
- add_v3_v3v3(v0, v0_nor, v0_tan);
-
- if (col->boid) {
- /* keep boids above ground */
- BoidParticle *bpa = pa->boid;
- if (bpa->data.mode == eBoidMode_OnLand || co[2] <= col->boid_z) {
- co[2] = col->boid_z;
- v0[2] = 0.0f;
- }
- }
-
- /* re-apply acceleration to final location and velocity */
- madd_v3_v3v3fl(pa->state.co, co, v0, dt2);
- madd_v3_v3fl(pa->state.co, col->acc, 0.5f*dt2*dt2);
- madd_v3_v3v3fl(pa->state.vel, v0, col->acc, dt2);
-
- /* make sure particle stays on the right side of the surface */
- if (!through) {
- distance = collision_point_distance_with_normal(co, pce, -1.f, col, nor);
-
- if (distance < col->radius + COLLISION_MIN_DISTANCE)
- madd_v3_v3fl(co, nor, col->radius + COLLISION_MIN_DISTANCE - distance);
-
- dot = dot_v3v3(nor, v0);
- if (dot < 0.f)
- madd_v3_v3fl(v0, nor, -dot);
-
- distance = collision_point_distance_with_normal(pa->state.co, pce, 1.f, col, nor);
-
- if (distance < col->radius + COLLISION_MIN_DISTANCE)
- madd_v3_v3fl(pa->state.co, nor, col->radius + COLLISION_MIN_DISTANCE - distance);
-
- dot = dot_v3v3(nor, pa->state.vel);
- if (dot < 0.f)
- madd_v3_v3fl(pa->state.vel, nor, -dot);
- }
-
- /* add stickiness to surface */
- madd_v3_v3fl(pa->state.vel, pce->nor, -pd->pdef_stickness);
-
- /* set coordinates for next iteration */
- copy_v3_v3(col->co1, co);
- copy_v3_v3(col->co2, pa->state.co);
-
- copy_v3_v3(col->ve1, v0);
- copy_v3_v3(col->ve2, pa->state.vel);
-
- col->f = f;
- }
-
- /* if permeability random roll succeeded, disable collider for this sim step */
- if (through) {
- col->skip[col->skip_count++] = col->hit;
- }
-
- return 1;
-}
-static void collision_fail(ParticleData *pa, ParticleCollision *col)
-{
- /* final chance to prevent total failure, so stick to the surface and hope for the best */
- collision_point_on_surface(col->co1, &col->pce, 1.f, col, pa->state.co);
-
- copy_v3_v3(pa->state.vel, col->pce.vel);
- mul_v3_fl(pa->state.vel, col->inv_timestep);
-
-
- /* printf("max iterations\n"); */
-}
-
-/* Particle - Mesh collision detection and response
- * Features:
- * -friction and damping
- * -angular momentum <-> linear momentum
- * -high accuracy by re-applying particle acceleration after collision
- * -handles moving, rotating and deforming meshes
- * -uses Newton-Rhapson iteration to find the collisions
- * -handles spherical particles and (nearly) point like particles
- */
-static void collision_check(ParticleSimulationData *sim, int p, float dfra, float cfra)
-{
- ParticleSettings *part = sim->psys->part;
- ParticleData *pa = sim->psys->particles + p;
- ParticleCollision col;
- BVHTreeRayHit hit;
- int collision_count=0;
-
- float timestep = psys_get_timestep(sim);
-
- memset(&col, 0, sizeof(ParticleCollision));
-
- col.total_time = timestep * dfra;
- col.inv_total_time = 1.0f/col.total_time;
- col.inv_timestep = 1.0f/timestep;
-
- col.cfra = cfra;
- col.old_cfra = sim->psys->cfra;
-
- /* get acceleration (from gravity, forcefields etc. to be re-applied in collision response) */
- sub_v3_v3v3(col.acc, pa->state.vel, pa->prev_state.vel);
- mul_v3_fl(col.acc, 1.f/col.total_time);
-
- /* set values for first iteration */
- copy_v3_v3(col.co1, pa->prev_state.co);
- copy_v3_v3(col.co2, pa->state.co);
- copy_v3_v3(col.ve1, pa->prev_state.vel);
- copy_v3_v3(col.ve2, pa->state.vel);
- col.f = 0.0f;
-
- col.radius = ((part->flag & PART_SIZE_DEFL) || (part->phystype == PART_PHYS_BOIDS)) ? pa->size : COLLISION_MIN_RADIUS;
-
- /* override for boids */
- if (part->phystype == PART_PHYS_BOIDS && part->boids->options & BOID_ALLOW_LAND) {
- col.boid = 1;
- col.boid_z = pa->state.co[2];
- col.skip[col.skip_count++] = pa->boid->ground;
- }
-
- /* 10 iterations to catch multiple collisions */
- while (collision_count < PARTICLE_COLLISION_MAX_COLLISIONS) {
- if (collision_detect(pa, &col, &hit, sim->colliders)) {
-
- collision_count++;
-
- if (collision_count == PARTICLE_COLLISION_MAX_COLLISIONS)
- collision_fail(pa, &col);
- else if (collision_response(pa, &col, &hit, part->flag & PART_DIE_ON_COL, part->flag & PART_ROT_DYN)==0)
- return;
- }
- else
- return;
- }
-}
-/************************************************/
-/* Hair */
-/************************************************/
-/* check if path cache or children need updating and do it if needed */
-static void psys_update_path_cache(ParticleSimulationData *sim, float cfra, const bool use_render_params)
-{
- ParticleSystem *psys = sim->psys;
- ParticleSettings *part = psys->part;
- ParticleEditSettings *pset = &sim->scene->toolsettings->particle;
- Base *base;
- int distr=0, alloc=0, skip=0;
-
- if ((psys->part->childtype && psys->totchild != psys_get_tot_child(sim->scene, psys)) || psys->recalc&PSYS_RECALC_RESET)
- alloc=1;
-
- if (alloc || psys->recalc&PSYS_RECALC_CHILD || (psys->vgroup[PSYS_VG_DENSITY] && (sim->ob && sim->ob->mode & OB_MODE_WEIGHT_PAINT)))
- distr=1;
-
- if (distr) {
- if (alloc)
- realloc_particles(sim, sim->psys->totpart);
-
- if (psys_get_tot_child(sim->scene, psys)) {
- /* don't generate children while computing the hair keys */
- if (!(psys->part->type == PART_HAIR) || (psys->flag & PSYS_HAIR_DONE)) {
- distribute_particles(sim, PART_FROM_CHILD);
-
- if (part->childtype==PART_CHILD_FACES && part->parents != 0.0f)
- psys_find_parents(sim, use_render_params);
- }
- }
- else
- psys_free_children(psys);
- }
-
- if ((part->type==PART_HAIR || psys->flag&PSYS_KEYED || psys->pointcache->flag & PTCACHE_BAKED)==0)
- skip = 1; /* only hair, keyed and baked stuff can have paths */
- else if (part->ren_as != PART_DRAW_PATH && !(part->type==PART_HAIR && ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR)))
- skip = 1; /* particle visualization must be set as path */
- else if (!psys->renderdata) {
- if (part->draw_as != PART_DRAW_REND)
- skip = 1; /* draw visualization */
- else if (psys->pointcache->flag & PTCACHE_BAKING)
- skip = 1; /* no need to cache paths while baking dynamics */
- else if (psys_in_edit_mode(sim->scene, psys)) {
- if ((pset->flag & PE_DRAW_PART)==0)
- skip = 1;
- else if (part->childtype==0 && (psys->flag & PSYS_HAIR_DYNAMICS && psys->pointcache->flag & PTCACHE_BAKED)==0)
- skip = 1; /* in edit mode paths are needed for child particles and dynamic hair */
- }
- }
-
-
- /* particle instance modifier with "path" option need cached paths even if particle system doesn't */
- for (base = sim->scene->base.first; base; base= base->next) {
- ModifierData *md = modifiers_findByType(base->object, eModifierType_ParticleInstance);
- if (md) {
- ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *)md;
- if (pimd->flag & eParticleInstanceFlag_Path && pimd->ob == sim->ob && pimd->psys == (psys - (ParticleSystem*)sim->ob->particlesystem.first)) {
- skip = 0;
- break;
- }
- }
- }
-
- if (!skip) {
- psys_cache_paths(sim, cfra, use_render_params);
-
- /* for render, child particle paths are computed on the fly */
- if (part->childtype) {
- if (!psys->totchild)
- skip = 1;
- else if (psys->part->type == PART_HAIR && (psys->flag & PSYS_HAIR_DONE)==0)
- skip = 1;
-
- if (!skip)
- psys_cache_child_paths(sim, cfra, 0, use_render_params);
- }
- }
- else if (psys->pathcache)
- psys_free_path_cache(psys, NULL);
-}
-
-static bool psys_hair_use_simulation(ParticleData *pa, float max_length)
-{
- /* Minimum segment length relative to average length.
- * Hairs with segments below this length will be excluded from the simulation,
- * because otherwise the solver will become unstable.
- * The hair system should always make sure the hair segments have reasonable length ratios,
- * but this can happen in old files when e.g. cutting hair.
- */
- const float min_length = 0.1f * max_length;
-
- HairKey *key;
- int k;
-
- if (pa->totkey < 2)
- return false;
-
- for (k=1, key=pa->hair+1; k<pa->totkey; k++,key++) {
- float length = len_v3v3(key->co, (key-1)->co);
- if (length < min_length)
- return false;
- }
-
- return true;
-}
-
-static MDeformVert *hair_set_pinning(MDeformVert *dvert, float weight)
-{
- if (dvert) {
- if (!dvert->totweight) {
- dvert->dw = MEM_callocN(sizeof(MDeformWeight), "deformWeight");
- dvert->totweight = 1;
- }
-
- dvert->dw->weight = weight;
- dvert++;
- }
- return dvert;
-}
-
-static void hair_create_input_dm(ParticleSimulationData *sim, int totpoint, int totedge, DerivedMesh **r_dm, ClothHairData **r_hairdata)
-{
- ParticleSystem *psys = sim->psys;
- ParticleSettings *part = psys->part;
- DerivedMesh *dm;
- ClothHairData *hairdata;
- MVert *mvert;
- MEdge *medge;
- MDeformVert *dvert;
- HairKey *key;
- PARTICLE_P;
- int k, hair_index;
- float hairmat[4][4];
- float max_length;
- float hair_radius;
-
- dm = *r_dm;
- if (!dm) {
- *r_dm = dm = CDDM_new(totpoint, totedge, 0, 0, 0);
- DM_add_vert_layer(dm, CD_MDEFORMVERT, CD_CALLOC, NULL);
- }
- mvert = CDDM_get_verts(dm);
- medge = CDDM_get_edges(dm);
- dvert = DM_get_vert_data_layer(dm, CD_MDEFORMVERT);
-
- hairdata = *r_hairdata;
- if (!hairdata) {
- *r_hairdata = hairdata = MEM_mallocN(sizeof(ClothHairData) * totpoint, "hair data");
- }
-
- /* calculate maximum segment length */
- max_length = 0.0f;
- LOOP_PARTICLES {
- for (k=1, key=pa->hair+1; k<pa->totkey; k++,key++) {
- float length = len_v3v3(key->co, (key-1)->co);
- if (max_length < length)
- max_length = length;
- }
- }
-
- psys->clmd->sim_parms->vgroup_mass = 1;
-
- /* XXX placeholder for more flexible future hair settings */
- hair_radius = part->size;
-
- /* make vgroup for pin roots etc.. */
- hair_index = 1;
- LOOP_PARTICLES {
- float root_mat[4][4];
- float bending_stiffness;
- bool use_hair;
-
- pa->hair_index = hair_index;
- use_hair = psys_hair_use_simulation(pa, max_length);
-
- psys_mat_hair_to_object(sim->ob, sim->psmd->dm_final, psys->part->from, pa, hairmat);
- mul_m4_m4m4(root_mat, sim->ob->obmat, hairmat);
- normalize_m4(root_mat);
-
- bending_stiffness = CLAMPIS(1.0f - part->bending_random * psys_frand(psys, p + 666), 0.0f, 1.0f);
-
- for (k=0, key=pa->hair; k<pa->totkey; k++,key++) {
- ClothHairData *hair;
- float *co, *co_next;
-
- co = key->co;
- co_next = (key+1)->co;
-
- /* create fake root before actual root to resist bending */
- if (k==0) {
- hair = &psys->clmd->hairdata[pa->hair_index - 1];
- copy_v3_v3(hair->loc, root_mat[3]);
- copy_m3_m4(hair->rot, root_mat);
-
- hair->radius = hair_radius;
- hair->bending_stiffness = bending_stiffness;
-
- add_v3_v3v3(mvert->co, co, co);
- sub_v3_v3(mvert->co, co_next);
- mul_m4_v3(hairmat, mvert->co);
-
- medge->v1 = pa->hair_index - 1;
- medge->v2 = pa->hair_index;
-
- dvert = hair_set_pinning(dvert, 1.0f);
-
- mvert++;
- medge++;
- }
-
- /* store root transform in cloth data */
- hair = &psys->clmd->hairdata[pa->hair_index + k];
- copy_v3_v3(hair->loc, root_mat[3]);
- copy_m3_m4(hair->rot, root_mat);
-
- hair->radius = hair_radius;
- hair->bending_stiffness = bending_stiffness;
-
- copy_v3_v3(mvert->co, co);
- mul_m4_v3(hairmat, mvert->co);
-
- if (k) {
- medge->v1 = pa->hair_index + k - 1;
- medge->v2 = pa->hair_index + k;
- }
-
- /* roots and disabled hairs should be 1.0, the rest can be anything from 0.0 to 1.0 */
- if (use_hair)
- dvert = hair_set_pinning(dvert, key->weight);
- else
- dvert = hair_set_pinning(dvert, 1.0f);
-
- mvert++;
- if (k)
- medge++;
- }
-
- hair_index += pa->totkey + 1;
- }
-}
-
-static void do_hair_dynamics(ParticleSimulationData *sim)
-{
- ParticleSystem *psys = sim->psys;
- PARTICLE_P;
- EffectorWeights *clmd_effweights;
- int totpoint;
- int totedge;
- float (*deformedVerts)[3];
- bool realloc_roots;
-
- if (!psys->clmd) {
- psys->clmd = (ClothModifierData*)modifier_new(eModifierType_Cloth);
- psys->clmd->sim_parms->goalspring = 0.0f;
- psys->clmd->sim_parms->vel_damping = 1.0f;
- psys->clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_GOAL|CLOTH_SIMSETTINGS_FLAG_NO_SPRING_COMPRESS;
- psys->clmd->coll_parms->flags &= ~CLOTH_COLLSETTINGS_FLAG_SELF;
- }
-
- /* count simulated points */
- totpoint = 0;
- totedge = 0;
- LOOP_PARTICLES {
- /* "out" dm contains all hairs */
- totedge += pa->totkey;
- totpoint += pa->totkey + 1; /* +1 for virtual root point */
- }
-
- realloc_roots = false; /* whether hair root info array has to be reallocated */
- if (psys->hair_in_dm) {
- DerivedMesh *dm = psys->hair_in_dm;
- if (totpoint != dm->getNumVerts(dm) || totedge != dm->getNumEdges(dm)) {
- dm->release(dm);
- psys->hair_in_dm = NULL;
- realloc_roots = true;
- }
- }
-
- if (!psys->hair_in_dm || !psys->clmd->hairdata || realloc_roots) {
- if (psys->clmd->hairdata) {
- MEM_freeN(psys->clmd->hairdata);
- psys->clmd->hairdata = NULL;
- }
- }
-
- hair_create_input_dm(sim, totpoint, totedge, &psys->hair_in_dm, &psys->clmd->hairdata);
-
- if (psys->hair_out_dm)
- psys->hair_out_dm->release(psys->hair_out_dm);
-
- psys->clmd->point_cache = psys->pointcache;
- /* for hair sim we replace the internal cloth effector weights temporarily
- * to use the particle settings
- */
- clmd_effweights = psys->clmd->sim_parms->effector_weights;
- psys->clmd->sim_parms->effector_weights = psys->part->effector_weights;
-
- deformedVerts = MEM_mallocN(sizeof(*deformedVerts) * psys->hair_in_dm->getNumVerts(psys->hair_in_dm), "do_hair_dynamics vertexCos");
- psys->hair_out_dm = CDDM_copy(psys->hair_in_dm);
- psys->hair_out_dm->getVertCos(psys->hair_out_dm, deformedVerts);
-
- clothModifier_do(psys->clmd, sim->scene, sim->ob, psys->hair_in_dm, deformedVerts);
-
- CDDM_apply_vert_coords(psys->hair_out_dm, deformedVerts);
-
- MEM_freeN(deformedVerts);
-
- /* restore cloth effector weights */
- psys->clmd->sim_parms->effector_weights = clmd_effweights;
-}
-static void hair_step(ParticleSimulationData *sim, float cfra, const bool use_render_params)
-{
- ParticleSystem *psys = sim->psys;
- ParticleSettings *part = psys->part;
- PARTICLE_P;
- float disp = psys_get_current_display_percentage(psys);
-
- LOOP_PARTICLES {
- pa->size = part->size;
- if (part->randsize > 0.0f)
- pa->size *= 1.0f - part->randsize * psys_frand(psys, p + 1);
-
- if (psys_frand(psys, p) > disp)
- pa->flag |= PARS_NO_DISP;
- else
- pa->flag &= ~PARS_NO_DISP;
- }
-
- if (psys->recalc & PSYS_RECALC_RESET) {
- /* need this for changing subsurf levels */
- psys_calc_dmcache(sim->ob, sim->psmd->dm_final, sim->psmd->dm_deformed, psys);
-
- if (psys->clmd)
- cloth_free_modifier(psys->clmd);
- }
-
- /* dynamics with cloth simulation, psys->particles can be NULL with 0 particles [#25519] */
- if (psys->part->type==PART_HAIR && psys->flag & PSYS_HAIR_DYNAMICS && psys->particles)
- do_hair_dynamics(sim);
-
- /* following lines were removed r29079 but cause bug [#22811], see report for details */
- psys_update_effectors(sim);
- psys_update_path_cache(sim, cfra, use_render_params);
-
- psys->flag |= PSYS_HAIR_UPDATED;
-}
-
-static void save_hair(ParticleSimulationData *sim, float UNUSED(cfra))
-{
- Object *ob = sim->ob;
- ParticleSystem *psys = sim->psys;
- HairKey *key, *root;
- PARTICLE_P;
-
- invert_m4_m4(ob->imat, ob->obmat);
-
- psys->lattice_deform_data= psys_create_lattice_deform_data(sim);
-
- if (psys->totpart==0) return;
-
- /* save new keys for elements if needed */
- LOOP_PARTICLES {
- /* first time alloc */
- if (pa->totkey==0 || pa->hair==NULL) {
- pa->hair = MEM_callocN((psys->part->hair_step + 1) * sizeof(HairKey), "HairKeys");
- pa->totkey = 0;
- }
-
- key = root = pa->hair;
- key += pa->totkey;
-
- /* convert from global to geometry space */
- copy_v3_v3(key->co, pa->state.co);
- mul_m4_v3(ob->imat, key->co);
-
- if (pa->totkey) {
- sub_v3_v3(key->co, root->co);
- psys_vec_rot_to_face(sim->psmd->dm_final, pa, key->co);
- }
-
- key->time = pa->state.time;
-
- key->weight = 1.0f - key->time / 100.0f;
-
- pa->totkey++;
-
- /* root is always in the origin of hair space so we set it to be so after the last key is saved*/
- if (pa->totkey == psys->part->hair_step + 1) {
- zero_v3(root->co);
- }
-
- }
-}
-
-/* Code for an adaptive time step based on the Courant-Friedrichs-Lewy
- * condition. */
-static const float MIN_TIMESTEP = 1.0f / 101.0f;
-/* Tolerance of 1.5 means the last subframe neither favors growing nor
- * shrinking (e.g if it were 1.3, the last subframe would tend to be too
- * small). */
-static const float TIMESTEP_EXPANSION_FACTOR = 0.1f;
-static const float TIMESTEP_EXPANSION_TOLERANCE = 1.5f;
-
-/* Calculate the speed of the particle relative to the local scale of the
- * simulation. This should be called once per particle during a simulation
- * step, after the velocity has been updated. element_size defines the scale of
- * the simulation, and is typically the distance to neighboring particles. */
-static void update_courant_num(ParticleSimulationData *sim, ParticleData *pa,
- float dtime, SPHData *sphdata, SpinLock *spin)
-{
- float relative_vel[3];
-
- sub_v3_v3v3(relative_vel, pa->prev_state.vel, sphdata->flow);
-
- const float courant_num = len_v3(relative_vel) * dtime / sphdata->element_size;
- if (sim->courant_num < courant_num) {
- BLI_spin_lock(spin);
- if (sim->courant_num < courant_num) {
- sim->courant_num = courant_num;
- }
- BLI_spin_unlock(spin);
- }
-}
-static float get_base_time_step(ParticleSettings *part)
-{
- return 1.0f / (float) (part->subframes + 1);
-}
-/* Update time step size to suit current conditions. */
-static void update_timestep(ParticleSystem *psys, ParticleSimulationData *sim)
-{
- float dt_target;
- if (sim->courant_num == 0.0f)
- dt_target = 1.0f;
- else
- dt_target = psys->dt_frac * (psys->part->courant_target / sim->courant_num);
-
- /* Make sure the time step is reasonable. For some reason, the CLAMP macro
- * doesn't work here. The time step becomes too large. - z0r */
- if (dt_target < MIN_TIMESTEP)
- dt_target = MIN_TIMESTEP;
- else if (dt_target > get_base_time_step(psys->part))
- dt_target = get_base_time_step(psys->part);
-
- /* Decrease time step instantly, but increase slowly. */
- if (dt_target > psys->dt_frac)
- psys->dt_frac = interpf(dt_target, psys->dt_frac, TIMESTEP_EXPANSION_FACTOR);
- else
- psys->dt_frac = dt_target;
-}
-
-static float sync_timestep(ParticleSystem *psys, float t_frac)
-{
- /* Sync with frame end if it's close. */
- if (t_frac == 1.0f)
- return psys->dt_frac;
- else if (t_frac + (psys->dt_frac * TIMESTEP_EXPANSION_TOLERANCE) >= 1.0f)
- return 1.0f - t_frac;
- else
- return psys->dt_frac;
-}
-
-/************************************************/
-/* System Core */
-/************************************************/
-
-typedef struct DynamicStepSolverTaskData {
- ParticleSimulationData *sim;
-
- float cfra;
- float timestep;
- float dtime;
-
- SpinLock spin;
-} DynamicStepSolverTaskData;
-
-static void dynamics_step_sph_ddr_task_cb_ex(
- void *userdata, void *userdata_chunk, const int p, const int UNUSED(thread_id))
-{
- DynamicStepSolverTaskData *data = userdata;
- ParticleSimulationData *sim = data->sim;
- ParticleSystem *psys = sim->psys;
- ParticleSettings *part = psys->part;
-
- SPHData *sphdata = userdata_chunk;
-
- ParticleData *pa;
-
- if ((pa = psys->particles + p)->state.time <= 0.0f) {
- return;
- }
-
- /* do global forces & effectors */
- basic_integrate(sim, p, pa->state.time, data->cfra);
-
- /* actual fluids calculations */
- sph_integrate(sim, pa, pa->state.time, sphdata);
-
- if (sim->colliders)
- collision_check(sim, p, pa->state.time, data->cfra);
-
- /* SPH particles are not physical particles, just interpolation
- * particles, thus rotation has not a direct sense for them */
- basic_rotate(part, pa, pa->state.time, data->timestep);
-
- if (part->time_flag & PART_TIME_AUTOSF) {
- update_courant_num(sim, pa, data->dtime, sphdata, &data->spin);
- }
-}
-
-static void dynamics_step_sph_classical_basic_integrate_task_cb_ex(
- void *userdata, void *UNUSED(userdata_chunk), const int p, const int UNUSED(thread_id))
-{
- DynamicStepSolverTaskData *data = userdata;
- ParticleSimulationData *sim = data->sim;
- ParticleSystem *psys = sim->psys;
-
- ParticleData *pa;
-
- if ((pa = psys->particles + p)->state.time <= 0.0f) {
- return;
- }
-
- basic_integrate(sim, p, pa->state.time, data->cfra);
-}
-
-static void dynamics_step_sph_classical_calc_density_task_cb_ex(
- void *userdata, void *userdata_chunk, const int p, const int UNUSED(thread_id))
-{
- DynamicStepSolverTaskData *data = userdata;
- ParticleSimulationData *sim = data->sim;
- ParticleSystem *psys = sim->psys;
-
- SPHData *sphdata = userdata_chunk;
-
- ParticleData *pa;
-
- if ((pa = psys->particles + p)->state.time <= 0.0f) {
- return;
- }
-
- sphclassical_calc_dens(pa, pa->state.time, sphdata);
-}
-
-static void dynamics_step_sph_classical_integrate_task_cb_ex(
- void *userdata, void *userdata_chunk, const int p, const int UNUSED(thread_id))
-{
- DynamicStepSolverTaskData *data = userdata;
- ParticleSimulationData *sim = data->sim;
- ParticleSystem *psys = sim->psys;
- ParticleSettings *part = psys->part;
-
- SPHData *sphdata = userdata_chunk;
-
- ParticleData *pa;
-
- if ((pa = psys->particles + p)->state.time <= 0.0f) {
- return;
- }
-
- /* actual fluids calculations */
- sph_integrate(sim, pa, pa->state.time, sphdata);
-
- if (sim->colliders)
- collision_check(sim, p, pa->state.time, data->cfra);
-
- /* SPH particles are not physical particles, just interpolation
- * particles, thus rotation has not a direct sense for them */
- basic_rotate(part, pa, pa->state.time, data->timestep);
-
- if (part->time_flag & PART_TIME_AUTOSF) {
- update_courant_num(sim, pa, data->dtime, sphdata, &data->spin);
- }
-}
-
-/* unbaked particles are calculated dynamically */
-static void dynamics_step(ParticleSimulationData *sim, float cfra)
-{
- ParticleSystem *psys = sim->psys;
- ParticleSettings *part=psys->part;
- RNG *rng;
- BoidBrainData bbd;
- ParticleTexture ptex;
- PARTICLE_P;
- float timestep;
- /* frame & time changes */
- float dfra, dtime;
- float birthtime, dietime;
-
- /* where have we gone in time since last time */
- dfra= cfra - psys->cfra;
-
- timestep = psys_get_timestep(sim);
- dtime= dfra*timestep;
-
- if (dfra < 0.0f) {
- LOOP_EXISTING_PARTICLES {
- psys_get_texture(sim, pa, &ptex, PAMAP_SIZE, cfra);
- pa->size = part->size*ptex.size;
- if (part->randsize > 0.0f)
- pa->size *= 1.0f - part->randsize * psys_frand(psys, p + 1);
-
- reset_particle(sim, pa, dtime, cfra);
- }
- return;
- }
-
- BLI_srandom(31415926 + (int)cfra + psys->seed);
- /* for now do both, boids us 'rng' */
- rng = BLI_rng_new_srandom(31415926 + (int)cfra + psys->seed);
-
- psys_update_effectors(sim);
-
- if (part->type != PART_HAIR)
- sim->colliders = get_collider_cache(sim->scene, sim->ob, part->collision_group);
-
- /* initialize physics type specific stuff */
- switch (part->phystype) {
- case PART_PHYS_BOIDS:
- {
- ParticleTarget *pt = psys->targets.first;
- bbd.sim = sim;
- bbd.part = part;
- bbd.cfra = cfra;
- bbd.dfra = dfra;
- bbd.timestep = timestep;
- bbd.rng = rng;
-
- psys_update_particle_tree(psys, cfra);
-
- boids_precalc_rules(part, cfra);
-
- for (; pt; pt=pt->next) {
- ParticleSystem *psys_target = psys_get_target_system(sim->ob, pt);
- if (psys_target && psys_target != psys) {
- psys_update_particle_tree(psys_target, cfra);
- }
- }
- break;
- }
- case PART_PHYS_FLUID:
- {
- ParticleTarget *pt = psys->targets.first;
- psys_update_particle_bvhtree(psys, cfra);
-
- for (; pt; pt=pt->next) { /* Updating others systems particle tree for fluid-fluid interaction */
- if (pt->ob)
- psys_update_particle_bvhtree(BLI_findlink(&pt->ob->particlesystem, pt->psys-1), cfra);
- }
- break;
- }
- }
- /* initialize all particles for dynamics */
- LOOP_SHOWN_PARTICLES {
- copy_particle_key(&pa->prev_state,&pa->state,1);
-
- psys_get_texture(sim, pa, &ptex, PAMAP_SIZE, cfra);
-
- pa->size = part->size*ptex.size;
- if (part->randsize > 0.0f)
- pa->size *= 1.0f - part->randsize * psys_frand(psys, p + 1);
-
- birthtime = pa->time;
- dietime = pa->dietime;
-
- /* store this, so we can do multiple loops over particles */
- pa->state.time = dfra;
-
- if (dietime <= cfra && psys->cfra < dietime) {
- /* particle dies some time between this and last step */
- pa->state.time = dietime - ((birthtime > psys->cfra) ? birthtime : psys->cfra);
- pa->alive = PARS_DYING;
- }
- else if (birthtime <= cfra && birthtime >= psys->cfra) {
- /* particle is born some time between this and last step*/
- reset_particle(sim, pa, dfra*timestep, cfra);
- pa->alive = PARS_ALIVE;
- pa->state.time = cfra - birthtime;
- }
- else if (dietime < cfra) {
- /* nothing to be done when particle is dead */
- }
-
- /* only reset unborn particles if they're shown or if the particle is born soon*/
- if (pa->alive==PARS_UNBORN && (part->flag & PART_UNBORN || (cfra + psys->pointcache->step > pa->time))) {
- reset_particle(sim, pa, dtime, cfra);
- }
- else if (part->phystype == PART_PHYS_NO) {
- reset_particle(sim, pa, dtime, cfra);
- }
-
- if (ELEM(pa->alive, PARS_ALIVE, PARS_DYING)==0 || (pa->flag & (PARS_UNEXIST|PARS_NO_DISP)))
- pa->state.time = -1.f;
- }
-
- switch (part->phystype) {
- case PART_PHYS_NEWTON:
- {
- LOOP_DYNAMIC_PARTICLES {
- /* do global forces & effectors */
- basic_integrate(sim, p, pa->state.time, cfra);
-
- /* deflection */
- if (sim->colliders)
- collision_check(sim, p, pa->state.time, cfra);
-
- /* rotations */
- basic_rotate(part, pa, pa->state.time, timestep);
- }
- break;
- }
- case PART_PHYS_BOIDS:
- {
- LOOP_DYNAMIC_PARTICLES {
- bbd.goal_ob = NULL;
-
- boid_brain(&bbd, p, pa);
-
- if (pa->alive != PARS_DYING) {
- boid_body(&bbd, pa);
-
- /* deflection */
- if (sim->colliders)
- collision_check(sim, p, pa->state.time, cfra);
- }
- }
- break;
- }
- case PART_PHYS_FLUID:
- {
- SPHData sphdata;
- psys_sph_init(sim, &sphdata);
-
- DynamicStepSolverTaskData task_data = {
- .sim = sim, .cfra = cfra, .timestep = timestep, .dtime = dtime,
- };
-
- BLI_spin_init(&task_data.spin);
-
- if (part->fluid->solver == SPH_SOLVER_DDR) {
- /* Apply SPH forces using double-density relaxation algorithm
- * (Clavat et. al.) */
-
- BLI_task_parallel_range_ex(
- 0, psys->totpart, &task_data, &sphdata, sizeof(sphdata),
- dynamics_step_sph_ddr_task_cb_ex, psys->totpart > 100, true);
-
- sph_springs_modify(psys, timestep);
- }
- else {
- /* SPH_SOLVER_CLASSICAL */
- /* Apply SPH forces using classical algorithm (due to Gingold
- * and Monaghan). Note that, unlike double-density relaxation,
- * this algorithm is separated into distinct loops. */
-
- BLI_task_parallel_range_ex(
- 0, psys->totpart, &task_data, NULL, 0,
- dynamics_step_sph_classical_basic_integrate_task_cb_ex, psys->totpart > 100, true);
-
- /* calculate summation density */
- /* Note that we could avoid copying sphdata for each thread here (it's only read here),
- * but doubt this would gain us anything except confusion... */
- BLI_task_parallel_range_ex(
- 0, psys->totpart, &task_data, &sphdata, sizeof(sphdata),
- dynamics_step_sph_classical_calc_density_task_cb_ex, psys->totpart > 100, true);
-
- /* do global forces & effectors */
- BLI_task_parallel_range_ex(
- 0, psys->totpart, &task_data, &sphdata, sizeof(sphdata),
- dynamics_step_sph_classical_integrate_task_cb_ex, psys->totpart > 100, true);
- }
-
- BLI_spin_end(&task_data.spin);
-
- psys_sph_finalise(&sphdata);
- break;
- }
- }
-
- /* finalize particle state and time after dynamics */
- LOOP_DYNAMIC_PARTICLES {
- if (pa->alive == PARS_DYING) {
- pa->alive=PARS_DEAD;
- pa->state.time=pa->dietime;
- }
- else
- pa->state.time=cfra;
- }
-
- free_collider_cache(&sim->colliders);
- BLI_rng_free(rng);
-}
-static void update_children(ParticleSimulationData *sim)
-{
- if ((sim->psys->part->type == PART_HAIR) && (sim->psys->flag & PSYS_HAIR_DONE)==0)
- /* don't generate children while growing hair - waste of time */
- psys_free_children(sim->psys);
- else if (sim->psys->part->childtype) {
- if (sim->psys->totchild != psys_get_tot_child(sim->scene, sim->psys))
- distribute_particles(sim, PART_FROM_CHILD);
- else {
- /* Children are up to date, nothing to do. */
- }
- }
- else
- psys_free_children(sim->psys);
-}
-/* updates cached particles' alive & other flags etc..*/
-static void cached_step(ParticleSimulationData *sim, float cfra)
-{
- ParticleSystem *psys = sim->psys;
- ParticleSettings *part = psys->part;
- ParticleTexture ptex;
- PARTICLE_P;
- float disp, dietime;
-
- psys_update_effectors(sim);
-
- disp= psys_get_current_display_percentage(psys);
-
- LOOP_PARTICLES {
- psys_get_texture(sim, pa, &ptex, PAMAP_SIZE, cfra);
- pa->size = part->size*ptex.size;
- if (part->randsize > 0.0f)
- pa->size *= 1.0f - part->randsize * psys_frand(psys, p + 1);
-
- psys->lattice_deform_data = psys_create_lattice_deform_data(sim);
-
- dietime = pa->dietime;
-
- /* update alive status and push events */
- if (pa->time > cfra) {
- pa->alive = PARS_UNBORN;
- if (part->flag & PART_UNBORN && (psys->pointcache->flag & PTCACHE_EXTERNAL) == 0)
- reset_particle(sim, pa, 0.0f, cfra);
- }
- else if (dietime <= cfra)
- pa->alive = PARS_DEAD;
- else
- pa->alive = PARS_ALIVE;
-
- if (psys->lattice_deform_data) {
- end_latt_deform(psys->lattice_deform_data);
- psys->lattice_deform_data = NULL;
- }
-
- if (psys_frand(psys, p) > disp)
- pa->flag |= PARS_NO_DISP;
- else
- pa->flag &= ~PARS_NO_DISP;
- }
-}
-
-static void particles_fluid_step(ParticleSimulationData *sim, int UNUSED(cfra), const bool use_render_params)
-{
- ParticleSystem *psys = sim->psys;
- if (psys->particles) {
- MEM_freeN(psys->particles);
- psys->particles = 0;
- psys->totpart = 0;
- }
-
- /* fluid sim particle import handling, actual loading of particles from file */
-#ifdef WITH_MOD_FLUID
- {
- FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(sim->ob, eModifierType_Fluidsim);
-
- if ( fluidmd && fluidmd->fss) {
- FluidsimSettings *fss= fluidmd->fss;
- ParticleSettings *part = psys->part;
- ParticleData *pa=NULL;
- char filename[256];
- char debugStrBuffer[256];
- int curFrame = sim->scene->r.cfra -1; // warning - sync with derived mesh fsmesh loading
- int p, j, totpart;
- int readMask, activeParts = 0, fileParts = 0;
- gzFile gzf;
-
-// XXX if (ob==G.obedit) // off...
-// return;
-
- // ok, start loading
- BLI_join_dirfile(filename, sizeof(filename), fss->surfdataPath, OB_FLUIDSIM_SURF_PARTICLES_FNAME);
-
- BLI_path_abs(filename, modifier_path_relbase(sim->ob));
-
- BLI_path_frame(filename, curFrame, 0); // fixed #frame-no
-
- gzf = BLI_gzopen(filename, "rb");
- if (!gzf) {
- BLI_snprintf(debugStrBuffer, sizeof(debugStrBuffer),"readFsPartData::error - Unable to open file for reading '%s'\n", filename);
- // XXX bad level call elbeemDebugOut(debugStrBuffer);
- return;
- }
-
- gzread(gzf, &totpart, sizeof(totpart));
- totpart = (use_render_params) ? totpart:(part->disp*totpart) / 100;
-
- part->totpart= totpart;
- part->sta=part->end = 1.0f;
- part->lifetime = sim->scene->r.efra + 1;
-
- /* allocate particles */
- realloc_particles(sim, part->totpart);
-
- // set up reading mask
- readMask = fss->typeFlags;
-
- for (p=0, pa=psys->particles; p<totpart; p++, pa++) {
- int ptype=0;
-
- gzread(gzf, &ptype, sizeof( ptype ));
- if (ptype & readMask) {
- activeParts++;
-
- gzread(gzf, &(pa->size), sizeof(float));
-
- pa->size /= 10.0f;
-
- for (j=0; j<3; j++) {
- float wrf;
- gzread(gzf, &wrf, sizeof( wrf ));
- pa->state.co[j] = wrf;
- //fprintf(stderr,"Rj%d ",j);
- }
- for (j=0; j<3; j++) {
- float wrf;
- gzread(gzf, &wrf, sizeof( wrf ));
- pa->state.vel[j] = wrf;
- }
-
- zero_v3(pa->state.ave);
- unit_qt(pa->state.rot);
-
- pa->time = 1.f;
- pa->dietime = sim->scene->r.efra + 1;
- pa->lifetime = sim->scene->r.efra;
- pa->alive = PARS_ALIVE;
- //if (a < 25) fprintf(stderr,"FSPARTICLE debug set %s, a%d = %f,%f,%f, life=%f\n", filename, a, pa->co[0],pa->co[1],pa->co[2], pa->lifetime );
- }
- else {
- // skip...
- for (j=0; j<2*3+1; j++) {
- float wrf; gzread(gzf, &wrf, sizeof( wrf ));
- }
- }
- fileParts++;
- }
- gzclose(gzf);
-
- totpart = psys->totpart = activeParts;
- BLI_snprintf(debugStrBuffer,sizeof(debugStrBuffer),"readFsPartData::done - particles:%d, active:%d, file:%d, mask:%d\n", psys->totpart,activeParts,fileParts,readMask);
- // bad level call
- // XXX elbeemDebugOut(debugStrBuffer);
-
- } // fluid sim particles done
- }
-#else
- UNUSED_VARS(use_render_params);
-#endif // WITH_MOD_FLUID
-}
-
-static int emit_particles(ParticleSimulationData *sim, PTCacheID *pid, float UNUSED(cfra))
-{
- ParticleSystem *psys = sim->psys;
- int oldtotpart = psys->totpart;
- int totpart = tot_particles(psys, pid);
-
- if (totpart != oldtotpart)
- realloc_particles(sim, totpart);
-
- return totpart - oldtotpart;
-}
-
-/* Calculates the next state for all particles of the system
- * In particles code most fra-ending are frames, time-ending are fra*timestep (seconds)
- * 1. Emit particles
- * 2. Check cache (if used) and return if frame is cached
- * 3. Do dynamics
- * 4. Save to cache */
-static void system_step(ParticleSimulationData *sim, float cfra, const bool use_render_params)
-{
- ParticleSystem *psys = sim->psys;
- ParticleSettings *part = psys->part;
- PointCache *cache = psys->pointcache;
- PTCacheID ptcacheid, *pid = NULL;
- PARTICLE_P;
- float disp, cache_cfra = cfra; /*, *vg_vel= 0, *vg_tan= 0, *vg_rot= 0, *vg_size= 0; */
- int startframe = 0, endframe = 100, oldtotpart = 0;
-
- /* cache shouldn't be used for hair or "continue physics" */
- if (part->type != PART_HAIR) {
- psys_clear_temp_pointcache(psys);
-
- /* set suitable cache range automatically */
- if ((cache->flag & (PTCACHE_BAKING|PTCACHE_BAKED))==0)
- psys_get_pointcache_start_end(sim->scene, psys, &cache->startframe, &cache->endframe);
-
- pid = &ptcacheid;
- BKE_ptcache_id_from_particles(pid, sim->ob, psys);
-
- BKE_ptcache_id_time(pid, sim->scene, 0.0f, &startframe, &endframe, NULL);
-
- /* clear everything on start frame, or when psys needs full reset! */
- if ((cfra == startframe) || (psys->recalc & PSYS_RECALC_RESET)) {
- BKE_ptcache_id_reset(sim->scene, pid, PTCACHE_RESET_OUTDATED);
- BKE_ptcache_validate(cache, startframe);
- cache->flag &= ~PTCACHE_REDO_NEEDED;
- }
-
- CLAMP(cache_cfra, startframe, endframe);
- }
-
-/* 1. emit particles and redo particles if needed */
- oldtotpart = psys->totpart;
- if (emit_particles(sim, pid, cfra) || psys->recalc & PSYS_RECALC_RESET) {
- distribute_particles(sim, part->from);
- initialize_all_particles(sim);
- /* reset only just created particles (on startframe all particles are recreated) */
- reset_all_particles(sim, 0.0, cfra, oldtotpart);
- free_unexisting_particles(sim);
-
- if (psys->fluid_springs) {
- MEM_freeN(psys->fluid_springs);
- psys->fluid_springs = NULL;
- }
-
- psys->tot_fluidsprings = psys->alloc_fluidsprings = 0;
-
- /* flag for possible explode modifiers after this system */
- sim->psmd->flag |= eParticleSystemFlag_Pars;
-
- BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, cfra);
- }
-
-/* 2. try to read from the cache */
- if (pid) {
- int cache_result = BKE_ptcache_read(pid, cache_cfra, true);
-
- if (ELEM(cache_result, PTCACHE_READ_EXACT, PTCACHE_READ_INTERPOLATED)) {
- cached_step(sim, cfra);
- update_children(sim);
- psys_update_path_cache(sim, cfra, use_render_params);
-
- BKE_ptcache_validate(cache, (int)cache_cfra);
-
- if (cache_result == PTCACHE_READ_INTERPOLATED && cache->flag & PTCACHE_REDO_NEEDED)
- BKE_ptcache_write(pid, (int)cache_cfra);
-
- return;
- }
- /* Cache is supposed to be baked, but no data was found so bail out */
- else if (cache->flag & PTCACHE_BAKED) {
- psys_reset(psys, PSYS_RESET_CACHE_MISS);
- return;
- }
- else if (cache_result == PTCACHE_READ_OLD) {
- psys->cfra = (float)cache->simframe;
- cached_step(sim, psys->cfra);
- }
-
- /* if on second frame, write cache for first frame */
- if (psys->cfra == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0))
- BKE_ptcache_write(pid, startframe);
- }
- else
- BKE_ptcache_invalidate(cache);
-
-/* 3. do dynamics */
- /* set particles to be not calculated TODO: can't work with pointcache */
- disp= psys_get_current_display_percentage(psys);
-
- LOOP_PARTICLES {
- if (psys_frand(psys, p) > disp)
- pa->flag |= PARS_NO_DISP;
- else
- pa->flag &= ~PARS_NO_DISP;
- }
-
- if (psys->totpart) {
- int dframe, totframesback = 0;
- float t_frac, dt_frac;
-
- /* handle negative frame start at the first frame by doing
- * all the steps before the first frame */
- if ((int)cfra == startframe && part->sta < startframe)
- totframesback = (startframe - (int)part->sta);
-
- if (!(part->time_flag & PART_TIME_AUTOSF)) {
- /* Constant time step */
- psys->dt_frac = get_base_time_step(part);
- }
- else if ((int)cfra == startframe) {
- /* Variable time step; initialise to subframes */
- psys->dt_frac = get_base_time_step(part);
- }
- else if (psys->dt_frac < MIN_TIMESTEP) {
- /* Variable time step; subsequent frames */
- psys->dt_frac = MIN_TIMESTEP;
- }
-
- for (dframe=-totframesback; dframe<=0; dframe++) {
- /* simulate each subframe */
- dt_frac = psys->dt_frac;
- for (t_frac = dt_frac; t_frac <= 1.0f; t_frac += dt_frac) {
- sim->courant_num = 0.0f;
- dynamics_step(sim, cfra+dframe+t_frac - 1.f);
- psys->cfra = cfra+dframe+t_frac - 1.f;
-#if 0
- printf("%f,%f,%f,%f\n", cfra+dframe+t_frac - 1.f, t_frac, dt_frac, sim->courant_num);
-#endif
- if (part->time_flag & PART_TIME_AUTOSF)
- update_timestep(psys, sim);
- /* Even without AUTOSF dt_frac may not add up to 1.0 due to float precision. */
- dt_frac = sync_timestep(psys, t_frac);
- }
- }
- }
-
-/* 4. only write cache starting from second frame */
- if (pid) {
- BKE_ptcache_validate(cache, (int)cache_cfra);
- if ((int)cache_cfra != startframe)
- BKE_ptcache_write(pid, (int)cache_cfra);
- }
-
- update_children(sim);
-
-/* cleanup */
- if (psys->lattice_deform_data) {
- end_latt_deform(psys->lattice_deform_data);
- psys->lattice_deform_data = NULL;
- }
-}
-
-/* system type has changed so set sensible defaults and clear non applicable flags */
-void psys_changed_type(Object *ob, ParticleSystem *psys)
-{
- ParticleSettings *part = psys->part;
- PTCacheID pid;
-
- BKE_ptcache_id_from_particles(&pid, ob, psys);
-
- if (part->phystype != PART_PHYS_KEYED)
- psys->flag &= ~PSYS_KEYED;
-
- if (part->type == PART_HAIR) {
- if (ELEM(part->ren_as, PART_DRAW_NOT, PART_DRAW_PATH, PART_DRAW_OB, PART_DRAW_GR)==0)
- part->ren_as = PART_DRAW_PATH;
-
- if (part->distr == PART_DISTR_GRID)
- part->distr = PART_DISTR_JIT;
-
- if (ELEM(part->draw_as, PART_DRAW_NOT, PART_DRAW_REND, PART_DRAW_PATH)==0)
- part->draw_as = PART_DRAW_REND;
-
- CLAMP(part->path_start, 0.0f, 100.0f);
- CLAMP(part->path_end, 0.0f, 100.0f);
-
- BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_ALL, 0);
- }
- else {
- free_hair(ob, psys, 1);
-
- CLAMP(part->path_start, 0.0f, MAX2(100.0f, part->end + part->lifetime));
- CLAMP(part->path_end, 0.0f, MAX2(100.0f, part->end + part->lifetime));
- }
-
- psys_reset(psys, PSYS_RESET_ALL);
-}
-void psys_check_boid_data(ParticleSystem *psys)
-{
- BoidParticle *bpa;
- PARTICLE_P;
-
- pa = psys->particles;
-
- if (!pa)
- return;
-
- if (psys->part && psys->part->phystype==PART_PHYS_BOIDS) {
- if (!pa->boid) {
- bpa = MEM_callocN(psys->totpart * sizeof(BoidParticle), "Boid Data");
-
- LOOP_PARTICLES
- pa->boid = bpa++;
- }
- }
- else if (pa->boid) {
- MEM_freeN(pa->boid);
- LOOP_PARTICLES
- pa->boid = NULL;
- }
-}
-
-static void fluid_default_settings(ParticleSettings *part)
-{
- SPHFluidSettings *fluid = part->fluid;
-
- fluid->spring_k = 0.f;
- fluid->plasticity_constant = 0.1f;
- fluid->yield_ratio = 0.1f;
- fluid->rest_length = 1.f;
- fluid->viscosity_omega = 2.f;
- fluid->viscosity_beta = 0.1f;
- fluid->stiffness_k = 1.f;
- fluid->stiffness_knear = 1.f;
- fluid->rest_density = 1.f;
- fluid->buoyancy = 0.f;
- fluid->radius = 1.f;
- fluid->flag |= SPH_FAC_REPULSION|SPH_FAC_DENSITY|SPH_FAC_RADIUS|SPH_FAC_VISCOSITY|SPH_FAC_REST_LENGTH;
-}
-
-static void psys_prepare_physics(ParticleSimulationData *sim)
-{
- ParticleSettings *part = sim->psys->part;
-
- if (ELEM(part->phystype, PART_PHYS_NO, PART_PHYS_KEYED)) {
- PTCacheID pid;
- BKE_ptcache_id_from_particles(&pid, sim->ob, sim->psys);
- BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_ALL, 0);
- }
- else {
- free_keyed_keys(sim->psys);
- sim->psys->flag &= ~PSYS_KEYED;
- }
-
- if (part->phystype == PART_PHYS_BOIDS && part->boids == NULL) {
- BoidState *state;
-
- part->boids = MEM_callocN(sizeof(BoidSettings), "Boid Settings");
- boid_default_settings(part->boids);
-
- state = boid_new_state(part->boids);
- BLI_addtail(&state->rules, boid_new_rule(eBoidRuleType_Separate));
- BLI_addtail(&state->rules, boid_new_rule(eBoidRuleType_Flock));
-
- ((BoidRule*)state->rules.first)->flag |= BOIDRULE_CURRENT;
-
- state->flag |= BOIDSTATE_CURRENT;
- BLI_addtail(&part->boids->states, state);
- }
- else if (part->phystype == PART_PHYS_FLUID && part->fluid == NULL) {
- part->fluid = MEM_callocN(sizeof(SPHFluidSettings), "SPH Fluid Settings");
- fluid_default_settings(part);
- }
-
- psys_check_boid_data(sim->psys);
-}
-static int hair_needs_recalc(ParticleSystem *psys)
-{
- if (!(psys->flag & PSYS_EDITED) && (!psys->edit || !psys->edit->edited) &&
- ((psys->flag & PSYS_HAIR_DONE)==0 || psys->recalc & PSYS_RECALC_RESET || (psys->part->flag & PART_HAIR_REGROW && !psys->edit)))
- {
- return 1;
- }
-
- return 0;
-}
-
-/* main particle update call, checks that things are ok on the large scale and
- * then advances in to actual particle calculations depending on particle type */
-void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys, const bool use_render_params)
-{
- ParticleSimulationData sim= {0};
- ParticleSettings *part = psys->part;
- float cfra;
-
- /* drawdata is outdated after ANY change */
- if (psys->pdd) psys->pdd->flag &= ~PARTICLE_DRAW_DATA_UPDATED;
-
- if (!psys_check_enabled(ob, psys, use_render_params))
- return;
-
- cfra= BKE_scene_frame_get(scene);
-
- sim.scene= scene;
- sim.ob= ob;
- sim.psys= psys;
- sim.psmd= psys_get_modifier(ob, psys);
-
- /* system was already updated from modifier stack */
- if (sim.psmd->flag & eParticleSystemFlag_psys_updated) {
- sim.psmd->flag &= ~eParticleSystemFlag_psys_updated;
- /* make sure it really was updated to cfra */
- if (psys->cfra == cfra)
- return;
- }
-
- if (!sim.psmd->dm_final)
- return;
-
- if (part->from != PART_FROM_VERT) {
- DM_ensure_tessface(sim.psmd->dm_final);
- }
-
- /* execute drivers only, as animation has already been done */
- BKE_animsys_evaluate_animdata(scene, &part->id, part->adt, cfra, ADT_RECALC_DRIVERS);
-
- /* to verify if we need to restore object afterwards */
- psys->flag &= ~PSYS_OB_ANIM_RESTORE;
-
- if (psys->recalc & PSYS_RECALC_TYPE)
- psys_changed_type(sim.ob, sim.psys);
-
- if (psys->recalc & PSYS_RECALC_RESET)
- psys->totunexist = 0;
-
- /* setup necessary physics type dependent additional data if it doesn't yet exist */
- psys_prepare_physics(&sim);
-
- switch (part->type) {
- case PART_HAIR:
- {
- /* nothing to do so bail out early */
- if (psys->totpart == 0 && part->totpart == 0) {
- psys_free_path_cache(psys, NULL);
- free_hair(ob, psys, 0);
- psys->flag |= PSYS_HAIR_DONE;
- }
- /* (re-)create hair */
- else if (hair_needs_recalc(psys)) {
- float hcfra=0.0f;
- int i, recalc = psys->recalc;
-
- free_hair(ob, psys, 0);
-
- if (psys->edit && psys->free_edit) {
- psys->free_edit(psys->edit);
- psys->edit = NULL;
- psys->free_edit = NULL;
- }
-
- /* first step is negative so particles get killed and reset */
- psys->cfra= 1.0f;
-
- for (i=0; i<=part->hair_step; i++) {
- hcfra=100.0f*(float)i/(float)psys->part->hair_step;
- if ((part->flag & PART_HAIR_REGROW)==0)
- BKE_animsys_evaluate_animdata(scene, &part->id, part->adt, hcfra, ADT_RECALC_ANIM);
- system_step(&sim, hcfra, use_render_params);
- psys->cfra = hcfra;
- psys->recalc = 0;
- save_hair(&sim, hcfra);
- }
-
- psys->flag |= PSYS_HAIR_DONE;
- psys->recalc = recalc;
- }
- else if (psys->flag & PSYS_EDITED)
- psys->flag |= PSYS_HAIR_DONE;
-
- if (psys->flag & PSYS_HAIR_DONE)
- hair_step(&sim, cfra, use_render_params);
- break;
- }
- case PART_FLUID:
- {
- particles_fluid_step(&sim, (int)cfra, use_render_params);
- break;
- }
- default:
- {
- switch (part->phystype) {
- case PART_PHYS_NO:
- case PART_PHYS_KEYED:
- {
- PARTICLE_P;
- float disp = psys_get_current_display_percentage(psys);
- bool free_unexisting = false;
-
- /* Particles without dynamics haven't been reset yet because they don't use pointcache */
- if (psys->recalc & PSYS_RECALC_RESET)
- psys_reset(psys, PSYS_RESET_ALL);
-
- if (emit_particles(&sim, NULL, cfra) || (psys->recalc & PSYS_RECALC_RESET)) {
- free_keyed_keys(psys);
- distribute_particles(&sim, part->from);
- initialize_all_particles(&sim);
- free_unexisting = true;
-
- /* flag for possible explode modifiers after this system */
- sim.psmd->flag |= eParticleSystemFlag_Pars;
- }
-
- LOOP_EXISTING_PARTICLES {
- pa->size = part->size;
- if (part->randsize > 0.0f)
- pa->size *= 1.0f - part->randsize * psys_frand(psys, p + 1);
-
- reset_particle(&sim, pa, 0.0, cfra);
-
- if (psys_frand(psys, p) > disp)
- pa->flag |= PARS_NO_DISP;
- else
- pa->flag &= ~PARS_NO_DISP;
- }
-
- /* free unexisting after reseting particles */
- if (free_unexisting)
- free_unexisting_particles(&sim);
-
- if (part->phystype == PART_PHYS_KEYED) {
- psys_count_keyed_targets(&sim);
- set_keyed_keys(&sim);
- psys_update_path_cache(&sim, (int)cfra, use_render_params);
- }
- break;
- }
- default:
- {
- /* the main dynamic particle system step */
- system_step(&sim, cfra, use_render_params);
- break;
- }
- }
- break;
- }
- }
-
- /* make sure emitter is left at correct time (particle emission can change this) */
- if (psys->flag & PSYS_OB_ANIM_RESTORE) {
- evaluate_emitter_anim(scene, ob, cfra);
- psys->flag &= ~PSYS_OB_ANIM_RESTORE;
- }
-
- psys->cfra = cfra;
- psys->recalc = 0;
-
- /* save matrix for duplicators, at rendertime the actual dupliobject's matrix is used so don't update! */
- if (psys->renderdata==0)
- invert_m4_m4(psys->imat, ob->obmat);
-}
-
-/* ID looper */
-
-void BKE_particlesystem_id_loop(ParticleSystem *psys, ParticleSystemIDFunc func, void *userdata)
-{
- ParticleTarget *pt;
-
- func(psys, (ID **)&psys->part, userdata, IDWALK_USER | IDWALK_NEVER_NULL);
- func(psys, (ID **)&psys->target_ob, userdata, IDWALK_NOP);
- func(psys, (ID **)&psys->parent, userdata, IDWALK_NOP);
-
- for (pt = psys->targets.first; pt; pt = pt->next) {
- func(psys, (ID **)&pt->ob, userdata, IDWALK_NOP);
- }
-
- /* Even though psys->part should never be NULL, this can happen as an exception during deletion.
- * See ID_REMAP_SKIP/FORCE/FLAG_NEVER_NULL_USAGE in BKE_library_remap. */
- if (psys->part && psys->part->phystype == PART_PHYS_BOIDS) {
- ParticleData *pa;
- int p;
-
- for (p = 0, pa = psys->particles; p < psys->totpart; p++, pa++) {
- func(psys, (ID **)&pa->boid->ground, userdata, IDWALK_NOP);
- }
- }
-}
-
-/* **** Depsgraph evaluation **** */
-
-void BKE_particle_system_eval(EvaluationContext *UNUSED(eval_ctx),
- Scene *scene,
- Object *ob,
- ParticleSystem *psys)
-{
- if (G.debug & G_DEBUG_DEPSGRAPH) {
- printf("%s on %s:%s\n", __func__, ob->id.name, psys->name);
- }
- BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_DEPSGRAPH);
-}
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c
deleted file mode 100644
index 30eb8dcb287..00000000000
--- a/source/blender/blenkernel/intern/pointcache.c
+++ /dev/null
@@ -1,4095 +0,0 @@
-/*
- * ***** 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) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * Contributor(s): Campbell Barton <ideasman42@gmail.com>
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/blenkernel/intern/pointcache.c
- * \ingroup bke
- */
-
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include "MEM_guardedalloc.h"
-
-#include "DNA_ID.h"
-#include "DNA_dynamicpaint_types.h"
-#include "DNA_modifier_types.h"
-#include "DNA_object_types.h"
-#include "DNA_object_force.h"
-#include "DNA_particle_types.h"
-#include "DNA_rigidbody_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_smoke_types.h"
-
-#include "BLI_blenlib.h"
-#include "BLI_threads.h"
-#include "BLI_math.h"
-#include "BLI_utildefines.h"
-
-#include "BLT_translation.h"
-
-#include "PIL_time.h"
-
-#include "BKE_appdir.h"
-#include "BKE_anim.h"
-#include "BKE_cloth.h"
-#include "BKE_dynamicpaint.h"
-#include "BKE_global.h"
-#include "BKE_main.h"
-#include "BKE_modifier.h"
-#include "BKE_object.h"
-#include "BKE_particle.h"
-#include "BKE_pointcache.h"
-#include "BKE_scene.h"
-#include "BKE_smoke.h"
-#include "BKE_softbody.h"
-
-#include "BIK_api.h"
-
-#ifdef WITH_BULLET
-# include "RBI_api.h"
-#endif
-
-/* both in intern */
-#ifdef WITH_SMOKE
-#include "smoke_API.h"
-#endif
-
-#ifdef WITH_OPENVDB
-#include "openvdb_capi.h"
-#endif
-
-#ifdef WITH_LZO
-# ifdef WITH_SYSTEM_LZO
-# include <lzo/lzo1x.h>
-# else
-# include "minilzo.h"
-# endif
-# define LZO_HEAP_ALLOC(var,size) \
- lzo_align_t __LZO_MMODEL var [ ((size) + (sizeof(lzo_align_t) - 1)) / sizeof(lzo_align_t) ]
-#endif
-
-#define LZO_OUT_LEN(size) ((size) + (size) / 16 + 64 + 3)
-
-#ifdef WITH_LZMA
-#include "LzmaLib.h"
-#endif
-
-/* needed for directory lookup */
-#ifndef WIN32
-# include <dirent.h>
-#else
-# include "BLI_winstuff.h"
-#endif
-
-#define PTCACHE_DATA_FROM(data, type, from) \
- if (data[type]) { \
- memcpy(data[type], from, ptcache_data_size[type]); \
- } (void)0
-
-#define PTCACHE_DATA_TO(data, type, index, to) \
- if (data[type]) { \
- memcpy(to, (char *)(data)[type] + ((index) ? (index) * ptcache_data_size[type] : 0), ptcache_data_size[type]); \
- } (void)0
-
-/* could be made into a pointcache option */
-#define DURIAN_POINTCACHE_LIB_OK 1
-
-static int ptcache_data_size[] = {
- sizeof(unsigned int), // BPHYS_DATA_INDEX
- 3 * sizeof(float), // BPHYS_DATA_LOCATION
- 3 * sizeof(float), // BPHYS_DATA_VELOCITY
- 4 * sizeof(float), // BPHYS_DATA_ROTATION
- 3 * sizeof(float), // BPHYS_DATA_AVELOCITY / BPHYS_DATA_XCONST
- sizeof(float), // BPHYS_DATA_SIZE
- 3 * sizeof(float), // BPHYS_DATA_TIMES
- sizeof(BoidData) // case BPHYS_DATA_BOIDS
-};
-
-static int ptcache_extra_datasize[] = {
- 0,
- sizeof(ParticleSpring)
-};
-
-/* forward declerations */
-static int ptcache_file_compressed_read(PTCacheFile *pf, unsigned char *result, unsigned int len);
-static int ptcache_file_compressed_write(PTCacheFile *pf, unsigned char *in, unsigned int in_len, unsigned char *out, int mode);
-static int ptcache_file_write(PTCacheFile *pf, const void *f, unsigned int tot, unsigned int size);
-static int ptcache_file_read(PTCacheFile *pf, void *f, unsigned int tot, unsigned int size);
-
-/* Common functions */
-static int ptcache_basic_header_read(PTCacheFile *pf)
-{
- int error=0;
-
- /* Custom functions should read these basic elements too! */
- if (!error && !fread(&pf->totpoint, sizeof(unsigned int), 1, pf->fp))
- error = 1;
-
- if (!error && !fread(&pf->data_types, sizeof(unsigned int), 1, pf->fp))
- error = 1;
-
- return !error;
-}
-static int ptcache_basic_header_write(PTCacheFile *pf)
-{
- /* Custom functions should write these basic elements too! */
- if (!fwrite(&pf->totpoint, sizeof(unsigned int), 1, pf->fp))
- return 0;
-
- if (!fwrite(&pf->data_types, sizeof(unsigned int), 1, pf->fp))
- return 0;
-
- return 1;
-}
-/* Softbody functions */
-static int ptcache_softbody_write(int index, void *soft_v, void **data, int UNUSED(cfra))
-{
- SoftBody *soft= soft_v;
- BodyPoint *bp = soft->bpoint + index;
-
- PTCACHE_DATA_FROM(data, BPHYS_DATA_LOCATION, bp->pos);
- PTCACHE_DATA_FROM(data, BPHYS_DATA_VELOCITY, bp->vec);
-
- return 1;
-}
-static void ptcache_softbody_read(int index, void *soft_v, void **data, float UNUSED(cfra), float *old_data)
-{
- SoftBody *soft= soft_v;
- BodyPoint *bp = soft->bpoint + index;
-
- if (old_data) {
- memcpy(bp->pos, data, 3 * sizeof(float));
- memcpy(bp->vec, data + 3, 3 * sizeof(float));
- }
- else {
- PTCACHE_DATA_TO(data, BPHYS_DATA_LOCATION, 0, bp->pos);
- PTCACHE_DATA_TO(data, BPHYS_DATA_VELOCITY, 0, bp->vec);
- }
-}
-static void ptcache_softbody_interpolate(int index, void *soft_v, void **data, float cfra, float cfra1, float cfra2, float *old_data)
-{
- SoftBody *soft= soft_v;
- BodyPoint *bp = soft->bpoint + index;
- ParticleKey keys[4];
- float dfra;
-
- if (cfra1 == cfra2)
- return;
-
- copy_v3_v3(keys[1].co, bp->pos);
- copy_v3_v3(keys[1].vel, bp->vec);
-
- if (old_data) {
- memcpy(keys[2].co, old_data, 3 * sizeof(float));
- memcpy(keys[2].vel, old_data + 3, 3 * sizeof(float));
- }
- else
- BKE_ptcache_make_particle_key(keys+2, 0, data, cfra2);
-
- dfra = cfra2 - cfra1;
-
- mul_v3_fl(keys[1].vel, dfra);
- mul_v3_fl(keys[2].vel, dfra);
-
- psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, keys, 1);
-
- mul_v3_fl(keys->vel, 1.0f / dfra);
-
- copy_v3_v3(bp->pos, keys->co);
- copy_v3_v3(bp->vec, keys->vel);
-}
-static int ptcache_softbody_totpoint(void *soft_v, int UNUSED(cfra))
-{
- SoftBody *soft= soft_v;
- return soft->totpoint;
-}
-static void ptcache_softbody_error(void *UNUSED(soft_v), const char *UNUSED(message))
-{
- /* ignored for now */
-}
-
-/* Particle functions */
-void BKE_ptcache_make_particle_key(ParticleKey *key, int index, void **data, float time)
-{
- PTCACHE_DATA_TO(data, BPHYS_DATA_LOCATION, index, key->co);
- PTCACHE_DATA_TO(data, BPHYS_DATA_VELOCITY, index, key->vel);
-
- /* no rotation info, so make something nice up */
- if (data[BPHYS_DATA_ROTATION]==NULL) {
- vec_to_quat(key->rot, key->vel, OB_NEGX, OB_POSZ);
- }
- else {
- PTCACHE_DATA_TO(data, BPHYS_DATA_ROTATION, index, key->rot);
- }
-
- PTCACHE_DATA_TO(data, BPHYS_DATA_AVELOCITY, index, key->ave);
- key->time = time;
-}
-static int ptcache_particle_write(int index, void *psys_v, void **data, int cfra)
-{
- ParticleSystem *psys= psys_v;
- ParticleData *pa = psys->particles + index;
- BoidParticle *boid = (psys->part->phystype == PART_PHYS_BOIDS) ? pa->boid : NULL;
- float times[3];
- int step = psys->pointcache->step;
-
- /* No need to store unborn or died particles outside cache step bounds */
- if (data[BPHYS_DATA_INDEX] && (cfra < pa->time - step || cfra > pa->dietime + step))
- return 0;
-
- times[0] = pa->time;
- times[1] = pa->dietime;
- times[2] = pa->lifetime;
-
- PTCACHE_DATA_FROM(data, BPHYS_DATA_INDEX, &index);
- PTCACHE_DATA_FROM(data, BPHYS_DATA_LOCATION, pa->state.co);
- PTCACHE_DATA_FROM(data, BPHYS_DATA_VELOCITY, pa->state.vel);
- PTCACHE_DATA_FROM(data, BPHYS_DATA_ROTATION, pa->state.rot);
- PTCACHE_DATA_FROM(data, BPHYS_DATA_AVELOCITY, pa->state.ave);
- PTCACHE_DATA_FROM(data, BPHYS_DATA_SIZE, &pa->size);
- PTCACHE_DATA_FROM(data, BPHYS_DATA_TIMES, times);
-
- if (boid) {
- PTCACHE_DATA_FROM(data, BPHYS_DATA_BOIDS, &boid->data);
- }
-
- /* return flag 1+1=2 for newly born particles to copy exact birth location to previously cached frame */
- return 1 + (pa->state.time >= pa->time && pa->prev_state.time <= pa->time);
-}
-static void ptcache_particle_read(int index, void *psys_v, void **data, float cfra, float *old_data)
-{
- ParticleSystem *psys= psys_v;
- ParticleData *pa;
- BoidParticle *boid;
- float timestep = 0.04f * psys->part->timetweak;
-
- if (index >= psys->totpart)
- return;
-
- pa = psys->particles + index;
- boid = (psys->part->phystype == PART_PHYS_BOIDS) ? pa->boid : NULL;
-
- if (cfra > pa->state.time)
- memcpy(&pa->prev_state, &pa->state, sizeof(ParticleKey));
-
- if (old_data) {
- /* old format cache */
- memcpy(&pa->state, old_data, sizeof(ParticleKey));
- return;
- }
-
- BKE_ptcache_make_particle_key(&pa->state, 0, data, cfra);
-
- /* set frames cached before birth to birth time */
- if (cfra < pa->time)
- pa->state.time = pa->time;
- else if (cfra > pa->dietime)
- pa->state.time = pa->dietime;
-
- if (data[BPHYS_DATA_SIZE]) {
- PTCACHE_DATA_TO(data, BPHYS_DATA_SIZE, 0, &pa->size);
- }
-
- if (data[BPHYS_DATA_TIMES]) {
- float times[3];
- PTCACHE_DATA_TO(data, BPHYS_DATA_TIMES, 0, &times);
- pa->time = times[0];
- pa->dietime = times[1];
- pa->lifetime = times[2];
- }
-
- if (boid) {
- PTCACHE_DATA_TO(data, BPHYS_DATA_BOIDS, 0, &boid->data);
- }
-
- /* determine velocity from previous location */
- if (data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_VELOCITY]) {
- if (cfra > pa->prev_state.time) {
- sub_v3_v3v3(pa->state.vel, pa->state.co, pa->prev_state.co);
- mul_v3_fl(pa->state.vel, (cfra - pa->prev_state.time) * timestep);
- }
- else {
- sub_v3_v3v3(pa->state.vel, pa->prev_state.co, pa->state.co);
- mul_v3_fl(pa->state.vel, (pa->prev_state.time - cfra) * timestep);
- }
- }
-
- /* default to no rotation */
- if (data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_ROTATION]) {
- unit_qt(pa->state.rot);
- }
-}
-static void ptcache_particle_interpolate(int index, void *psys_v, void **data, float cfra, float cfra1, float cfra2, float *old_data)
-{
- ParticleSystem *psys= psys_v;
- ParticleData *pa;
- ParticleKey keys[4];
- float dfra, timestep = 0.04f * psys->part->timetweak;
-
- if (index >= psys->totpart)
- return;
-
- pa = psys->particles + index;
-
- /* particle wasn't read from first cache so can't interpolate */
- if ((int)cfra1 < pa->time - psys->pointcache->step || (int)cfra1 > pa->dietime + psys->pointcache->step)
- return;
-
- cfra = MIN2(cfra, pa->dietime);
- cfra1 = MIN2(cfra1, pa->dietime);
- cfra2 = MIN2(cfra2, pa->dietime);
-
- if (cfra1 == cfra2)
- return;
-
- memcpy(keys+1, &pa->state, sizeof(ParticleKey));
- if (old_data)
- memcpy(keys+2, old_data, sizeof(ParticleKey));
- else
- BKE_ptcache_make_particle_key(keys+2, 0, data, cfra2);
-
- /* determine velocity from previous location */
- if (data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_VELOCITY]) {
- if (keys[1].time > keys[2].time) {
- sub_v3_v3v3(keys[2].vel, keys[1].co, keys[2].co);
- mul_v3_fl(keys[2].vel, (keys[1].time - keys[2].time) * timestep);
- }
- else {
- sub_v3_v3v3(keys[2].vel, keys[2].co, keys[1].co);
- mul_v3_fl(keys[2].vel, (keys[2].time - keys[1].time) * timestep);
- }
- }
-
- /* default to no rotation */
- if (data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_ROTATION]) {
- unit_qt(keys[2].rot);
- }
-
- if (cfra > pa->time)
- cfra1 = MAX2(cfra1, pa->time);
-
- dfra = cfra2 - cfra1;
-
- mul_v3_fl(keys[1].vel, dfra * timestep);
- mul_v3_fl(keys[2].vel, dfra * timestep);
-
- psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, &pa->state, 1);
- interp_qt_qtqt(pa->state.rot, keys[1].rot, keys[2].rot, (cfra - cfra1) / dfra);
-
- mul_v3_fl(pa->state.vel, 1.f / (dfra * timestep));
-
- pa->state.time = cfra;
-}
-
-static int ptcache_particle_totpoint(void *psys_v, int UNUSED(cfra))
-{
- ParticleSystem *psys = psys_v;
- return psys->totpart;
-}
-
-static void ptcache_particle_error(void *UNUSED(psys_v), const char *UNUSED(message))
-{
- /* ignored for now */
-}
-
-static int ptcache_particle_totwrite(void *psys_v, int cfra)
-{
- ParticleSystem *psys = psys_v;
- ParticleData *pa= psys->particles;
- int p, step = psys->pointcache->step;
- int totwrite = 0;
-
- if (cfra == 0)
- return psys->totpart;
-
- for (p=0; p<psys->totpart; p++, pa++)
- totwrite += (cfra >= pa->time - step && cfra <= pa->dietime + step);
-
- return totwrite;
-}
-
-static void ptcache_particle_extra_write(void *psys_v, PTCacheMem *pm, int UNUSED(cfra))
-{
- ParticleSystem *psys = psys_v;
- PTCacheExtra *extra = NULL;
-
- if (psys->part->phystype == PART_PHYS_FLUID &&
- psys->part->fluid && psys->part->fluid->flag & SPH_VISCOELASTIC_SPRINGS &&
- psys->tot_fluidsprings && psys->fluid_springs) {
-
- extra = MEM_callocN(sizeof(PTCacheExtra), "Point cache: fluid extra data");
-
- extra->type = BPHYS_EXTRA_FLUID_SPRINGS;
- extra->totdata = psys->tot_fluidsprings;
-
- extra->data = MEM_callocN(extra->totdata * ptcache_extra_datasize[extra->type], "Point cache: extra data");
- memcpy(extra->data, psys->fluid_springs, extra->totdata * ptcache_extra_datasize[extra->type]);
-
- BLI_addtail(&pm->extradata, extra);
- }
-}
-
-static void ptcache_particle_extra_read(void *psys_v, PTCacheMem *pm, float UNUSED(cfra))
-{
- ParticleSystem *psys = psys_v;
- PTCacheExtra *extra = pm->extradata.first;
-
- for (; extra; extra=extra->next) {
- switch (extra->type) {
- case BPHYS_EXTRA_FLUID_SPRINGS:
- {
- if (psys->fluid_springs)
- MEM_freeN(psys->fluid_springs);
-
- psys->fluid_springs = MEM_dupallocN(extra->data);
- psys->tot_fluidsprings = psys->alloc_fluidsprings = extra->totdata;
- break;
- }
- }
- }
-}
-
-/* Cloth functions */
-static int ptcache_cloth_write(int index, void *cloth_v, void **data, int UNUSED(cfra))
-{
- ClothModifierData *clmd= cloth_v;
- Cloth *cloth= clmd->clothObject;
- ClothVertex *vert = cloth->verts + index;
-
- PTCACHE_DATA_FROM(data, BPHYS_DATA_LOCATION, vert->x);
- PTCACHE_DATA_FROM(data, BPHYS_DATA_VELOCITY, vert->v);
- PTCACHE_DATA_FROM(data, BPHYS_DATA_XCONST, vert->xconst);
-
- return 1;
-}
-static void ptcache_cloth_read(int index, void *cloth_v, void **data, float UNUSED(cfra), float *old_data)
-{
- ClothModifierData *clmd= cloth_v;
- Cloth *cloth= clmd->clothObject;
- ClothVertex *vert = cloth->verts + index;
-
- if (old_data) {
- memcpy(vert->x, data, 3 * sizeof(float));
- memcpy(vert->xconst, data + 3, 3 * sizeof(float));
- memcpy(vert->v, data + 6, 3 * sizeof(float));
- }
- else {
- PTCACHE_DATA_TO(data, BPHYS_DATA_LOCATION, 0, vert->x);
- PTCACHE_DATA_TO(data, BPHYS_DATA_VELOCITY, 0, vert->v);
- PTCACHE_DATA_TO(data, BPHYS_DATA_XCONST, 0, vert->xconst);
- }
-}
-static void ptcache_cloth_interpolate(int index, void *cloth_v, void **data, float cfra, float cfra1, float cfra2, float *old_data)
-{
- ClothModifierData *clmd= cloth_v;
- Cloth *cloth= clmd->clothObject;
- ClothVertex *vert = cloth->verts + index;
- ParticleKey keys[4];
- float dfra;
-
- if (cfra1 == cfra2)
- return;
-
- copy_v3_v3(keys[1].co, vert->x);
- copy_v3_v3(keys[1].vel, vert->v);
-
- if (old_data) {
- memcpy(keys[2].co, old_data, 3 * sizeof(float));
- memcpy(keys[2].vel, old_data + 6, 3 * sizeof(float));
- }
- else
- BKE_ptcache_make_particle_key(keys+2, 0, data, cfra2);
-
- dfra = cfra2 - cfra1;
-
- mul_v3_fl(keys[1].vel, dfra);
- mul_v3_fl(keys[2].vel, dfra);
-
- psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, keys, 1);
-
- mul_v3_fl(keys->vel, 1.0f / dfra);
-
- copy_v3_v3(vert->x, keys->co);
- copy_v3_v3(vert->v, keys->vel);
-
- /* should vert->xconst be interpolated somehow too? - jahka */
-}
-
-static int ptcache_cloth_totpoint(void *cloth_v, int UNUSED(cfra))
-{
- ClothModifierData *clmd= cloth_v;
- return clmd->clothObject ? clmd->clothObject->mvert_num : 0;
-}
-
-static void ptcache_cloth_error(void *cloth_v, const char *message)
-{
- ClothModifierData *clmd= cloth_v;
- modifier_setError(&clmd->modifier, "%s", message);
-}
-
-#ifdef WITH_SMOKE
-/* Smoke functions */
-static int ptcache_smoke_totpoint(void *smoke_v, int UNUSED(cfra))
-{
- SmokeModifierData *smd= (SmokeModifierData *)smoke_v;
- SmokeDomainSettings *sds = smd->domain;
-
- if (sds->fluid) {
- return sds->base_res[0]*sds->base_res[1]*sds->base_res[2];
- }
- else
- return 0;
-}
-
-static void ptcache_smoke_error(void *smoke_v, const char *message)
-{
- SmokeModifierData *smd= (SmokeModifierData *)smoke_v;
- modifier_setError(&smd->modifier, "%s", message);
-}
-
-#define SMOKE_CACHE_VERSION "1.04"
-
-static int ptcache_smoke_write(PTCacheFile *pf, void *smoke_v)
-{
- SmokeModifierData *smd= (SmokeModifierData *)smoke_v;
- SmokeDomainSettings *sds = smd->domain;
- int ret = 0;
- int fluid_fields = smoke_get_data_flags(sds);
-
- /* version header */
- ptcache_file_write(pf, SMOKE_CACHE_VERSION, 4, sizeof(char));
- ptcache_file_write(pf, &fluid_fields, 1, sizeof(int));
- ptcache_file_write(pf, &sds->active_fields, 1, sizeof(int));
- ptcache_file_write(pf, &sds->res, 3, sizeof(int));
- ptcache_file_write(pf, &sds->dx, 1, sizeof(float));
-
- if (sds->fluid) {
- size_t res = sds->res[0]*sds->res[1]*sds->res[2];
- float dt, dx, *dens, *react, *fuel, *flame, *heat, *heatold, *vx, *vy, *vz, *r, *g, *b;
- unsigned char *obstacles;
- unsigned int in_len = sizeof(float)*(unsigned int)res;
- unsigned char *out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len) * 4, "pointcache_lzo_buffer");
- //int mode = res >= 1000000 ? 2 : 1;
- int mode=1; // light
- if (sds->cache_comp == SM_CACHE_HEAVY) mode=2; // heavy
-
- smoke_export(sds->fluid, &dt, &dx, &dens, &react, &flame, &fuel, &heat, &heatold, &vx, &vy, &vz, &r, &g, &b, &obstacles);
-
- ptcache_file_compressed_write(pf, (unsigned char *)sds->shadow, in_len, out, mode);
- ptcache_file_compressed_write(pf, (unsigned char *)dens, in_len, out, mode);
- if (fluid_fields & SM_ACTIVE_HEAT) {
- ptcache_file_compressed_write(pf, (unsigned char *)heat, in_len, out, mode);
- ptcache_file_compressed_write(pf, (unsigned char *)heatold, in_len, out, mode);
- }
- if (fluid_fields & SM_ACTIVE_FIRE) {
- ptcache_file_compressed_write(pf, (unsigned char *)flame, in_len, out, mode);
- ptcache_file_compressed_write(pf, (unsigned char *)fuel, in_len, out, mode);
- ptcache_file_compressed_write(pf, (unsigned char *)react, in_len, out, mode);
- }
- if (fluid_fields & SM_ACTIVE_COLORS) {
- ptcache_file_compressed_write(pf, (unsigned char *)r, in_len, out, mode);
- ptcache_file_compressed_write(pf, (unsigned char *)g, in_len, out, mode);
- ptcache_file_compressed_write(pf, (unsigned char *)b, in_len, out, mode);
- }
- ptcache_file_compressed_write(pf, (unsigned char *)vx, in_len, out, mode);
- ptcache_file_compressed_write(pf, (unsigned char *)vy, in_len, out, mode);
- ptcache_file_compressed_write(pf, (unsigned char *)vz, in_len, out, mode);
- ptcache_file_compressed_write(pf, (unsigned char *)obstacles, (unsigned int)res, out, mode);
- ptcache_file_write(pf, &dt, 1, sizeof(float));
- ptcache_file_write(pf, &dx, 1, sizeof(float));
- ptcache_file_write(pf, &sds->p0, 3, sizeof(float));
- ptcache_file_write(pf, &sds->p1, 3, sizeof(float));
- ptcache_file_write(pf, &sds->dp0, 3, sizeof(float));
- ptcache_file_write(pf, &sds->shift, 3, sizeof(int));
- ptcache_file_write(pf, &sds->obj_shift_f, 3, sizeof(float));
- ptcache_file_write(pf, &sds->obmat, 16, sizeof(float));
- ptcache_file_write(pf, &sds->base_res, 3, sizeof(int));
- ptcache_file_write(pf, &sds->res_min, 3, sizeof(int));
- ptcache_file_write(pf, &sds->res_max, 3, sizeof(int));
- ptcache_file_write(pf, &sds->active_color, 3, sizeof(float));
-
- MEM_freeN(out);
-
- ret = 1;
- }
-
- if (sds->wt) {
- int res_big_array[3];
- int res_big;
- int res = sds->res[0]*sds->res[1]*sds->res[2];
- float *dens, *react, *fuel, *flame, *tcu, *tcv, *tcw, *r, *g, *b;
- unsigned int in_len = sizeof(float)*(unsigned int)res;
- unsigned int in_len_big;
- unsigned char *out;
- int mode;
-
- smoke_turbulence_get_res(sds->wt, res_big_array);
- res_big = res_big_array[0]*res_big_array[1]*res_big_array[2];
- //mode = res_big >= 1000000 ? 2 : 1;
- mode = 1; // light
- if (sds->cache_high_comp == SM_CACHE_HEAVY) mode=2; // heavy
-
- in_len_big = sizeof(float) * (unsigned int)res_big;
-
- smoke_turbulence_export(sds->wt, &dens, &react, &flame, &fuel, &r, &g, &b, &tcu, &tcv, &tcw);
-
- out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len_big), "pointcache_lzo_buffer");
- ptcache_file_compressed_write(pf, (unsigned char *)dens, in_len_big, out, mode);
- if (fluid_fields & SM_ACTIVE_FIRE) {
- ptcache_file_compressed_write(pf, (unsigned char *)flame, in_len_big, out, mode);
- ptcache_file_compressed_write(pf, (unsigned char *)fuel, in_len_big, out, mode);
- ptcache_file_compressed_write(pf, (unsigned char *)react, in_len_big, out, mode);
- }
- if (fluid_fields & SM_ACTIVE_COLORS) {
- ptcache_file_compressed_write(pf, (unsigned char *)r, in_len_big, out, mode);
- ptcache_file_compressed_write(pf, (unsigned char *)g, in_len_big, out, mode);
- ptcache_file_compressed_write(pf, (unsigned char *)b, in_len_big, out, mode);
- }
- MEM_freeN(out);
-
- out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len), "pointcache_lzo_buffer");
- ptcache_file_compressed_write(pf, (unsigned char *)tcu, in_len, out, mode);
- ptcache_file_compressed_write(pf, (unsigned char *)tcv, in_len, out, mode);
- ptcache_file_compressed_write(pf, (unsigned char *)tcw, in_len, out, mode);
- MEM_freeN(out);
-
- ret = 1;
- }
-
- return ret;
-}
-
-/* read old smoke cache from 2.64 */
-static int ptcache_smoke_read_old(PTCacheFile *pf, void *smoke_v)
-{
- SmokeModifierData *smd= (SmokeModifierData *)smoke_v;
- SmokeDomainSettings *sds = smd->domain;
-
- if (sds->fluid) {
- const size_t res = sds->res[0] * sds->res[1] * sds->res[2];
- const unsigned int out_len = (unsigned int)res * sizeof(float);
- float dt, dx, *dens, *heat, *heatold, *vx, *vy, *vz;
- unsigned char *obstacles;
- float *tmp_array = MEM_callocN(out_len, "Smoke old cache tmp");
-
- int fluid_fields = smoke_get_data_flags(sds);
-
- /* Part part of the new cache header */
- sds->active_color[0] = 0.7f;
- sds->active_color[1] = 0.7f;
- sds->active_color[2] = 0.7f;
-
- smoke_export(sds->fluid, &dt, &dx, &dens, NULL, NULL, NULL, &heat, &heatold, &vx, &vy, &vz, NULL, NULL, NULL, &obstacles);
-
- ptcache_file_compressed_read(pf, (unsigned char *)sds->shadow, out_len);
- ptcache_file_compressed_read(pf, (unsigned char*)dens, out_len);
- ptcache_file_compressed_read(pf, (unsigned char*)tmp_array, out_len);
-
- if (fluid_fields & SM_ACTIVE_HEAT)
- {
- ptcache_file_compressed_read(pf, (unsigned char*)heat, out_len);
- ptcache_file_compressed_read(pf, (unsigned char*)heatold, out_len);
- }
- else
- {
- ptcache_file_compressed_read(pf, (unsigned char*)tmp_array, out_len);
- ptcache_file_compressed_read(pf, (unsigned char*)tmp_array, out_len);
- }
- ptcache_file_compressed_read(pf, (unsigned char*)vx, out_len);
- ptcache_file_compressed_read(pf, (unsigned char*)vy, out_len);
- ptcache_file_compressed_read(pf, (unsigned char*)vz, out_len);
- ptcache_file_compressed_read(pf, (unsigned char*)tmp_array, out_len);
- ptcache_file_compressed_read(pf, (unsigned char*)tmp_array, out_len);
- ptcache_file_compressed_read(pf, (unsigned char*)tmp_array, out_len);
- ptcache_file_compressed_read(pf, (unsigned char*)obstacles, (unsigned int)res);
- ptcache_file_read(pf, &dt, 1, sizeof(float));
- ptcache_file_read(pf, &dx, 1, sizeof(float));
-
- MEM_freeN(tmp_array);
-
- if (pf->data_types & (1<<BPHYS_DATA_SMOKE_HIGH) && sds->wt) {
- int res_big, res_big_array[3];
- float *tcu, *tcv, *tcw;
- unsigned int out_len_big;
- unsigned char *tmp_array_big;
- smoke_turbulence_get_res(sds->wt, res_big_array);
- res_big = res_big_array[0]*res_big_array[1]*res_big_array[2];
- out_len_big = sizeof(float) * (unsigned int)res_big;
-
- tmp_array_big = MEM_callocN(out_len_big, "Smoke old cache tmp");
-
- smoke_turbulence_export(sds->wt, &dens, NULL, NULL, NULL, NULL, NULL, NULL, &tcu, &tcv, &tcw);
-
- ptcache_file_compressed_read(pf, (unsigned char*)dens, out_len_big);
- ptcache_file_compressed_read(pf, (unsigned char*)tmp_array_big, out_len_big);
-
- ptcache_file_compressed_read(pf, (unsigned char*)tcu, out_len);
- ptcache_file_compressed_read(pf, (unsigned char*)tcv, out_len);
- ptcache_file_compressed_read(pf, (unsigned char*)tcw, out_len);
-
- MEM_freeN(tmp_array_big);
- }
- }
-
- return 1;
-}
-
-static int ptcache_smoke_read(PTCacheFile *pf, void *smoke_v)
-{
- SmokeModifierData *smd= (SmokeModifierData *)smoke_v;
- SmokeDomainSettings *sds = smd->domain;
- char version[4];
- int ch_res[3];
- float ch_dx;
- int fluid_fields = smoke_get_data_flags(sds);
- int cache_fields = 0;
- int active_fields = 0;
- int reallocate = 0;
-
- /* version header */
- ptcache_file_read(pf, version, 4, sizeof(char));
- if (!STREQLEN(version, SMOKE_CACHE_VERSION, 4))
- {
- /* reset file pointer */
- fseek(pf->fp, -4, SEEK_CUR);
- return ptcache_smoke_read_old(pf, smoke_v);
- }
-
- /* fluid info */
- ptcache_file_read(pf, &cache_fields, 1, sizeof(int));
- ptcache_file_read(pf, &active_fields, 1, sizeof(int));
- ptcache_file_read(pf, &ch_res, 3, sizeof(int));
- ptcache_file_read(pf, &ch_dx, 1, sizeof(float));
-
- /* check if resolution has changed */
- if (sds->res[0] != ch_res[0] ||
- sds->res[1] != ch_res[1] ||
- sds->res[2] != ch_res[2]) {
- if (sds->flags & MOD_SMOKE_ADAPTIVE_DOMAIN)
- reallocate = 1;
- else
- return 0;
- }
- /* check if active fields have changed */
- if (fluid_fields != cache_fields ||
- active_fields != sds->active_fields)
- reallocate = 1;
-
- /* reallocate fluid if needed*/
- if (reallocate) {
- sds->active_fields = active_fields | cache_fields;
- smoke_reallocate_fluid(sds, ch_dx, ch_res, 1);
- sds->dx = ch_dx;
- VECCOPY(sds->res, ch_res);
- sds->total_cells = ch_res[0]*ch_res[1]*ch_res[2];
- if (sds->flags & MOD_SMOKE_HIGHRES) {
- smoke_reallocate_highres_fluid(sds, ch_dx, ch_res, 1);
- }
- }
-
- if (sds->fluid) {
- size_t res = sds->res[0]*sds->res[1]*sds->res[2];
- float dt, dx, *dens, *react, *fuel, *flame, *heat, *heatold, *vx, *vy, *vz, *r, *g, *b;
- unsigned char *obstacles;
- unsigned int out_len = (unsigned int)res * sizeof(float);
-
- smoke_export(sds->fluid, &dt, &dx, &dens, &react, &flame, &fuel, &heat, &heatold, &vx, &vy, &vz, &r, &g, &b, &obstacles);
-
- ptcache_file_compressed_read(pf, (unsigned char *)sds->shadow, out_len);
- ptcache_file_compressed_read(pf, (unsigned char *)dens, out_len);
- if (cache_fields & SM_ACTIVE_HEAT) {
- ptcache_file_compressed_read(pf, (unsigned char *)heat, out_len);
- ptcache_file_compressed_read(pf, (unsigned char *)heatold, out_len);
- }
- if (cache_fields & SM_ACTIVE_FIRE) {
- ptcache_file_compressed_read(pf, (unsigned char *)flame, out_len);
- ptcache_file_compressed_read(pf, (unsigned char *)fuel, out_len);
- ptcache_file_compressed_read(pf, (unsigned char *)react, out_len);
- }
- if (cache_fields & SM_ACTIVE_COLORS) {
- ptcache_file_compressed_read(pf, (unsigned char *)r, out_len);
- ptcache_file_compressed_read(pf, (unsigned char *)g, out_len);
- ptcache_file_compressed_read(pf, (unsigned char *)b, out_len);
- }
- ptcache_file_compressed_read(pf, (unsigned char *)vx, out_len);
- ptcache_file_compressed_read(pf, (unsigned char *)vy, out_len);
- ptcache_file_compressed_read(pf, (unsigned char *)vz, out_len);
- ptcache_file_compressed_read(pf, (unsigned char *)obstacles, (unsigned int)res);
- ptcache_file_read(pf, &dt, 1, sizeof(float));
- ptcache_file_read(pf, &dx, 1, sizeof(float));
- ptcache_file_read(pf, &sds->p0, 3, sizeof(float));
- ptcache_file_read(pf, &sds->p1, 3, sizeof(float));
- ptcache_file_read(pf, &sds->dp0, 3, sizeof(float));
- ptcache_file_read(pf, &sds->shift, 3, sizeof(int));
- ptcache_file_read(pf, &sds->obj_shift_f, 3, sizeof(float));
- ptcache_file_read(pf, &sds->obmat, 16, sizeof(float));
- ptcache_file_read(pf, &sds->base_res, 3, sizeof(int));
- ptcache_file_read(pf, &sds->res_min, 3, sizeof(int));
- ptcache_file_read(pf, &sds->res_max, 3, sizeof(int));
- ptcache_file_read(pf, &sds->active_color, 3, sizeof(float));
- }
-
- if (pf->data_types & (1<<BPHYS_DATA_SMOKE_HIGH) && sds->wt) {
- int res = sds->res[0]*sds->res[1]*sds->res[2];
- int res_big, res_big_array[3];
- float *dens, *react, *fuel, *flame, *tcu, *tcv, *tcw, *r, *g, *b;
- unsigned int out_len = sizeof(float)*(unsigned int)res;
- unsigned int out_len_big;
-
- smoke_turbulence_get_res(sds->wt, res_big_array);
- res_big = res_big_array[0]*res_big_array[1]*res_big_array[2];
- out_len_big = sizeof(float) * (unsigned int)res_big;
-
- smoke_turbulence_export(sds->wt, &dens, &react, &flame, &fuel, &r, &g, &b, &tcu, &tcv, &tcw);
-
- ptcache_file_compressed_read(pf, (unsigned char *)dens, out_len_big);
- if (cache_fields & SM_ACTIVE_FIRE) {
- ptcache_file_compressed_read(pf, (unsigned char *)flame, out_len_big);
- ptcache_file_compressed_read(pf, (unsigned char *)fuel, out_len_big);
- ptcache_file_compressed_read(pf, (unsigned char *)react, out_len_big);
- }
- if (cache_fields & SM_ACTIVE_COLORS) {
- ptcache_file_compressed_read(pf, (unsigned char *)r, out_len_big);
- ptcache_file_compressed_read(pf, (unsigned char *)g, out_len_big);
- ptcache_file_compressed_read(pf, (unsigned char *)b, out_len_big);
- }
-
- ptcache_file_compressed_read(pf, (unsigned char *)tcu, out_len);
- ptcache_file_compressed_read(pf, (unsigned char *)tcv, out_len);
- ptcache_file_compressed_read(pf, (unsigned char *)tcw, out_len);
- }
-
- return 1;
-}
-
-#ifdef WITH_OPENVDB
-/**
- * Construct matrices which represent the fluid object, for low and high res:
- * <pre>
- * vs 0 0 0
- * 0 vs 0 0
- * 0 0 vs 0
- * px py pz 1
- * </pre>
- *
- * with `vs` = voxel size, and `px, py, pz`,
- * the min position of the domain's bounding box.
- */
-static void compute_fluid_matrices(SmokeDomainSettings *sds)
-{
- float bbox_min[3];
-
- copy_v3_v3(bbox_min, sds->p0);
-
- if (sds->flags & MOD_SMOKE_ADAPTIVE_DOMAIN) {
- bbox_min[0] += (sds->cell_size[0] * (float)sds->res_min[0]);
- bbox_min[1] += (sds->cell_size[1] * (float)sds->res_min[1]);
- bbox_min[2] += (sds->cell_size[2] * (float)sds->res_min[2]);
- add_v3_v3(bbox_min, sds->obj_shift_f);
- }
-
- /* construct low res matrix */
- size_to_mat4(sds->fluidmat, sds->cell_size);
- copy_v3_v3(sds->fluidmat[3], bbox_min);
-
- /* The smoke simulator stores voxels cell-centered, whilst VDB is node
- * centered, so we offset the matrix by half a voxel to compensate. */
- madd_v3_v3fl(sds->fluidmat[3], sds->cell_size, 0.5f);
-
- mul_m4_m4m4(sds->fluidmat, sds->obmat, sds->fluidmat);
-
- if (sds->wt) {
- float voxel_size_high[3];
- /* construct high res matrix */
- mul_v3_v3fl(voxel_size_high, sds->cell_size, 1.0f / (float)(sds->amplify + 1));
- size_to_mat4(sds->fluidmat_wt, voxel_size_high);
- copy_v3_v3(sds->fluidmat_wt[3], bbox_min);
-
- /* Same here, add half a voxel to adjust the position of the fluid. */
- madd_v3_v3fl(sds->fluidmat_wt[3], voxel_size_high, 0.5f);
-
- mul_m4_m4m4(sds->fluidmat_wt, sds->obmat, sds->fluidmat_wt);
- }
-}
-
-static int ptcache_smoke_openvdb_write(struct OpenVDBWriter *writer, void *smoke_v)
-{
- SmokeModifierData *smd = (SmokeModifierData *)smoke_v;
- SmokeDomainSettings *sds = smd->domain;
-
- OpenVDBWriter_set_flags(writer, sds->openvdb_comp, (sds->data_depth == 16));
-
- OpenVDBWriter_add_meta_int(writer, "blender/smoke/active_fields", sds->active_fields);
- OpenVDBWriter_add_meta_v3_int(writer, "blender/smoke/resolution", sds->res);
- OpenVDBWriter_add_meta_v3_int(writer, "blender/smoke/min_resolution", sds->res_min);
- OpenVDBWriter_add_meta_v3_int(writer, "blender/smoke/max_resolution", sds->res_max);
- OpenVDBWriter_add_meta_v3_int(writer, "blender/smoke/base_resolution", sds->base_res);
- OpenVDBWriter_add_meta_v3(writer, "blender/smoke/min_bbox", sds->p0);
- OpenVDBWriter_add_meta_v3(writer, "blender/smoke/max_bbox", sds->p1);
- OpenVDBWriter_add_meta_v3(writer, "blender/smoke/dp0", sds->dp0);
- OpenVDBWriter_add_meta_v3_int(writer, "blender/smoke/shift", sds->shift);
- OpenVDBWriter_add_meta_v3(writer, "blender/smoke/obj_shift_f", sds->obj_shift_f);
- OpenVDBWriter_add_meta_v3(writer, "blender/smoke/active_color", sds->active_color);
- OpenVDBWriter_add_meta_mat4(writer, "blender/smoke/obmat", sds->obmat);
-
- int fluid_fields = smoke_get_data_flags(sds);
-
- struct OpenVDBFloatGrid *clip_grid = NULL;
-
- compute_fluid_matrices(sds);
-
- OpenVDBWriter_add_meta_int(writer, "blender/smoke/fluid_fields", fluid_fields);
-
- if (sds->wt) {
- struct OpenVDBFloatGrid *wt_density_grid;
- float *dens, *react, *fuel, *flame, *tcu, *tcv, *tcw, *r, *g, *b;
-
- smoke_turbulence_export(sds->wt, &dens, &react, &flame, &fuel, &r, &g, &b, &tcu, &tcv, &tcw);
-
- wt_density_grid = OpenVDB_export_grid_fl(writer, "density", dens, sds->res_wt, sds->fluidmat_wt, NULL);
- clip_grid = wt_density_grid;
-
- if (fluid_fields & SM_ACTIVE_FIRE) {
- OpenVDB_export_grid_fl(writer, "flame", flame, sds->res_wt, sds->fluidmat_wt, wt_density_grid);
- OpenVDB_export_grid_fl(writer, "fuel", fuel, sds->res_wt, sds->fluidmat_wt, wt_density_grid);
- OpenVDB_export_grid_fl(writer, "react", react, sds->res_wt, sds->fluidmat_wt, wt_density_grid);
- }
-
- if (fluid_fields & SM_ACTIVE_COLORS) {
- OpenVDB_export_grid_vec(writer, "color", r, g, b, sds->res_wt, sds->fluidmat_wt, VEC_INVARIANT, true, wt_density_grid);
- }
-
- OpenVDB_export_grid_vec(writer, "texture coordinates", tcu, tcv, tcw, sds->res, sds->fluidmat, VEC_INVARIANT, false, wt_density_grid);
- }
-
- if (sds->fluid) {
- struct OpenVDBFloatGrid *density_grid;
- float dt, dx, *dens, *react, *fuel, *flame, *heat, *heatold, *vx, *vy, *vz, *r, *g, *b;
- unsigned char *obstacles;
-
- smoke_export(sds->fluid, &dt, &dx, &dens, &react, &flame, &fuel, &heat,
- &heatold, &vx, &vy, &vz, &r, &g, &b, &obstacles);
-
- OpenVDBWriter_add_meta_fl(writer, "blender/smoke/dx", dx);
- OpenVDBWriter_add_meta_fl(writer, "blender/smoke/dt", dt);
-
- const char *name = (!sds->wt) ? "density" : "density low";
- density_grid = OpenVDB_export_grid_fl(writer, name, dens, sds->res, sds->fluidmat, NULL);
- clip_grid = sds->wt ? clip_grid : density_grid;
-
- OpenVDB_export_grid_fl(writer, "shadow", sds->shadow, sds->res, sds->fluidmat, NULL);
-
- if (fluid_fields & SM_ACTIVE_HEAT) {
- OpenVDB_export_grid_fl(writer, "heat", heat, sds->res, sds->fluidmat, clip_grid);
- OpenVDB_export_grid_fl(writer, "heat old", heatold, sds->res, sds->fluidmat, clip_grid);
- }
-
- if (fluid_fields & SM_ACTIVE_FIRE) {
- name = (!sds->wt) ? "flame" : "flame low";
- OpenVDB_export_grid_fl(writer, name, flame, sds->res, sds->fluidmat, density_grid);
- name = (!sds->wt) ? "fuel" : "fuel low";
- OpenVDB_export_grid_fl(writer, name, fuel, sds->res, sds->fluidmat, density_grid);
- name = (!sds->wt) ? "react" : "react low";
- OpenVDB_export_grid_fl(writer, name, react, sds->res, sds->fluidmat, density_grid);
- }
-
- if (fluid_fields & SM_ACTIVE_COLORS) {
- name = (!sds->wt) ? "color" : "color low";
- OpenVDB_export_grid_vec(writer, name, r, g, b, sds->res, sds->fluidmat, VEC_INVARIANT, true, density_grid);
- }
-
- OpenVDB_export_grid_vec(writer, "velocity", vx, vy, vz, sds->res, sds->fluidmat, VEC_CONTRAVARIANT_RELATIVE, false, clip_grid);
- OpenVDB_export_grid_ch(writer, "obstacles", obstacles, sds->res, sds->fluidmat, NULL);
- }
-
- return 1;
-}
-
-static int ptcache_smoke_openvdb_read(struct OpenVDBReader *reader, void *smoke_v)
-{
- SmokeModifierData *smd = (SmokeModifierData *)smoke_v;
-
- if (!smd) {
- return 0;
- }
-
- SmokeDomainSettings *sds = smd->domain;
-
- int fluid_fields = smoke_get_data_flags(sds);
- int active_fields, cache_fields = 0;
- int cache_res[3];
- float cache_dx;
- bool reallocate = false;
-
- OpenVDBReader_get_meta_v3_int(reader, "blender/smoke/min_resolution", sds->res_min);
- OpenVDBReader_get_meta_v3_int(reader, "blender/smoke/max_resolution", sds->res_max);
- OpenVDBReader_get_meta_v3_int(reader, "blender/smoke/base_resolution", sds->base_res);
- OpenVDBReader_get_meta_v3(reader, "blender/smoke/min_bbox", sds->p0);
- OpenVDBReader_get_meta_v3(reader, "blender/smoke/max_bbox", sds->p1);
- OpenVDBReader_get_meta_v3(reader, "blender/smoke/dp0", sds->dp0);
- OpenVDBReader_get_meta_v3_int(reader, "blender/smoke/shift", sds->shift);
- OpenVDBReader_get_meta_v3(reader, "blender/smoke/obj_shift_f", sds->obj_shift_f);
- OpenVDBReader_get_meta_v3(reader, "blender/smoke/active_color", sds->active_color);
- OpenVDBReader_get_meta_mat4(reader, "blender/smoke/obmat", sds->obmat);
- OpenVDBReader_get_meta_int(reader, "blender/smoke/fluid_fields", &cache_fields);
- OpenVDBReader_get_meta_int(reader, "blender/smoke/active_fields", &active_fields);
- OpenVDBReader_get_meta_fl(reader, "blender/smoke/dx", &cache_dx);
- OpenVDBReader_get_meta_v3_int(reader, "blender/smoke/resolution", cache_res);
-
- /* check if resolution has changed */
- if (sds->res[0] != cache_res[0] ||
- sds->res[1] != cache_res[1] ||
- sds->res[2] != cache_res[2])
- {
- if (sds->flags & MOD_SMOKE_ADAPTIVE_DOMAIN) {
- reallocate = true;
- }
- else {
- return 0;
- }
- }
-
- /* check if active fields have changed */
- if ((fluid_fields != cache_fields) || (active_fields != sds->active_fields)) {
- reallocate = true;
- }
-
- /* reallocate fluid if needed*/
- if (reallocate) {
- sds->active_fields = active_fields | cache_fields;
- smoke_reallocate_fluid(sds, cache_dx, cache_res, 1);
- sds->dx = cache_dx;
- copy_v3_v3_int(sds->res, cache_res);
- sds->total_cells = cache_res[0] * cache_res[1] * cache_res[2];
-
- if (sds->flags & MOD_SMOKE_HIGHRES) {
- smoke_reallocate_highres_fluid(sds, cache_dx, cache_res, 1);
- }
- }
-
- if (sds->fluid) {
- float dt, dx, *dens, *react, *fuel, *flame, *heat, *heatold, *vx, *vy, *vz, *r, *g, *b;
- unsigned char *obstacles;
-
- smoke_export(sds->fluid, &dt, &dx, &dens, &react, &flame, &fuel, &heat,
- &heatold, &vx, &vy, &vz, &r, &g, &b, &obstacles);
-
- OpenVDBReader_get_meta_fl(reader, "blender/smoke/dt", &dt);
-
- OpenVDB_import_grid_fl(reader, "shadow", &sds->shadow, sds->res);
-
- const char *name = (!sds->wt) ? "density" : "density low";
- OpenVDB_import_grid_fl(reader, name, &dens, sds->res);
-
- if (cache_fields & SM_ACTIVE_HEAT) {
- OpenVDB_import_grid_fl(reader, "heat", &heat, sds->res);
- OpenVDB_import_grid_fl(reader, "heat old", &heatold, sds->res);
- }
-
- if (cache_fields & SM_ACTIVE_FIRE) {
- name = (!sds->wt) ? "flame" : "flame low";
- OpenVDB_import_grid_fl(reader, name, &flame, sds->res);
- name = (!sds->wt) ? "fuel" : "fuel low";
- OpenVDB_import_grid_fl(reader, name, &fuel, sds->res);
- name = (!sds->wt) ? "react" : "react low";
- OpenVDB_import_grid_fl(reader, name, &react, sds->res);
- }
-
- if (cache_fields & SM_ACTIVE_COLORS) {
- name = (!sds->wt) ? "color" : "color low";
- OpenVDB_import_grid_vec(reader, name, &r, &g, &b, sds->res);
- }
-
- OpenVDB_import_grid_vec(reader, "velocity", &vx, &vy, &vz, sds->res);
- OpenVDB_import_grid_ch(reader, "obstacles", &obstacles, sds->res);
- }
-
- if (sds->wt) {
- float *dens, *react, *fuel, *flame, *tcu, *tcv, *tcw, *r, *g, *b;
-
- smoke_turbulence_export(sds->wt, &dens, &react, &flame, &fuel, &r, &g, &b, &tcu, &tcv, &tcw);
-
- OpenVDB_import_grid_fl(reader, "density", &dens, sds->res_wt);
-
- if (cache_fields & SM_ACTIVE_FIRE) {
- OpenVDB_import_grid_fl(reader, "flame", &flame, sds->res_wt);
- OpenVDB_import_grid_fl(reader, "fuel", &fuel, sds->res_wt);
- OpenVDB_import_grid_fl(reader, "react", &react, sds->res_wt);
- }
-
- if (cache_fields & SM_ACTIVE_COLORS) {
- OpenVDB_import_grid_vec(reader, "color", &r, &g, &b, sds->res_wt);
- }
-
- OpenVDB_import_grid_vec(reader, "texture coordinates", &tcu, &tcv, &tcw, sds->res);
- }
-
- OpenVDBReader_free(reader);
-
- return 1;
-}
-#endif
-
-#else // WITH_SMOKE
-static int ptcache_smoke_totpoint(void *UNUSED(smoke_v), int UNUSED(cfra)) { return 0; }
-static void ptcache_smoke_error(void *UNUSED(smoke_v), const char *UNUSED(message)) { }
-static int ptcache_smoke_read(PTCacheFile *UNUSED(pf), void *UNUSED(smoke_v)) { return 0; }
-static int ptcache_smoke_write(PTCacheFile *UNUSED(pf), void *UNUSED(smoke_v)) { return 0; }
-#endif // WITH_SMOKE
-
-#if !defined(WITH_SMOKE) || !defined(WITH_OPENVDB)
-static int ptcache_smoke_openvdb_write(struct OpenVDBWriter *writer, void *smoke_v)
-{
- UNUSED_VARS(writer, smoke_v);
- return 0;
-}
-
-static int ptcache_smoke_openvdb_read(struct OpenVDBReader *reader, void *smoke_v)
-{
- UNUSED_VARS(reader, smoke_v);
- return 0;
-}
-#endif
-
-static int ptcache_dynamicpaint_totpoint(void *sd, int UNUSED(cfra))
-{
- DynamicPaintSurface *surface = (DynamicPaintSurface*)sd;
-
- if (!surface->data) return 0;
- else return surface->data->total_points;
-}
-
-static void ptcache_dynamicpaint_error(void *UNUSED(sd), const char *UNUSED(message))
-{
- /* ignored for now */
-}
-
-#define DPAINT_CACHE_VERSION "1.01"
-
-static int ptcache_dynamicpaint_write(PTCacheFile *pf, void *dp_v)
-{
- DynamicPaintSurface *surface = (DynamicPaintSurface*)dp_v;
- int cache_compress = 1;
-
- /* version header */
- ptcache_file_write(pf, DPAINT_CACHE_VERSION, 1, sizeof(char) * 4);
-
- if (surface->format != MOD_DPAINT_SURFACE_F_IMAGESEQ && surface->data) {
- int total_points=surface->data->total_points;
- unsigned int in_len;
- unsigned char *out;
-
- /* cache type */
- ptcache_file_write(pf, &surface->type, 1, sizeof(int));
-
- if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
- in_len = sizeof(PaintPoint) * total_points;
- }
- else if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE ||
- surface->type == MOD_DPAINT_SURFACE_T_WEIGHT)
- {
- in_len = sizeof(float) * total_points;
- }
- else if (surface->type == MOD_DPAINT_SURFACE_T_WAVE) {
- in_len = sizeof(PaintWavePoint) * total_points;
- }
- else {
- return 0;
- }
-
- out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len), "pointcache_lzo_buffer");
-
- ptcache_file_compressed_write(pf, (unsigned char *)surface->data->type_data, in_len, out, cache_compress);
- MEM_freeN(out);
-
- }
- return 1;
-}
-static int ptcache_dynamicpaint_read(PTCacheFile *pf, void *dp_v)
-{
- DynamicPaintSurface *surface = (DynamicPaintSurface*)dp_v;
- char version[4];
-
- /* version header */
- ptcache_file_read(pf, version, 1, sizeof(char) * 4);
- if (!STREQLEN(version, DPAINT_CACHE_VERSION, 4)) {
- printf("Dynamic Paint: Invalid cache version: '%c%c%c%c'!\n", UNPACK4(version));
- return 0;
- }
-
- if (surface->format != MOD_DPAINT_SURFACE_F_IMAGESEQ && surface->data) {
- unsigned int data_len;
- int surface_type;
-
- /* cache type */
- ptcache_file_read(pf, &surface_type, 1, sizeof(int));
-
- if (surface_type != surface->type)
- return 0;
-
- /* read surface data */
- if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
- data_len = sizeof(PaintPoint);
- }
- else if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE ||
- surface->type == MOD_DPAINT_SURFACE_T_WEIGHT)
- {
- data_len = sizeof(float);
- }
- else if (surface->type == MOD_DPAINT_SURFACE_T_WAVE) {
- data_len = sizeof(PaintWavePoint);
- }
- else {
- return 0;
- }
-
- ptcache_file_compressed_read(pf, (unsigned char *)surface->data->type_data, data_len*surface->data->total_points);
-
- }
- return 1;
-}
-
-/* Rigid Body functions */
-static int ptcache_rigidbody_write(int index, void *rb_v, void **data, int UNUSED(cfra))
-{
- RigidBodyWorld *rbw = rb_v;
- Object *ob = NULL;
-
- if (rbw->objects)
- ob = rbw->objects[index];
-
- if (ob && ob->rigidbody_object) {
- RigidBodyOb *rbo = ob->rigidbody_object;
-
- if (rbo->type == RBO_TYPE_ACTIVE) {
-#ifdef WITH_BULLET
- RB_body_get_position(rbo->physics_object, rbo->pos);
- RB_body_get_orientation(rbo->physics_object, rbo->orn);
-#endif
- PTCACHE_DATA_FROM(data, BPHYS_DATA_LOCATION, rbo->pos);
- PTCACHE_DATA_FROM(data, BPHYS_DATA_ROTATION, rbo->orn);
- }
- }
-
- return 1;
-}
-static void ptcache_rigidbody_read(int index, void *rb_v, void **data, float UNUSED(cfra), float *old_data)
-{
- RigidBodyWorld *rbw = rb_v;
- Object *ob = NULL;
-
- if (rbw->objects)
- ob = rbw->objects[index];
-
- if (ob && ob->rigidbody_object) {
- RigidBodyOb *rbo = ob->rigidbody_object;
-
- if (rbo->type == RBO_TYPE_ACTIVE) {
-
- if (old_data) {
- memcpy(rbo->pos, data, 3 * sizeof(float));
- memcpy(rbo->orn, data + 3, 4 * sizeof(float));
- }
- else {
- PTCACHE_DATA_TO(data, BPHYS_DATA_LOCATION, 0, rbo->pos);
- PTCACHE_DATA_TO(data, BPHYS_DATA_ROTATION, 0, rbo->orn);
- }
- }
- }
-}
-static void ptcache_rigidbody_interpolate(int index, void *rb_v, void **data, float cfra, float cfra1, float cfra2, float *old_data)
-{
- RigidBodyWorld *rbw = rb_v;
- Object *ob = NULL;
-
- if (rbw->objects)
- ob = rbw->objects[index];
-
- if (ob && ob->rigidbody_object) {
- RigidBodyOb *rbo = ob->rigidbody_object;
-
- if (rbo->type == RBO_TYPE_ACTIVE) {
- ParticleKey keys[4];
- ParticleKey result;
- float dfra;
-
- memset(keys, 0, sizeof(keys));
-
- copy_v3_v3(keys[1].co, rbo->pos);
- copy_qt_qt(keys[1].rot, rbo->orn);
-
- if (old_data) {
- memcpy(keys[2].co, data, 3 * sizeof(float));
- memcpy(keys[2].rot, data + 3, 4 * sizeof(float));
- }
- else {
- BKE_ptcache_make_particle_key(&keys[2], 0, data, cfra2);
- }
-
- dfra = cfra2 - cfra1;
-
- /* note: keys[0] and keys[3] unused for type < 1 (crappy) */
- psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, &result, true);
- interp_qt_qtqt(result.rot, keys[1].rot, keys[2].rot, (cfra - cfra1) / dfra);
-
- copy_v3_v3(rbo->pos, result.co);
- copy_qt_qt(rbo->orn, result.rot);
- }
- }
-}
-static int ptcache_rigidbody_totpoint(void *rb_v, int UNUSED(cfra))
-{
- RigidBodyWorld *rbw = rb_v;
-
- return rbw->numbodies;
-}
-
-static void ptcache_rigidbody_error(void *UNUSED(rb_v), const char *UNUSED(message))
-{
- /* ignored for now */
-}
-
-/* Creating ID's */
-void BKE_ptcache_id_from_softbody(PTCacheID *pid, Object *ob, SoftBody *sb)
-{
- memset(pid, 0, sizeof(PTCacheID));
-
- pid->ob= ob;
- pid->calldata= sb;
- pid->type= PTCACHE_TYPE_SOFTBODY;
- pid->cache= sb->pointcache;
- pid->cache_ptr= &sb->pointcache;
- pid->ptcaches= &sb->ptcaches;
- pid->totpoint= pid->totwrite= ptcache_softbody_totpoint;
- pid->error = ptcache_softbody_error;
-
- pid->write_point = ptcache_softbody_write;
- pid->read_point = ptcache_softbody_read;
- pid->interpolate_point = ptcache_softbody_interpolate;
-
- pid->write_stream = NULL;
- pid->read_stream = NULL;
-
- pid->write_openvdb_stream = NULL;
- pid->read_openvdb_stream = NULL;
-
- pid->write_extra_data = NULL;
- pid->read_extra_data = NULL;
- pid->interpolate_extra_data = NULL;
-
- pid->write_header = ptcache_basic_header_write;
- pid->read_header = ptcache_basic_header_read;
-
- pid->data_types= (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY);
- pid->info_types= 0;
-
- pid->stack_index = pid->cache->index;
-
- pid->default_step = 10;
- pid->max_step = 20;
- pid->file_type = PTCACHE_FILE_PTCACHE;
-}
-void BKE_ptcache_id_from_particles(PTCacheID *pid, Object *ob, ParticleSystem *psys)
-{
- memset(pid, 0, sizeof(PTCacheID));
-
- pid->ob= ob;
- pid->calldata= psys;
- pid->type= PTCACHE_TYPE_PARTICLES;
- pid->stack_index= psys->pointcache->index;
- pid->cache= psys->pointcache;
- pid->cache_ptr= &psys->pointcache;
- pid->ptcaches= &psys->ptcaches;
-
- if (psys->part->type != PART_HAIR)
- pid->flag |= PTCACHE_VEL_PER_SEC;
-
- pid->totpoint = ptcache_particle_totpoint;
- pid->totwrite = ptcache_particle_totwrite;
- pid->error = ptcache_particle_error;
-
- pid->write_point = ptcache_particle_write;
- pid->read_point = ptcache_particle_read;
- pid->interpolate_point = ptcache_particle_interpolate;
-
- pid->write_stream = NULL;
- pid->read_stream = NULL;
-
- pid->write_openvdb_stream = NULL;
- pid->read_openvdb_stream = NULL;
-
- pid->write_extra_data = NULL;
- pid->read_extra_data = NULL;
- pid->interpolate_extra_data = NULL;
-
- pid->write_header = ptcache_basic_header_write;
- pid->read_header = ptcache_basic_header_read;
-
- pid->data_types = (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY) | (1<<BPHYS_DATA_INDEX);
-
- if (psys->part->phystype == PART_PHYS_BOIDS)
- pid->data_types|= (1<<BPHYS_DATA_AVELOCITY) | (1<<BPHYS_DATA_ROTATION) | (1<<BPHYS_DATA_BOIDS);
- else if (psys->part->phystype == PART_PHYS_FLUID && psys->part->fluid && psys->part->fluid->flag & SPH_VISCOELASTIC_SPRINGS) {
- pid->write_extra_data = ptcache_particle_extra_write;
- pid->read_extra_data = ptcache_particle_extra_read;
- }
-
- if (psys->part->flag & PART_ROTATIONS) {
- pid->data_types|= (1<<BPHYS_DATA_ROTATION);
-
- if (psys->part->rotmode != PART_ROT_VEL ||
- psys->part->avemode == PART_AVE_RAND ||
- psys->part->avefac != 0.0f)
- {
- pid->data_types |= (1 << BPHYS_DATA_AVELOCITY);
- }
- }
-
- pid->info_types= (1<<BPHYS_DATA_TIMES);
-
- pid->default_step = 10;
- pid->max_step = 20;
- pid->file_type = PTCACHE_FILE_PTCACHE;
-}
-void BKE_ptcache_id_from_cloth(PTCacheID *pid, Object *ob, ClothModifierData *clmd)
-{
- memset(pid, 0, sizeof(PTCacheID));
-
- pid->ob= ob;
- pid->calldata= clmd;
- pid->type= PTCACHE_TYPE_CLOTH;
- pid->stack_index= clmd->point_cache->index;
- pid->cache= clmd->point_cache;
- pid->cache_ptr= &clmd->point_cache;
- pid->ptcaches= &clmd->ptcaches;
- pid->totpoint= pid->totwrite= ptcache_cloth_totpoint;
- pid->error = ptcache_cloth_error;
-
- pid->write_point = ptcache_cloth_write;
- pid->read_point = ptcache_cloth_read;
- pid->interpolate_point = ptcache_cloth_interpolate;
-
- pid->write_openvdb_stream = NULL;
- pid->read_openvdb_stream = NULL;
-
- pid->write_stream = NULL;
- pid->read_stream = NULL;
-
- pid->write_extra_data = NULL;
- pid->read_extra_data = NULL;
- pid->interpolate_extra_data = NULL;
-
- pid->write_header = ptcache_basic_header_write;
- pid->read_header = ptcache_basic_header_read;
-
- pid->data_types= (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY) | (1<<BPHYS_DATA_XCONST);
- pid->info_types= 0;
-
- pid->default_step = 1;
- pid->max_step = 1;
- pid->file_type = PTCACHE_FILE_PTCACHE;
-}
-void BKE_ptcache_id_from_smoke(PTCacheID *pid, struct Object *ob, struct SmokeModifierData *smd)
-{
- SmokeDomainSettings *sds = smd->domain;
-
- memset(pid, 0, sizeof(PTCacheID));
-
- pid->ob= ob;
- pid->calldata= smd;
-
- pid->type= PTCACHE_TYPE_SMOKE_DOMAIN;
- pid->stack_index= sds->point_cache[0]->index;
-
- pid->cache= sds->point_cache[0];
- pid->cache_ptr= &(sds->point_cache[0]);
- pid->ptcaches= &(sds->ptcaches[0]);
-
- pid->totpoint= pid->totwrite= ptcache_smoke_totpoint;
- pid->error = ptcache_smoke_error;
-
- pid->write_point = NULL;
- pid->read_point = NULL;
- pid->interpolate_point = NULL;
-
- pid->read_stream = ptcache_smoke_read;
- pid->write_stream = ptcache_smoke_write;
-
- pid->write_openvdb_stream = ptcache_smoke_openvdb_write;
- pid->read_openvdb_stream = ptcache_smoke_openvdb_read;
-
- pid->write_extra_data = NULL;
- pid->read_extra_data = NULL;
- pid->interpolate_extra_data = NULL;
-
- pid->write_header = ptcache_basic_header_write;
- pid->read_header = ptcache_basic_header_read;
-
- pid->data_types= 0;
- pid->info_types= 0;
-
- if (sds->fluid)
- pid->data_types |= (1<<BPHYS_DATA_SMOKE_LOW);
- if (sds->wt)
- pid->data_types |= (1<<BPHYS_DATA_SMOKE_HIGH);
-
- pid->default_step = 1;
- pid->max_step = 1;
- pid->file_type = smd->domain->cache_file_format;
-}
-
-void BKE_ptcache_id_from_dynamicpaint(PTCacheID *pid, Object *ob, DynamicPaintSurface *surface)
-{
-
- memset(pid, 0, sizeof(PTCacheID));
-
- pid->ob= ob;
- pid->calldata= surface;
- pid->type= PTCACHE_TYPE_DYNAMICPAINT;
- pid->cache= surface->pointcache;
- pid->cache_ptr= &surface->pointcache;
- pid->ptcaches= &surface->ptcaches;
- pid->totpoint= pid->totwrite= ptcache_dynamicpaint_totpoint;
- pid->error = ptcache_dynamicpaint_error;
-
- pid->write_point = NULL;
- pid->read_point = NULL;
- pid->interpolate_point = NULL;
-
- pid->write_stream = ptcache_dynamicpaint_write;
- pid->read_stream = ptcache_dynamicpaint_read;
-
- pid->write_openvdb_stream = NULL;
- pid->read_openvdb_stream = NULL;
-
- pid->write_extra_data = NULL;
- pid->read_extra_data = NULL;
- pid->interpolate_extra_data = NULL;
-
- pid->write_header = ptcache_basic_header_write;
- pid->read_header = ptcache_basic_header_read;
-
- pid->data_types= BPHYS_DATA_DYNAMICPAINT;
- pid->info_types= 0;
-
- pid->stack_index = pid->cache->index;
-
- pid->default_step = 1;
- pid->max_step = 1;
- pid->file_type = PTCACHE_FILE_PTCACHE;
-}
-
-void BKE_ptcache_id_from_rigidbody(PTCacheID *pid, Object *ob, RigidBodyWorld *rbw)
-{
-
- memset(pid, 0, sizeof(PTCacheID));
-
- pid->ob= ob;
- pid->calldata= rbw;
- pid->type= PTCACHE_TYPE_RIGIDBODY;
- pid->cache= rbw->pointcache;
- pid->cache_ptr= &rbw->pointcache;
- pid->ptcaches= &rbw->ptcaches;
- pid->totpoint= pid->totwrite= ptcache_rigidbody_totpoint;
- pid->error = ptcache_rigidbody_error;
-
- pid->write_point = ptcache_rigidbody_write;
- pid->read_point = ptcache_rigidbody_read;
- pid->interpolate_point = ptcache_rigidbody_interpolate;
-
- pid->write_stream = NULL;
- pid->read_stream = NULL;
-
- pid->write_openvdb_stream = NULL;
- pid->read_openvdb_stream = NULL;
-
- pid->write_extra_data = NULL;
- pid->read_extra_data = NULL;
- pid->interpolate_extra_data = NULL;
-
- pid->write_header = ptcache_basic_header_write;
- pid->read_header = ptcache_basic_header_read;
-
- pid->data_types= (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_ROTATION);
- pid->info_types= 0;
-
- pid->stack_index = pid->cache->index;
-
- pid->default_step = 1;
- pid->max_step = 1;
- pid->file_type = PTCACHE_FILE_PTCACHE;
-}
-
-void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int duplis)
-{
- PTCacheID *pid;
- ParticleSystem *psys;
- ModifierData *md;
-
- lb->first= lb->last= NULL;
-
- if (ob->soft) {
- pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID");
- BKE_ptcache_id_from_softbody(pid, ob, ob->soft);
- BLI_addtail(lb, pid);
- }
-
- for (psys=ob->particlesystem.first; psys; psys=psys->next) {
- if (psys->part==NULL)
- continue;
-
- /* check to make sure point cache is actually used by the particles */
- if (ELEM(psys->part->phystype, PART_PHYS_NO, PART_PHYS_KEYED))
- continue;
-
- /* hair needs to be included in id-list for cache edit mode to work */
- /* if (psys->part->type == PART_HAIR && (psys->flag & PSYS_HAIR_DYNAMICS)==0) */
- /* continue; */
-
- if (psys->part->type == PART_FLUID)
- continue;
-
- pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID");
- BKE_ptcache_id_from_particles(pid, ob, psys);
- BLI_addtail(lb, pid);
- }
-
- for (md=ob->modifiers.first; md; md=md->next) {
- if (md->type == eModifierType_Cloth) {
- pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID");
- BKE_ptcache_id_from_cloth(pid, ob, (ClothModifierData*)md);
- BLI_addtail(lb, pid);
- }
- else if (md->type == eModifierType_Smoke) {
- SmokeModifierData *smd = (SmokeModifierData *)md;
- if (smd->type & MOD_SMOKE_TYPE_DOMAIN) {
- pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID");
- BKE_ptcache_id_from_smoke(pid, ob, (SmokeModifierData*)md);
- BLI_addtail(lb, pid);
- }
- }
- else if (md->type == eModifierType_DynamicPaint) {
- DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md;
- if (pmd->canvas) {
- DynamicPaintSurface *surface = pmd->canvas->surfaces.first;
-
- for (; surface; surface=surface->next) {
- pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID");
- BKE_ptcache_id_from_dynamicpaint(pid, ob, surface);
- BLI_addtail(lb, pid);
- }
- }
- }
- }
-
- if (scene && ob->rigidbody_object && scene->rigidbody_world) {
- pid = MEM_callocN(sizeof(PTCacheID), "PTCacheID");
- BKE_ptcache_id_from_rigidbody(pid, ob, scene->rigidbody_world);
- BLI_addtail(lb, pid);
- }
-
- if (scene && (duplis-- > 0) && (ob->transflag & OB_DUPLI)) {
- ListBase *lb_dupli_ob;
- /* don't update the dupli groups, we only want their pid's */
- if ((lb_dupli_ob = object_duplilist_ex(G.main->eval_ctx, scene, ob, false))) {
- DupliObject *dob;
- for (dob= lb_dupli_ob->first; dob; dob= dob->next) {
- if (dob->ob != ob) { /* avoids recursive loops with dupliframes: bug 22988 */
- ListBase lb_dupli_pid;
- BKE_ptcache_ids_from_object(&lb_dupli_pid, dob->ob, scene, duplis);
- BLI_movelisttolist(lb, &lb_dupli_pid);
- if (lb_dupli_pid.first)
- printf("Adding Dupli\n");
- }
- }
-
- free_object_duplilist(lb_dupli_ob); /* does restore */
- }
- }
-}
-
-/* File handling */
-
-static const char *ptcache_file_extension(const PTCacheID *pid)
-{
- switch (pid->file_type) {
- default:
- case PTCACHE_FILE_PTCACHE:
- return PTCACHE_EXT;
- case PTCACHE_FILE_OPENVDB:
- return ".vdb";
- }
-}
-
-/**
- * Similar to #BLI_path_frame_get, but takes into account the stack-index which is after the frame.
- */
-static int ptcache_frame_from_filename(const char *filename, const char *ext)
-{
- const int frame_len = 6;
- const int ext_len = frame_len + strlen(ext);
- const int len = strlen(filename);
-
- /* could crash if trying to copy a string out of this range */
- if (len > ext_len) {
- /* using frame_len here gives compile error (vla) */
- char num[/* frame_len */6 + 1];
- BLI_strncpy(num, filename + len - ext_len, sizeof(num));
-
- return atoi(num);
- }
-
- return -1;
-}
-
-/* Takes an Object ID and returns a unique name
- * - id: object id
- * - cfra: frame for the cache, can be negative
- * - stack_index: index in the modifier stack. we can have cache for more than one stack_index
- */
-
-#define MAX_PTCACHE_PATH FILE_MAX
-#define MAX_PTCACHE_FILE (FILE_MAX * 2)
-
-static int ptcache_path(PTCacheID *pid, char *filename)
-{
- Library *lib = (pid->ob) ? pid->ob->id.lib : NULL;
- const char *blendfilename= (lib && (pid->cache->flag & PTCACHE_IGNORE_LIBPATH)==0) ? lib->filepath: G.main->name;
- size_t i;
-
- if (pid->cache->flag & PTCACHE_EXTERNAL) {
- strcpy(filename, pid->cache->path);
-
- if (BLI_path_is_rel(filename)) {
- BLI_path_abs(filename, blendfilename);
- }
-
- return BLI_add_slash(filename); /* new strlen() */
- }
- else if (G.relbase_valid || lib) {
- char file[MAX_PTCACHE_PATH]; /* we don't want the dir, only the file */
-
- BLI_split_file_part(blendfilename, file, sizeof(file));
- i = strlen(file);
-
- /* remove .blend */
- if (i > 6)
- file[i-6] = '\0';
-
- BLI_snprintf(filename, MAX_PTCACHE_PATH, "//"PTCACHE_PATH"%s", file); /* add blend file name to pointcache dir */
- BLI_path_abs(filename, blendfilename);
- return BLI_add_slash(filename); /* new strlen() */
- }
-
- /* use the temp path. this is weak but better then not using point cache at all */
- /* temporary directory is assumed to exist and ALWAYS has a trailing slash */
- BLI_snprintf(filename, MAX_PTCACHE_PATH, "%s"PTCACHE_PATH, BKE_tempdir_session());
-
- return BLI_add_slash(filename); /* new strlen() */
-}
-
-static int ptcache_filename(PTCacheID *pid, char *filename, int cfra, short do_path, short do_ext)
-{
- int len=0;
- char *idname;
- char *newname;
- filename[0] = '\0';
- newname = filename;
-
- if (!G.relbase_valid && (pid->cache->flag & PTCACHE_EXTERNAL)==0) return 0; /* save blend file before using disk pointcache */
-
- /* start with temp dir */
- if (do_path) {
- len = ptcache_path(pid, filename);
- newname += len;
- }
- if (pid->cache->name[0] == '\0' && (pid->cache->flag & PTCACHE_EXTERNAL)==0) {
- idname = (pid->ob->id.name + 2);
- /* convert chars to hex so they are always a valid filename */
- while ('\0' != *idname) {
- BLI_snprintf(newname, MAX_PTCACHE_FILE, "%02X", (unsigned int)(*idname++));
- newname+=2;
- len += 2;
- }
- }
- else {
- int temp = (int)strlen(pid->cache->name);
- strcpy(newname, pid->cache->name);
- newname+=temp;
- len += temp;
- }
-
- if (do_ext) {
- if (pid->cache->index < 0)
- pid->cache->index = pid->stack_index = BKE_object_insert_ptcache(pid->ob);
-
- const char *ext = ptcache_file_extension(pid);
-
- if (pid->cache->flag & PTCACHE_EXTERNAL) {
- if (pid->cache->index >= 0)
- BLI_snprintf(newname, MAX_PTCACHE_FILE, "_%06d_%02u%s", cfra, pid->stack_index, ext); /* always 6 chars */
- else
- BLI_snprintf(newname, MAX_PTCACHE_FILE, "_%06d%s", cfra, ext); /* always 6 chars */
- }
- else {
- BLI_snprintf(newname, MAX_PTCACHE_FILE, "_%06d_%02u%s", cfra, pid->stack_index, ext); /* always 6 chars */
- }
- len += 16;
- }
-
- return len; /* make sure the above string is always 16 chars */
-}
-
-/* youll need to close yourself after! */
-static PTCacheFile *ptcache_file_open(PTCacheID *pid, int mode, int cfra)
-{
- PTCacheFile *pf;
- FILE *fp = NULL;
- char filename[FILE_MAX * 2];
-
-#ifndef DURIAN_POINTCACHE_LIB_OK
- /* don't allow writing for linked objects */
- if (pid->ob->id.lib && mode == PTCACHE_FILE_WRITE)
- return NULL;
-#endif
- if (!G.relbase_valid && (pid->cache->flag & PTCACHE_EXTERNAL)==0) return NULL; /* save blend file before using disk pointcache */
-
- ptcache_filename(pid, filename, cfra, 1, 1);
-
- if (mode==PTCACHE_FILE_READ) {
- fp = BLI_fopen(filename, "rb");
- }
- else if (mode==PTCACHE_FILE_WRITE) {
- BLI_make_existing_file(filename); /* will create the dir if needs be, same as //textures is created */
- fp = BLI_fopen(filename, "wb");
- }
- else if (mode==PTCACHE_FILE_UPDATE) {
- BLI_make_existing_file(filename);
- fp = BLI_fopen(filename, "rb+");
- }
-
- if (!fp)
- return NULL;
-
- pf= MEM_mallocN(sizeof(PTCacheFile), "PTCacheFile");
- pf->fp= fp;
- pf->old_format = 0;
- pf->frame = cfra;
-
- return pf;
-}
-static void ptcache_file_close(PTCacheFile *pf)
-{
- if (pf) {
- fclose(pf->fp);
- MEM_freeN(pf);
- }
-}
-
-static int ptcache_file_compressed_read(PTCacheFile *pf, unsigned char *result, unsigned int len)
-{
- int r = 0;
- unsigned char compressed = 0;
- size_t in_len;
-#ifdef WITH_LZO
- size_t out_len = len;
-#endif
- unsigned char *in;
- unsigned char *props = MEM_callocN(16 * sizeof(char), "tmp");
-
- ptcache_file_read(pf, &compressed, 1, sizeof(unsigned char));
- if (compressed) {
- unsigned int size;
- ptcache_file_read(pf, &size, 1, sizeof(unsigned int));
- in_len = (size_t)size;
- if (in_len==0) {
- /* do nothing */
- }
- else {
- in = (unsigned char *)MEM_callocN(sizeof(unsigned char)*in_len, "pointcache_compressed_buffer");
- ptcache_file_read(pf, in, in_len, sizeof(unsigned char));
-#ifdef WITH_LZO
- if (compressed == 1)
- r = lzo1x_decompress_safe(in, (lzo_uint)in_len, result, (lzo_uint *)&out_len, NULL);
-#endif
-#ifdef WITH_LZMA
- if (compressed == 2) {
- size_t sizeOfIt;
- size_t leni = in_len, leno = len;
- ptcache_file_read(pf, &size, 1, sizeof(unsigned int));
- sizeOfIt = (size_t)size;
- ptcache_file_read(pf, props, sizeOfIt, sizeof(unsigned char));
- r = LzmaUncompress(result, &leno, in, &leni, props, sizeOfIt);
- }
-#endif
- MEM_freeN(in);
- }
- }
- else {
- ptcache_file_read(pf, result, len, sizeof(unsigned char));
- }
-
- MEM_freeN(props);
-
- return r;
-}
-static int ptcache_file_compressed_write(PTCacheFile *pf, unsigned char *in, unsigned int in_len, unsigned char *out, int mode)
-{
- int r = 0;
- unsigned char compressed = 0;
- size_t out_len= 0;
- unsigned char *props = MEM_callocN(16 * sizeof(char), "tmp");
- size_t sizeOfIt = 5;
-
- (void)mode; /* unused when building w/o compression */
-
-#ifdef WITH_LZO
- out_len= LZO_OUT_LEN(in_len);
- if (mode == 1) {
- LZO_HEAP_ALLOC(wrkmem, LZO1X_MEM_COMPRESS);
-
- r = lzo1x_1_compress(in, (lzo_uint)in_len, out, (lzo_uint *)&out_len, wrkmem);
- if (!(r == LZO_E_OK) || (out_len >= in_len))
- compressed = 0;
- else
- compressed = 1;
- }
-#endif
-#ifdef WITH_LZMA
- if (mode == 2) {
-
- r = LzmaCompress(out, &out_len, in, in_len, //assume sizeof(char)==1....
- props, &sizeOfIt, 5, 1 << 24, 3, 0, 2, 32, 2);
-
- if (!(r == SZ_OK) || (out_len >= in_len))
- compressed = 0;
- else
- compressed = 2;
- }
-#endif
-
- ptcache_file_write(pf, &compressed, 1, sizeof(unsigned char));
- if (compressed) {
- unsigned int size = out_len;
- ptcache_file_write(pf, &size, 1, sizeof(unsigned int));
- ptcache_file_write(pf, out, out_len, sizeof(unsigned char));
- }
- else
- ptcache_file_write(pf, in, in_len, sizeof(unsigned char));
-
- if (compressed == 2) {
- unsigned int size = sizeOfIt;
- ptcache_file_write(pf, &sizeOfIt, 1, sizeof(unsigned int));
- ptcache_file_write(pf, props, size, sizeof(unsigned char));
- }
-
- MEM_freeN(props);
-
- return r;
-}
-static int ptcache_file_read(PTCacheFile *pf, void *f, unsigned int tot, unsigned int size)
-{
- return (fread(f, size, tot, pf->fp) == tot);
-}
-static int ptcache_file_write(PTCacheFile *pf, const void *f, unsigned int tot, unsigned int size)
-{
- return (fwrite(f, size, tot, pf->fp) == tot);
-}
-static int ptcache_file_data_read(PTCacheFile *pf)
-{
- int i;
-
- for (i=0; i<BPHYS_TOT_DATA; i++) {
- if ((pf->data_types & (1<<i)) && !ptcache_file_read(pf, pf->cur[i], 1, ptcache_data_size[i]))
- return 0;
- }
-
- return 1;
-}
-static int ptcache_file_data_write(PTCacheFile *pf)
-{
- int i;
-
- for (i=0; i<BPHYS_TOT_DATA; i++) {
- if ((pf->data_types & (1<<i)) && !ptcache_file_write(pf, pf->cur[i], 1, ptcache_data_size[i]))
- return 0;
- }
-
- return 1;
-}
-static int ptcache_file_header_begin_read(PTCacheFile *pf)
-{
- unsigned int typeflag=0;
- int error=0;
- char bphysics[8];
-
- pf->data_types = 0;
-
- if (fread(bphysics, sizeof(char), 8, pf->fp) != 8)
- error = 1;
-
- if (!error && !STREQLEN(bphysics, "BPHYSICS", 8))
- error = 1;
-
- if (!error && !fread(&typeflag, sizeof(unsigned int), 1, pf->fp))
- error = 1;
-
- pf->type = (typeflag & PTCACHE_TYPEFLAG_TYPEMASK);
- pf->flag = (typeflag & PTCACHE_TYPEFLAG_FLAGMASK);
-
- /* if there was an error set file as it was */
- if (error)
- fseek(pf->fp, 0, SEEK_SET);
-
- return !error;
-}
-static int ptcache_file_header_begin_write(PTCacheFile *pf)
-{
- const char *bphysics = "BPHYSICS";
- unsigned int typeflag = pf->type + pf->flag;
-
- if (fwrite(bphysics, sizeof(char), 8, pf->fp) != 8)
- return 0;
-
- if (!fwrite(&typeflag, sizeof(unsigned int), 1, pf->fp))
- return 0;
-
- return 1;
-}
-
-/* Data pointer handling */
-int BKE_ptcache_data_size(int data_type)
-{
- return ptcache_data_size[data_type];
-}
-
-static void ptcache_file_pointers_init(PTCacheFile *pf)
-{
- int data_types = pf->data_types;
-
- pf->cur[BPHYS_DATA_INDEX] = (data_types & (1<<BPHYS_DATA_INDEX)) ? &pf->data.index : NULL;
- pf->cur[BPHYS_DATA_LOCATION] = (data_types & (1<<BPHYS_DATA_LOCATION)) ? &pf->data.loc : NULL;
- pf->cur[BPHYS_DATA_VELOCITY] = (data_types & (1<<BPHYS_DATA_VELOCITY)) ? &pf->data.vel : NULL;
- pf->cur[BPHYS_DATA_ROTATION] = (data_types & (1<<BPHYS_DATA_ROTATION)) ? &pf->data.rot : NULL;
- pf->cur[BPHYS_DATA_AVELOCITY] = (data_types & (1<<BPHYS_DATA_AVELOCITY))? &pf->data.ave : NULL;
- pf->cur[BPHYS_DATA_SIZE] = (data_types & (1<<BPHYS_DATA_SIZE)) ? &pf->data.size : NULL;
- pf->cur[BPHYS_DATA_TIMES] = (data_types & (1<<BPHYS_DATA_TIMES)) ? &pf->data.times : NULL;
- pf->cur[BPHYS_DATA_BOIDS] = (data_types & (1<<BPHYS_DATA_BOIDS)) ? &pf->data.boids : NULL;
-}
-
-/* Check to see if point number "index" is in pm, uses binary search for index data. */
-int BKE_ptcache_mem_index_find(PTCacheMem *pm, unsigned int index)
-{
- if (pm->totpoint > 0 && pm->data[BPHYS_DATA_INDEX]) {
- unsigned int *data = pm->data[BPHYS_DATA_INDEX];
- unsigned int mid, low = 0, high = pm->totpoint - 1;
-
- if (index < *data || index > *(data+high))
- return -1;
-
- /* check simple case for continuous indexes first */
- if (index-*data < high && data[index-*data] == index)
- return index-*data;
-
- while (low <= high) {
- mid= (low + high)/2;
-
- if (data[mid] > index)
- high = mid - 1;
- else if (data[mid] < index)
- low = mid + 1;
- else
- return mid;
- }
-
- return -1;
- }
- else {
- return (index < pm->totpoint ? index : -1);
- }
-}
-
-void BKE_ptcache_mem_pointers_init(PTCacheMem *pm)
-{
- int data_types = pm->data_types;
- int i;
-
- for (i=0; i<BPHYS_TOT_DATA; i++)
- pm->cur[i] = ((data_types & (1<<i)) ? pm->data[i] : NULL);
-}
-
-void BKE_ptcache_mem_pointers_incr(PTCacheMem *pm)
-{
- int i;
-
- for (i=0; i<BPHYS_TOT_DATA; i++) {
- if (pm->cur[i])
- pm->cur[i] = (char *)pm->cur[i] + ptcache_data_size[i];
- }
-}
-int BKE_ptcache_mem_pointers_seek(int point_index, PTCacheMem *pm)
-{
- int data_types = pm->data_types;
- int i, index = BKE_ptcache_mem_index_find(pm, point_index);
-
- if (index < 0) {
- /* Can't give proper location without reallocation, so don't give any location.
- * Some points will be cached improperly, but this only happens with simulation
- * steps bigger than cache->step, so the cache has to be recalculated anyways
- * at some point.
- */
- return 0;
- }
-
- for (i=0; i<BPHYS_TOT_DATA; i++)
- pm->cur[i] = data_types & (1<<i) ? (char *)pm->data[i] + index * ptcache_data_size[i] : NULL;
-
- return 1;
-}
-static void ptcache_data_alloc(PTCacheMem *pm)
-{
- int data_types = pm->data_types;
- int totpoint = pm->totpoint;
- int i;
-
- for (i=0; i<BPHYS_TOT_DATA; i++) {
- if (data_types & (1<<i))
- pm->data[i] = MEM_callocN(totpoint * ptcache_data_size[i], "PTCache Data");
- }
-}
-static void ptcache_data_free(PTCacheMem *pm)
-{
- void **data = pm->data;
- int i;
-
- for (i=0; i<BPHYS_TOT_DATA; i++) {
- if (data[i])
- MEM_freeN(data[i]);
- }
-}
-static void ptcache_data_copy(void *from[], void *to[])
-{
- int i;
- for (i=0; i<BPHYS_TOT_DATA; i++) {
- /* note, durian file 03.4b_comp crashes if to[i] is not tested
- * its NULL, not sure if this should be fixed elsewhere but for now its needed */
- if (from[i] && to[i])
- memcpy(to[i], from[i], ptcache_data_size[i]);
- }
-}
-
-static void ptcache_extra_free(PTCacheMem *pm)
-{
- PTCacheExtra *extra = pm->extradata.first;
-
- if (extra) {
- for (; extra; extra=extra->next) {
- if (extra->data)
- MEM_freeN(extra->data);
- }
-
- BLI_freelistN(&pm->extradata);
- }
-}
-static int ptcache_old_elemsize(PTCacheID *pid)
-{
- if (pid->type==PTCACHE_TYPE_SOFTBODY)
- return 6 * sizeof(float);
- else if (pid->type==PTCACHE_TYPE_PARTICLES)
- return sizeof(ParticleKey);
- else if (pid->type==PTCACHE_TYPE_CLOTH)
- return 9 * sizeof(float);
-
- return 0;
-}
-
-static void ptcache_find_frames_around(PTCacheID *pid, unsigned int frame, int *fra1, int *fra2)
-{
- if (pid->cache->flag & PTCACHE_DISK_CACHE) {
- int cfra1=frame, cfra2=frame+1;
-
- while (cfra1 >= pid->cache->startframe && !BKE_ptcache_id_exist(pid, cfra1))
- cfra1--;
-
- if (cfra1 < pid->cache->startframe)
- cfra1 = 0;
-
- while (cfra2 <= pid->cache->endframe && !BKE_ptcache_id_exist(pid, cfra2))
- cfra2++;
-
- if (cfra2 > pid->cache->endframe)
- cfra2 = 0;
-
- if (cfra1 && !cfra2) {
- *fra1 = 0;
- *fra2 = cfra1;
- }
- else {
- *fra1 = cfra1;
- *fra2 = cfra2;
- }
- }
- else if (pid->cache->mem_cache.first) {
- PTCacheMem *pm = pid->cache->mem_cache.first;
- PTCacheMem *pm2 = pid->cache->mem_cache.last;
-
- while (pm->next && pm->next->frame <= frame)
- pm= pm->next;
-
- if (pm2->frame < frame) {
- pm2 = NULL;
- }
- else {
- while (pm2->prev && pm2->prev->frame > frame) {
- pm2= pm2->prev;
- }
- }
-
- if (!pm2) {
- *fra1 = 0;
- *fra2 = pm->frame;
- }
- else {
- *fra1 = pm->frame;
- *fra2 = pm2->frame;
- }
- }
-}
-
-static PTCacheMem *ptcache_disk_frame_to_mem(PTCacheID *pid, int cfra)
-{
- PTCacheFile *pf = ptcache_file_open(pid, PTCACHE_FILE_READ, cfra);
- PTCacheMem *pm = NULL;
- unsigned int i, error = 0;
-
- if (pf == NULL)
- return NULL;
-
- if (!ptcache_file_header_begin_read(pf))
- error = 1;
-
- if (!error && (pf->type != pid->type || !pid->read_header(pf)))
- error = 1;
-
- if (!error) {
- pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem");
-
- pm->totpoint = pf->totpoint;
- pm->data_types = pf->data_types;
- pm->frame = pf->frame;
-
- ptcache_data_alloc(pm);
-
- if (pf->flag & PTCACHE_TYPEFLAG_COMPRESS) {
- for (i=0; i<BPHYS_TOT_DATA; i++) {
- unsigned int out_len = pm->totpoint*ptcache_data_size[i];
- if (pf->data_types & (1<<i))
- ptcache_file_compressed_read(pf, (unsigned char *)(pm->data[i]), out_len);
- }
- }
- else {
- BKE_ptcache_mem_pointers_init(pm);
- ptcache_file_pointers_init(pf);
-
- for (i=0; i<pm->totpoint; i++) {
- if (!ptcache_file_data_read(pf)) {
- error = 1;
- break;
- }
- ptcache_data_copy(pf->cur, pm->cur);
- BKE_ptcache_mem_pointers_incr(pm);
- }
- }
- }
-
- if (!error && pf->flag & PTCACHE_TYPEFLAG_EXTRADATA) {
- unsigned int extratype = 0;
-
- while (ptcache_file_read(pf, &extratype, 1, sizeof(unsigned int))) {
- PTCacheExtra *extra = MEM_callocN(sizeof(PTCacheExtra), "Pointcache extradata");
-
- extra->type = extratype;
-
- ptcache_file_read(pf, &extra->totdata, 1, sizeof(unsigned int));
-
- extra->data = MEM_callocN(extra->totdata * ptcache_extra_datasize[extra->type], "Pointcache extradata->data");
-
- if (pf->flag & PTCACHE_TYPEFLAG_COMPRESS)
- ptcache_file_compressed_read(pf, (unsigned char *)(extra->data), extra->totdata*ptcache_extra_datasize[extra->type]);
- else
- ptcache_file_read(pf, extra->data, extra->totdata, ptcache_extra_datasize[extra->type]);
-
- BLI_addtail(&pm->extradata, extra);
- }
- }
-
- if (error && pm) {
- ptcache_data_free(pm);
- ptcache_extra_free(pm);
- MEM_freeN(pm);
- pm = NULL;
- }
-
- ptcache_file_close(pf);
-
- if (error && G.debug & G_DEBUG)
- printf("Error reading from disk cache\n");
-
- return pm;
-}
-static int ptcache_mem_frame_to_disk(PTCacheID *pid, PTCacheMem *pm)
-{
- PTCacheFile *pf = NULL;
- unsigned int i, error = 0;
-
- BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, pm->frame);
-
- pf = ptcache_file_open(pid, PTCACHE_FILE_WRITE, pm->frame);
-
- if (pf==NULL) {
- if (G.debug & G_DEBUG)
- printf("Error opening disk cache file for writing\n");
- return 0;
- }
-
- pf->data_types = pm->data_types;
- pf->totpoint = pm->totpoint;
- pf->type = pid->type;
- pf->flag = 0;
-
- if (pm->extradata.first)
- pf->flag |= PTCACHE_TYPEFLAG_EXTRADATA;
-
- if (pid->cache->compression)
- pf->flag |= PTCACHE_TYPEFLAG_COMPRESS;
-
- if (!ptcache_file_header_begin_write(pf) || !pid->write_header(pf))
- error = 1;
-
- if (!error) {
- if (pid->cache->compression) {
- for (i=0; i<BPHYS_TOT_DATA; i++) {
- if (pm->data[i]) {
- unsigned int in_len = pm->totpoint*ptcache_data_size[i];
- unsigned char *out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len) * 4, "pointcache_lzo_buffer");
- ptcache_file_compressed_write(pf, (unsigned char *)(pm->data[i]), in_len, out, pid->cache->compression);
- MEM_freeN(out);
- }
- }
- }
- else {
- BKE_ptcache_mem_pointers_init(pm);
- ptcache_file_pointers_init(pf);
-
- for (i=0; i<pm->totpoint; i++) {
- ptcache_data_copy(pm->cur, pf->cur);
- if (!ptcache_file_data_write(pf)) {
- error = 1;
- break;
- }
- BKE_ptcache_mem_pointers_incr(pm);
- }
- }
- }
-
- if (!error && pm->extradata.first) {
- PTCacheExtra *extra = pm->extradata.first;
-
- for (; extra; extra=extra->next) {
- if (extra->data == NULL || extra->totdata == 0)
- continue;
-
- ptcache_file_write(pf, &extra->type, 1, sizeof(unsigned int));
- ptcache_file_write(pf, &extra->totdata, 1, sizeof(unsigned int));
-
- if (pid->cache->compression) {
- unsigned int in_len = extra->totdata * ptcache_extra_datasize[extra->type];
- unsigned char *out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len) * 4, "pointcache_lzo_buffer");
- ptcache_file_compressed_write(pf, (unsigned char *)(extra->data), in_len, out, pid->cache->compression);
- MEM_freeN(out);
- }
- else {
- ptcache_file_write(pf, extra->data, extra->totdata, ptcache_extra_datasize[extra->type]);
- }
- }
- }
-
- ptcache_file_close(pf);
-
- if (error && G.debug & G_DEBUG)
- printf("Error writing to disk cache\n");
-
- return error==0;
-}
-
-static int ptcache_read_stream(PTCacheID *pid, int cfra)
-{
- PTCacheFile *pf = ptcache_file_open(pid, PTCACHE_FILE_READ, cfra);
- int error = 0;
-
- if (pid->read_stream == NULL)
- return 0;
-
- if (pf == NULL) {
- if (G.debug & G_DEBUG)
- printf("Error opening disk cache file for reading\n");
- return 0;
- }
-
- if (!ptcache_file_header_begin_read(pf)) {
- pid->error(pid->calldata, "Failed to read point cache file");
- error = 1;
- }
- else if (pf->type != pid->type) {
- pid->error(pid->calldata, "Point cache file has wrong type");
- error = 1;
- }
- else if (!pid->read_header(pf)) {
- pid->error(pid->calldata, "Failed to read point cache file header");
- error = 1;
- }
- else if (pf->totpoint != pid->totpoint(pid->calldata, cfra)) {
- pid->error(pid->calldata, "Number of points in cache does not match mesh");
- error = 1;
- }
-
- if (!error) {
- ptcache_file_pointers_init(pf);
-
- // we have stream reading here
- if (!pid->read_stream(pf, pid->calldata)) {
- pid->error(pid->calldata, "Failed to read point cache file data");
- error = 1;
- }
- }
-
- ptcache_file_close(pf);
-
- return error == 0;
-}
-
-static int ptcache_read_openvdb_stream(PTCacheID *pid, int cfra)
-{
-#ifdef WITH_OPENVDB
- char filename[FILE_MAX * 2];
-
- /* save blend file before using disk pointcache */
- if (!G.relbase_valid && (pid->cache->flag & PTCACHE_EXTERNAL) == 0)
- return 0;
-
- ptcache_filename(pid, filename, cfra, 1, 1);
-
- if (!BLI_exists(filename)) {
- return 0;
- }
-
- struct OpenVDBReader *reader = OpenVDBReader_create();
- OpenVDBReader_open(reader, filename);
-
- if (!pid->read_openvdb_stream(reader, pid->calldata)) {
- return 0;
- }
-
- return 1;
-#else
- UNUSED_VARS(pid, cfra);
- return 0;
-#endif
-}
-
-static int ptcache_read(PTCacheID *pid, int cfra)
-{
- PTCacheMem *pm = NULL;
- int i;
- int *index = &i;
-
- /* get a memory cache to read from */
- if (pid->cache->flag & PTCACHE_DISK_CACHE) {
- pm = ptcache_disk_frame_to_mem(pid, cfra);
- }
- else {
- pm = pid->cache->mem_cache.first;
-
- while (pm && pm->frame != cfra)
- pm = pm->next;
- }
-
- /* read the cache */
- if (pm) {
- int totpoint = pm->totpoint;
-
- if ((pid->data_types & (1<<BPHYS_DATA_INDEX)) == 0) {
- int pid_totpoint = pid->totpoint(pid->calldata, cfra);
-
- if (totpoint != pid_totpoint) {
- pid->error(pid->calldata, "Number of points in cache does not match mesh");
- totpoint = MIN2(totpoint, pid_totpoint);
- }
- }
-
- BKE_ptcache_mem_pointers_init(pm);
-
- for (i=0; i<totpoint; i++) {
- if (pm->data_types & (1<<BPHYS_DATA_INDEX))
- index = pm->cur[BPHYS_DATA_INDEX];
-
- pid->read_point(*index, pid->calldata, pm->cur, (float)pm->frame, NULL);
-
- BKE_ptcache_mem_pointers_incr(pm);
- }
-
- if (pid->read_extra_data && pm->extradata.first)
- pid->read_extra_data(pid->calldata, pm, (float)pm->frame);
-
- /* clean up temporary memory cache */
- if (pid->cache->flag & PTCACHE_DISK_CACHE) {
- ptcache_data_free(pm);
- ptcache_extra_free(pm);
- MEM_freeN(pm);
- }
- }
-
- return 1;
-}
-static int ptcache_interpolate(PTCacheID *pid, float cfra, int cfra1, int cfra2)
-{
- PTCacheMem *pm = NULL;
- int i;
- int *index = &i;
-
- /* get a memory cache to read from */
- if (pid->cache->flag & PTCACHE_DISK_CACHE) {
- pm = ptcache_disk_frame_to_mem(pid, cfra2);
- }
- else {
- pm = pid->cache->mem_cache.first;
-
- while (pm && pm->frame != cfra2)
- pm = pm->next;
- }
-
- /* read the cache */
- if (pm) {
- int totpoint = pm->totpoint;
-
- if ((pid->data_types & (1<<BPHYS_DATA_INDEX)) == 0) {
- int pid_totpoint = pid->totpoint(pid->calldata, (int)cfra);
-
- if (totpoint != pid_totpoint) {
- pid->error(pid->calldata, "Number of points in cache does not match mesh");
- totpoint = MIN2(totpoint, pid_totpoint);
- }
- }
-
- BKE_ptcache_mem_pointers_init(pm);
-
- for (i=0; i<totpoint; i++) {
- if (pm->data_types & (1<<BPHYS_DATA_INDEX))
- index = pm->cur[BPHYS_DATA_INDEX];
-
- pid->interpolate_point(*index, pid->calldata, pm->cur, cfra, (float)cfra1, (float)cfra2, NULL);
- BKE_ptcache_mem_pointers_incr(pm);
- }
-
- if (pid->interpolate_extra_data && pm->extradata.first)
- pid->interpolate_extra_data(pid->calldata, pm, cfra, (float)cfra1, (float)cfra2);
-
- /* clean up temporary memory cache */
- if (pid->cache->flag & PTCACHE_DISK_CACHE) {
- ptcache_data_free(pm);
- ptcache_extra_free(pm);
- MEM_freeN(pm);
- }
- }
-
- return 1;
-}
-/* reads cache from disk or memory */
-/* possible to get old or interpolated result */
-int BKE_ptcache_read(PTCacheID *pid, float cfra, bool no_extrapolate_old)
-{
- int cfrai = (int)floor(cfra), cfra1=0, cfra2=0;
- int ret = 0;
-
- /* nothing to read to */
- if (pid->totpoint(pid->calldata, cfrai) == 0)
- return 0;
-
- if (pid->cache->flag & PTCACHE_READ_INFO) {
- pid->cache->flag &= ~PTCACHE_READ_INFO;
- ptcache_read(pid, 0);
- }
-
- /* first check if we have the actual frame cached */
- if (cfra == (float)cfrai && BKE_ptcache_id_exist(pid, cfrai))
- cfra1 = cfrai;
-
- /* no exact cache frame found so try to find cached frames around cfra */
- if (cfra1 == 0)
- ptcache_find_frames_around(pid, cfrai, &cfra1, &cfra2);
-
- if (cfra1 == 0 && cfra2 == 0)
- return 0;
-
- /* don't read old cache if already simulated past cached frame */
- if (no_extrapolate_old) {
- if (cfra1 == 0 && cfra2 && cfra2 <= pid->cache->simframe)
- return 0;
- if (cfra1 && cfra1 == cfra2)
- return 0;
- }
- else {
- /* avoid calling interpolate between the same frame values */
- if (cfra1 && cfra1 == cfra2)
- cfra1 = 0;
- }
-
- if (cfra1) {
- if (pid->file_type == PTCACHE_FILE_OPENVDB && pid->read_openvdb_stream) {
- if (!ptcache_read_openvdb_stream(pid, cfra1)) {
- return 0;
- }
- }
- else if (pid->read_stream) {
- if (!ptcache_read_stream(pid, cfra1))
- return 0;
- }
- else if (pid->read_point)
- ptcache_read(pid, cfra1);
- }
-
- if (cfra2) {
- if (pid->file_type == PTCACHE_FILE_OPENVDB && pid->read_openvdb_stream) {
- if (!ptcache_read_openvdb_stream(pid, cfra2)) {
- return 0;
- }
- }
- else if (pid->read_stream) {
- if (!ptcache_read_stream(pid, cfra2))
- return 0;
- }
- else if (pid->read_point) {
- if (cfra1 && cfra2 && pid->interpolate_point)
- ptcache_interpolate(pid, cfra, cfra1, cfra2);
- else
- ptcache_read(pid, cfra2);
- }
- }
-
- if (cfra1)
- ret = (cfra2 ? PTCACHE_READ_INTERPOLATED : PTCACHE_READ_EXACT);
- else if (cfra2) {
- ret = PTCACHE_READ_OLD;
- pid->cache->simframe = cfra2;
- }
-
- cfrai = (int)cfra;
- /* clear invalid cache frames so that better stuff can be simulated */
- if (pid->cache->flag & PTCACHE_OUTDATED) {
- BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, cfrai);
- }
- else if (pid->cache->flag & PTCACHE_FRAMES_SKIPPED) {
- if (cfra <= pid->cache->last_exact)
- pid->cache->flag &= ~PTCACHE_FRAMES_SKIPPED;
-
- BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, MAX2(cfrai, pid->cache->last_exact));
- }
-
- return ret;
-}
-static int ptcache_write_stream(PTCacheID *pid, int cfra, int totpoint)
-{
- PTCacheFile *pf = NULL;
- int error = 0;
-
- BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, cfra);
-
- pf = ptcache_file_open(pid, PTCACHE_FILE_WRITE, cfra);
-
- if (pf==NULL) {
- if (G.debug & G_DEBUG)
- printf("Error opening disk cache file for writing\n");
- return 0;
- }
-
- pf->data_types = pid->data_types;
- pf->totpoint = totpoint;
- pf->type = pid->type;
- pf->flag = 0;
-
- if (!error && (!ptcache_file_header_begin_write(pf) || !pid->write_header(pf)))
- error = 1;
-
- if (!error && pid->write_stream)
- pid->write_stream(pf, pid->calldata);
-
- ptcache_file_close(pf);
-
- if (error && G.debug & G_DEBUG)
- printf("Error writing to disk cache\n");
-
- return error == 0;
-}
-static int ptcache_write_openvdb_stream(PTCacheID *pid, int cfra)
-{
-#ifdef WITH_OPENVDB
- struct OpenVDBWriter *writer = OpenVDBWriter_create();
- char filename[FILE_MAX * 2];
-
- BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, cfra);
-
- ptcache_filename(pid, filename, cfra, 1, 1);
- BLI_make_existing_file(filename);
-
- int error = pid->write_openvdb_stream(writer, pid->calldata);
-
- OpenVDBWriter_write(writer, filename);
- OpenVDBWriter_free(writer);
-
- return error == 0;
-#else
- UNUSED_VARS(pid, cfra);
- return 0;
-#endif
-}
-static int ptcache_write(PTCacheID *pid, int cfra, int overwrite)
-{
- PointCache *cache = pid->cache;
- PTCacheMem *pm=NULL, *pm2=NULL;
- int totpoint = pid->totpoint(pid->calldata, cfra);
- int i, error = 0;
-
- pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem");
-
- pm->totpoint = pid->totwrite(pid->calldata, cfra);
- pm->data_types = cfra ? pid->data_types : pid->info_types;
-
- ptcache_data_alloc(pm);
- BKE_ptcache_mem_pointers_init(pm);
-
- if (overwrite) {
- if (cache->flag & PTCACHE_DISK_CACHE) {
- int fra = cfra-1;
-
- while (fra >= cache->startframe && !BKE_ptcache_id_exist(pid, fra))
- fra--;
-
- pm2 = ptcache_disk_frame_to_mem(pid, fra);
- }
- else
- pm2 = cache->mem_cache.last;
- }
-
- if (pid->write_point) {
- for (i=0; i<totpoint; i++) {
- int write = pid->write_point(i, pid->calldata, pm->cur, cfra);
- if (write) {
- BKE_ptcache_mem_pointers_incr(pm);
-
- /* newly born particles have to be copied to previous cached frame */
- if (overwrite && write == 2 && pm2 && BKE_ptcache_mem_pointers_seek(i, pm2))
- pid->write_point(i, pid->calldata, pm2->cur, cfra);
- }
- }
- }
-
- if (pid->write_extra_data)
- pid->write_extra_data(pid->calldata, pm, cfra);
-
- pm->frame = cfra;
-
- if (cache->flag & PTCACHE_DISK_CACHE) {
- error += !ptcache_mem_frame_to_disk(pid, pm);
-
- // if (pm) /* pm is always set */
- {
- ptcache_data_free(pm);
- ptcache_extra_free(pm);
- MEM_freeN(pm);
- }
-
- if (pm2) {
- error += !ptcache_mem_frame_to_disk(pid, pm2);
- ptcache_data_free(pm2);
- ptcache_extra_free(pm2);
- MEM_freeN(pm2);
- }
- }
- else {
- BLI_addtail(&cache->mem_cache, pm);
- }
-
- return error;
-}
-static int ptcache_write_needed(PTCacheID *pid, int cfra, int *overwrite)
-{
- PointCache *cache = pid->cache;
- int ofra = 0, efra = cache->endframe;
-
- /* always start from scratch on the first frame */
- if (cfra && cfra == cache->startframe) {
- BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, cfra);
- cache->flag &= ~PTCACHE_REDO_NEEDED;
- return 1;
- }
-
- if (pid->cache->flag & PTCACHE_DISK_CACHE) {
- if (cfra==0 && cache->startframe > 0)
- return 1;
-
- /* find last cached frame */
- while (efra > cache->startframe && !BKE_ptcache_id_exist(pid, efra))
- efra--;
-
- /* find second last cached frame */
- ofra = efra-1;
- while (ofra > cache->startframe && !BKE_ptcache_id_exist(pid, ofra))
- ofra--;
- }
- else {
- PTCacheMem *pm = cache->mem_cache.last;
- /* don't write info file in memory */
- if (cfra == 0)
- return 0;
-
- if (pm == NULL)
- return 1;
-
- efra = pm->frame;
- ofra = (pm->prev ? pm->prev->frame : efra - cache->step);
- }
-
- if (efra >= cache->startframe && cfra > efra) {
- if (ofra >= cache->startframe && efra - ofra < cache->step) {
- /* overwrite previous frame */
- BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, efra);
- *overwrite = 1;
- }
- return 1;
- }
-
- return 0;
-}
-/* writes cache to disk or memory */
-int BKE_ptcache_write(PTCacheID *pid, unsigned int cfra)
-{
- PointCache *cache = pid->cache;
- int totpoint = pid->totpoint(pid->calldata, cfra);
- int overwrite = 0, error = 0;
-
- if (totpoint == 0 || (cfra ? pid->data_types == 0 : pid->info_types == 0))
- return 0;
-
- if (ptcache_write_needed(pid, cfra, &overwrite)==0)
- return 0;
-
- if (pid->file_type == PTCACHE_FILE_OPENVDB && pid->write_openvdb_stream) {
- ptcache_write_openvdb_stream(pid, cfra);
- }
- else if (pid->write_stream) {
- ptcache_write_stream(pid, cfra, totpoint);
- }
- else if (pid->write_point) {
- error += ptcache_write(pid, cfra, overwrite);
- }
-
- /* Mark frames skipped if more than 1 frame forwards since last non-skipped frame. */
- if (cfra - cache->last_exact == 1 || cfra == cache->startframe) {
- cache->last_exact = cfra;
- cache->flag &= ~PTCACHE_FRAMES_SKIPPED;
- }
- /* Don't mark skipped when writing info file (frame 0) */
- else if (cfra)
- cache->flag |= PTCACHE_FRAMES_SKIPPED;
-
- /* Update timeline cache display */
- if (cfra && cache->cached_frames)
- cache->cached_frames[cfra-cache->startframe] = 1;
-
- BKE_ptcache_update_info(pid);
-
- return !error;
-}
-/* youll need to close yourself after!
- * mode - PTCACHE_CLEAR_ALL,
- */
-
-/* Clears & resets */
-void BKE_ptcache_id_clear(PTCacheID *pid, int mode, unsigned int cfra)
-{
- unsigned int len; /* store the length of the string */
- unsigned int sta, end;
-
- /* mode is same as fopen's modes */
- DIR *dir;
- struct dirent *de;
- char path[MAX_PTCACHE_PATH];
- char filename[MAX_PTCACHE_FILE];
- char path_full[MAX_PTCACHE_FILE];
- char ext[MAX_PTCACHE_PATH];
-
- if (!pid || !pid->cache || pid->cache->flag & PTCACHE_BAKED)
- return;
-
- if (pid->cache->flag & PTCACHE_IGNORE_CLEAR)
- return;
-
- sta = pid->cache->startframe;
- end = pid->cache->endframe;
-
-#ifndef DURIAN_POINTCACHE_LIB_OK
- /* don't allow clearing for linked objects */
- if (pid->ob->id.lib)
- return;
-#endif
-
- /*if (!G.relbase_valid) return; *//* save blend file before using pointcache */
-
- const char *fext = ptcache_file_extension(pid);
-
- /* clear all files in the temp dir with the prefix of the ID and the ".bphys" suffix */
- switch (mode) {
- case PTCACHE_CLEAR_ALL:
- case PTCACHE_CLEAR_BEFORE:
- case PTCACHE_CLEAR_AFTER:
- if (pid->cache->flag & PTCACHE_DISK_CACHE) {
- ptcache_path(pid, path);
-
- dir = opendir(path);
- if (dir==NULL)
- return;
-
- len = ptcache_filename(pid, filename, cfra, 0, 0); /* no path */
- /* append underscore terminator to ensure we don't match similar names
- * from objects whose names start with the same prefix
- */
- if (len < sizeof(filename) - 2) {
- BLI_strncpy(filename + len, "_", sizeof(filename) - 2 - len);
- len += 1;
- }
-
- BLI_snprintf(ext, sizeof(ext), "_%02u%s", pid->stack_index, fext);
-
- while ((de = readdir(dir)) != NULL) {
- if (strstr(de->d_name, ext)) { /* do we have the right extension?*/
- if (STREQLEN(filename, de->d_name, len)) { /* do we have the right prefix */
- if (mode == PTCACHE_CLEAR_ALL) {
- pid->cache->last_exact = MIN2(pid->cache->startframe, 0);
- BLI_join_dirfile(path_full, sizeof(path_full), path, de->d_name);
- BLI_delete(path_full, false, false);
- }
- else {
- /* read the number of the file */
- const int frame = ptcache_frame_from_filename(de->d_name, ext);
-
- if (frame != -1) {
- if ((mode == PTCACHE_CLEAR_BEFORE && frame < cfra) ||
- (mode == PTCACHE_CLEAR_AFTER && frame > cfra))
- {
-
- BLI_join_dirfile(path_full, sizeof(path_full), path, de->d_name);
- BLI_delete(path_full, false, false);
- if (pid->cache->cached_frames && frame >=sta && frame <= end)
- pid->cache->cached_frames[frame-sta] = 0;
- }
- }
- }
- }
- }
- }
- closedir(dir);
-
- if (mode == PTCACHE_CLEAR_ALL && pid->cache->cached_frames)
- memset(pid->cache->cached_frames, 0, MEM_allocN_len(pid->cache->cached_frames));
- }
- else {
- PTCacheMem *pm= pid->cache->mem_cache.first;
- PTCacheMem *link= NULL;
-
- if (mode == PTCACHE_CLEAR_ALL) {
- /*we want startframe if the cache starts before zero*/
- pid->cache->last_exact = MIN2(pid->cache->startframe, 0);
- for (; pm; pm=pm->next) {
- ptcache_data_free(pm);
- ptcache_extra_free(pm);
- }
- BLI_freelistN(&pid->cache->mem_cache);
-
- if (pid->cache->cached_frames)
- memset(pid->cache->cached_frames, 0, MEM_allocN_len(pid->cache->cached_frames));
- }
- else {
- while (pm) {
- if ((mode == PTCACHE_CLEAR_BEFORE && pm->frame < cfra) ||
- (mode == PTCACHE_CLEAR_AFTER && pm->frame > cfra))
- {
- link = pm;
- if (pid->cache->cached_frames && pm->frame >=sta && pm->frame <= end)
- pid->cache->cached_frames[pm->frame-sta] = 0;
- ptcache_data_free(pm);
- ptcache_extra_free(pm);
- pm = pm->next;
- BLI_freelinkN(&pid->cache->mem_cache, link);
- }
- else
- pm = pm->next;
- }
- }
- }
- break;
-
- case PTCACHE_CLEAR_FRAME:
- if (pid->cache->flag & PTCACHE_DISK_CACHE) {
- if (BKE_ptcache_id_exist(pid, cfra)) {
- ptcache_filename(pid, filename, cfra, 1, 1); /* no path */
- BLI_delete(filename, false, false);
- }
- }
- else {
- PTCacheMem *pm = pid->cache->mem_cache.first;
-
- for (; pm; pm=pm->next) {
- if (pm->frame == cfra) {
- ptcache_data_free(pm);
- ptcache_extra_free(pm);
- BLI_freelinkN(&pid->cache->mem_cache, pm);
- break;
- }
- }
- }
- if (pid->cache->cached_frames && cfra >= sta && cfra <= end)
- pid->cache->cached_frames[cfra-sta] = 0;
- break;
- }
-
- BKE_ptcache_update_info(pid);
-}
-int BKE_ptcache_id_exist(PTCacheID *pid, int cfra)
-{
- if (!pid->cache)
- return 0;
-
- if (cfra<pid->cache->startframe || cfra > pid->cache->endframe)
- return 0;
-
- if (pid->cache->cached_frames && pid->cache->cached_frames[cfra-pid->cache->startframe]==0)
- return 0;
-
- if (pid->cache->flag & PTCACHE_DISK_CACHE) {
- char filename[MAX_PTCACHE_FILE];
-
- ptcache_filename(pid, filename, cfra, 1, 1);
-
- return BLI_exists(filename);
- }
- else {
- PTCacheMem *pm = pid->cache->mem_cache.first;
-
- for (; pm; pm=pm->next) {
- if (pm->frame==cfra)
- return 1;
- }
- return 0;
- }
-}
-void BKE_ptcache_id_time(PTCacheID *pid, Scene *scene, float cfra, int *startframe, int *endframe, float *timescale)
-{
- /* Object *ob; */ /* UNUSED */
- PointCache *cache;
- /* float offset; unused for now */
- float time, nexttime;
-
- /* TODO: this has to be sorted out once bsystem_time gets redone, */
- /* now caches can handle interpolating etc. too - jahka */
-
- /* time handling for point cache:
- * - simulation time is scaled by result of bsystem_time
- * - for offsetting time only time offset is taken into account, since
- * that's always the same and can't be animated. a timeoffset which
- * varies over time is not simple to support.
- * - field and motion blur offsets are currently ignored, proper solution
- * is probably to interpolate results from two frames for that ..
- */
-
- /* ob= pid->ob; */ /* UNUSED */
- cache= pid->cache;
-
- if (timescale) {
- time= BKE_scene_frame_get(scene);
- nexttime = BKE_scene_frame_get_from_ctime(scene, CFRA + 1.0f);
-
- *timescale= MAX2(nexttime - time, 0.0f);
- }
-
- if (startframe && endframe) {
- *startframe= cache->startframe;
- *endframe= cache->endframe;
-
- /* TODO: time handling with object offsets and simulated vs. cached
- * particles isn't particularly easy, so for now what you see is what
- * you get. In the future point cache could handle the whole particle
- * system timing. */
-#if 0
- if ((ob->partype & PARSLOW)==0) {
- offset= ob->sf;
-
- *startframe += (int)(offset+0.5f);
- *endframe += (int)(offset+0.5f);
- }
-#endif
- }
-
- /* verify cached_frames array is up to date */
- if (cache->cached_frames) {
- if (MEM_allocN_len(cache->cached_frames) != sizeof(char) * (cache->endframe-cache->startframe+1)) {
- MEM_freeN(cache->cached_frames);
- cache->cached_frames = NULL;
- }
- }
-
- if (cache->cached_frames==NULL && cache->endframe > cache->startframe) {
- unsigned int sta=cache->startframe;
- unsigned int end=cache->endframe;
-
- cache->cached_frames = MEM_callocN(sizeof(char) * (cache->endframe-cache->startframe+1), "cached frames array");
-
- if (pid->cache->flag & PTCACHE_DISK_CACHE) {
- /* mode is same as fopen's modes */
- DIR *dir;
- struct dirent *de;
- char path[MAX_PTCACHE_PATH];
- char filename[MAX_PTCACHE_FILE];
- char ext[MAX_PTCACHE_PATH];
- unsigned int len; /* store the length of the string */
-
- ptcache_path(pid, path);
-
- len = ptcache_filename(pid, filename, (int)cfra, 0, 0); /* no path */
-
- dir = opendir(path);
- if (dir==NULL)
- return;
-
- const char *fext = ptcache_file_extension(pid);
-
- BLI_snprintf(ext, sizeof(ext), "_%02u%s", pid->stack_index, fext);
-
- while ((de = readdir(dir)) != NULL) {
- if (strstr(de->d_name, ext)) { /* do we have the right extension?*/
- if (STREQLEN(filename, de->d_name, len)) { /* do we have the right prefix */
- /* read the number of the file */
- const int frame = ptcache_frame_from_filename(de->d_name, ext);
-
- if ((frame != -1) && (frame >= sta && frame <= end)) {
- cache->cached_frames[frame-sta] = 1;
- }
- }
- }
- }
- closedir(dir);
- }
- else {
- PTCacheMem *pm= pid->cache->mem_cache.first;
-
- while (pm) {
- if (pm->frame >= sta && pm->frame <= end)
- cache->cached_frames[pm->frame-sta] = 1;
- pm = pm->next;
- }
- }
- }
-}
-int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode)
-{
- PointCache *cache;
- int reset, clear, after;
-
- if (!pid->cache)
- return 0;
-
- cache= pid->cache;
- reset= 0;
- clear= 0;
- after= 0;
-
- if (mode == PTCACHE_RESET_DEPSGRAPH) {
- if (!(cache->flag & PTCACHE_BAKED)) {
-
- after= 1;
- }
-
- cache->flag |= PTCACHE_OUTDATED;
- }
- else if (mode == PTCACHE_RESET_BAKED) {
- cache->flag |= PTCACHE_OUTDATED;
- }
- else if (mode == PTCACHE_RESET_OUTDATED) {
- reset = 1;
-
- if (cache->flag & PTCACHE_OUTDATED && !(cache->flag & PTCACHE_BAKED)) {
- clear= 1;
- cache->flag &= ~PTCACHE_OUTDATED;
- }
- }
-
- if (reset) {
- BKE_ptcache_invalidate(cache);
- cache->flag &= ~PTCACHE_REDO_NEEDED;
-
- if (pid->type == PTCACHE_TYPE_CLOTH)
- cloth_free_modifier(pid->calldata);
- else if (pid->type == PTCACHE_TYPE_SOFTBODY)
- sbFreeSimulation(pid->calldata);
- else if (pid->type == PTCACHE_TYPE_PARTICLES)
- psys_reset(pid->calldata, PSYS_RESET_DEPSGRAPH);
-#if 0
- else if (pid->type == PTCACHE_TYPE_SMOKE_DOMAIN)
- smokeModifier_reset(pid->calldata);
- else if (pid->type == PTCACHE_TYPE_SMOKE_HIGHRES)
- smokeModifier_reset_turbulence(pid->calldata);
-#endif
- else if (pid->type == PTCACHE_TYPE_DYNAMICPAINT)
- dynamicPaint_clearSurface(scene, (DynamicPaintSurface*)pid->calldata);
- }
- if (clear)
- BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
- else if (after)
- BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, CFRA);
-
- return (reset || clear || after);
-}
-int BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode)
-{
- PTCacheID pid;
- ParticleSystem *psys;
- ModifierData *md;
- int reset, skip;
-
- reset= 0;
- skip= 0;
-
- if (ob->soft) {
- BKE_ptcache_id_from_softbody(&pid, ob, ob->soft);
- reset |= BKE_ptcache_id_reset(scene, &pid, mode);
- }
-
- for (psys=ob->particlesystem.first; psys; psys=psys->next) {
- /* children or just redo can be calculated without resetting anything */
- if (psys->recalc & PSYS_RECALC_REDO || psys->recalc & PSYS_RECALC_CHILD)
- skip = 1;
- /* Baked cloth hair has to be checked too, because we don't want to reset */
- /* particles or cloth in that case -jahka */
- else if (psys->clmd) {
- BKE_ptcache_id_from_cloth(&pid, ob, psys->clmd);
- if (mode == PSYS_RESET_ALL || !(psys->part->type == PART_HAIR && (pid.cache->flag & PTCACHE_BAKED)))
- reset |= BKE_ptcache_id_reset(scene, &pid, mode);
- else
- skip = 1;
- }
-
- if (skip == 0 && psys->part) {
- BKE_ptcache_id_from_particles(&pid, ob, psys);
- reset |= BKE_ptcache_id_reset(scene, &pid, mode);
- }
- }
-
- for (md=ob->modifiers.first; md; md=md->next) {
- if (md->type == eModifierType_Cloth) {
- BKE_ptcache_id_from_cloth(&pid, ob, (ClothModifierData*)md);
- reset |= BKE_ptcache_id_reset(scene, &pid, mode);
- }
- if (md->type == eModifierType_Smoke) {
- SmokeModifierData *smd = (SmokeModifierData *)md;
- if (smd->type & MOD_SMOKE_TYPE_DOMAIN) {
- BKE_ptcache_id_from_smoke(&pid, ob, (SmokeModifierData*)md);
- reset |= BKE_ptcache_id_reset(scene, &pid, mode);
- }
- }
- if (md->type == eModifierType_DynamicPaint) {
- DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md;
- if (pmd->canvas) {
- DynamicPaintSurface *surface = pmd->canvas->surfaces.first;
-
- for (; surface; surface=surface->next) {
- BKE_ptcache_id_from_dynamicpaint(&pid, ob, surface);
- reset |= BKE_ptcache_id_reset(scene, &pid, mode);
- }
- }
- }
- }
-
- if (scene->rigidbody_world && (ob->rigidbody_object || ob->rigidbody_constraint)) {
- if (ob->rigidbody_object)
- ob->rigidbody_object->flag |= RBO_FLAG_NEEDS_RESHAPE;
- BKE_ptcache_id_from_rigidbody(&pid, ob, scene->rigidbody_world);
- /* only flag as outdated, resetting should happen on start frame */
- pid.cache->flag |= PTCACHE_OUTDATED;
- }
-
- if (ob->type == OB_ARMATURE)
- BIK_clear_cache(ob->pose);
-
- return reset;
-}
-
-/* Use this when quitting blender, with unsaved files */
-void BKE_ptcache_remove(void)
-{
- char path[MAX_PTCACHE_PATH];
- char path_full[MAX_PTCACHE_PATH];
- int rmdir = 1;
-
- ptcache_path(NULL, path);
-
- if (BLI_exists(path)) {
- /* The pointcache dir exists? - remove all pointcache */
-
- DIR *dir;
- struct dirent *de;
-
- dir = opendir(path);
- if (dir==NULL)
- return;
-
- while ((de = readdir(dir)) != NULL) {
- if (FILENAME_IS_CURRPAR(de->d_name)) {
- /* do nothing */
- }
- else if (strstr(de->d_name, PTCACHE_EXT)) { /* do we have the right extension?*/
- BLI_join_dirfile(path_full, sizeof(path_full), path, de->d_name);
- BLI_delete(path_full, false, false);
- }
- else {
- rmdir = 0; /* unknown file, don't remove the dir */
- }
- }
-
- closedir(dir);
- }
- else {
- rmdir = 0; /* path dosnt exist */
- }
-
- if (rmdir) {
- BLI_delete(path, true, false);
- }
-}
-
-/* Point Cache handling */
-
-PointCache *BKE_ptcache_add(ListBase *ptcaches)
-{
- PointCache *cache;
-
- cache= MEM_callocN(sizeof(PointCache), "PointCache");
- cache->startframe= 1;
- cache->endframe= 250;
- cache->step = 1;
- cache->index = -1;
-
- BLI_addtail(ptcaches, cache);
-
- return cache;
-}
-
-void BKE_ptcache_free_mem(ListBase *mem_cache)
-{
- PTCacheMem *pm = mem_cache->first;
-
- if (pm) {
- for (; pm; pm=pm->next) {
- ptcache_data_free(pm);
- ptcache_extra_free(pm);
- }
-
- BLI_freelistN(mem_cache);
- }
-}
-void BKE_ptcache_free(PointCache *cache)
-{
- BKE_ptcache_free_mem(&cache->mem_cache);
- if (cache->edit && cache->free_edit)
- cache->free_edit(cache->edit);
- if (cache->cached_frames)
- MEM_freeN(cache->cached_frames);
- MEM_freeN(cache);
-}
-void BKE_ptcache_free_list(ListBase *ptcaches)
-{
- PointCache *cache;
-
- while ((cache = BLI_pophead(ptcaches))) {
- BKE_ptcache_free(cache);
- }
-}
-
-static PointCache *ptcache_copy(PointCache *cache, bool copy_data)
-{
- PointCache *ncache;
-
- ncache= MEM_dupallocN(cache);
-
- BLI_listbase_clear(&ncache->mem_cache);
-
- if (copy_data == false) {
- ncache->cached_frames = NULL;
-
- /* flag is a mix of user settings and simulator/baking state */
- ncache->flag= ncache->flag & (PTCACHE_DISK_CACHE|PTCACHE_EXTERNAL|PTCACHE_IGNORE_LIBPATH);
- ncache->simframe= 0;
- }
- else {
- PTCacheMem *pm;
-
- for (pm = cache->mem_cache.first; pm; pm = pm->next) {
- PTCacheMem *pmn = MEM_dupallocN(pm);
- int i;
-
- for (i = 0; i < BPHYS_TOT_DATA; i++) {
- if (pmn->data[i])
- pmn->data[i] = MEM_dupallocN(pm->data[i]);
- }
-
- BKE_ptcache_mem_pointers_init(pm);
-
- BLI_addtail(&ncache->mem_cache, pmn);
- }
-
- if (ncache->cached_frames)
- ncache->cached_frames = MEM_dupallocN(cache->cached_frames);
- }
-
- /* hmm, should these be copied over instead? */
- ncache->edit = NULL;
-
- return ncache;
-}
-
-/* returns first point cache */
-PointCache *BKE_ptcache_copy_list(ListBase *ptcaches_new, const ListBase *ptcaches_old, bool copy_data)
-{
- PointCache *cache = ptcaches_old->first;
-
- BLI_listbase_clear(ptcaches_new);
-
- for (; cache; cache=cache->next)
- BLI_addtail(ptcaches_new, ptcache_copy(cache, copy_data));
-
- return ptcaches_new->first;
-}
-
-/* Disabled this code; this is being called on scene_update_tagged, and that in turn gets called on
- * every user action changing stuff, and then it runs a complete bake??? (ton) */
-
-/* Baking */
-void BKE_ptcache_quick_cache_all(Main *bmain, Scene *scene)
-{
- PTCacheBaker baker;
-
- memset(&baker, 0, sizeof(baker));
- baker.main = bmain;
- baker.scene = scene;
- baker.bake = 0;
- baker.render = 0;
- baker.anim_init = 0;
- baker.quick_step = scene->physics_settings.quick_cache_step;
-
- BKE_ptcache_bake(&baker);
-}
-
-static void ptcache_dt_to_str(char *str, double dtime)
-{
- if (dtime > 60.0) {
- if (dtime > 3600.0)
- sprintf(str, "%ih %im %is", (int)(dtime/3600), ((int)(dtime/60))%60, ((int)dtime) % 60);
- else
- sprintf(str, "%im %is", ((int)(dtime/60))%60, ((int)dtime) % 60);
- }
- else
- sprintf(str, "%is", ((int)dtime) % 60);
-}
-
-/* if bake is not given run simulations to current frame */
-void BKE_ptcache_bake(PTCacheBaker *baker)
-{
- Main *bmain = baker->main;
- Scene *scene = baker->scene;
- Scene *sce_iter; /* SETLOOPER macro only */
- Base *base;
- ListBase pidlist;
- PTCacheID *pid = &baker->pid;
- PointCache *cache = NULL;
- float frameleno = scene->r.framelen;
- int cfrao = CFRA;
- int startframe = MAXFRAME, endframe = baker->anim_init ? scene->r.sfra : CFRA;
- int bake = baker->bake;
- int render = baker->render;
-
- G.is_break = false;
-
- /* set caches to baking mode and figure out start frame */
- if (pid->ob) {
- /* cache/bake a single object */
- cache = pid->cache;
- if ((cache->flag & PTCACHE_BAKED)==0) {
- if (pid->type==PTCACHE_TYPE_PARTICLES) {
- ParticleSystem *psys= pid->calldata;
-
- /* a bit confusing, could make this work better in the UI */
- if (psys->part->type == PART_EMITTER)
- psys_get_pointcache_start_end(scene, pid->calldata, &cache->startframe, &cache->endframe);
- }
- else if (pid->type == PTCACHE_TYPE_SMOKE_HIGHRES) {
- /* get all pids from the object and search for smoke low res */
- ListBase pidlist2;
- PTCacheID *pid2;
- BKE_ptcache_ids_from_object(&pidlist2, pid->ob, scene, MAX_DUPLI_RECUR);
- for (pid2=pidlist2.first; pid2; pid2=pid2->next) {
- if (pid2->type == PTCACHE_TYPE_SMOKE_DOMAIN) {
- if (pid2->cache && !(pid2->cache->flag & PTCACHE_BAKED)) {
- if (bake || pid2->cache->flag & PTCACHE_REDO_NEEDED)
- BKE_ptcache_id_clear(pid2, PTCACHE_CLEAR_ALL, 0);
- if (bake) {
- pid2->cache->flag |= PTCACHE_BAKING;
- pid2->cache->flag &= ~PTCACHE_BAKED;
- }
- }
- }
- }
- BLI_freelistN(&pidlist2);
- }
-
- if (bake || cache->flag & PTCACHE_REDO_NEEDED)
- BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
-
- startframe = MAX2(cache->last_exact, cache->startframe);
-
- if (bake) {
- endframe = cache->endframe;
- cache->flag |= PTCACHE_BAKING;
- }
- else {
- endframe = MIN2(endframe, cache->endframe);
- }
-
- cache->flag &= ~PTCACHE_BAKED;
- }
- }
- else {
- for (SETLOOPER(scene, sce_iter, base)) {
- /* cache/bake everything in the scene */
- BKE_ptcache_ids_from_object(&pidlist, base->object, scene, MAX_DUPLI_RECUR);
-
- for (pid=pidlist.first; pid; pid=pid->next) {
- cache = pid->cache;
- if ((cache->flag & PTCACHE_BAKED)==0) {
- if (pid->type==PTCACHE_TYPE_PARTICLES) {
- ParticleSystem *psys = (ParticleSystem*)pid->calldata;
- /* skip hair & keyed particles */
- if (psys->part->type == PART_HAIR || psys->part->phystype == PART_PHYS_KEYED)
- continue;
-
- psys_get_pointcache_start_end(scene, pid->calldata, &cache->startframe, &cache->endframe);
- }
-
- if ((cache->flag & PTCACHE_REDO_NEEDED || (cache->flag & PTCACHE_SIMULATION_VALID)==0) &&
- (render || bake))
- {
- BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
- }
-
- startframe = MIN2(startframe, cache->startframe);
-
- if (bake || render) {
- cache->flag |= PTCACHE_BAKING;
-
- if (bake)
- endframe = MAX2(endframe, cache->endframe);
- }
-
- cache->flag &= ~PTCACHE_BAKED;
-
- }
- }
- BLI_freelistN(&pidlist);
- }
- }
-
- CFRA = startframe;
- scene->r.framelen = 1.0;
-
- /* bake */
-
- bool use_timer = false;
- double stime, ptime, ctime, fetd;
- char run[32], cur[32], etd[32];
- int cancel = 0;
-
- stime = ptime = PIL_check_seconds_timer();
-
- for (int fr = CFRA; fr <= endframe; fr += baker->quick_step, CFRA = fr) {
- BKE_scene_update_for_newframe(G.main->eval_ctx, bmain, scene, scene->lay);
-
- if (baker->update_progress) {
- float progress = ((float)(CFRA - startframe)/(float)(endframe - startframe));
- baker->update_progress(baker->bake_job, progress, &cancel);
- }
-
- if (G.background) {
- printf("bake: frame %d :: %d\n", CFRA, endframe);
- }
- else {
- ctime = PIL_check_seconds_timer();
-
- fetd = (ctime - ptime) * (endframe - CFRA) / baker->quick_step;
-
- if (use_timer || fetd > 60.0) {
- use_timer = true;
-
- ptcache_dt_to_str(cur, ctime - ptime);
- ptcache_dt_to_str(run, ctime - stime);
- ptcache_dt_to_str(etd, fetd);
-
- printf("Baked for %s, current frame: %i/%i (%.3fs), ETC: %s\r",
- run, CFRA - startframe + 1, endframe - startframe + 1, ctime - ptime, etd);
- }
-
- ptime = ctime;
- }
-
- /* NOTE: breaking baking should leave calculated frames in cache, not clear it */
- if ((cancel || G.is_break)) {
- break;
- }
-
- CFRA += 1;
- }
-
- if (use_timer) {
- /* start with newline because of \r above */
- ptcache_dt_to_str(run, PIL_check_seconds_timer()-stime);
- printf("\nBake %s %s (%i frames simulated).\n", (cancel ? "canceled after" : "finished in"), run, CFRA - startframe);
- }
-
- /* clear baking flag */
- if (pid) {
- cache->flag &= ~(PTCACHE_BAKING|PTCACHE_REDO_NEEDED);
- cache->flag |= PTCACHE_SIMULATION_VALID;
- if (bake) {
- cache->flag |= PTCACHE_BAKED;
- /* write info file */
- if (cache->flag & PTCACHE_DISK_CACHE)
- BKE_ptcache_write(pid, 0);
- }
- }
- else {
- for (SETLOOPER(scene, sce_iter, base)) {
- BKE_ptcache_ids_from_object(&pidlist, base->object, scene, MAX_DUPLI_RECUR);
-
- for (pid=pidlist.first; pid; pid=pid->next) {
- /* skip hair particles */
- if (pid->type==PTCACHE_TYPE_PARTICLES && ((ParticleSystem*)pid->calldata)->part->type == PART_HAIR)
- continue;
-
- cache = pid->cache;
-
- if (baker->quick_step > 1)
- cache->flag &= ~(PTCACHE_BAKING|PTCACHE_OUTDATED);
- else
- cache->flag &= ~(PTCACHE_BAKING|PTCACHE_REDO_NEEDED);
-
- cache->flag |= PTCACHE_SIMULATION_VALID;
-
- if (bake) {
- cache->flag |= PTCACHE_BAKED;
- if (cache->flag & PTCACHE_DISK_CACHE)
- BKE_ptcache_write(pid, 0);
- }
- }
- BLI_freelistN(&pidlist);
- }
- }
-
- scene->r.framelen = frameleno;
- CFRA = cfrao;
-
- if (bake) { /* already on cfra unless baking */
- BKE_scene_update_for_newframe(bmain->eval_ctx, bmain, scene, scene->lay);
- }
-
- /* TODO: call redraw all windows somehow */
-}
-/* Helpers */
-void BKE_ptcache_disk_to_mem(PTCacheID *pid)
-{
- PointCache *cache = pid->cache;
- PTCacheMem *pm = NULL;
- int baked = cache->flag & PTCACHE_BAKED;
- int cfra, sfra = cache->startframe, efra = cache->endframe;
-
- /* Remove possible bake flag to allow clear */
- cache->flag &= ~PTCACHE_BAKED;
-
- /* PTCACHE_DISK_CACHE flag was cleared already */
- BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
-
- /* restore possible bake flag */
- cache->flag |= baked;
-
- for (cfra=sfra; cfra <= efra; cfra++) {
- pm = ptcache_disk_frame_to_mem(pid, cfra);
-
- if (pm)
- BLI_addtail(&pid->cache->mem_cache, pm);
- }
-}
-void BKE_ptcache_mem_to_disk(PTCacheID *pid)
-{
- PointCache *cache = pid->cache;
- PTCacheMem *pm = cache->mem_cache.first;
- int baked = cache->flag & PTCACHE_BAKED;
-
- /* Remove possible bake flag to allow clear */
- cache->flag &= ~PTCACHE_BAKED;
-
- /* PTCACHE_DISK_CACHE flag was set already */
- BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
-
- /* restore possible bake flag */
- cache->flag |= baked;
-
- for (; pm; pm=pm->next) {
- if (ptcache_mem_frame_to_disk(pid, pm)==0) {
- cache->flag &= ~PTCACHE_DISK_CACHE;
- break;
- }
- }
-
- /* write info file */
- if (cache->flag & PTCACHE_BAKED)
- BKE_ptcache_write(pid, 0);
-}
-void BKE_ptcache_toggle_disk_cache(PTCacheID *pid)
-{
- PointCache *cache = pid->cache;
- int last_exact = cache->last_exact;
-
- if (!G.relbase_valid) {
- cache->flag &= ~PTCACHE_DISK_CACHE;
- if (G.debug & G_DEBUG)
- printf("File must be saved before using disk cache!\n");
- return;
- }
-
- if (cache->cached_frames) {
- MEM_freeN(cache->cached_frames);
- cache->cached_frames=NULL;
- }
-
- if (cache->flag & PTCACHE_DISK_CACHE)
- BKE_ptcache_mem_to_disk(pid);
- else
- BKE_ptcache_disk_to_mem(pid);
-
- cache->flag ^= PTCACHE_DISK_CACHE;
- BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
- cache->flag ^= PTCACHE_DISK_CACHE;
-
- cache->last_exact = last_exact;
-
- BKE_ptcache_id_time(pid, NULL, 0.0f, NULL, NULL, NULL);
-
- BKE_ptcache_update_info(pid);
-
- if ((cache->flag & PTCACHE_DISK_CACHE) == 0) {
- if (cache->index) {
- BKE_object_delete_ptcache(pid->ob, cache->index);
- cache->index = -1;
- }
- }
-}
-
-void BKE_ptcache_disk_cache_rename(PTCacheID *pid, const char *name_src, const char *name_dst)
-{
- char old_name[80];
- int len; /* store the length of the string */
- /* mode is same as fopen's modes */
- DIR *dir;
- struct dirent *de;
- char path[MAX_PTCACHE_PATH];
- char old_filename[MAX_PTCACHE_FILE];
- char new_path_full[MAX_PTCACHE_FILE];
- char old_path_full[MAX_PTCACHE_FILE];
- char ext[MAX_PTCACHE_PATH];
-
- /* save old name */
- BLI_strncpy(old_name, pid->cache->name, sizeof(old_name));
-
- /* get "from" filename */
- BLI_strncpy(pid->cache->name, name_src, sizeof(pid->cache->name));
-
- len = ptcache_filename(pid, old_filename, 0, 0, 0); /* no path */
-
- ptcache_path(pid, path);
- dir = opendir(path);
- if (dir==NULL) {
- BLI_strncpy(pid->cache->name, old_name, sizeof(pid->cache->name));
- return;
- }
-
- const char *fext = ptcache_file_extension(pid);
-
- BLI_snprintf(ext, sizeof(ext), "_%02u%s", pid->stack_index, fext);
-
- /* put new name into cache */
- BLI_strncpy(pid->cache->name, name_dst, sizeof(pid->cache->name));
-
- while ((de = readdir(dir)) != NULL) {
- if (strstr(de->d_name, ext)) { /* do we have the right extension?*/
- if (STREQLEN(old_filename, de->d_name, len)) { /* do we have the right prefix */
- /* read the number of the file */
- const int frame = ptcache_frame_from_filename(de->d_name, ext);
-
- if (frame != -1) {
- BLI_join_dirfile(old_path_full, sizeof(old_path_full), path, de->d_name);
- ptcache_filename(pid, new_path_full, frame, 1, 1);
- BLI_rename(old_path_full, new_path_full);
- }
- }
- }
- }
- closedir(dir);
-
- BLI_strncpy(pid->cache->name, old_name, sizeof(pid->cache->name));
-}
-
-void BKE_ptcache_load_external(PTCacheID *pid)
-{
- /*todo*/
- PointCache *cache = pid->cache;
- int len; /* store the length of the string */
- int info = 0;
- int start = MAXFRAME;
- int end = -1;
-
- /* mode is same as fopen's modes */
- DIR *dir;
- struct dirent *de;
- char path[MAX_PTCACHE_PATH];
- char filename[MAX_PTCACHE_FILE];
- char ext[MAX_PTCACHE_PATH];
-
- if (!cache)
- return;
-
- ptcache_path(pid, path);
-
- len = ptcache_filename(pid, filename, 1, 0, 0); /* no path */
-
- dir = opendir(path);
- if (dir==NULL)
- return;
-
- const char *fext = ptcache_file_extension(pid);
-
- if (cache->index >= 0)
- BLI_snprintf(ext, sizeof(ext), "_%02d%s", cache->index, fext);
- else
- BLI_strncpy(ext, fext, sizeof(ext));
-
- while ((de = readdir(dir)) != NULL) {
- if (strstr(de->d_name, ext)) { /* do we have the right extension?*/
- if (STREQLEN(filename, de->d_name, len)) { /* do we have the right prefix */
- /* read the number of the file */
- const int frame = ptcache_frame_from_filename(de->d_name, ext);
-
- if (frame != -1) {
- if (frame) {
- start = MIN2(start, frame);
- end = MAX2(end, frame);
- }
- else
- info = 1;
- }
- }
- }
- }
- closedir(dir);
-
- if (start != MAXFRAME) {
- PTCacheFile *pf;
-
- cache->startframe = start;
- cache->endframe = end;
- cache->totpoint = 0;
-
- if (pid->type == PTCACHE_TYPE_SMOKE_DOMAIN) {
- /* necessary info in every file */
- }
- /* read totpoint from info file (frame 0) */
- else if (info) {
- pf= ptcache_file_open(pid, PTCACHE_FILE_READ, 0);
-
- if (pf) {
- if (ptcache_file_header_begin_read(pf)) {
- if (pf->type == pid->type && pid->read_header(pf)) {
- cache->totpoint = pf->totpoint;
- cache->flag |= PTCACHE_READ_INFO;
- }
- else {
- cache->totpoint = 0;
- }
- }
- ptcache_file_close(pf);
- }
- }
- /* or from any old format cache file */
- else {
- float old_data[14];
- int elemsize = ptcache_old_elemsize(pid);
- pf= ptcache_file_open(pid, PTCACHE_FILE_READ, cache->startframe);
-
- if (pf) {
- while (ptcache_file_read(pf, old_data, 1, elemsize))
- cache->totpoint++;
-
- ptcache_file_close(pf);
- }
- }
- cache->flag |= (PTCACHE_BAKED|PTCACHE_DISK_CACHE|PTCACHE_SIMULATION_VALID);
- cache->flag &= ~(PTCACHE_OUTDATED|PTCACHE_FRAMES_SKIPPED);
- }
-
- /* make sure all new frames are loaded */
- if (cache->cached_frames) {
- MEM_freeN(cache->cached_frames);
- cache->cached_frames=NULL;
- }
- BKE_ptcache_update_info(pid);
-}
-
-void BKE_ptcache_update_info(PTCacheID *pid)
-{
- PointCache *cache = pid->cache;
- PTCacheExtra *extra = NULL;
- int totframes = 0;
- char mem_info[64];
-
- if (cache->flag & PTCACHE_EXTERNAL) {
- int cfra = cache->startframe;
-
- for (; cfra <= cache->endframe; cfra++) {
- if (BKE_ptcache_id_exist(pid, cfra))
- totframes++;
- }
-
- /* smoke doesn't use frame 0 as info frame so can't check based on totpoint */
- if (pid->type == PTCACHE_TYPE_SMOKE_DOMAIN && totframes)
- BLI_snprintf(cache->info, sizeof(cache->info), IFACE_("%i frames found!"), totframes);
- else if (totframes && cache->totpoint)
- BLI_snprintf(cache->info, sizeof(cache->info), IFACE_("%i points found!"), cache->totpoint);
- else
- BLI_strncpy(cache->info, IFACE_("No valid data to read!"), sizeof(cache->info));
- return;
- }
-
- if (cache->flag & PTCACHE_DISK_CACHE) {
- if (pid->type == PTCACHE_TYPE_SMOKE_DOMAIN) {
- int totpoint = pid->totpoint(pid->calldata, 0);
-
- if (cache->totpoint > totpoint)
- BLI_snprintf(mem_info, sizeof(mem_info), IFACE_("%i cells + High Resolution cached"), totpoint);
- else
- BLI_snprintf(mem_info, sizeof(mem_info), IFACE_("%i cells cached"), totpoint);
- }
- else {
- int cfra = cache->startframe;
-
- for (; cfra <= cache->endframe; cfra++) {
- if (BKE_ptcache_id_exist(pid, cfra))
- totframes++;
- }
-
- BLI_snprintf(mem_info, sizeof(mem_info), IFACE_("%i frames on disk"), totframes);
- }
- }
- else {
- PTCacheMem *pm = cache->mem_cache.first;
- float bytes = 0.0f;
- int i, mb;
-
- for (; pm; pm=pm->next) {
- for (i=0; i<BPHYS_TOT_DATA; i++)
- bytes += MEM_allocN_len(pm->data[i]);
-
- for (extra=pm->extradata.first; extra; extra=extra->next) {
- bytes += MEM_allocN_len(extra->data);
- bytes += sizeof(PTCacheExtra);
- }
-
- bytes += sizeof(PTCacheMem);
-
- totframes++;
- }
-
- mb = (bytes > 1024.0f * 1024.0f);
-
- BLI_snprintf(mem_info, sizeof(mem_info), IFACE_("%i frames in memory (%.1f %s)"),
- totframes,
- bytes / (mb ? 1024.0f * 1024.0f : 1024.0f),
- mb ? IFACE_("Mb") : IFACE_("kb"));
- }
-
- if (cache->flag & PTCACHE_OUTDATED) {
- BLI_snprintf(cache->info, sizeof(cache->info), IFACE_("%s, cache is outdated!"), mem_info);
- }
- else if (cache->flag & PTCACHE_FRAMES_SKIPPED) {
- BLI_snprintf(cache->info, sizeof(cache->info), IFACE_("%s, not exact since frame %i"),
- mem_info, cache->last_exact);
- }
- else {
- BLI_snprintf(cache->info, sizeof(cache->info), "%s.", mem_info);
- }
-}
-
-void BKE_ptcache_validate(PointCache *cache, int framenr)
-{
- if (cache) {
- cache->flag |= PTCACHE_SIMULATION_VALID;
- cache->simframe = framenr;
- }
-}
-void BKE_ptcache_invalidate(PointCache *cache)
-{
- if (cache) {
- cache->flag &= ~PTCACHE_SIMULATION_VALID;
- cache->simframe = 0;
- cache->last_exact = MIN2(cache->startframe, 0);
- }
-}
diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c
index c3ae5736aa9..9eefcbe4885 100644
--- a/source/blender/blenkernel/intern/rigidbody.c
+++ b/source/blender/blenkernel/intern/rigidbody.c
@@ -61,7 +61,6 @@
#include "BKE_library_query.h"
#include "BKE_mesh.h"
#include "BKE_object.h"
-#include "BKE_pointcache.h"
#include "BKE_rigidbody.h"
#include "BKE_scene.h"
@@ -108,10 +107,6 @@ void BKE_rigidbody_free_world(RigidBodyWorld *rbw)
if (rbw->objects)
free(rbw->objects);
- /* free cache */
- BKE_ptcache_free_list(&(rbw->ptcaches));
- rbw->pointcache = NULL;
-
/* free effector weights */
if (rbw->effector_weights)
MEM_freeN(rbw->effector_weights);
@@ -921,9 +916,6 @@ RigidBodyWorld *BKE_rigidbody_create_world(Scene *scene)
rbw->steps_per_second = 60; /* Bullet default (60 Hz) */
rbw->num_solver_iterations = 10; /* 10 is bullet default */
- rbw->pointcache = BKE_ptcache_add(&(rbw->ptcaches));
- rbw->pointcache->step = 1;
-
/* return this sim world */
return rbw;
}
@@ -939,8 +931,6 @@ RigidBodyWorld *BKE_rigidbody_world_copy(RigidBodyWorld *rbw)
if (rbwn->constraints)
id_us_plus(&rbwn->constraints->id);
- rbwn->pointcache = BKE_ptcache_copy_list(&rbwn->ptcaches, &rbw->ptcaches, false);
-
rbwn->objects = NULL;
rbwn->physics_world = NULL;
rbwn->numbodies = 0;
@@ -973,10 +963,9 @@ void BKE_rigidbody_world_id_loop(RigidBodyWorld *rbw, RigidbodyWorldIDFunc func,
}
/* Add rigid body settings to the specified object */
-RigidBodyOb *BKE_rigidbody_create_object(Scene *scene, Object *ob, short type)
+RigidBodyOb *BKE_rigidbody_create_object(Scene *UNUSED(scene), Object *ob, short type)
{
RigidBodyOb *rbo;
- RigidBodyWorld *rbw = scene->rigidbody_world;
/* sanity checks
* - rigidbody world must exist
@@ -1020,18 +1009,14 @@ RigidBodyOb *BKE_rigidbody_create_object(Scene *scene, Object *ob, short type)
/* set initial transform */
mat4_to_loc_quat(rbo->pos, rbo->orn, ob->obmat);
- /* flag cache as outdated */
- BKE_rigidbody_cache_reset(rbw);
-
/* return this object */
return rbo;
}
/* Add rigid body constraint to the specified object */
-RigidBodyCon *BKE_rigidbody_create_constraint(Scene *scene, Object *ob, short type)
+RigidBodyCon *BKE_rigidbody_create_constraint(Scene *UNUSED(scene), Object *ob, short type)
{
RigidBodyCon *rbc;
- RigidBodyWorld *rbw = scene->rigidbody_world;
/* sanity checks
* - rigidbody world must exist
@@ -1081,9 +1066,6 @@ RigidBodyCon *BKE_rigidbody_create_constraint(Scene *scene, Object *ob, short ty
rbc->motor_ang_max_impulse = 1.0f;
rbc->motor_ang_target_velocity = 1.0f;
- /* flag cache as outdated */
- BKE_rigidbody_cache_reset(rbw);
-
/* return this object */
return rbc;
}
@@ -1143,9 +1125,6 @@ void BKE_rigidbody_remove_object(Scene *scene, Object *ob)
/* remove object's settings */
BKE_rigidbody_free_object(ob);
-
- /* flag cache as outdated */
- BKE_rigidbody_cache_reset(rbw);
}
void BKE_rigidbody_remove_constraint(Scene *scene, Object *ob)
@@ -1159,9 +1138,6 @@ void BKE_rigidbody_remove_constraint(Scene *scene, Object *ob)
}
/* remove object's settings */
BKE_rigidbody_free_constraint(ob);
-
- /* flag cache as outdated */
- BKE_rigidbody_cache_reset(rbw);
}
@@ -1255,7 +1231,7 @@ static void rigidbody_update_sim_ob(Scene *scene, RigidBodyWorld *rbw, Object *o
ListBase *effectors;
/* get effectors present in the group specified by effector_weights */
- effectors = pdInitEffectors(scene, ob, NULL, effector_weights, true);
+ effectors = pdInitEffectors(scene, ob, effector_weights, true);
if (effectors) {
float eff_force[3] = {0.0f, 0.0f, 0.0f};
float eff_loc[3], eff_vel[3];
@@ -1428,9 +1404,9 @@ static void rigidbody_update_simulation_post_step(RigidBodyWorld *rbw)
}
}
-bool BKE_rigidbody_check_sim_running(RigidBodyWorld *rbw, float ctime)
+bool BKE_rigidbody_check_sim_running(RigidBodyWorld *rbw, float UNUSED(ctime))
{
- return (rbw && (rbw->flag & RBW_FLAG_MUTED) == 0 && ctime > rbw->pointcache->startframe);
+ return (rbw && (rbw->flag & RBW_FLAG_MUTED) == 0);
}
/* Sync rigid body and object transformations */
@@ -1493,12 +1469,6 @@ void BKE_rigidbody_aftertrans_update(Object *ob, float loc[3], float rot[3], flo
// RB_TODO update rigid body physics object's loc/rot for dynamic objects here as well (needs to be done outside bullet's update loop)
}
-void BKE_rigidbody_cache_reset(RigidBodyWorld *rbw)
-{
- if (rbw)
- rbw->pointcache->flag |= PTCACHE_OUTDATED;
-}
-
/* ------------------ */
/* Rebuild rigid body world */
@@ -1506,27 +1476,10 @@ void BKE_rigidbody_cache_reset(RigidBodyWorld *rbw)
void BKE_rigidbody_rebuild_world(Scene *scene, float ctime)
{
RigidBodyWorld *rbw = scene->rigidbody_world;
- PointCache *cache;
- PTCacheID pid;
- int startframe, endframe;
-
- BKE_ptcache_id_from_rigidbody(&pid, NULL, rbw);
- BKE_ptcache_id_time(&pid, scene, ctime, &startframe, &endframe, NULL);
- cache = rbw->pointcache;
-
- /* flag cache as outdated if we don't have a world or number of objects in the simulation has changed */
- if (rbw->physics_world == NULL || rbw->numbodies != BLI_listbase_count(&rbw->group->gobject)) {
- cache->flag |= PTCACHE_OUTDATED;
- }
+ int startframe = scene->r.sfra;
if (ctime == startframe + 1 && rbw->ltime == startframe) {
- if (cache->flag & PTCACHE_OUTDATED) {
- BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED);
- rigidbody_update_simulation(scene, rbw, true);
- BKE_ptcache_validate(cache, (int)ctime);
- cache->last_exact = 0;
- cache->flag &= ~PTCACHE_REDO_NEEDED;
- }
+ rigidbody_update_simulation(scene, rbw, true);
}
}
@@ -1535,13 +1488,7 @@ void BKE_rigidbody_do_simulation(Scene *scene, float ctime)
{
float timestep;
RigidBodyWorld *rbw = scene->rigidbody_world;
- PointCache *cache;
- PTCacheID pid;
- int startframe, endframe;
-
- BKE_ptcache_id_from_rigidbody(&pid, NULL, rbw);
- BKE_ptcache_id_time(&pid, scene, ctime, &startframe, &endframe, NULL);
- cache = rbw->pointcache;
+ int startframe = scene->r.sfra, endframe = scene->r.efra;
if (ctime <= startframe) {
rbw->ltime = startframe;
@@ -1552,29 +1499,14 @@ void BKE_rigidbody_do_simulation(Scene *scene, float ctime)
ctime = endframe;
}
- /* don't try to run the simulation if we don't have a world yet but allow reading baked cache */
- if (rbw->physics_world == NULL && !(cache->flag & PTCACHE_BAKED))
+ /* don't try to run the simulation if we don't have a world yet */
+ if (rbw->physics_world == NULL)
return;
else if (rbw->objects == NULL)
rigidbody_update_ob_array(rbw);
- /* try to read from cache */
- // RB_TODO deal with interpolated, old and baked results
- bool can_simulate = (ctime == rbw->ltime + 1) && !(cache->flag & PTCACHE_BAKED);
-
- if (BKE_ptcache_read(&pid, ctime, can_simulate)) {
- BKE_ptcache_validate(cache, (int)ctime);
- rbw->ltime = ctime;
- return;
- }
-
/* advance simulation, we can only step one frame forward */
- if (can_simulate) {
- /* write cache for first frame when on second frame */
- if (rbw->ltime == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact == 0)) {
- BKE_ptcache_write(&pid, startframe);
- }
-
+ if (ctime == rbw->ltime + 1) {
/* update and validate simulation */
rigidbody_update_simulation(scene, rbw, false);
@@ -1585,10 +1517,6 @@ void BKE_rigidbody_do_simulation(Scene *scene, float ctime)
rigidbody_update_simulation_post_step(rbw);
- /* write cache for current frame */
- BKE_ptcache_validate(cache, (int)ctime);
- BKE_ptcache_write(&pid, (unsigned int)ctime);
-
rbw->ltime = ctime;
}
}
@@ -1623,7 +1551,6 @@ void BKE_rigidbody_remove_constraint(Scene *scene, Object *ob) {}
void BKE_rigidbody_sync_transforms(RigidBodyWorld *rbw, Object *ob, float ctime) {}
void BKE_rigidbody_aftertrans_update(Object *ob, float loc[3], float rot[3], float quat[4], float rotAxis[3], float rotAngle) {}
bool BKE_rigidbody_check_sim_running(RigidBodyWorld *rbw, float ctime) { return false; }
-void BKE_rigidbody_cache_reset(RigidBodyWorld *rbw) {}
void BKE_rigidbody_rebuild_world(Scene *scene, float ctime) {}
void BKE_rigidbody_do_simulation(Scene *scene, float ctime) {}
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index 6e1f11cb526..125d6962332 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -286,7 +286,6 @@ Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type)
BKE_paint_copy(&ts->imapaint.paint, &ts->imapaint.paint);
ts->imapaint.paintcursor = NULL;
id_us_plus((ID *)ts->imapaint.stencil);
- ts->particle.paintcursor = NULL;
/* duplicate Grease Pencil Drawing Brushes */
BLI_listbase_clear(&ts->gp_brushes);
for (bGPDbrush *brush = sce->toolsettings->gp_brushes.first; brush; brush = brush->next) {
@@ -467,8 +466,6 @@ void BKE_scene_free(Scene *sce)
void BKE_scene_init(Scene *sce)
{
- ParticleEditSettings *pset;
- int a;
const char *colorspace_name;
SceneRenderView *srv;
CurveMapping *mblur_shutter_curve;
@@ -644,23 +641,6 @@ void BKE_scene_init(Scene *sce)
sce->unit.scale_length = 1.0f;
- pset = &sce->toolsettings->particle;
- pset->flag = PE_KEEP_LENGTHS | PE_LOCK_FIRST | PE_DEFLECT_EMITTER | PE_AUTO_VELOCITY;
- pset->emitterdist = 0.25f;
- pset->totrekey = 5;
- pset->totaddkey = 5;
- pset->brushtype = PE_BRUSH_NONE;
- pset->draw_step = 2;
- pset->fade_frames = 2;
- pset->selectmode = SCE_SELECT_PATH;
- for (a = 0; a < PE_TOT_BRUSH; a++) {
- pset->brush[a].strength = 0.5f;
- pset->brush[a].size = 50;
- pset->brush[a].step = 10;
- pset->brush[a].count = 10;
- }
- pset->brush[PE_BRUSH_CUT].strength = 1.0f;
-
sce->r.ffcodecdata.audio_mixrate = 48000;
sce->r.ffcodecdata.audio_volume = 1.0f;
sce->r.ffcodecdata.audio_bitrate = 192;
diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c
index 857bd5447c8..14820565478 100644
--- a/source/blender/blenkernel/intern/screen.c
+++ b/source/blender/blenkernel/intern/screen.c
@@ -180,6 +180,7 @@ ARegion *BKE_area_region_copy(SpaceType *st, ARegion *ar)
BLI_listbase_clear(&newar->panels_category_active);
BLI_listbase_clear(&newar->ui_lists);
newar->swinid = 0;
+ newar->manipulator_map = NULL;
newar->regiontimer = NULL;
/* use optional regiondata callback */
@@ -288,6 +289,17 @@ void BKE_spacedata_id_unref(struct ScrArea *sa, struct SpaceLink *sl, struct ID
}
}
+
+/**
+ * Avoid bad-level calls to #WM_manipulatormap_delete.
+ */
+static void (*region_free_manipulatormap_callback)(struct wmManipulatorMap *) = NULL;
+
+void BKE_region_callback_free_manipulatormap_set(void (*callback)(struct wmManipulatorMap *))
+{
+ region_free_manipulatormap_callback = callback;
+}
+
/* not region itself */
void BKE_area_region_free(SpaceType *st, ARegion *ar)
{
@@ -337,6 +349,8 @@ void BKE_area_region_free(SpaceType *st, ARegion *ar)
MEM_freeN(uilst->properties);
}
}
+
+ region_free_manipulatormap_callback(ar->manipulator_map);
BLI_freelistN(&ar->ui_lists);
BLI_freelistN(&ar->ui_previews);
BLI_freelistN(&ar->panels_category);
diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c
index 05540f51588..05356123727 100644
--- a/source/blender/blenkernel/intern/smoke.c
+++ b/source/blender/blenkernel/intern/smoke.c
@@ -56,8 +56,8 @@
#include "DNA_lamp_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_modifier_types.h"
+#include "DNA_object_force.h"
#include "DNA_object_types.h"
-#include "DNA_particle_types.h"
#include "DNA_scene_types.h"
#include "DNA_smoke_types.h"
@@ -77,8 +77,6 @@
#include "BKE_main.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
-#include "BKE_particle.h"
-#include "BKE_pointcache.h"
#include "BKE_scene.h"
#include "BKE_smoke.h"
#include "BKE_texture.h"
@@ -357,9 +355,6 @@ static void smokeModifier_freeDomain(SmokeModifierData *smd)
MEM_freeN(smd->domain->effector_weights);
smd->domain->effector_weights = NULL;
- BKE_ptcache_free_list(&(smd->domain->ptcaches[0]));
- smd->domain->point_cache[0] = NULL;
-
MEM_freeN(smd->domain);
smd->domain = NULL;
}
@@ -484,13 +479,6 @@ void smokeModifier_createType(struct SmokeModifierData *smd)
smd->domain->smd = smd;
- smd->domain->point_cache[0] = BKE_ptcache_add(&(smd->domain->ptcaches[0]));
- smd->domain->point_cache[0]->flag |= PTCACHE_DISK_CACHE;
- smd->domain->point_cache[0]->step = 1;
-
- /* Deprecated */
- smd->domain->point_cache[1] = NULL;
- BLI_listbase_clear(&smd->domain->ptcaches[1]);
/* set some standard values */
smd->domain->fluid = NULL;
smd->domain->fluid_mutex = BLI_rw_mutex_alloc();
@@ -535,7 +523,6 @@ void smokeModifier_createType(struct SmokeModifierData *smd)
smd->domain->openvdb_comp = VDB_COMPRESSION_ZIP;
#endif
smd->domain->data_depth = 0;
- smd->domain->cache_file_format = PTCACHE_FILE_PTCACHE;
smd->domain->display_thickness = 1.0f;
smd->domain->slice_method = MOD_SMOKE_SLICE_VIEW_ALIGNED;
@@ -572,8 +559,6 @@ void smokeModifier_createType(struct SmokeModifierData *smd)
smd->flow->color[2] = 0.7f;
smd->flow->dm = NULL;
- smd->flow->psys = NULL;
-
}
else if (smd->type & MOD_SMOKE_TYPE_COLL)
{
@@ -648,7 +633,6 @@ void smokeModifier_copy(struct SmokeModifierData *smd, struct SmokeModifierData
tsmd->domain->vector_scale = smd->domain->vector_scale;
}
else if (tsmd->flow) {
- tsmd->flow->psys = smd->flow->psys;
tsmd->flow->noise_texture = smd->flow->noise_texture;
tsmd->flow->vel_multi = smd->flow->vel_multi;
@@ -1158,248 +1142,6 @@ static void em_combineMaps(EmissionMap *output, EmissionMap *em2, int hires_mult
em_freeData(&em1);
}
-typedef struct EmitFromParticlesData {
- SmokeFlowSettings *sfs;
- KDTree *tree;
- int hires_multiplier;
-
- EmissionMap *em;
- float *particle_vel;
- float hr;
-
- int *min, *max, *res;
-
- float solid;
- float smooth;
- float hr_smooth;
-} EmitFromParticlesData;
-
-static void emit_from_particles_task_cb(void *userdata, const int z)
-{
- EmitFromParticlesData *data = userdata;
- SmokeFlowSettings *sfs = data->sfs;
- EmissionMap *em = data->em;
- const int hires_multiplier = data->hires_multiplier;
-
- for (int x = data->min[0]; x < data->max[0]; x++) {
- for (int y = data->min[1]; y < data->max[1]; y++) {
- /* take low res samples where possible */
- if (hires_multiplier <= 1 || !(x % hires_multiplier || y % hires_multiplier || z % hires_multiplier)) {
- /* get low res space coordinates */
- const int lx = x / hires_multiplier;
- const int ly = y / hires_multiplier;
- const int lz = z / hires_multiplier;
-
- const int index = smoke_get_index(lx - em->min[0], em->res[0], ly - em->min[1], em->res[1], lz - em->min[2]);
- const float ray_start[3] = {((float)lx) + 0.5f, ((float)ly) + 0.5f, ((float)lz) + 0.5f};
-
- /* find particle distance from the kdtree */
- KDTreeNearest nearest;
- const float range = data->solid + data->smooth;
- BLI_kdtree_find_nearest(data->tree, ray_start, &nearest);
-
- if (nearest.dist < range) {
- em->influence[index] = (nearest.dist < data->solid) ?
- 1.0f : (1.0f - (nearest.dist - data->solid) / data->smooth);
- /* Uses particle velocity as initial velocity for smoke */
- if (sfs->flags & MOD_SMOKE_FLOW_INITVELOCITY && (sfs->psys->part->phystype != PART_PHYS_NO)) {
- VECADDFAC(&em->velocity[index * 3], &em->velocity[index * 3],
- &data->particle_vel[nearest.index * 3], sfs->vel_multi);
- }
- }
- }
-
- /* take high res samples if required */
- if (hires_multiplier > 1) {
- /* get low res space coordinates */
- const float lx = ((float)x) * data->hr;
- const float ly = ((float)y) * data->hr;
- const float lz = ((float)z) * data->hr;
-
- const int index = smoke_get_index(
- x - data->min[0], data->res[0], y - data->min[1], data->res[1], z - data->min[2]);
- const float ray_start[3] = {lx + 0.5f * data->hr, ly + 0.5f * data->hr, lz + 0.5f * data->hr};
-
- /* find particle distance from the kdtree */
- KDTreeNearest nearest;
- const float range = data->solid + data->hr_smooth;
- BLI_kdtree_find_nearest(data->tree, ray_start, &nearest);
-
- if (nearest.dist < range) {
- em->influence_high[index] = (nearest.dist < data->solid) ?
- 1.0f : (1.0f - (nearest.dist - data->solid) / data->smooth);
- }
- }
-
- }
- }
-}
-
-static void emit_from_particles(
- Object *flow_ob, SmokeDomainSettings *sds, SmokeFlowSettings *sfs, EmissionMap *em, Scene *scene, float dt)
-{
- if (sfs && sfs->psys && sfs->psys->part && ELEM(sfs->psys->part->type, PART_EMITTER, PART_FLUID)) // is particle system selected
- {
- ParticleSimulationData sim;
- ParticleSystem *psys = sfs->psys;
- float *particle_pos;
- float *particle_vel;
- int totpart = psys->totpart, totchild;
- int p = 0;
- int valid_particles = 0;
- int bounds_margin = 1;
-
- /* radius based flow */
- const float solid = sfs->particle_size * 0.5f;
- const float smooth = 0.5f; /* add 0.5 cells of linear falloff to reduce aliasing */
- int hires_multiplier = 1;
- KDTree *tree = NULL;
-
- sim.scene = scene;
- sim.ob = flow_ob;
- sim.psys = psys;
-
- /* prepare curvemapping tables */
- if ((psys->part->child_flag & PART_CHILD_USE_CLUMP_CURVE) && psys->part->clumpcurve)
- curvemapping_changed_all(psys->part->clumpcurve);
- if ((psys->part->child_flag & PART_CHILD_USE_ROUGH_CURVE) && psys->part->roughcurve)
- curvemapping_changed_all(psys->part->roughcurve);
-
- /* initialize particle cache */
- if (psys->part->type == PART_HAIR) {
- // TODO: PART_HAIR not supported whatsoever
- totchild = 0;
- }
- else {
- totchild = psys->totchild * psys->part->disp / 100;
- }
-
- particle_pos = MEM_callocN(sizeof(float) * (totpart + totchild) * 3, "smoke_flow_particles");
- particle_vel = MEM_callocN(sizeof(float) * (totpart + totchild) * 3, "smoke_flow_particles");
-
- /* setup particle radius emission if enabled */
- if (sfs->flags & MOD_SMOKE_FLOW_USE_PART_SIZE) {
- tree = BLI_kdtree_new(psys->totpart + psys->totchild);
-
- /* check need for high resolution map */
- if ((sds->flags & MOD_SMOKE_HIGHRES) && (sds->highres_sampling == SM_HRES_FULLSAMPLE)) {
- hires_multiplier = sds->amplify + 1;
- }
-
- bounds_margin = (int)ceil(solid + smooth);
- }
-
- /* calculate local position for each particle */
- for (p = 0; p < totpart + totchild; p++)
- {
- ParticleKey state;
- float *pos;
- if (p < totpart) {
- if (psys->particles[p].flag & (PARS_NO_DISP | PARS_UNEXIST))
- continue;
- }
- else {
- /* handle child particle */
- ChildParticle *cpa = &psys->child[p - totpart];
- if (psys->particles[cpa->parent].flag & (PARS_NO_DISP | PARS_UNEXIST))
- continue;
- }
-
- state.time = BKE_scene_frame_get(scene); /* use scene time */
- if (psys_get_particle_state(&sim, p, &state, 0) == 0)
- continue;
-
- /* location */
- pos = &particle_pos[valid_particles * 3];
- copy_v3_v3(pos, state.co);
- smoke_pos_to_cell(sds, pos);
-
- /* velocity */
- copy_v3_v3(&particle_vel[valid_particles * 3], state.vel);
- mul_mat3_m4_v3(sds->imat, &particle_vel[valid_particles * 3]);
-
- if (sfs->flags & MOD_SMOKE_FLOW_USE_PART_SIZE) {
- BLI_kdtree_insert(tree, valid_particles, pos);
- }
-
- /* calculate emission map bounds */
- em_boundInsert(em, pos);
- valid_particles++;
- }
-
- /* set emission map */
- clampBoundsInDomain(sds, em->min, em->max, NULL, NULL, bounds_margin, dt);
- em_allocateData(em, sfs->flags & MOD_SMOKE_FLOW_INITVELOCITY, hires_multiplier);
-
- if (!(sfs->flags & MOD_SMOKE_FLOW_USE_PART_SIZE)) {
- for (p = 0; p < valid_particles; p++)
- {
- int cell[3];
- size_t i = 0;
- size_t index = 0;
- int badcell = 0;
-
- /* 1. get corresponding cell */
- cell[0] = floor(particle_pos[p * 3]) - em->min[0];
- cell[1] = floor(particle_pos[p * 3 + 1]) - em->min[1];
- cell[2] = floor(particle_pos[p * 3 + 2]) - em->min[2];
- /* check if cell is valid (in the domain boundary) */
- for (i = 0; i < 3; i++) {
- if ((cell[i] > em->res[i] - 1) || (cell[i] < 0)) {
- badcell = 1;
- break;
- }
- }
- if (badcell)
- continue;
- /* get cell index */
- index = smoke_get_index(cell[0], em->res[0], cell[1], em->res[1], cell[2]);
- /* Add influence to emission map */
- em->influence[index] = 1.0f;
- /* Uses particle velocity as initial velocity for smoke */
- if (sfs->flags & MOD_SMOKE_FLOW_INITVELOCITY && (psys->part->phystype != PART_PHYS_NO))
- {
- VECADDFAC(&em->velocity[index * 3], &em->velocity[index * 3], &particle_vel[p * 3], sfs->vel_multi);
- }
- } // particles loop
- }
- else if (valid_particles > 0) { // MOD_SMOKE_FLOW_USE_PART_SIZE
- int min[3], max[3], res[3];
- const float hr = 1.0f / ((float)hires_multiplier);
- /* slightly adjust high res antialias smoothness based on number of divisions
- * to allow smaller details but yet not differing too much from the low res size */
- const float hr_smooth = smooth * powf(hr, 1.0f / 3.0f);
-
- /* setup loop bounds */
- for (int i = 0; i < 3; i++) {
- min[i] = em->min[i] * hires_multiplier;
- max[i] = em->max[i] * hires_multiplier;
- res[i] = em->res[i] * hires_multiplier;
- }
-
- BLI_kdtree_balance(tree);
-
- EmitFromParticlesData data = {
- .sfs = sfs, .tree = tree, .hires_multiplier = hires_multiplier, .hr = hr,
- .em = em, .particle_vel = particle_vel, .min = min, .max = max, .res = res,
- .solid = solid, .smooth = smooth, .hr_smooth = hr_smooth,
- };
-
- BLI_task_parallel_range(min[2], max[2], &data, emit_from_particles_task_cb, true);
- }
-
- if (sfs->flags & MOD_SMOKE_FLOW_USE_PART_SIZE) {
- BLI_kdtree_free(tree);
- }
-
- /* free data */
- if (particle_pos)
- MEM_freeN(particle_pos);
- if (particle_vel)
- MEM_freeN(particle_vel);
- }
-}
-
static void sample_derivedmesh(
SmokeFlowSettings *sfs,
const MVert *mvert, const MLoop *mloop, const MLoopTri *mlooptri, const MLoopUV *mloopuv,
@@ -2124,10 +1866,7 @@ static void update_flowsfluids(Scene *scene, Object *ob, SmokeDomainSettings *sd
/* just sample flow directly to emission map if no subframes */
if (!subframes) {
- if (sfs->source == MOD_SMOKE_FLOW_SOURCE_PARTICLES) {
- emit_from_particles(collob, sds, sfs, em, scene, dt);
- }
- else {
+ if (sfs->source == MOD_SMOKE_FLOW_SOURCE_MESH) {
emit_from_derivedmesh(collob, sds, sfs, em, dt);
}
}
@@ -2158,14 +1897,7 @@ static void update_flowsfluids(Scene *scene, Object *ob, SmokeDomainSettings *sd
scene->r.subframe = 0.0f;
}
- if (sfs->source == MOD_SMOKE_FLOW_SOURCE_PARTICLES) {
- /* emit_from_particles() updates timestep internally */
- emit_from_particles(collob, sds, sfs, &em_temp, scene, sdt);
- if (!(sfs->flags & MOD_SMOKE_FLOW_USE_PART_SIZE)) {
- hires_multiplier = 1;
- }
- }
- else { /* MOD_SMOKE_FLOW_SOURCE_MESH */
+ if (sfs->source == MOD_SMOKE_FLOW_SOURCE_MESH) {
/* update flow object frame */
BLI_mutex_lock(&object_update_lock);
BKE_object_modifier_update_subframe(scene, collob, true, 5, BKE_scene_frame_get(scene), eModifierType_Smoke);
@@ -2482,7 +2214,7 @@ static void update_effectors(Scene *scene, Object *ob, SmokeDomainSettings *sds,
ListBase *effectors;
/* make sure smoke flow influence is 0.0f */
sds->effector_weights->weight[PFIELD_SMOKEFLOW] = 0.0f;
- effectors = pdInitEffectors(scene, ob, NULL, sds->effector_weights, true);
+ effectors = pdInitEffectors(scene, ob, sds->effector_weights, true);
if (effectors) {
// precalculate wind forces
@@ -2717,28 +2449,16 @@ static void smokeModifier_process(SmokeModifierData *smd, Scene *scene, Object *
else if (smd->type & MOD_SMOKE_TYPE_DOMAIN)
{
SmokeDomainSettings *sds = smd->domain;
- PointCache *cache = NULL;
- PTCacheID pid;
- int startframe, endframe, framenr;
- float timescale;
-
- framenr = scene->r.cfra;
+ int startframe = scene->r.sfra, endframe = scene->r.efra, framenr = scene->r.cfra;
//printf("time: %d\n", scene->r.cfra);
- cache = sds->point_cache[0];
- BKE_ptcache_id_from_smoke(&pid, ob, smd);
- BKE_ptcache_id_time(&pid, scene, framenr, &startframe, &endframe, &timescale);
-
if (!smd->domain->fluid || framenr == startframe)
{
- BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED);
smokeModifier_reset_ex(smd, false);
- BKE_ptcache_validate(cache, framenr);
- cache->flag &= ~PTCACHE_REDO_NEEDED;
}
- if (!smd->domain->fluid && (framenr != startframe) && (smd->domain->flags & MOD_SMOKE_FILE_LOAD) == 0 && (cache->flag & PTCACHE_BAKED) == 0)
+ if (!smd->domain->fluid && (framenr != startframe) && (smd->domain->flags & MOD_SMOKE_FILE_LOAD) == 0)
return;
smd->domain->flags &= ~MOD_SMOKE_FILE_LOAD;
@@ -2758,13 +2478,6 @@ static void smokeModifier_process(SmokeModifierData *smd, Scene *scene, Object *
/* don't simulate if viewing start frame, but scene frame is not real start frame */
bool can_simulate = (framenr == (int)smd->time + 1) && (framenr == scene->r.cfra);
- /* try to read from cache */
- if (BKE_ptcache_read(&pid, (float)framenr, can_simulate) == PTCACHE_READ_EXACT) {
- BKE_ptcache_validate(cache, framenr);
- smd->time = framenr;
- return;
- }
-
if (!can_simulate)
return;
@@ -2772,11 +2485,6 @@ static void smokeModifier_process(SmokeModifierData *smd, Scene *scene, Object *
double start = PIL_check_seconds_timer();
#endif
- /* if on second frame, write cache for first frame */
- if ((int)smd->time == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact == 0)) {
- BKE_ptcache_write(&pid, startframe);
- }
-
// set new time
smd->time = scene->r.cfra;
@@ -2806,10 +2514,6 @@ static void smokeModifier_process(SmokeModifierData *smd, Scene *scene, Object *
smoke_turbulence_step(sds->wt, sds->fluid);
}
- BKE_ptcache_validate(cache, framenr);
- if (framenr != startframe)
- BKE_ptcache_write(&pid, framenr);
-
#ifdef DEBUG_TIME
double end = PIL_check_seconds_timer();
printf("Frame: %d, Time: %f\n\n", (int)smd->time, (float)(end - start));
diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c
index 03cf33083da..f0e2cbd657e 100644
--- a/source/blender/blenkernel/intern/softbody.c
+++ b/source/blender/blenkernel/intern/softbody.c
@@ -63,6 +63,7 @@ variables on the UI for now
#include "DNA_curve_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
+#include "DNA_object_force.h"
#include "DNA_group_types.h"
#include "BLI_math.h"
@@ -76,7 +77,6 @@ variables on the UI for now
#include "BKE_global.h"
#include "BKE_modifier.h"
#include "BKE_softbody.h"
-#include "BKE_pointcache.h"
#include "BKE_deform.h"
#include "BKE_mesh.h"
#include "BKE_scene.h"
@@ -1549,7 +1549,7 @@ static void scan_for_ext_spring_forces(Scene *scene, Object *ob, float timenow)
SoftBody *sb = ob->soft;
ListBase *do_effector = NULL;
- do_effector = pdInitEffectors(scene, ob, NULL, sb->effector_weights, true);
+ do_effector = pdInitEffectors(scene, ob, sb->effector_weights, true);
_scan_for_ext_spring_forces(scene, ob, timenow, 0, sb->totspring, do_effector);
pdEndEffectors(&do_effector);
}
@@ -1569,7 +1569,7 @@ static void sb_sfesf_threads_run(Scene *scene, struct Object *ob, float timenow,
int i, totthread, left, dec;
int lowsprings =100; /* wild guess .. may increase with better thread management 'above' or even be UI option sb->spawn_cf_threads_nopts */
- do_effector= pdInitEffectors(scene, ob, NULL, ob->soft->effector_weights, true);
+ do_effector= pdInitEffectors(scene, ob, ob->soft->effector_weights, true);
/* figure the number of threads while preventing pretty pointless threading overhead */
totthread= BKE_scene_num_threads(scene);
@@ -2259,7 +2259,7 @@ static void softbody_calc_forcesEx(Scene *scene, Object *ob, float forcetime, fl
sb_sfesf_threads_run(scene, ob, timenow, sb->totspring, NULL);
/* after spring scan because it uses Effoctors too */
- do_effector= pdInitEffectors(scene, ob, NULL, sb->effector_weights, true);
+ do_effector= pdInitEffectors(scene, ob, sb->effector_weights, true);
if (do_deflector) {
float defforce[3];
@@ -2321,7 +2321,7 @@ static void softbody_calc_forces(Scene *scene, Object *ob, float forcetime, floa
if (do_springcollision || do_aero) scan_for_ext_spring_forces(scene, ob, timenow);
/* after spring scan because it uses Effoctors too */
- do_effector= pdInitEffectors(scene, ob, NULL, ob->soft->effector_weights, true);
+ do_effector= pdInitEffectors(scene, ob, ob->soft->effector_weights, true);
if (do_deflector) {
float defforce[3];
@@ -3323,8 +3323,6 @@ SoftBody *sbNew(Scene *scene)
sb->shearstiff = 1.0f;
sb->solverflags |= SBSO_OLDERR;
- sb->pointcache = BKE_ptcache_add(&sb->ptcaches);
-
if (!sb->effector_weights)
sb->effector_weights = BKE_add_effector_weights(NULL);
@@ -3337,8 +3335,6 @@ SoftBody *sbNew(Scene *scene)
void sbFree(SoftBody *sb)
{
free_softbody_intern(sb);
- BKE_ptcache_free_list(&sb->ptcaches);
- sb->pointcache = NULL;
if (sb->effector_weights)
MEM_freeN(sb->effector_weights);
MEM_freeN(sb);
@@ -3645,30 +3641,17 @@ static void softbody_step(Scene *scene, Object *ob, SoftBody *sb, float dtime)
void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], int numVerts)
{
SoftBody *sb= ob->soft;
- PointCache *cache;
- PTCacheID pid;
- float dtime, timescale;
- int framedelta, framenr, startframe, endframe;
- int cache_result;
-
- cache= sb->pointcache;
-
- framenr= (int)cfra;
- framedelta= framenr - cache->simframe;
-
- BKE_ptcache_id_from_softbody(&pid, ob, sb);
- BKE_ptcache_id_time(&pid, scene, framenr, &startframe, &endframe, &timescale);
+ float dtime, timescale = 1.0f;
+ int framedelta = 1, framenr = (int)cfra, startframe = scene->r.sfra, endframe = scene->r.efra;
/* check for changes in mesh, should only happen in case the mesh
* structure changes during an animation */
if (sb->bpoint && numVerts != sb->totpoint) {
- BKE_ptcache_invalidate(cache);
return;
}
/* clamp frame ranges */
if (framenr < startframe) {
- BKE_ptcache_invalidate(cache);
return;
}
else if (framenr > endframe) {
@@ -3705,53 +3688,20 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i
return;
}
if (framenr == startframe) {
- BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED);
-
/* first frame, no simulation to do, just set the positions */
softbody_update_positions(ob, sb, vertexCos, numVerts);
- BKE_ptcache_validate(cache, framenr);
- cache->flag &= ~PTCACHE_REDO_NEEDED;
-
sb->last_frame = framenr;
return;
}
/* try to read from cache */
- bool can_simulate = (framenr == sb->last_frame+1) && !(cache->flag & PTCACHE_BAKED);
-
- cache_result = BKE_ptcache_read(&pid, (float)framenr+scene->r.subframe, can_simulate);
-
- if (cache_result == PTCACHE_READ_EXACT || cache_result == PTCACHE_READ_INTERPOLATED ||
- (!can_simulate && cache_result == PTCACHE_READ_OLD)) {
- softbody_to_object(ob, vertexCos, numVerts, sb->local);
-
- BKE_ptcache_validate(cache, framenr);
-
- if (cache_result == PTCACHE_READ_INTERPOLATED && cache->flag & PTCACHE_REDO_NEEDED)
- BKE_ptcache_write(&pid, framenr);
-
- sb->last_frame = framenr;
-
- return;
- }
- else if (cache_result==PTCACHE_READ_OLD) {
- ; /* do nothing */
- }
- else if (/*ob->id.lib || */(cache->flag & PTCACHE_BAKED)) { /* "library linking & pointcaches" has to be solved properly at some point */
- /* if baked and nothing in cache, do nothing */
- BKE_ptcache_invalidate(cache);
- return;
- }
+ bool can_simulate = (framenr == sb->last_frame + 1);
if (!can_simulate)
return;
- /* if on second frame, write cache for first frame */
- if (cache->simframe == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0))
- BKE_ptcache_write(&pid, startframe);
-
softbody_update_positions(ob, sb, vertexCos, numVerts);
/* checking time: */
@@ -3762,9 +3712,6 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i
softbody_to_object(ob, vertexCos, numVerts, 0);
- BKE_ptcache_validate(cache, framenr);
- BKE_ptcache_write(&pid, framenr);
-
sb->last_frame = framenr;
}
diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c
index 2d3ecad19ad..e98b6b60331 100644
--- a/source/blender/blenkernel/intern/texture.c
+++ b/source/blender/blenkernel/intern/texture.c
@@ -50,7 +50,6 @@
#include "DNA_brush_types.h"
#include "DNA_node_types.h"
#include "DNA_color_types.h"
-#include "DNA_particle_types.h"
#include "DNA_linestyle_types.h"
#include "IMB_imbuf.h"
@@ -1065,10 +1064,6 @@ bool give_active_mtex(ID *id, MTex ***mtex_ar, short *act)
*mtex_ar = ((FreestyleLineStyle *)id)->mtex;
if (act) *act = (((FreestyleLineStyle *)id)->texact);
break;
- case ID_PA:
- *mtex_ar = ((ParticleSettings *)id)->mtex;
- if (act) *act = (((ParticleSettings *)id)->texact);
- break;
default:
*mtex_ar = NULL;
if (act) *act = 0;
@@ -1096,9 +1091,6 @@ void set_active_mtex(ID *id, short act)
case ID_LS:
((FreestyleLineStyle *)id)->texact = act;
break;
- case ID_PA:
- ((ParticleSettings *)id)->texact = act;
- break;
}
}
@@ -1208,42 +1200,6 @@ void set_current_brush_texture(Brush *br, Tex *newtex)
}
}
-Tex *give_current_particle_texture(ParticleSettings *part)
-{
- MTex *mtex = NULL;
- Tex *tex = NULL;
-
- if (!part) return NULL;
-
- mtex = part->mtex[(int)(part->texact)];
- if (mtex) tex = mtex->tex;
-
- return tex;
-}
-
-void set_current_particle_texture(ParticleSettings *part, Tex *newtex)
-{
- int act = part->texact;
-
- if (part->mtex[act] && part->mtex[act]->tex)
- id_us_min(&part->mtex[act]->tex->id);
-
- if (newtex) {
- if (!part->mtex[act]) {
- part->mtex[act] = BKE_texture_mtex_add();
- part->mtex[act]->texco = TEXCO_ORCO;
- part->mtex[act]->blendtype = MTEX_MUL;
- }
-
- part->mtex[act]->tex = newtex;
- id_us_plus(&newtex->id);
- }
- else if (part->mtex[act]) {
- MEM_freeN(part->mtex[act]);
- part->mtex[act] = NULL;
- }
-}
-
/* ------------------------------------------------------------------------- */
EnvMap *BKE_texture_envmap_add(void)
diff --git a/source/blender/blenlib/BLI_math_matrix.h b/source/blender/blenlib/BLI_math_matrix.h
index 8124e07dd47..fc4bca12dac 100644
--- a/source/blender/blenlib/BLI_math_matrix.h
+++ b/source/blender/blenlib/BLI_math_matrix.h
@@ -46,31 +46,43 @@ void unit_m2(float R[2][2]);
void unit_m3(float R[3][3]);
void unit_m4(float R[4][4]);
-void copy_m2_m2(float R[2][2], float A[2][2]);
-void copy_m3_m3(float R[3][3], float A[3][3]);
-void copy_m4_m4(float R[4][4], float A[4][4]);
-void copy_m3_m4(float R[3][3], float A[4][4]);
-void copy_m4_m3(float R[4][4], float A[3][3]);
+void copy_m2_m2(float R[2][2], const float A[2][2]);
+void copy_m3_m3(float R[3][3], const float A[3][3]);
+void copy_m4_m4(float R[4][4], const float A[4][4]);
+void copy_m3_m4(float R[3][3], const float A[4][4]);
+void copy_m4_m3(float R[4][4], const float A[3][3]);
/* double->float */
-void copy_m3_m3d(float R[3][3], double A[3][3]);
+void copy_m3_m3d(float R[3][3], const double A[3][3]);
void swap_m3m3(float A[3][3], float B[3][3]);
void swap_m4m4(float A[4][4], float B[4][4]);
/******************************** Arithmetic *********************************/
-void add_m3_m3m3(float R[3][3], float A[3][3], float B[3][3]);
-void add_m4_m4m4(float R[4][4], float A[4][4], float B[4][4]);
+void add_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3]);
+void add_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4]);
-void sub_m3_m3m3(float R[3][3], float A[3][3], float B[3][3]);
-void sub_m4_m4m4(float R[4][4], float A[4][4], float B[4][4]);
+void sub_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3]);
+void sub_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4]);
-void mul_m3_m3m3(float R[3][3], float A[3][3], float B[3][3]);
-void mul_m4_m3m4(float R[4][4], float A[3][3], float B[4][4]);
-void mul_m4_m4m3(float R[4][4], float A[4][4], float B[3][3]);
-void mul_m4_m4m4(float R[4][4], float A[4][4], float B[4][4]);
-void mul_m3_m3m4(float R[3][3], float A[4][4], float B[3][3]);
+void mul_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3]);
+void mul_m4_m3m4(float R[4][4], const float A[3][3], const float B[4][4]);
+void mul_m4_m4m3(float R[4][4], const float A[4][4], const float B[3][3]);
+void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4]);
+void mul_m3_m3m4(float R[3][3], const float A[4][4], const float B[3][3]);
+
+/* special matrix multiplies
+ * uniq: R <-- AB, R is neither A nor B
+ * pre: R <-- AR
+ * post: R <-- RB
+ */
+void mul_m3_m3m3_uniq(float R[3][3], const float A[3][3], const float B[3][3]);
+void mul_m3_m3_pre(float R[3][3], const float A[3][3]);
+void mul_m3_m3_post(float R[3][3], const float B[3][3]);
+void mul_m4_m4m4_uniq(float R[4][4], const float A[4][4], const float B[4][4]);
+void mul_m4_m4_pre(float R[4][4], const float A[4][4]);
+void mul_m4_m4_post(float R[4][4], const float B[4][4]);
/* mul_m3_series */
void _va_mul_m3_series_3(float R[3][3], float M1[3][3], float M2[3][3]) ATTR_NONNULL();
@@ -100,27 +112,28 @@ void _va_mul_m4_series_9(float R[4][4], float M1[4][4], float M2[4][4], float M3
#define mul_m3_series(...) VA_NARGS_CALL_OVERLOAD(_va_mul_m3_series_, __VA_ARGS__)
#define mul_m4_series(...) VA_NARGS_CALL_OVERLOAD(_va_mul_m4_series_, __VA_ARGS__)
-void mul_m4_v3(float M[4][4], float r[3]);
-void mul_v3_m4v3(float r[3], float M[4][4], const float v[3]);
-void mul_v2_m4v3(float r[2], float M[4][4], const float v[3]);
-void mul_v2_m2v2(float r[2], float M[2][2], const float v[2]);
-void mul_m2v2(float M[2][2], float v[2]);
-void mul_mat3_m4_v3(float M[4][4], float r[3]);
-void mul_v3_mat3_m4v3(float r[3], float M[4][4], const float v[3]);
-void mul_m4_v4(float M[4][4], float r[4]);
-void mul_v4_m4v4(float r[4], float M[4][4], const float v[4]);
-void mul_project_m4_v3(float M[4][4], float vec[3]);
-void mul_v3_project_m4_v3(float r[3], float mat[4][4], const float vec[3]);
-void mul_v2_project_m4_v3(float r[2], float M[4][4], const float vec[3]);
-
-void mul_m3_v2(float m[3][3], float r[2]);
-void mul_v2_m3v2(float r[2], float m[3][3], float v[2]);
-void mul_m3_v3(float M[3][3], float r[3]);
-void mul_v3_m3v3(float r[3], float M[3][3], const float a[3]);
-void mul_v2_m3v3(float r[2], float M[3][3], const float a[3]);
-void mul_transposed_m3_v3(float M[3][3], float r[3]);
-void mul_transposed_mat3_m4_v3(float M[4][4], float r[3]);
-void mul_m3_v3_double(float M[3][3], double r[3]);
+void mul_m4_v3(const float M[4][4], float r[3]);
+void mul_v3_m4v3(float r[3], const float M[4][4], const float v[3]);
+void mul_v2_m4v3(float r[2], const float M[4][4], const float v[3]);
+void mul_v2_m2v2(float r[2], const float M[2][2], const float v[2]);
+void mul_m2v2(const float M[2][2], float v[2]);
+void mul_mat3_m4_v3(const float M[4][4], float r[3]);
+void mul_v3_mat3_m4v3(float r[3], const float M[4][4], const float v[3]);
+void mul_m4_v4(const float M[4][4], float r[4]);
+void mul_v4_m4v4(float r[4], const float M[4][4], const float v[4]);
+void mul_v4_m4v3(float r[4], const float M[4][4], const float v[3]); /* v has implicit w = 1.0f */
+void mul_project_m4_v3(const float M[4][4], float vec[3]);
+void mul_v3_project_m4_v3(float r[3], const float mat[4][4], const float vec[3]);
+void mul_v2_project_m4_v3(float r[2], const float M[4][4], const float vec[3]);
+
+void mul_m3_v2(const float m[3][3], float r[2]);
+void mul_v2_m3v2(float r[2], const float m[3][3], const float v[2]);
+void mul_m3_v3(const float M[3][3], float r[3]);
+void mul_v3_m3v3(float r[3], const float M[3][3], const float a[3]);
+void mul_v2_m3v3(float r[2], const float M[3][3], const float a[3]);
+void mul_transposed_m3_v3(const float M[3][3], float r[3]);
+void mul_transposed_mat3_m4_v3(const float M[4][4], float r[3]);
+void mul_m3_v3_double(const float M[3][3], double r[3]);
void mul_m3_fl(float R[3][3], float f);
void mul_m4_fl(float R[4][4], float f);
@@ -131,103 +144,103 @@ void negate_mat3_m4(float R[4][4]);
void negate_m4(float R[4][4]);
bool invert_m3_ex(float m[3][3], const float epsilon);
-bool invert_m3_m3_ex(float m1[3][3], float m2[3][3], const float epsilon);
+bool invert_m3_m3_ex(float m1[3][3], const float m2[3][3], const float epsilon);
bool invert_m3(float R[3][3]);
-bool invert_m3_m3(float R[3][3], float A[3][3]);
+bool invert_m3_m3(float R[3][3], const float A[3][3]);
bool invert_m4(float R[4][4]);
-bool invert_m4_m4(float R[4][4], float A[4][4]);
+bool invert_m4_m4(float R[4][4], const float A[4][4]);
/* double arithmetic (mixed float/double) */
-void mul_m4_v4d(float M[4][4], double r[4]);
-void mul_v4d_m4v4d(double r[4], float M[4][4], double v[4]);
+void mul_m4_v4d(const float M[4][4], double r[4]);
+void mul_v4d_m4v4d(double r[4], const float M[4][4], const double v[4]);
/* double matrix functions (no mixing types) */
-void mul_v3_m3v3_db(double r[3], double M[3][3], const double a[3]);
-void mul_m3_v3_db(double M[3][3], double r[3]);
+void mul_v3_m3v3_db(double r[3], const double M[3][3], const double a[3]);
+void mul_m3_v3_db(const double M[3][3], double r[3]);
/****************************** Linear Algebra *******************************/
void transpose_m3(float R[3][3]);
-void transpose_m3_m3(float R[3][3], float A[3][3]);
-void transpose_m3_m4(float R[3][3], float A[4][4]);
+void transpose_m3_m3(float R[3][3], const float A[3][3]);
+void transpose_m3_m4(float R[3][3], const float A[4][4]);
void transpose_m4(float R[4][4]);
-void transpose_m4_m4(float R[4][4], float A[4][4]);
+void transpose_m4_m4(float R[4][4], const float A[4][4]);
-int compare_m4m4(float mat1[4][4], float mat2[4][4], float limit);
+int compare_m4m4(const float mat1[4][4], const float mat2[4][4], float limit);
void normalize_m3_ex(float R[3][3], float r_scale[3]) ATTR_NONNULL();
void normalize_m3(float R[3][3]) ATTR_NONNULL();
-void normalize_m3_m3_ex(float R[3][3], float A[3][3], float r_scale[3]) ATTR_NONNULL();
-void normalize_m3_m3(float R[3][3], float A[3][3]) ATTR_NONNULL();
+void normalize_m3_m3_ex(float R[3][3], const float A[3][3], float r_scale[3]) ATTR_NONNULL();
+void normalize_m3_m3(float R[3][3], const float A[3][3]) ATTR_NONNULL();
void normalize_m4_ex(float R[4][4], float r_scale[3]) ATTR_NONNULL();
void normalize_m4(float R[4][4]) ATTR_NONNULL();
-void normalize_m4_m4_ex(float R[4][4], float A[4][4], float r_scale[3]) ATTR_NONNULL();
-void normalize_m4_m4(float R[4][4], float A[4][4]) ATTR_NONNULL();
+void normalize_m4_m4_ex(float R[4][4], const float A[4][4], float r_scale[3]) ATTR_NONNULL();
+void normalize_m4_m4(float R[4][4],const float A[4][4]) ATTR_NONNULL();
void orthogonalize_m3(float R[3][3], int axis);
void orthogonalize_m4(float R[4][4], int axis);
-bool is_orthogonal_m3(float mat[3][3]);
-bool is_orthogonal_m4(float mat[4][4]);
-bool is_orthonormal_m3(float mat[3][3]);
-bool is_orthonormal_m4(float mat[4][4]);
+bool is_orthogonal_m3(const float mat[3][3]);
+bool is_orthogonal_m4(const float mat[4][4]);
+bool is_orthonormal_m3(const float mat[3][3]);
+bool is_orthonormal_m4(const float mat[4][4]);
-bool is_uniform_scaled_m3(float mat[3][3]);
-bool is_uniform_scaled_m4(float m[4][4]);
+bool is_uniform_scaled_m3(const float mat[3][3]);
+bool is_uniform_scaled_m4(const float m[4][4]);
/* Note: 'adjoint' here means the adjugate (adjunct, "classical adjoint") matrix!
* Nowadays 'adjoint' usually refers to the conjugate transpose,
* which for real-valued matrices is simply the transpose.
*/
-void adjoint_m2_m2(float R[2][2], float A[2][2]);
-void adjoint_m3_m3(float R[3][3], float A[3][3]);
-void adjoint_m4_m4(float R[4][4], float A[4][4]);
+void adjoint_m2_m2(float R[2][2], const float A[2][2]);
+void adjoint_m3_m3(float R[3][3], const float A[3][3]);
+void adjoint_m4_m4(float R[4][4], const float A[4][4]);
float determinant_m2(float a, float b,
float c, float d);
float determinant_m3(float a, float b, float c,
float d, float e, float f,
float g, float h, float i);
-float determinant_m3_array(float m[3][3]);
-float determinant_m4(float A[4][4]);
+float determinant_m3_array(const float m[3][3]);
+float determinant_m4(const float A[4][4]);
#define PSEUDOINVERSE_EPSILON 1e-8f
void svd_m4(float U[4][4], float s[4], float V[4][4], float A[4][4]);
-void pseudoinverse_m4_m4(float Ainv[4][4], float A[4][4], float epsilon);
-void pseudoinverse_m3_m3(float Ainv[3][3], float A[3][3], float epsilon);
+void pseudoinverse_m4_m4(float Ainv[4][4], const float A[4][4], float epsilon);
+void pseudoinverse_m3_m3(float Ainv[3][3], const float A[3][3], float epsilon);
-bool has_zero_axis_m4(float matrix[4][4]);
+bool has_zero_axis_m4(const float matrix[4][4]);
-void invert_m4_m4_safe(float Ainv[4][4], float A[4][4]);
+void invert_m4_m4_safe(float Ainv[4][4], const float A[4][4]);
/****************************** Transformations ******************************/
void scale_m3_fl(float R[3][3], float scale);
void scale_m4_fl(float R[4][4], float scale);
-float mat3_to_scale(float M[3][3]);
-float mat4_to_scale(float M[4][4]);
+float mat3_to_scale(const float M[3][3]);
+float mat4_to_scale(const float M[4][4]);
void size_to_mat3(float R[3][3], const float size[3]);
void size_to_mat4(float R[4][4], const float size[3]);
-void mat3_to_size(float r[3], float M[3][3]);
-void mat4_to_size(float r[3], float M[4][4]);
+void mat3_to_size(float r[3], const float M[3][3]);
+void mat4_to_size(float r[3], const float M[4][4]);
void translate_m4(float mat[4][4], float tx, float ty, float tz);
void rotate_m4(float mat[4][4], const char axis, const float angle);
void rotate_m2(float mat[2][2], const float angle);
void transform_pivot_set_m4(float mat[4][4], const float pivot[3]);
-void mat3_to_rot_size(float rot[3][3], float size[3], float mat3[3][3]);
-void mat4_to_loc_rot_size(float loc[3], float rot[3][3], float size[3], float wmat[4][4]);
-void mat4_to_loc_quat(float loc[3], float quat[4], float wmat[4][4]);
-void mat4_decompose(float loc[3], float quat[4], float size[3], float wmat[4][4]);
+void mat3_to_rot_size(float rot[3][3], float size[3], const float mat3[3][3]);
+void mat4_to_loc_rot_size(float loc[3], float rot[3][3], float size[3], const float wmat[4][4]);
+void mat4_to_loc_quat(float loc[3], float quat[4], const float wmat[4][4]);
+void mat4_decompose(float loc[3], float quat[4], float size[3], const float wmat[4][4]);
-void mat3_polar_decompose(float mat3[3][3], float r_U[3][3], float r_P[3][3]);
+void mat3_polar_decompose(const float mat3[3][3], float r_U[3][3], float r_P[3][3]);
void loc_eul_size_to_mat4(float R[4][4],
const float loc[3], const float eul[3], const float size[3]);
@@ -238,20 +251,20 @@ void loc_quat_size_to_mat4(float R[4][4],
void loc_axisangle_size_to_mat4(float R[4][4],
const float loc[3], const float axis[4], const float angle, const float size[3]);
-void blend_m3_m3m3(float R[3][3], float A[3][3], float B[3][3], const float t);
-void blend_m4_m4m4(float R[4][4], float A[4][4], float B[4][4], const float t);
+void blend_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3], const float t);
+void blend_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4], const float t);
-void interp_m3_m3m3(float R[3][3], float A[3][3], float B[3][3], const float t);
-void interp_m4_m4m4(float R[4][4], float A[4][4], float B[4][4], const float t);
+void interp_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3], const float t);
+void interp_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4], const float t);
-bool is_negative_m3(float mat[3][3]);
-bool is_negative_m4(float mat[4][4]);
+bool is_negative_m3(const float mat[3][3]);
+bool is_negative_m4(const float mat[4][4]);
-bool is_zero_m3(float mat[3][3]);
-bool is_zero_m4(float mat[4][4]);
+bool is_zero_m3(const float mat[3][3]);
+bool is_zero_m4(const float mat[4][4]);
-bool equals_m3m3(float mat1[3][3], float mat2[3][3]);
-bool equals_m4m4(float mat1[4][4], float mat2[4][4]);
+bool equals_m3m3(const float mat1[3][3], const float mat2[3][3]);
+bool equals_m4m4(const float mat1[4][4], const float mat2[4][4]);
/* SpaceTransform helper */
typedef struct SpaceTransform {
@@ -260,8 +273,8 @@ typedef struct SpaceTransform {
} SpaceTransform;
-void BLI_space_transform_from_matrices(struct SpaceTransform *data, float local[4][4], float target[4][4]);
-void BLI_space_transform_global_from_matrices(struct SpaceTransform *data, float local[4][4], float target[4][4]);
+void BLI_space_transform_from_matrices(struct SpaceTransform *data, const float local[4][4], const float target[4][4]);
+void BLI_space_transform_global_from_matrices(struct SpaceTransform *data, const float local[4][4], const float target[4][4]);
void BLI_space_transform_apply(const struct SpaceTransform *data, float co[3]);
void BLI_space_transform_invert(const struct SpaceTransform *data, float co[3]);
void BLI_space_transform_apply_normal(const struct SpaceTransform *data, float no[3]);
@@ -272,8 +285,8 @@ void BLI_space_transform_invert_normal(const struct SpaceTransform *data, float
/*********************************** Other ***********************************/
-void print_m3(const char *str, float M[3][3]);
-void print_m4(const char *str, float M[4][4]);
+void print_m3(const char *str, const float M[3][3]);
+void print_m4(const char *str, const float M[4][4]);
#define print_m3_id(M) print_m3(STRINGIFY(M), M)
#define print_m4_id(M) print_m4(STRINGIFY(M), M)
diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h
index d15fe1a95dc..fbecffc1270 100644
--- a/source/blender/blenlib/BLI_math_vector.h
+++ b/source/blender/blenlib/BLI_math_vector.h
@@ -123,13 +123,13 @@ MINLINE void mul_v4_fl(float r[4], float f);
MINLINE void mul_v4_v4fl(float r[3], const float a[3], float f);
MINLINE void mul_v2_v2_cw(float r[2], const float mat[2], const float vec[2]);
MINLINE void mul_v2_v2_ccw(float r[2], const float mat[2], const float vec[2]);
-MINLINE float mul_project_m4_v3_zfac(float mat[4][4], const float co[3]) ATTR_WARN_UNUSED_RESULT;
-MINLINE float dot_m3_v3_row_x(float M[3][3], const float a[3]) ATTR_WARN_UNUSED_RESULT;
-MINLINE float dot_m3_v3_row_y(float M[3][3], const float a[3]) ATTR_WARN_UNUSED_RESULT;
-MINLINE float dot_m3_v3_row_z(float M[3][3], const float a[3]) ATTR_WARN_UNUSED_RESULT;
-MINLINE float dot_m4_v3_row_x(float M[4][4], const float a[3]) ATTR_WARN_UNUSED_RESULT;
-MINLINE float dot_m4_v3_row_y(float M[4][4], const float a[3]) ATTR_WARN_UNUSED_RESULT;
-MINLINE float dot_m4_v3_row_z(float M[4][4], const float a[3]) ATTR_WARN_UNUSED_RESULT;
+MINLINE float mul_project_m4_v3_zfac(const float mat[4][4], const float co[3]) ATTR_WARN_UNUSED_RESULT;
+MINLINE float dot_m3_v3_row_x(const float M[3][3], const float a[3]) ATTR_WARN_UNUSED_RESULT;
+MINLINE float dot_m3_v3_row_y(const float M[3][3], const float a[3]) ATTR_WARN_UNUSED_RESULT;
+MINLINE float dot_m3_v3_row_z(const float M[3][3], const float a[3]) ATTR_WARN_UNUSED_RESULT;
+MINLINE float dot_m4_v3_row_x(const float M[4][4], const float a[3]) ATTR_WARN_UNUSED_RESULT;
+MINLINE float dot_m4_v3_row_y(const float M[4][4], const float a[3]) ATTR_WARN_UNUSED_RESULT;
+MINLINE float dot_m4_v3_row_z(const float M[4][4], const float a[3]) ATTR_WARN_UNUSED_RESULT;
MINLINE void madd_v2_v2fl(float r[2], const float a[2], float f);
MINLINE void madd_v3_v3fl(float r[3], const float a[3], float f);
@@ -171,7 +171,7 @@ MINLINE void cross_v3_v3v3(float r[3], const float a[3], const float b[3]);
MINLINE void add_newell_cross_v3_v3v3(float n[3], const float v_prev[3], const float v_curr[3]);
-MINLINE void star_m3_v3(float rmat[3][3], float a[3]);
+MINLINE void star_m3_v3(float rmat[3][3], const float a[3]);
/*********************************** Length **********************************/
@@ -304,6 +304,7 @@ void ortho_basis_v3v3_v3(float r_n1[3], float r_n2[3], const float n[3]);
void ortho_v3_v3(float out[3], const float v[3]);
void ortho_v2_v2(float out[2], const float v[2]);
void bisect_v3_v3v3v3(float r[3], const float a[3], const float b[3], const float c[3]);
+void rotate_v2_v2fl(float r[2], const float p[2], const float angle);
void rotate_v3_v3v3fl(float v[3], const float p[3], const float axis[3], const float angle);
void rotate_normalized_v3_v3v3fl(float out[3], const float p[3], const float axis[3], const float angle);
diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c
index c9c61d5c878..d95371b4ebc 100644
--- a/source/blender/blenlib/intern/math_matrix.c
+++ b/source/blender/blenlib/intern/math_matrix.c
@@ -74,23 +74,23 @@ void unit_m4(float m[4][4])
m[3][0] = m[3][1] = m[3][2] = 0.0f;
}
-void copy_m2_m2(float m1[2][2], float m2[2][2])
+void copy_m2_m2(float m1[2][2], const float m2[2][2])
{
memcpy(m1, m2, sizeof(float[2][2]));
}
-void copy_m3_m3(float m1[3][3], float m2[3][3])
+void copy_m3_m3(float m1[3][3], const float m2[3][3])
{
/* destination comes first: */
memcpy(m1, m2, sizeof(float[3][3]));
}
-void copy_m4_m4(float m1[4][4], float m2[4][4])
+void copy_m4_m4(float m1[4][4], const float m2[4][4])
{
memcpy(m1, m2, sizeof(float[4][4]));
}
-void copy_m3_m4(float m1[3][3], float m2[4][4])
+void copy_m3_m4(float m1[3][3], const float m2[4][4])
{
m1[0][0] = m2[0][0];
m1[0][1] = m2[0][1];
@@ -105,7 +105,7 @@ void copy_m3_m4(float m1[3][3], float m2[4][4])
m1[2][2] = m2[2][2];
}
-void copy_m4_m3(float m1[4][4], float m2[3][3]) /* no clear */
+void copy_m4_m3(float m1[4][4], const float m2[3][3]) /* no clear */
{
m1[0][0] = m2[0][0];
m1[0][1] = m2[0][1];
@@ -131,7 +131,7 @@ void copy_m4_m3(float m1[4][4], float m2[3][3]) /* no clear */
}
-void copy_m3_m3d(float R[3][3], double A[3][3])
+void copy_m3_m3d(float R[3][3], const double A[3][3])
{
/* Keep it stupid simple for better data flow in CPU. */
R[0][0] = (float)A[0][0];
@@ -177,64 +177,107 @@ void swap_m4m4(float m1[4][4], float m2[4][4])
/******************************** Arithmetic *********************************/
-void mul_m4_m4m4(float m1[4][4], float m3_[4][4], float m2_[4][4])
+void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
{
- float m2[4][4], m3[4][4];
+ if (A == R)
+ mul_m4_m4_post(R, B);
+ else if (B == R)
+ mul_m4_m4_pre(R, A);
+ else
+ mul_m4_m4m4_uniq(R, A, B);
+}
- /* copy so it works when m1 is the same pointer as m2 or m3 */
- copy_m4_m4(m2, m2_);
- copy_m4_m4(m3, m3_);
+void mul_m4_m4m4_uniq(float R[4][4], const float A[4][4], const float B[4][4])
+{
+ BLI_assert(R != A && R != B);
- /* matrix product: m1[j][k] = m2[j][i].m3[i][k] */
- m1[0][0] = m2[0][0] * m3[0][0] + m2[0][1] * m3[1][0] + m2[0][2] * m3[2][0] + m2[0][3] * m3[3][0];
- m1[0][1] = m2[0][0] * m3[0][1] + m2[0][1] * m3[1][1] + m2[0][2] * m3[2][1] + m2[0][3] * m3[3][1];
- m1[0][2] = m2[0][0] * m3[0][2] + m2[0][1] * m3[1][2] + m2[0][2] * m3[2][2] + m2[0][3] * m3[3][2];
- m1[0][3] = m2[0][0] * m3[0][3] + m2[0][1] * m3[1][3] + m2[0][2] * m3[2][3] + m2[0][3] * m3[3][3];
+ /* matrix product: R[j][k] = A[j][i] . B[i][k] */
+ R[0][0] = B[0][0] * A[0][0] + B[0][1] * A[1][0] + B[0][2] * A[2][0] + B[0][3] * A[3][0];
+ R[0][1] = B[0][0] * A[0][1] + B[0][1] * A[1][1] + B[0][2] * A[2][1] + B[0][3] * A[3][1];
+ R[0][2] = B[0][0] * A[0][2] + B[0][1] * A[1][2] + B[0][2] * A[2][2] + B[0][3] * A[3][2];
+ R[0][3] = B[0][0] * A[0][3] + B[0][1] * A[1][3] + B[0][2] * A[2][3] + B[0][3] * A[3][3];
- m1[1][0] = m2[1][0] * m3[0][0] + m2[1][1] * m3[1][0] + m2[1][2] * m3[2][0] + m2[1][3] * m3[3][0];
- m1[1][1] = m2[1][0] * m3[0][1] + m2[1][1] * m3[1][1] + m2[1][2] * m3[2][1] + m2[1][3] * m3[3][1];
- m1[1][2] = m2[1][0] * m3[0][2] + m2[1][1] * m3[1][2] + m2[1][2] * m3[2][2] + m2[1][3] * m3[3][2];
- m1[1][3] = m2[1][0] * m3[0][3] + m2[1][1] * m3[1][3] + m2[1][2] * m3[2][3] + m2[1][3] * m3[3][3];
+ R[1][0] = B[1][0] * A[0][0] + B[1][1] * A[1][0] + B[1][2] * A[2][0] + B[1][3] * A[3][0];
+ R[1][1] = B[1][0] * A[0][1] + B[1][1] * A[1][1] + B[1][2] * A[2][1] + B[1][3] * A[3][1];
+ R[1][2] = B[1][0] * A[0][2] + B[1][1] * A[1][2] + B[1][2] * A[2][2] + B[1][3] * A[3][2];
+ R[1][3] = B[1][0] * A[0][3] + B[1][1] * A[1][3] + B[1][2] * A[2][3] + B[1][3] * A[3][3];
- m1[2][0] = m2[2][0] * m3[0][0] + m2[2][1] * m3[1][0] + m2[2][2] * m3[2][0] + m2[2][3] * m3[3][0];
- m1[2][1] = m2[2][0] * m3[0][1] + m2[2][1] * m3[1][1] + m2[2][2] * m3[2][1] + m2[2][3] * m3[3][1];
- m1[2][2] = m2[2][0] * m3[0][2] + m2[2][1] * m3[1][2] + m2[2][2] * m3[2][2] + m2[2][3] * m3[3][2];
- m1[2][3] = m2[2][0] * m3[0][3] + m2[2][1] * m3[1][3] + m2[2][2] * m3[2][3] + m2[2][3] * m3[3][3];
+ R[2][0] = B[2][0] * A[0][0] + B[2][1] * A[1][0] + B[2][2] * A[2][0] + B[2][3] * A[3][0];
+ R[2][1] = B[2][0] * A[0][1] + B[2][1] * A[1][1] + B[2][2] * A[2][1] + B[2][3] * A[3][1];
+ R[2][2] = B[2][0] * A[0][2] + B[2][1] * A[1][2] + B[2][2] * A[2][2] + B[2][3] * A[3][2];
+ R[2][3] = B[2][0] * A[0][3] + B[2][1] * A[1][3] + B[2][2] * A[2][3] + B[2][3] * A[3][3];
- m1[3][0] = m2[3][0] * m3[0][0] + m2[3][1] * m3[1][0] + m2[3][2] * m3[2][0] + m2[3][3] * m3[3][0];
- m1[3][1] = m2[3][0] * m3[0][1] + m2[3][1] * m3[1][1] + m2[3][2] * m3[2][1] + m2[3][3] * m3[3][1];
- m1[3][2] = m2[3][0] * m3[0][2] + m2[3][1] * m3[1][2] + m2[3][2] * m3[2][2] + m2[3][3] * m3[3][2];
- m1[3][3] = m2[3][0] * m3[0][3] + m2[3][1] * m3[1][3] + m2[3][2] * m3[2][3] + m2[3][3] * m3[3][3];
+ R[3][0] = B[3][0] * A[0][0] + B[3][1] * A[1][0] + B[3][2] * A[2][0] + B[3][3] * A[3][0];
+ R[3][1] = B[3][0] * A[0][1] + B[3][1] * A[1][1] + B[3][2] * A[2][1] + B[3][3] * A[3][1];
+ R[3][2] = B[3][0] * A[0][2] + B[3][1] * A[1][2] + B[3][2] * A[2][2] + B[3][3] * A[3][2];
+ R[3][3] = B[3][0] * A[0][3] + B[3][1] * A[1][3] + B[3][2] * A[2][3] + B[3][3] * A[3][3];
+}
+void mul_m4_m4_pre(float R[4][4], const float A[4][4])
+{
+ BLI_assert(A != R);
+ float B[4][4];
+ copy_m4_m4(B, R);
+ mul_m4_m4m4_uniq(R, A, B);
}
-void mul_m3_m3m3(float m1[3][3], float m3_[3][3], float m2_[3][3])
+void mul_m4_m4_post(float R[4][4], const float B[4][4])
{
- float m2[3][3], m3[3][3];
+ BLI_assert(B != R);
+ float A[4][4];
+ copy_m4_m4(A, R);
+ mul_m4_m4m4_uniq(R, A, B);
+}
- /* copy so it works when m1 is the same pointer as m2 or m3 */
- copy_m3_m3(m2, m2_);
- copy_m3_m3(m3, m3_);
+void mul_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3])
+{
+ if (A == R)
+ mul_m3_m3_post(R, B);
+ else if (B == R)
+ mul_m3_m3_pre(R, A);
+ else
+ mul_m3_m3m3_uniq(R, A, B);
+}
- /* m1[i][j] = m2[i][k] * m3[k][j], args are flipped! */
- m1[0][0] = m2[0][0] * m3[0][0] + m2[0][1] * m3[1][0] + m2[0][2] * m3[2][0];
- m1[0][1] = m2[0][0] * m3[0][1] + m2[0][1] * m3[1][1] + m2[0][2] * m3[2][1];
- m1[0][2] = m2[0][0] * m3[0][2] + m2[0][1] * m3[1][2] + m2[0][2] * m3[2][2];
+void mul_m3_m3_pre(float R[3][3], const float A[3][3])
+{
+ BLI_assert(A != R);
+ float B[3][3];
+ copy_m3_m3(B, R);
+ mul_m3_m3m3_uniq(R, A, B);
+}
- m1[1][0] = m2[1][0] * m3[0][0] + m2[1][1] * m3[1][0] + m2[1][2] * m3[2][0];
- m1[1][1] = m2[1][0] * m3[0][1] + m2[1][1] * m3[1][1] + m2[1][2] * m3[2][1];
- m1[1][2] = m2[1][0] * m3[0][2] + m2[1][1] * m3[1][2] + m2[1][2] * m3[2][2];
+void mul_m3_m3_post(float R[3][3], const float B[3][3])
+{
+ BLI_assert(B != R);
+ float A[3][3];
+ copy_m3_m3(A, R);
+ mul_m3_m3m3_uniq(R, A, B);
+}
- m1[2][0] = m2[2][0] * m3[0][0] + m2[2][1] * m3[1][0] + m2[2][2] * m3[2][0];
- m1[2][1] = m2[2][0] * m3[0][1] + m2[2][1] * m3[1][1] + m2[2][2] * m3[2][1];
- m1[2][2] = m2[2][0] * m3[0][2] + m2[2][1] * m3[1][2] + m2[2][2] * m3[2][2];
+void mul_m3_m3m3_uniq(float R[3][3], const float A[3][3], const float B[3][3])
+{
+ BLI_assert(R != A && R != B);
+
+ R[0][0] = B[0][0] * A[0][0] + B[0][1] * A[1][0] + B[0][2] * A[2][0];
+ R[0][1] = B[0][0] * A[0][1] + B[0][1] * A[1][1] + B[0][2] * A[2][1];
+ R[0][2] = B[0][0] * A[0][2] + B[0][1] * A[1][2] + B[0][2] * A[2][2];
+
+ R[1][0] = B[1][0] * A[0][0] + B[1][1] * A[1][0] + B[1][2] * A[2][0];
+ R[1][1] = B[1][0] * A[0][1] + B[1][1] * A[1][1] + B[1][2] * A[2][1];
+ R[1][2] = B[1][0] * A[0][2] + B[1][1] * A[1][2] + B[1][2] * A[2][2];
+
+ R[2][0] = B[2][0] * A[0][0] + B[2][1] * A[1][0] + B[2][2] * A[2][0];
+ R[2][1] = B[2][0] * A[0][1] + B[2][1] * A[1][1] + B[2][2] * A[2][1];
+ R[2][2] = B[2][0] * A[0][2] + B[2][1] * A[1][2] + B[2][2] * A[2][2];
}
-void mul_m4_m4m3(float m1[4][4], float m3_[4][4], float m2_[3][3])
+void mul_m4_m4m3(float m1[4][4], const float m3_[4][4], const float m2_[3][3])
{
float m2[3][3], m3[4][4];
/* copy so it works when m1 is the same pointer as m2 or m3 */
+ /* TODO: avoid copying when matrices are different */
copy_m3_m3(m2, m2_);
copy_m4_m4(m3, m3_);
@@ -250,11 +293,12 @@ void mul_m4_m4m3(float m1[4][4], float m3_[4][4], float m2_[3][3])
}
/* m1 = m2 * m3, ignore the elements on the 4th row/column of m3 */
-void mul_m3_m3m4(float m1[3][3], float m3_[4][4], float m2_[3][3])
+void mul_m3_m3m4(float m1[3][3], const float m3_[4][4], const float m2_[3][3])
{
float m2[3][3], m3[4][4];
/* copy so it works when m1 is the same pointer as m2 or m3 */
+ /* TODO: avoid copying when matrices are different */
copy_m3_m3(m2, m2_);
copy_m4_m4(m3, m3_);
@@ -272,11 +316,12 @@ void mul_m3_m3m4(float m1[3][3], float m3_[4][4], float m2_[3][3])
m1[2][2] = m2[2][0] * m3[0][2] + m2[2][1] * m3[1][2] + m2[2][2] * m3[2][2];
}
-void mul_m4_m3m4(float m1[4][4], float m3_[3][3], float m2_[4][4])
+void mul_m4_m3m4(float m1[4][4], const float m3_[3][3], const float m2_[4][4])
{
float m2[4][4], m3[3][3];
/* copy so it works when m1 is the same pointer as m2 or m3 */
+ /* TODO: avoid copying when matrices are different */
copy_m4_m4(m2, m2_);
copy_m3_m3(m3, m3_);
@@ -434,7 +479,7 @@ void _va_mul_m4_series_9(
}
/** \} */
-void mul_v2_m3v2(float r[2], float m[3][3], float v[2])
+void mul_v2_m3v2(float r[2], const float m[3][3], const float v[2])
{
float temp[3], warped[3];
@@ -447,12 +492,12 @@ void mul_v2_m3v2(float r[2], float m[3][3], float v[2])
r[1] = warped[1] / warped[2];
}
-void mul_m3_v2(float m[3][3], float r[2])
+void mul_m3_v2(const float m[3][3], float r[2])
{
mul_v2_m3v2(r, m, r);
}
-void mul_m4_v3(float mat[4][4], float vec[3])
+void mul_m4_v3(const float mat[4][4], float vec[3])
{
const float x = vec[0];
const float y = vec[1];
@@ -462,7 +507,7 @@ void mul_m4_v3(float mat[4][4], float vec[3])
vec[2] = x * mat[0][2] + y * mat[1][2] + mat[2][2] * vec[2] + mat[3][2];
}
-void mul_v3_m4v3(float r[3], float mat[4][4], const float vec[3])
+void mul_v3_m4v3(float r[3], const float mat[4][4], const float vec[3])
{
const float x = vec[0];
const float y = vec[1];
@@ -472,7 +517,7 @@ void mul_v3_m4v3(float r[3], float mat[4][4], const float vec[3])
r[2] = x * mat[0][2] + y * mat[1][2] + mat[2][2] * vec[2] + mat[3][2];
}
-void mul_v2_m4v3(float r[2], float mat[4][4], const float vec[3])
+void mul_v2_m4v3(float r[2], const float mat[4][4], const float vec[3])
{
const float x = vec[0];
@@ -480,7 +525,7 @@ void mul_v2_m4v3(float r[2], float mat[4][4], const float vec[3])
r[1] = x * mat[0][1] + vec[1] * mat[1][1] + mat[2][1] * vec[2] + mat[3][1];
}
-void mul_v2_m2v2(float r[2], float mat[2][2], const float vec[2])
+void mul_v2_m2v2(float r[2], const float mat[2][2], const float vec[2])
{
const float x = vec[0];
@@ -488,13 +533,13 @@ void mul_v2_m2v2(float r[2], float mat[2][2], const float vec[2])
r[1] = mat[0][1] * x + mat[1][1] * vec[1];
}
-void mul_m2v2(float mat[2][2], float vec[2])
+void mul_m2v2(const float mat[2][2], float vec[2])
{
mul_v2_m2v2(vec, mat, vec);
}
/* same as mul_m4_v3() but doesnt apply translation component */
-void mul_mat3_m4_v3(float mat[4][4], float vec[3])
+void mul_mat3_m4_v3(const float mat[4][4], float vec[3])
{
const float x = vec[0];
const float y = vec[1];
@@ -504,7 +549,7 @@ void mul_mat3_m4_v3(float mat[4][4], float vec[3])
vec[2] = x * mat[0][2] + y * mat[1][2] + mat[2][2] * vec[2];
}
-void mul_v3_mat3_m4v3(float r[3], float mat[4][4], const float vec[3])
+void mul_v3_mat3_m4v3(float r[3], const float mat[4][4], const float vec[3])
{
const float x = vec[0];
const float y = vec[1];
@@ -514,7 +559,7 @@ void mul_v3_mat3_m4v3(float r[3], float mat[4][4], const float vec[3])
r[2] = x * mat[0][2] + y * mat[1][2] + mat[2][2] * vec[2];
}
-void mul_project_m4_v3(float mat[4][4], float vec[3])
+void mul_project_m4_v3(const float mat[4][4], float vec[3])
{
/* absolute value to not flip the frustum upside down behind the camera */
const float w = fabsf(mul_project_m4_v3_zfac(mat, vec));
@@ -525,7 +570,7 @@ void mul_project_m4_v3(float mat[4][4], float vec[3])
vec[2] /= w;
}
-void mul_v3_project_m4_v3(float r[3], float mat[4][4], const float vec[3])
+void mul_v3_project_m4_v3(float r[3], const float mat[4][4], const float vec[3])
{
const float w = fabsf(mul_project_m4_v3_zfac(mat, vec));
mul_v3_m4v3(r, mat, vec);
@@ -535,7 +580,7 @@ void mul_v3_project_m4_v3(float r[3], float mat[4][4], const float vec[3])
r[2] /= w;
}
-void mul_v2_project_m4_v3(float r[2], float mat[4][4], const float vec[3])
+void mul_v2_project_m4_v3(float r[2], const float mat[4][4], const float vec[3])
{
const float w = fabsf(mul_project_m4_v3_zfac(mat, vec));
mul_v2_m4v3(r, mat, vec);
@@ -544,7 +589,7 @@ void mul_v2_project_m4_v3(float r[2], float mat[4][4], const float vec[3])
r[1] /= w;
}
-void mul_v4_m4v4(float r[4], float mat[4][4], const float v[4])
+void mul_v4_m4v4(float r[4], const float mat[4][4], const float v[4])
{
const float x = v[0];
const float y = v[1];
@@ -556,12 +601,12 @@ void mul_v4_m4v4(float r[4], float mat[4][4], const float v[4])
r[3] = x * mat[0][3] + y * mat[1][3] + z * mat[2][3] + mat[3][3] * v[3];
}
-void mul_m4_v4(float mat[4][4], float r[4])
+void mul_m4_v4(const float mat[4][4], float r[4])
{
mul_v4_m4v4(r, mat, r);
}
-void mul_v4d_m4v4d(double r[4], float mat[4][4], double v[4])
+void mul_v4d_m4v4d(double r[4], const float mat[4][4], const double v[4])
{
const double x = v[0];
const double y = v[1];
@@ -573,12 +618,21 @@ void mul_v4d_m4v4d(double r[4], float mat[4][4], double v[4])
r[3] = x * (double)mat[0][3] + y * (double)mat[1][3] + z * (double)mat[2][3] + (double)mat[3][3] * v[3];
}
-void mul_m4_v4d(float mat[4][4], double r[4])
+void mul_m4_v4d(const float mat[4][4], double r[4])
{
mul_v4d_m4v4d(r, mat, r);
}
-void mul_v3_m3v3(float r[3], float M[3][3], const float a[3])
+void mul_v4_m4v3(float r[4], const float M[4][4], const float v[3])
+{
+ /* v has implicit w = 1.0f */
+ r[0] = v[0] * M[0][0] + v[1] * M[1][0] + M[2][0] * v[2] + M[3][0];
+ r[1] = v[0] * M[0][1] + v[1] * M[1][1] + M[2][1] * v[2] + M[3][1];
+ r[2] = v[0] * M[0][2] + v[1] * M[1][2] + M[2][2] * v[2] + M[3][2];
+ r[3] = v[0] * M[0][3] + v[1] * M[1][3] + M[2][3] * v[2] + M[3][3];
+}
+
+void mul_v3_m3v3(float r[3], const float M[3][3], const float a[3])
{
BLI_assert(r != a);
@@ -587,7 +641,7 @@ void mul_v3_m3v3(float r[3], float M[3][3], const float a[3])
r[2] = M[0][2] * a[0] + M[1][2] * a[1] + M[2][2] * a[2];
}
-void mul_v3_m3v3_db(double r[3], double M[3][3], const double a[3])
+void mul_v3_m3v3_db(double r[3], const double M[3][3], const double a[3])
{
BLI_assert(r != a);
@@ -596,7 +650,7 @@ void mul_v3_m3v3_db(double r[3], double M[3][3], const double a[3])
r[2] = M[0][2] * a[0] + M[1][2] * a[1] + M[2][2] * a[2];
}
-void mul_v2_m3v3(float r[2], float M[3][3], const float a[3])
+void mul_v2_m3v3(float r[2], const float M[3][3], const float a[3])
{
BLI_assert(r != a);
@@ -604,17 +658,17 @@ void mul_v2_m3v3(float r[2], float M[3][3], const float a[3])
r[1] = M[0][1] * a[0] + M[1][1] * a[1] + M[2][1] * a[2];
}
-void mul_m3_v3(float M[3][3], float r[3])
+void mul_m3_v3(const float M[3][3], float r[3])
{
mul_v3_m3v3(r, M, (const float[3]){UNPACK3(r)});
}
-void mul_m3_v3_db(double M[3][3], double r[3])
+void mul_m3_v3_db(const double M[3][3], double r[3])
{
mul_v3_m3v3_db(r, M, (const double[3]){UNPACK3(r)});
}
-void mul_transposed_m3_v3(float mat[3][3], float vec[3])
+void mul_transposed_m3_v3(const float mat[3][3], float vec[3])
{
const float x = vec[0];
const float y = vec[1];
@@ -624,7 +678,7 @@ void mul_transposed_m3_v3(float mat[3][3], float vec[3])
vec[2] = x * mat[2][0] + y * mat[2][1] + mat[2][2] * vec[2];
}
-void mul_transposed_mat3_m4_v3(float mat[4][4], float vec[3])
+void mul_transposed_mat3_m4_v3(const float mat[4][4], float vec[3])
{
const float x = vec[0];
const float y = vec[1];
@@ -688,7 +742,7 @@ void negate_m4(float m[4][4])
m[i][j] *= -1.0f;
}
-void mul_m3_v3_double(float mat[3][3], double vec[3])
+void mul_m3_v3_double(const float mat[3][3], double vec[3])
{
const double x = vec[0];
const double y = vec[1];
@@ -698,7 +752,7 @@ void mul_m3_v3_double(float mat[3][3], double vec[3])
vec[2] = x * (double)mat[0][2] + y * (double)mat[1][2] + (double)mat[2][2] * vec[2];
}
-void add_m3_m3m3(float m1[3][3], float m2[3][3], float m3[3][3])
+void add_m3_m3m3(float m1[3][3], const float m2[3][3], const float m3[3][3])
{
int i, j;
@@ -707,7 +761,7 @@ void add_m3_m3m3(float m1[3][3], float m2[3][3], float m3[3][3])
m1[i][j] = m2[i][j] + m3[i][j];
}
-void add_m4_m4m4(float m1[4][4], float m2[4][4], float m3[4][4])
+void add_m4_m4m4(float m1[4][4], const float m2[4][4], const float m3[4][4])
{
int i, j;
@@ -716,7 +770,7 @@ void add_m4_m4m4(float m1[4][4], float m2[4][4], float m3[4][4])
m1[i][j] = m2[i][j] + m3[i][j];
}
-void sub_m3_m3m3(float m1[3][3], float m2[3][3], float m3[3][3])
+void sub_m3_m3m3(float m1[3][3], const float m2[3][3], const float m3[3][3])
{
int i, j;
@@ -725,7 +779,7 @@ void sub_m3_m3m3(float m1[3][3], float m2[3][3], float m3[3][3])
m1[i][j] = m2[i][j] - m3[i][j];
}
-void sub_m4_m4m4(float m1[4][4], float m2[4][4], float m3[4][4])
+void sub_m4_m4m4(float m1[4][4], const float m2[4][4], const float m3[4][4])
{
int i, j;
@@ -734,7 +788,7 @@ void sub_m4_m4m4(float m1[4][4], float m2[4][4], float m3[4][4])
m1[i][j] = m2[i][j] - m3[i][j];
}
-float determinant_m3_array(float m[3][3])
+float determinant_m3_array(const float m[3][3])
{
return (m[0][0] * (m[1][1] * m[2][2] - m[1][2] * m[2][1]) -
m[1][0] * (m[0][1] * m[2][2] - m[0][2] * m[2][1]) +
@@ -750,7 +804,7 @@ bool invert_m3_ex(float m[3][3], const float epsilon)
return success;
}
-bool invert_m3_m3_ex(float m1[3][3], float m2[3][3], const float epsilon)
+bool invert_m3_m3_ex(float m1[3][3], const float m2[3][3], const float epsilon)
{
float det;
int a, b;
@@ -786,7 +840,7 @@ bool invert_m3(float m[3][3])
return success;
}
-bool invert_m3_m3(float m1[3][3], float m2[3][3])
+bool invert_m3_m3(float m1[3][3], const float m2[3][3])
{
float det;
int a, b;
@@ -830,7 +884,7 @@ bool invert_m4(float m[4][4])
* Mark Segal - 1992
*/
-bool invert_m4_m4(float inverse[4][4], float mat[4][4])
+bool invert_m4_m4(float inverse[4][4], const float mat[4][4])
{
int i, j, k;
double temp;
@@ -908,7 +962,7 @@ void transpose_m3(float mat[3][3])
mat[2][1] = t;
}
-void transpose_m3_m3(float rmat[3][3], float mat[3][3])
+void transpose_m3_m3(float rmat[3][3], const float mat[3][3])
{
BLI_assert(rmat != mat);
@@ -924,7 +978,7 @@ void transpose_m3_m3(float rmat[3][3], float mat[3][3])
}
/* seems obscure but in-fact a common operation */
-void transpose_m3_m4(float rmat[3][3], float mat[4][4])
+void transpose_m3_m4(float rmat[3][3], const float mat[4][4])
{
BLI_assert(&rmat[0][0] != &mat[0][0]);
@@ -965,7 +1019,7 @@ void transpose_m4(float mat[4][4])
mat[3][2] = t;
}
-void transpose_m4_m4(float rmat[4][4], float mat[4][4])
+void transpose_m4_m4(float rmat[4][4], const float mat[4][4])
{
BLI_assert(rmat != mat);
@@ -987,7 +1041,8 @@ void transpose_m4_m4(float rmat[4][4], float mat[4][4])
rmat[3][3] = mat[3][3];
}
-int compare_m4m4(float mat1[4][4], float mat2[4][4], float limit)
+/* TODO: return bool */
+int compare_m4m4(const float mat1[4][4], const float mat2[4][4], float limit)
{
if (compare_v4v4(mat1[0], mat2[0], limit))
if (compare_v4v4(mat1[1], mat2[1], limit))
@@ -1165,7 +1220,7 @@ void orthogonalize_m4(float mat[4][4], int axis)
mul_v3_fl(mat[2], size[2]);
}
-bool is_orthogonal_m3(float m[3][3])
+bool is_orthogonal_m3(const float m[3][3])
{
int i, j;
@@ -1179,7 +1234,7 @@ bool is_orthogonal_m3(float m[3][3])
return true;
}
-bool is_orthogonal_m4(float m[4][4])
+bool is_orthogonal_m4(const float m[4][4])
{
int i, j;
@@ -1194,7 +1249,7 @@ bool is_orthogonal_m4(float m[4][4])
return true;
}
-bool is_orthonormal_m3(float m[3][3])
+bool is_orthonormal_m3(const float m[3][3])
{
if (is_orthogonal_m3(m)) {
int i;
@@ -1209,7 +1264,7 @@ bool is_orthonormal_m3(float m[3][3])
return false;
}
-bool is_orthonormal_m4(float m[4][4])
+bool is_orthonormal_m4(const float m[4][4])
{
if (is_orthogonal_m4(m)) {
int i;
@@ -1224,7 +1279,7 @@ bool is_orthonormal_m4(float m[4][4])
return false;
}
-bool is_uniform_scaled_m3(float m[3][3])
+bool is_uniform_scaled_m3(const float m[3][3])
{
const float eps = 1e-7f;
float t[3][3];
@@ -1252,7 +1307,7 @@ bool is_uniform_scaled_m3(float m[3][3])
return false;
}
-bool is_uniform_scaled_m4(float m[4][4])
+bool is_uniform_scaled_m4(const float m[4][4])
{
float t[3][3];
copy_m3_m4(t, m);
@@ -1274,14 +1329,14 @@ void normalize_m3(float mat[3][3])
}
}
-void normalize_m3_m3_ex(float rmat[3][3], float mat[3][3], float r_scale[3])
+void normalize_m3_m3_ex(float rmat[3][3], const float mat[3][3], float r_scale[3])
{
int i;
for (i = 0; i < 3; i++) {
r_scale[i] = normalize_v3_v3(rmat[i], mat[i]);
}
}
-void normalize_m3_m3(float rmat[3][3], float mat[3][3])
+void normalize_m3_m3(float rmat[3][3], const float mat[3][3])
{
int i;
for (i = 0; i < 3; i++) {
@@ -1310,7 +1365,7 @@ void normalize_m4(float mat[4][4])
}
}
-void normalize_m4_m4_ex(float rmat[4][4], float mat[4][4], float r_scale[3])
+void normalize_m4_m4_ex(float rmat[4][4], const float mat[4][4], float r_scale[3])
{
int i;
for (i = 0; i < 3; i++) {
@@ -1319,7 +1374,7 @@ void normalize_m4_m4_ex(float rmat[4][4], float mat[4][4], float r_scale[3])
}
copy_v4_v4(rmat[3], mat[3]);
}
-void normalize_m4_m4(float rmat[4][4], float mat[4][4])
+void normalize_m4_m4(float rmat[4][4], const float mat[4][4])
{
int i;
for (i = 0; i < 3; i++) {
@@ -1329,7 +1384,7 @@ void normalize_m4_m4(float rmat[4][4], float mat[4][4])
copy_v4_v4(rmat[3], mat[3]);
}
-void adjoint_m2_m2(float m1[2][2], float m[2][2])
+void adjoint_m2_m2(float m1[2][2], const float m[2][2])
{
BLI_assert(m1 != m);
m1[0][0] = m[1][1];
@@ -1338,7 +1393,7 @@ void adjoint_m2_m2(float m1[2][2], float m[2][2])
m1[1][1] = m[0][0];
}
-void adjoint_m3_m3(float m1[3][3], float m[3][3])
+void adjoint_m3_m3(float m1[3][3], const float m[3][3])
{
BLI_assert(m1 != m);
m1[0][0] = m[1][1] * m[2][2] - m[1][2] * m[2][1];
@@ -1354,7 +1409,7 @@ void adjoint_m3_m3(float m1[3][3], float m[3][3])
m1[2][2] = m[0][0] * m[1][1] - m[0][1] * m[1][0];
}
-void adjoint_m4_m4(float out[4][4], float in[4][4]) /* out = ADJ(in) */
+void adjoint_m4_m4(float out[4][4], const float in[4][4]) /* out = ADJ(in) */
{
float a1, a2, a3, a4, b1, b2, b3, b4;
float c1, c2, c3, c4, d1, d2, d3, d4;
@@ -1420,7 +1475,7 @@ float determinant_m3(float a1, float a2, float a3,
return ans;
}
-float determinant_m4(float m[4][4])
+float determinant_m4(const float m[4][4])
{
float ans;
float a1, a2, a3, a4, b1, b2, b3, b4, c1, c2, c3, c4, d1, d2, d3, d4;
@@ -1488,14 +1543,14 @@ void size_to_mat4(float mat[4][4], const float size[3])
mat[3][3] = 1.0f;
}
-void mat3_to_size(float size[3], float mat[3][3])
+void mat3_to_size(float size[3], const float mat[3][3])
{
size[0] = len_v3(mat[0]);
size[1] = len_v3(mat[1]);
size[2] = len_v3(mat[2]);
}
-void mat4_to_size(float size[3], float mat[4][4])
+void mat4_to_size(float size[3], const float mat[4][4])
{
size[0] = len_v3(mat[0]);
size[1] = len_v3(mat[1]);
@@ -1505,7 +1560,7 @@ void mat4_to_size(float size[3], float mat[4][4])
/* this gets the average scale of a matrix, only use when your scaling
* data that has no idea of scale axis, examples are bone-envelope-radius
* and curve radius */
-float mat3_to_scale(float mat[3][3])
+float mat3_to_scale(const float mat[3][3])
{
/* unit length vector */
float unit_vec[3];
@@ -1514,7 +1569,7 @@ float mat3_to_scale(float mat[3][3])
return len_v3(unit_vec);
}
-float mat4_to_scale(float mat[4][4])
+float mat4_to_scale(const float mat[4][4])
{
/* unit length vector */
float unit_vec[3];
@@ -1523,7 +1578,7 @@ float mat4_to_scale(float mat[4][4])
return len_v3(unit_vec);
}
-void mat3_to_rot_size(float rot[3][3], float size[3], float mat3[3][3])
+void mat3_to_rot_size(float rot[3][3], float size[3], const float mat3[3][3])
{
/* keep rot as a 3x3 matrix, the caller can convert into a quat or euler */
size[0] = normalize_v3_v3(rot[0], mat3[0]);
@@ -1535,7 +1590,7 @@ void mat3_to_rot_size(float rot[3][3], float size[3], float mat3[3][3])
}
}
-void mat4_to_loc_rot_size(float loc[3], float rot[3][3], float size[3], float wmat[4][4])
+void mat4_to_loc_rot_size(float loc[3], float rot[3][3], float size[3], const float wmat[4][4])
{
float mat3[3][3]; /* wmat -> 3x3 */
@@ -1546,7 +1601,7 @@ void mat4_to_loc_rot_size(float loc[3], float rot[3][3], float size[3], float wm
copy_v3_v3(loc, wmat[3]);
}
-void mat4_to_loc_quat(float loc[3], float quat[4], float wmat[4][4])
+void mat4_to_loc_quat(float loc[3], float quat[4], const float wmat[4][4])
{
float mat3[3][3];
float mat3_n[3][3]; /* normalized mat3 */
@@ -1564,7 +1619,7 @@ void mat4_to_loc_quat(float loc[3], float quat[4], float wmat[4][4])
copy_v3_v3(loc, wmat[3]);
}
-void mat4_decompose(float loc[3], float quat[4], float size[3], float wmat[4][4])
+void mat4_decompose(float loc[3], float quat[4], float size[3], const float wmat[4][4])
{
float rot[3][3];
mat4_to_loc_rot_size(loc, rot, size, wmat);
@@ -1581,7 +1636,7 @@ void mat4_decompose(float loc[3], float quat[4], float size[3], float wmat[4][4]
* See https://en.wikipedia.org/wiki/Polar_decomposition for more.
*/
#ifndef MATH_STANDALONE
-void mat3_polar_decompose(float mat3[3][3], float r_U[3][3], float r_P[3][3])
+void mat3_polar_decompose(const float mat3[3][3], float r_U[3][3], float r_P[3][3])
{
/* From svd decomposition (M = WSV*), we have:
* U = WV*
@@ -1625,6 +1680,7 @@ void translate_m4(float mat[4][4], float Tx, float Ty, float Tz)
mat[3][2] += (Tx * mat[0][2] + Ty * mat[1][2] + Tz * mat[2][2]);
}
+/* TODO: enum for axis? */
void rotate_m4(float mat[4][4], const char axis, const float angle)
{
int col;
@@ -1694,7 +1750,7 @@ void transform_pivot_set_m4(float mat[4][4], const float pivot[3])
mul_m4_m4m4(mat, mat, tmat);
}
-void blend_m3_m3m3(float out[3][3], float dst[3][3], float src[3][3], const float srcweight)
+void blend_m3_m3m3(float out[3][3], const float dst[3][3], const float src[3][3], const float srcweight)
{
float srot[3][3], drot[3][3];
float squat[4], dquat[4], fquat[4];
@@ -1717,7 +1773,7 @@ void blend_m3_m3m3(float out[3][3], float dst[3][3], float src[3][3], const floa
mul_m3_m3m3(out, rmat, smat);
}
-void blend_m4_m4m4(float out[4][4], float dst[4][4], float src[4][4], const float srcweight)
+void blend_m4_m4m4(float out[4][4], const float dst[4][4], const float src[4][4], const float srcweight)
{
float sloc[3], dloc[3], floc[3];
float srot[3][3], drot[3][3];
@@ -1755,7 +1811,7 @@ void blend_m4_m4m4(float out[4][4], float dst[4][4], float src[4][4], const floa
* @param B the intput matrix which is totally effective with \a t = 1.0.
* @param t the interpolation factor.
*/
-void interp_m3_m3m3(float R[3][3], float A[3][3], float B[3][3], const float t)
+void interp_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3], const float t)
{
/* 'Rotation' component ('U' part of polar decomposition, the closest orthogonal matrix to M3 rot/scale
* transformation matrix), spherically interpolated. */
@@ -1790,7 +1846,7 @@ void interp_m3_m3m3(float R[3][3], float A[3][3], float B[3][3], const float t)
* @param B the intput matrix which is totally effective with \a t = 1.0.
* @param t the interpolation factor.
*/
-void interp_m4_m4m4(float R[4][4], float A[4][4], float B[4][4], const float t)
+void interp_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4], const float t)
{
float A3[3][3], B3[3][3], R3[3][3];
@@ -1811,27 +1867,27 @@ void interp_m4_m4m4(float R[4][4], float A[4][4], float B[4][4], const float t)
}
#endif /* MATH_STANDALONE */
-bool is_negative_m3(float mat[3][3])
+bool is_negative_m3(const float mat[3][3])
{
float vec[3];
cross_v3_v3v3(vec, mat[0], mat[1]);
return (dot_v3v3(vec, mat[2]) < 0.0f);
}
-bool is_negative_m4(float mat[4][4])
+bool is_negative_m4(const float mat[4][4])
{
float vec[3];
cross_v3_v3v3(vec, mat[0], mat[1]);
return (dot_v3v3(vec, mat[2]) < 0.0f);
}
-bool is_zero_m3(float mat[3][3])
+bool is_zero_m3(const float mat[3][3])
{
return (is_zero_v3(mat[0]) &&
is_zero_v3(mat[1]) &&
is_zero_v3(mat[2]));
}
-bool is_zero_m4(float mat[4][4])
+bool is_zero_m4(const float mat[4][4])
{
return (is_zero_v4(mat[0]) &&
is_zero_v4(mat[1]) &&
@@ -1839,14 +1895,14 @@ bool is_zero_m4(float mat[4][4])
is_zero_v4(mat[3]));
}
-bool equals_m3m3(float mat1[3][3], float mat2[3][3])
+bool equals_m3m3(const float mat1[3][3], const float mat2[3][3])
{
return (equals_v3v3(mat1[0], mat2[0]) &&
equals_v3v3(mat1[1], mat2[1]) &&
equals_v3v3(mat1[2], mat2[2]));
}
-bool equals_m4m4(float mat1[4][4], float mat2[4][4])
+bool equals_m4m4(const float mat1[4][4], const float mat2[4][4])
{
return (equals_v4v4(mat1[0], mat2[0]) &&
equals_v4v4(mat1[1], mat2[1]) &&
@@ -1937,7 +1993,7 @@ void loc_axisangle_size_to_mat4(float mat[4][4], const float loc[3], const float
/*********************************** Other ***********************************/
-void print_m3(const char *str, float m[3][3])
+void print_m3(const char *str, const float m[3][3])
{
printf("%s\n", str);
printf("%f %f %f\n", m[0][0], m[1][0], m[2][0]);
@@ -1946,7 +2002,7 @@ void print_m3(const char *str, float m[3][3])
printf("\n");
}
-void print_m4(const char *str, float m[4][4])
+void print_m4(const char *str, const float m[4][4])
{
printf("%s\n", str);
printf("%f %f %f %f\n", m[0][0], m[1][0], m[2][0], m[3][0]);
@@ -2400,7 +2456,7 @@ void svd_m4(float U[4][4], float s[4], float V[4][4], float A_[4][4])
}
}
-void pseudoinverse_m4_m4(float Ainv[4][4], float A_[4][4], float epsilon)
+void pseudoinverse_m4_m4(float Ainv[4][4], const float A_[4][4], float epsilon)
{
/* compute Moore-Penrose pseudo inverse of matrix, singular values
* below epsilon are ignored for stability (truncated SVD) */
@@ -2421,7 +2477,7 @@ void pseudoinverse_m4_m4(float Ainv[4][4], float A_[4][4], float epsilon)
mul_m4_series(Ainv, U, Wm, V);
}
-void pseudoinverse_m3_m3(float Ainv[3][3], float A[3][3], float epsilon)
+void pseudoinverse_m3_m3(float Ainv[3][3], const float A[3][3], float epsilon)
{
/* try regular inverse when possible, otherwise fall back to slow svd */
if (!invert_m3_m3(Ainv, A)) {
@@ -2433,14 +2489,14 @@ void pseudoinverse_m3_m3(float Ainv[3][3], float A[3][3], float epsilon)
}
}
-bool has_zero_axis_m4(float matrix[4][4])
+bool has_zero_axis_m4(const float matrix[4][4])
{
return len_squared_v3(matrix[0]) < FLT_EPSILON ||
len_squared_v3(matrix[1]) < FLT_EPSILON ||
len_squared_v3(matrix[2]) < FLT_EPSILON;
}
-void invert_m4_m4_safe(float Ainv[4][4], float A[4][4])
+void invert_m4_m4_safe(float Ainv[4][4], const float A[4][4])
{
if (!invert_m4_m4(Ainv, A)) {
float Atemp[4][4];
@@ -2488,7 +2544,7 @@ void invert_m4_m4_safe(float Ainv[4][4], float A[4][4])
* this defines a transform matrix TM such that (x', y', z') = TM * (x, y, z)
* where (x', y', z') are the coordinates of P' in target space such that it keeps (X, Y, Z) coordinates in global space.
*/
-void BLI_space_transform_from_matrices(SpaceTransform *data, float local[4][4], float target[4][4])
+void BLI_space_transform_from_matrices(SpaceTransform *data, const float local[4][4], const float target[4][4])
{
float itarget[4][4];
invert_m4_m4(itarget, target);
@@ -2506,7 +2562,7 @@ void BLI_space_transform_from_matrices(SpaceTransform *data, float local[4][4],
* this defines a transform matrix TM such that (X', Y', Z') = TM * (X, Y, Z)
* where (X', Y', Z') are the coordinates of p' in global space such that it keeps (x, y, z) coordinates in target space.
*/
-void BLI_space_transform_global_from_matrices(SpaceTransform *data, float local[4][4], float target[4][4])
+void BLI_space_transform_global_from_matrices(SpaceTransform *data, const float local[4][4], const float target[4][4])
{
float ilocal[4][4];
invert_m4_m4(ilocal, local);
diff --git a/source/blender/blenlib/intern/math_vector.c b/source/blender/blenlib/intern/math_vector.c
index 95d5c9fde87..90e39da5d46 100644
--- a/source/blender/blenlib/intern/math_vector.c
+++ b/source/blender/blenlib/intern/math_vector.c
@@ -772,6 +772,20 @@ void ortho_v2_v2(float out[2], const float v[2])
}
/**
+ * Rotate a point \a p by \a angle around origin (0, 0)
+ */
+void rotate_v2_v2fl(float r[2], const float p[2], const float angle)
+{
+ const float co = cosf(angle);
+ const float si = sinf(angle);
+
+ BLI_assert(r != p);
+
+ r[0] = co * p[0] - si * p[1];
+ r[1] = si * p[0] + co * p[1];
+}
+
+/**
* Rotate a point \a p by \a angle around an arbitrary unit length \a axis.
* http://local.wasp.uwa.edu.au/~pbourke/geometry/
*/
diff --git a/source/blender/blenlib/intern/math_vector_inline.c b/source/blender/blenlib/intern/math_vector_inline.c
index e9fb77f6302..dbc46ffc233 100644
--- a/source/blender/blenlib/intern/math_vector_inline.c
+++ b/source/blender/blenlib/intern/math_vector_inline.c
@@ -480,7 +480,7 @@ MINLINE void mul_v2_v2_ccw(float r[2], const float mat[2], const float vec[2])
}
/* note: could add a matrix inline */
-MINLINE float mul_project_m4_v3_zfac(float mat[4][4], const float co[3])
+MINLINE float mul_project_m4_v3_zfac(const float mat[4][4], const float co[3])
{
return (mat[0][3] * co[0]) +
(mat[1][3] * co[1]) +
@@ -490,15 +490,15 @@ MINLINE float mul_project_m4_v3_zfac(float mat[4][4], const float co[3])
/**
* Has the effect of #mul_m3_v3(), on a single axis.
*/
-MINLINE float dot_m3_v3_row_x(float M[3][3], const float a[3])
+MINLINE float dot_m3_v3_row_x(const float M[3][3], const float a[3])
{
return M[0][0] * a[0] + M[1][0] * a[1] + M[2][0] * a[2];
}
-MINLINE float dot_m3_v3_row_y(float M[3][3], const float a[3])
+MINLINE float dot_m3_v3_row_y(const float M[3][3], const float a[3])
{
return M[0][1] * a[0] + M[1][1] * a[1] + M[2][1] * a[2];
}
-MINLINE float dot_m3_v3_row_z(float M[3][3], const float a[3])
+MINLINE float dot_m3_v3_row_z(const float M[3][3], const float a[3])
{
return M[0][2] * a[0] + M[1][2] * a[1] + M[2][2] * a[2];
}
@@ -507,15 +507,15 @@ MINLINE float dot_m3_v3_row_z(float M[3][3], const float a[3])
* Has the effect of #mul_mat3_m4_v3(), on a single axis.
* (no adding translation)
*/
-MINLINE float dot_m4_v3_row_x(float M[4][4], const float a[3])
+MINLINE float dot_m4_v3_row_x(const float M[4][4], const float a[3])
{
return M[0][0] * a[0] + M[1][0] * a[1] + M[2][0] * a[2];
}
-MINLINE float dot_m4_v3_row_y(float M[4][4], const float a[3])
+MINLINE float dot_m4_v3_row_y(const float M[4][4], const float a[3])
{
return M[0][1] * a[0] + M[1][1] * a[1] + M[2][1] * a[2];
}
-MINLINE float dot_m4_v3_row_z(float M[4][4], const float a[3])
+MINLINE float dot_m4_v3_row_z(const float M[4][4], const float a[3])
{
return M[0][2] * a[0] + M[1][2] * a[1] + M[2][2] * a[2];
}
@@ -745,7 +745,7 @@ MINLINE void add_newell_cross_v3_v3v3(float n[3], const float v_prev[3], const f
n[2] += (v_prev[0] - v_curr[0]) * (v_prev[1] + v_curr[1]);
}
-MINLINE void star_m3_v3(float rmat[3][3], float a[3])
+MINLINE void star_m3_v3(float rmat[3][3], const float a[3])
{
rmat[0][0] = rmat[1][1] = rmat[2][2] = 0.0;
rmat[0][1] = -a[2];
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index e097e35f60e..60e72fcff82 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -81,9 +81,9 @@
#include "DNA_nla_types.h"
#include "DNA_node_types.h"
#include "DNA_object_fluidsim.h" // NT
+#include "DNA_object_force.h"
#include "DNA_object_types.h"
#include "DNA_packedFile_types.h"
-#include "DNA_particle_types.h"
#include "DNA_property_types.h"
#include "DNA_rigidbody_types.h"
#include "DNA_text_types.h"
@@ -137,8 +137,6 @@
#include "BKE_node.h" // for tree type defines
#include "BKE_object.h"
#include "BKE_paint.h"
-#include "BKE_particle.h"
-#include "BKE_pointcache.h"
#include "BKE_report.h"
#include "BKE_sca.h" // for init_actuator
#include "BKE_scene.h"
@@ -3979,83 +3977,6 @@ static void direct_link_material(FileData *fd, Material *ma)
}
/* ************ READ PARTICLE SETTINGS ***************** */
-/* update this also to writefile.c */
-static const char *ptcache_data_struct[] = {
- "", // BPHYS_DATA_INDEX
- "", // BPHYS_DATA_LOCATION
- "", // BPHYS_DATA_VELOCITY
- "", // BPHYS_DATA_ROTATION
- "", // BPHYS_DATA_AVELOCITY / BPHYS_DATA_XCONST */
- "", // BPHYS_DATA_SIZE:
- "", // BPHYS_DATA_TIMES:
- "BoidData" // case BPHYS_DATA_BOIDS:
-};
-
-static void direct_link_pointcache_cb(FileData *fd, void *data)
-{
- PTCacheMem *pm = data;
- PTCacheExtra *extra;
- int i;
- for (i = 0; i < BPHYS_TOT_DATA; i++) {
- pm->data[i] = newdataadr(fd, pm->data[i]);
-
- /* the cache saves non-struct data without DNA */
- if (pm->data[i] && ptcache_data_struct[i][0]=='\0' && (fd->flags & FD_FLAGS_SWITCH_ENDIAN)) {
- int tot = (BKE_ptcache_data_size(i) * pm->totpoint) / sizeof(int); /* data_size returns bytes */
- int *poin = pm->data[i];
-
- BLI_endian_switch_int32_array(poin, tot);
- }
- }
-
- link_list(fd, &pm->extradata);
-
- for (extra=pm->extradata.first; extra; extra=extra->next)
- extra->data = newdataadr(fd, extra->data);
-}
-
-static void direct_link_pointcache(FileData *fd, PointCache *cache)
-{
- if ((cache->flag & PTCACHE_DISK_CACHE)==0) {
- link_list_ex(fd, &cache->mem_cache, direct_link_pointcache_cb);
- }
- else
- BLI_listbase_clear(&cache->mem_cache);
-
- cache->flag &= ~PTCACHE_SIMULATION_VALID;
- cache->simframe = 0;
- cache->edit = NULL;
- cache->free_edit = NULL;
- cache->cached_frames = NULL;
-}
-
-static void direct_link_pointcache_list(FileData *fd, ListBase *ptcaches, PointCache **ocache, int force_disk)
-{
- if (ptcaches->first) {
- PointCache *cache= NULL;
- link_list(fd, ptcaches);
- for (cache=ptcaches->first; cache; cache=cache->next) {
- direct_link_pointcache(fd, cache);
- if (force_disk) {
- cache->flag |= PTCACHE_DISK_CACHE;
- cache->step = 1;
- }
- }
-
- *ocache = newdataadr(fd, *ocache);
- }
- else if (*ocache) {
- /* old "single" caches need to be linked too */
- *ocache = newdataadr(fd, *ocache);
- direct_link_pointcache(fd, *ocache);
- if (force_disk) {
- (*ocache)->flag |= PTCACHE_DISK_CACHE;
- (*ocache)->step = 1;
- }
-
- ptcaches->first = ptcaches->last = *ocache;
- }
-}
static void lib_link_partdeflect(FileData *fd, ID *id, PartDeflect *pd)
{
@@ -4065,279 +3986,11 @@ static void lib_link_partdeflect(FileData *fd, ID *id, PartDeflect *pd)
pd->f_source = newlibadr(fd, id->lib, pd->f_source);
}
-static void lib_link_particlesettings(FileData *fd, Main *main)
-{
- ParticleSettings *part;
- ParticleDupliWeight *dw;
- MTex *mtex;
- int a;
-
- for (part = main->particle.first; part; part = part->id.next) {
- if (part->id.tag & LIB_TAG_NEED_LINK) {
- lib_link_animdata(fd, &part->id, part->adt);
- part->ipo = newlibadr_us(fd, part->id.lib, part->ipo); // XXX deprecated - old animation system
-
- part->dup_ob = newlibadr(fd, part->id.lib, part->dup_ob);
- part->dup_group = newlibadr(fd, part->id.lib, part->dup_group);
- part->eff_group = newlibadr(fd, part->id.lib, part->eff_group);
- part->bb_ob = newlibadr(fd, part->id.lib, part->bb_ob);
- part->collision_group = newlibadr(fd, part->id.lib, part->collision_group);
-
- lib_link_partdeflect(fd, &part->id, part->pd);
- lib_link_partdeflect(fd, &part->id, part->pd2);
-
- if (part->effector_weights) {
- part->effector_weights->group = newlibadr(fd, part->id.lib, part->effector_weights->group);
- }
- else {
- part->effector_weights = BKE_add_effector_weights(part->eff_group);
- }
-
- if (part->dupliweights.first && part->dup_group) {
- int index_ok = 0;
- /* check for old files without indices (all indexes 0) */
- if (BLI_listbase_is_single(&part->dupliweights)) {
- /* special case for only one object in the group */
- index_ok = 1;
- }
- else {
- for (dw = part->dupliweights.first; dw; dw = dw->next) {
- if (dw->index > 0) {
- index_ok = 1;
- break;
- }
- }
- }
-
- if (index_ok) {
- /* if we have indexes, let's use them */
- for (dw = part->dupliweights.first; dw; dw = dw->next) {
- /* Do not try to restore pointer here, we have to search for group objects in another
- * separated step.
- * Reason is, the used group may be linked from another library, which has not yet
- * been 'lib_linked'.
- * Since dw->ob is not considered as an object user (it does not make objet directly linked),
- * we may have no valid way to retrieve it yet.
- * See T49273. */
- dw->ob = NULL;
- }
- }
- else {
- /* otherwise try to get objects from own library (won't work on library linked groups) */
- for (dw = part->dupliweights.first; dw; dw = dw->next) {
- dw->ob = newlibadr(fd, part->id.lib, dw->ob);
- }
- }
- }
- else {
- BLI_listbase_clear(&part->dupliweights);
- }
-
- if (part->boids) {
- BoidState *state = part->boids->states.first;
- BoidRule *rule;
- for (; state; state=state->next) {
- rule = state->rules.first;
- for (; rule; rule=rule->next) {
- switch (rule->type) {
- case eBoidRuleType_Goal:
- case eBoidRuleType_Avoid:
- {
- BoidRuleGoalAvoid *brga = (BoidRuleGoalAvoid*)rule;
- brga->ob = newlibadr(fd, part->id.lib, brga->ob);
- break;
- }
- case eBoidRuleType_FollowLeader:
- {
- BoidRuleFollowLeader *brfl = (BoidRuleFollowLeader*)rule;
- brfl->ob = newlibadr(fd, part->id.lib, brfl->ob);
- break;
- }
- }
- }
- }
- }
-
- for (a = 0; a < MAX_MTEX; a++) {
- mtex= part->mtex[a];
- if (mtex) {
- mtex->tex = newlibadr_us(fd, part->id.lib, mtex->tex);
- mtex->object = newlibadr(fd, part->id.lib, mtex->object);
- }
- }
-
- part->id.tag &= ~LIB_TAG_NEED_LINK;
- }
- }
-}
-
static void direct_link_partdeflect(PartDeflect *pd)
{
if (pd) pd->rng = NULL;
}
-static void direct_link_particlesettings(FileData *fd, ParticleSettings *part)
-{
- int a;
-
- part->adt = newdataadr(fd, part->adt);
- part->pd = newdataadr(fd, part->pd);
- part->pd2 = newdataadr(fd, part->pd2);
-
- direct_link_animdata(fd, part->adt);
- direct_link_partdeflect(part->pd);
- direct_link_partdeflect(part->pd2);
-
- part->clumpcurve = newdataadr(fd, part->clumpcurve);
- if (part->clumpcurve)
- direct_link_curvemapping(fd, part->clumpcurve);
- part->roughcurve = newdataadr(fd, part->roughcurve);
- if (part->roughcurve)
- direct_link_curvemapping(fd, part->roughcurve);
-
- part->effector_weights = newdataadr(fd, part->effector_weights);
- if (!part->effector_weights)
- part->effector_weights = BKE_add_effector_weights(part->eff_group);
-
- link_list(fd, &part->dupliweights);
-
- part->boids = newdataadr(fd, part->boids);
- part->fluid = newdataadr(fd, part->fluid);
-
- if (part->boids) {
- BoidState *state;
- link_list(fd, &part->boids->states);
-
- for (state=part->boids->states.first; state; state=state->next) {
- link_list(fd, &state->rules);
- link_list(fd, &state->conditions);
- link_list(fd, &state->actions);
- }
- }
- for (a = 0; a < MAX_MTEX; a++) {
- part->mtex[a] = newdataadr(fd, part->mtex[a]);
- }
-}
-
-static void lib_link_particlesystems(FileData *fd, Object *ob, ID *id, ListBase *particles)
-{
- ParticleSystem *psys, *psysnext;
-
- for (psys=particles->first; psys; psys=psysnext) {
- psysnext = psys->next;
-
- psys->part = newlibadr_us(fd, id->lib, psys->part);
- if (psys->part) {
- ParticleTarget *pt = psys->targets.first;
-
- for (; pt; pt=pt->next)
- pt->ob=newlibadr(fd, id->lib, pt->ob);
-
- psys->parent = newlibadr(fd, id->lib, psys->parent);
- psys->target_ob = newlibadr(fd, id->lib, psys->target_ob);
-
- if (psys->clmd) {
- /* XXX - from reading existing code this seems correct but intended usage of
- * pointcache /w cloth should be added in 'ParticleSystem' - campbell */
- psys->clmd->point_cache = psys->pointcache;
- psys->clmd->ptcaches.first = psys->clmd->ptcaches.last= NULL;
- psys->clmd->coll_parms->group = newlibadr(fd, id->lib, psys->clmd->coll_parms->group);
- psys->clmd->modifier.error = NULL;
- }
- }
- else {
- /* particle modifier must be removed before particle system */
- ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys);
- BLI_remlink(&ob->modifiers, psmd);
- modifier_free((ModifierData *)psmd);
-
- BLI_remlink(particles, psys);
- MEM_freeN(psys);
- }
- }
-}
-static void direct_link_particlesystems(FileData *fd, ListBase *particles)
-{
- ParticleSystem *psys;
- ParticleData *pa;
- int a;
-
- for (psys=particles->first; psys; psys=psys->next) {
- psys->particles=newdataadr(fd, psys->particles);
-
- if (psys->particles && psys->particles->hair) {
- for (a=0, pa=psys->particles; a<psys->totpart; a++, pa++)
- pa->hair=newdataadr(fd, pa->hair);
- }
-
- if (psys->particles && psys->particles->keys) {
- for (a=0, pa=psys->particles; a<psys->totpart; a++, pa++) {
- pa->keys= NULL;
- pa->totkey= 0;
- }
-
- psys->flag &= ~PSYS_KEYED;
- }
-
- if (psys->particles && psys->particles->boid) {
- pa = psys->particles;
- pa->boid = newdataadr(fd, pa->boid);
- pa->boid->ground = NULL; /* This is purely runtime data, but still can be an issue if left dangling. */
- for (a = 1, pa++; a < psys->totpart; a++, pa++) {
- pa->boid = (pa - 1)->boid + 1;
- pa->boid->ground = NULL;
- }
- }
- else if (psys->particles) {
- for (a=0, pa=psys->particles; a<psys->totpart; a++, pa++)
- pa->boid = NULL;
- }
-
- psys->fluid_springs = newdataadr(fd, psys->fluid_springs);
-
- psys->child = newdataadr(fd, psys->child);
- psys->effectors = NULL;
-
- link_list(fd, &psys->targets);
-
- psys->edit = NULL;
- psys->free_edit = NULL;
- psys->pathcache = NULL;
- psys->childcache = NULL;
- BLI_listbase_clear(&psys->pathcachebufs);
- BLI_listbase_clear(&psys->childcachebufs);
- psys->pdd = NULL;
- psys->renderdata = NULL;
-
- if (psys->clmd) {
- psys->clmd = newdataadr(fd, psys->clmd);
- psys->clmd->clothObject = NULL;
- psys->clmd->hairdata = NULL;
-
- psys->clmd->sim_parms= newdataadr(fd, psys->clmd->sim_parms);
- psys->clmd->coll_parms= newdataadr(fd, psys->clmd->coll_parms);
-
- if (psys->clmd->sim_parms) {
- psys->clmd->sim_parms->effector_weights = NULL;
- if (psys->clmd->sim_parms->presets > 10)
- psys->clmd->sim_parms->presets = 0;
- }
-
- psys->hair_in_dm = psys->hair_out_dm = NULL;
- psys->clmd->solver_result = NULL;
- }
-
- direct_link_pointcache_list(fd, &psys->ptcaches, &psys->pointcache, 0);
- if (psys->clmd) {
- psys->clmd->point_cache = psys->pointcache;
- }
-
- psys->tree = NULL;
- psys->bvhtree = NULL;
- }
- return;
-}
-
/* ************ READ MESH ***************** */
static void lib_link_mtface(FileData *fd, Mesh *me, MTFace *mtface, int totface)
@@ -4948,7 +4601,6 @@ static void lib_link_object(FileData *fd, Main *main)
ob->soft->effector_weights->group = newlibadr(fd, ob->id.lib, ob->soft->effector_weights->group);
}
- lib_link_particlesystems(fd, ob, &ob->id, &ob->particlesystem);
lib_link_modifiers(fd, ob);
if (ob->rigidbody_constraint) {
@@ -5056,8 +4708,6 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
clmd->sim_parms= newdataadr(fd, clmd->sim_parms);
clmd->coll_parms= newdataadr(fd, clmd->coll_parms);
- direct_link_pointcache_list(fd, &clmd->ptcaches, &clmd->point_cache, 0);
-
if (clmd->sim_parms) {
if (clmd->sim_parms->presets > 10)
clmd->sim_parms->presets = 0;
@@ -5102,24 +4752,6 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
smd->domain->effector_weights = newdataadr(fd, smd->domain->effector_weights);
if (!smd->domain->effector_weights)
smd->domain->effector_weights = BKE_add_effector_weights(NULL);
-
- direct_link_pointcache_list(fd, &(smd->domain->ptcaches[0]), &(smd->domain->point_cache[0]), 1);
-
- /* Smoke uses only one cache from now on, so store pointer convert */
- if (smd->domain->ptcaches[1].first || smd->domain->point_cache[1]) {
- if (smd->domain->point_cache[1]) {
- PointCache *cache = newdataadr(fd, smd->domain->point_cache[1]);
- if (cache->flag & PTCACHE_FAKE_SMOKE) {
- /* Smoke was already saved in "new format" and this cache is a fake one. */
- }
- else {
- printf("High resolution smoke cache not available due to pointcache update. Please reset the simulation.\n");
- }
- BKE_ptcache_free(cache);
- }
- BLI_listbase_clear(&smd->domain->ptcaches[1]);
- smd->domain->point_cache[1] = NULL;
- }
}
else if (smd->type == MOD_SMOKE_TYPE_FLOW) {
smd->domain = NULL;
@@ -5129,7 +4761,6 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
smd->flow->dm = NULL;
smd->flow->verts_old = NULL;
smd->flow->numverts = 0;
- smd->flow->psys = newdataadr(fd, smd->flow->psys);
}
else if (smd->type == MOD_SMOKE_TYPE_COLL) {
smd->flow = NULL;
@@ -5165,7 +4796,6 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
for (surface=pmd->canvas->surfaces.first; surface; surface=surface->next) {
surface->canvas = pmd->canvas;
surface->data = NULL;
- direct_link_pointcache_list(fd, &(surface->ptcaches), &(surface->pointcache), 1);
if (!(surface->effector_weights = newdataadr(fd, surface->effector_weights)))
surface->effector_weights = BKE_add_effector_weights(NULL);
@@ -5175,7 +4805,6 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
if (pmd->brush) {
pmd->brush = newdataadr(fd, pmd->brush);
pmd->brush->pmd = pmd;
- pmd->brush->psys = newdataadr(fd, pmd->brush->psys);
pmd->brush->paint_ramp = newdataadr(fd, pmd->brush->paint_ramp);
pmd->brush->vel_ramp = newdataadr(fd, pmd->brush->vel_ramp);
pmd->brush->dm = NULL;
@@ -5230,15 +4859,6 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
direct_link_curvemapping(fd, hmd->curfalloff);
}
}
- else if (md->type == eModifierType_ParticleSystem) {
- ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md;
-
- psmd->dm_final = NULL;
- psmd->dm_deformed = NULL;
- psmd->psys= newdataadr(fd, psmd->psys);
- psmd->flag &= ~eParticleSystemFlag_psys_updated;
- psmd->flag |= eParticleSystemFlag_file_loaded;
- }
else if (md->type == eModifierType_Explode) {
ExplodeModifierData *psmd = (ExplodeModifierData *)md;
@@ -5337,7 +4957,7 @@ static void direct_link_object(FileData *fd, Object *ob)
* See [#34776, #42780] for more information.
*/
if (fd->memfile || (ob->id.tag & (LIB_TAG_EXTERN | LIB_TAG_INDIRECT))) {
- ob->mode &= ~(OB_MODE_EDIT | OB_MODE_PARTICLE_EDIT);
+ ob->mode &= ~OB_MODE_EDIT;
if (!fd->memfile) {
ob->mode &= ~OB_MODE_POSE;
}
@@ -5440,8 +5060,6 @@ static void direct_link_object(FileData *fd, Object *ob)
sb->effector_weights = newdataadr(fd, sb->effector_weights);
if (!sb->effector_weights)
sb->effector_weights = BKE_add_effector_weights(NULL);
-
- direct_link_pointcache_list(fd, &sb->ptcaches, &sb->pointcache, 0);
}
ob->bsoft = newdataadr(fd, ob->bsoft);
ob->fluidsimSettings= newdataadr(fd, ob->fluidsimSettings); /* NT */
@@ -5459,9 +5077,6 @@ static void direct_link_object(FileData *fd, Object *ob)
ob->rigidbody_constraint = newdataadr(fd, ob->rigidbody_constraint);
if (ob->rigidbody_constraint)
ob->rigidbody_constraint->physics_constraint = NULL;
-
- link_list(fd, &ob->particlesystem);
- direct_link_particlesystems(fd, &ob->particlesystem);
link_list(fd, &ob->prop);
for (prop = ob->prop.first; prop; prop = prop->next) {
@@ -5674,8 +5289,6 @@ static void lib_link_scene(FileData *fd, Main *main)
sce->toolsettings->skgen_template = newlibadr(fd, sce->id.lib, sce->toolsettings->skgen_template);
- sce->toolsettings->particle.shape_object = newlibadr(fd, sce->id.lib, sce->toolsettings->particle.shape_object);
-
for (base = sce->base.first; base; base = next) {
next = base->next;
@@ -5916,9 +5529,6 @@ static void direct_link_scene(FileData *fd, Scene *sce)
direct_link_paint(fd, &sce->toolsettings->imapaint.paint);
sce->toolsettings->imapaint.paintcursor = NULL;
- sce->toolsettings->particle.paintcursor = NULL;
- sce->toolsettings->particle.scene = NULL;
- sce->toolsettings->particle.object = NULL;
sce->toolsettings->gp_sculpt.paintcursor = NULL;
/* in rare cases this is needed, see [#33806] */
@@ -6112,13 +5722,6 @@ static void direct_link_scene(FileData *fd, Scene *sce)
rbw->effector_weights = newdataadr(fd, rbw->effector_weights);
if (!rbw->effector_weights)
rbw->effector_weights = BKE_add_effector_weights(NULL);
-
- /* link cache */
- direct_link_pointcache_list(fd, &rbw->ptcaches, &rbw->pointcache, false);
- /* make sure simulation starts from the beginning after loading file */
- if (rbw->pointcache) {
- rbw->ltime = (float)rbw->pointcache->startframe;
- }
}
sce->preview = direct_link_preview_image(fd, sce->preview);
@@ -6908,6 +6511,7 @@ static void direct_link_region(FileData *fd, ARegion *ar, int spacetype)
rv3d->sms = NULL;
rv3d->smooth_timer = NULL;
rv3d->compositor = NULL;
+ rv3d->viewport = NULL;
}
}
}
@@ -6924,6 +6528,7 @@ static void direct_link_region(FileData *fd, ARegion *ar, int spacetype)
ar->type = NULL;
ar->swap = 0;
ar->do_draw = 0;
+ ar->manipulator_map = NULL;
ar->regiontimer = NULL;
memset(&ar->drawrct, 0, sizeof(ar->drawrct));
}
@@ -7973,7 +7578,6 @@ static const char *dataname(short id_code)
case ID_SO: return "Data from SO";
case ID_NT: return "Data from NT";
case ID_BR: return "Data from BR";
- case ID_PA: return "Data from PA";
case ID_PAL: return "Data from PAL";
case ID_PC: return "Data from PCRV";
case ID_GD: return "Data from GD";
@@ -8212,9 +7816,6 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, const short
case ID_BR:
direct_link_brush(fd, (Brush*)id);
break;
- case ID_PA:
- direct_link_particlesettings(fd, (ParticleSettings*)id);
- break;
case ID_GD:
direct_link_gpencil(fd, (bGPdata *)id);
break;
@@ -8424,7 +8025,6 @@ static void lib_link_all(FileData *fd, Main *main)
lib_link_brush(fd, main);
lib_link_palette(fd, main);
lib_link_paint_curve(fd, main);
- lib_link_particlesettings(fd, main);
lib_link_movieclip(fd, main);
lib_link_mask(fd, main);
lib_link_linestyle(fd, main);
@@ -8939,58 +8539,6 @@ static void expand_animdata(FileData *fd, Main *mainvar, AnimData *adt)
expand_animdata_nlastrips(fd, mainvar, &nlt->strips);
}
-static void expand_particlesettings(FileData *fd, Main *mainvar, ParticleSettings *part)
-{
- int a;
-
- expand_doit(fd, mainvar, part->dup_ob);
- expand_doit(fd, mainvar, part->dup_group);
- expand_doit(fd, mainvar, part->eff_group);
- expand_doit(fd, mainvar, part->bb_ob);
- expand_doit(fd, mainvar, part->collision_group);
-
- if (part->adt)
- expand_animdata(fd, mainvar, part->adt);
-
- for (a = 0; a < MAX_MTEX; a++) {
- if (part->mtex[a]) {
- expand_doit(fd, mainvar, part->mtex[a]->tex);
- expand_doit(fd, mainvar, part->mtex[a]->object);
- }
- }
-
- if (part->effector_weights) {
- expand_doit(fd, mainvar, part->effector_weights->group);
- }
-
- if (part->pd) {
- expand_doit(fd, mainvar, part->pd->tex);
- expand_doit(fd, mainvar, part->pd->f_source);
- }
- if (part->pd2) {
- expand_doit(fd, mainvar, part->pd2->tex);
- expand_doit(fd, mainvar, part->pd2->f_source);
- }
-
- if (part->boids) {
- BoidState *state;
- BoidRule *rule;
-
- for (state = part->boids->states.first; state; state = state->next) {
- for (rule = state->rules.first; rule; rule = rule->next) {
- if (rule->type == eBoidRuleType_Avoid) {
- BoidRuleGoalAvoid *gabr = (BoidRuleGoalAvoid *)rule;
- expand_doit(fd, mainvar, gabr->ob);
- }
- else if (rule->type == eBoidRuleType_FollowLeader) {
- BoidRuleFollowLeader *flbr = (BoidRuleFollowLeader *)rule;
- expand_doit(fd, mainvar, flbr->ob);
- }
- }
- }
- }
-}
-
static void expand_group(FileData *fd, Main *mainvar, Group *group)
{
GroupObject *go;
@@ -9293,7 +8841,6 @@ static void expand_object_expandModifiers(
static void expand_object(FileData *fd, Main *mainvar, Object *ob)
{
- ParticleSystem *psys;
bSensor *sens;
bController *cont;
bActuator *act;
@@ -9349,9 +8896,6 @@ static void expand_object(FileData *fd, Main *mainvar, Object *ob)
expand_doit(fd, mainvar, ob->proxy);
if (ob->proxy_group)
expand_doit(fd, mainvar, ob->proxy_group);
-
- for (psys = ob->particlesystem.first; psys; psys = psys->next)
- expand_doit(fd, mainvar, psys->part);
for (sens = ob->sensors.first; sens; sens = sens->next) {
if (sens->type == SENS_MESSAGE) {
@@ -9727,9 +9271,6 @@ void BLO_expand_main(void *fdhandle, Main *mainvar)
case ID_IP:
expand_ipo(fd, mainvar, (Ipo *)id); // XXX deprecated - old animation system
break;
- case ID_PA:
- expand_particlesettings(fd, mainvar, (ParticleSettings *)id);
- break;
case ID_MC:
expand_movieclip(fd, mainvar, (MovieClip *)id);
break;
diff --git a/source/blender/blenloader/intern/versioning_250.c b/source/blender/blenloader/intern/versioning_250.c
index 1956a17d57b..631aec545c2 100644
--- a/source/blender/blenloader/intern/versioning_250.c
+++ b/source/blender/blenloader/intern/versioning_250.c
@@ -53,6 +53,7 @@
#include "DNA_meshdata_types.h"
#include "DNA_node_types.h"
#include "DNA_object_fluidsim.h" // NT
+#include "DNA_object_force.h"
#include "DNA_object_types.h"
#include "DNA_view3d_types.h"
#include "DNA_screen_types.h"
@@ -78,8 +79,6 @@
#include "BKE_mesh.h" // for ME_ defines (patching)
#include "BKE_modifier.h"
#include "BKE_multires.h"
-#include "BKE_particle.h"
-#include "BKE_pointcache.h"
#include "BKE_screen.h"
#include "BKE_sequencer.h"
#include "BKE_texture.h"
@@ -743,7 +742,6 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *main)
Curve *cu;
Scene *sce;
Tex *tx;
- ParticleSettings *part;
Object *ob;
//PTCacheID *pid;
//ListBase pidlist;
@@ -874,25 +872,6 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *main)
me->drawflag = ME_DRAWEDGES|ME_DRAWFACES|ME_DRAWCREASES;
}
- /* particle draw and render types */
- for (part = main->particle.first; part; part = part->id.next) {
- if (part->draw_as) {
- if (part->draw_as == PART_DRAW_DOT) {
- part->ren_as = PART_DRAW_HALO;
- part->draw_as = PART_DRAW_REND;
- }
- else if (part->draw_as <= PART_DRAW_AXIS) {
- part->ren_as = PART_DRAW_HALO;
- }
- else {
- part->ren_as = part->draw_as;
- part->draw_as = PART_DRAW_REND;
- }
- }
- part->path_end = 1.0f;
- part->clength = 1.0f;
- }
-
/* set old pointcaches to have disk cache flag */
for (ob = main->object.first; ob; ob = ob->id.next) {
@@ -1136,7 +1115,6 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *main)
Lamp *la;
World *wo;
Tex *tex;
- ParticleSettings *part;
bool do_gravity = false;
for (sce = main->scene.first; sce; sce = sce->id.next)
@@ -1197,12 +1175,6 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *main)
}
}
- /* Assign proper global gravity weights for dynamics (only z-coordinate is taken into account) */
- if (do_gravity) {
- for (part = main->particle.first; part; part = part->id.next)
- part->effector_weights->global_gravity = part->acc[2]/-9.81f;
- }
-
for (ob = main->object.first; ob; ob = ob->id.next) {
ModifierData *md;
@@ -1444,14 +1416,9 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *main)
}
if (main->versionfile < 250 || (main->versionfile == 250 && main->subversionfile < 9)) {
- Scene *sce;
Mesh *me;
Object *ob;
- for (sce = main->scene.first; sce; sce = sce->id.next)
- if (!sce->toolsettings->particle.selectmode)
- sce->toolsettings->particle.selectmode = SCE_SELECT_PATH;
-
if (main->versionfile == 250 && main->subversionfile > 1) {
for (me = main->mesh.first; me; me = me->id.next)
multires_load_old_250(me);
@@ -1780,15 +1747,6 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *main)
SEQ_END
}
- /* particle brush strength factor was changed from int to float */
- for (sce = main->scene.first; sce; sce = sce->id.next) {
- ParticleEditSettings *pset = &sce->toolsettings->particle;
- int a;
-
- for (a = 0; a < PE_TOT_BRUSH; a++)
- pset->brush[a].strength /= 100.0f;
- }
-
for (ma = main->mat.first; ma; ma = ma->id.next)
if (ma->mode & MA_TRACEBLE)
ma->shade_flag |= MA_APPROX_OCCLUSION;
@@ -2195,7 +2153,6 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *main)
if (main->versionfile < 255 || (main->versionfile == 255 && main->subversionfile < 1)) {
Brush *br;
- ParticleSettings *part;
bScreen *sc;
Object *ob;
@@ -2204,14 +2161,6 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *main)
br->ob_mode = OB_MODE_ALL_PAINT;
}
- for (part = main->particle.first; part; part = part->id.next) {
- if (part->boids)
- part->boids->pitch = 1.0f;
-
- part->flag &= ~PART_HAIR_REGROW; /* this was a deprecated flag before */
- part->kink_amp_clump = 1.f; /* keep old files looking similar */
- }
-
for (sc = main->screen.first; sc; sc = sc->id.next) {
ScrArea *sa;
for (sa = sc->areabase.first; sa; sa = sa->next) {
@@ -2429,7 +2378,6 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *main)
bScreen *sc;
Brush *brush;
Object *ob;
- ParticleSettings *part;
Material *mat;
int tex_nr, transp_tex;
@@ -2479,12 +2427,6 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *main)
}
}
}
-
- /* particle draw color from material */
- for (part = main->particle.first; part; part = part->id.next) {
- if (part->draw & PART_DRAW_MAT_COL)
- part->draw_col = PART_DRAW_COL_MAT;
- }
}
if (main->versionfile < 256 || (main->versionfile == 256 && main->subversionfile < 6)) {
@@ -2577,14 +2519,6 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *main)
}
}
}
-
- {
- ParticleSettings *part;
- for (part = main->particle.first; part; part = part->id.next) {
- /* Initialize particle billboard scale */
- part->bb_size[0] = part->bb_size[1] = 1.0f;
- }
- }
}
if (main->versionfile < 259 || (main->versionfile == 259 && main->subversionfile < 1)) {
@@ -2753,15 +2687,6 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *main)
if (main->versionfile < 259 || (main->versionfile == 259 && main->subversionfile < 4)) {
{
- /* Adaptive time step for particle systems */
- ParticleSettings *part;
- for (part = main->particle.first; part; part = part->id.next) {
- part->courant_target = 0.2f;
- part->time_flag &= ~PART_TIME_AUTOSF;
- }
- }
-
- {
/* set defaults for obstacle avoidance, recast data */
Scene *sce;
for (sce = main->scene.first; sce; sce = sce->id.next) {
diff --git a/source/blender/blenloader/intern/versioning_260.c b/source/blender/blenloader/intern/versioning_260.c
index 907baab0aee..3e4b6534ad8 100644
--- a/source/blender/blenloader/intern/versioning_260.c
+++ b/source/blender/blenloader/intern/versioning_260.c
@@ -36,12 +36,14 @@
#include "DNA_camera_types.h"
#include "DNA_cloth_types.h"
#include "DNA_constraint_types.h"
+#include "DNA_dynamicpaint_types.h"
#include "DNA_genfile.h"
#include "DNA_key_types.h"
#include "DNA_linestyle_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_fluidsim.h" // NT
+#include "DNA_object_force.h"
#include "DNA_object_types.h"
#include "DNA_property_types.h"
#include "DNA_text_types.h"
@@ -64,8 +66,6 @@
#include "BKE_main.h" // for Main
#include "BKE_mesh.h" // for ME_ defines (patching)
#include "BKE_modifier.h"
-#include "BKE_particle.h"
-#include "BKE_pointcache.h"
#include "BKE_property.h" // for BKE_bproperty_object_get
#include "BKE_scene.h"
#include "BKE_screen.h"
@@ -651,20 +651,6 @@ void blo_do_versions_260(FileData *fd, Library *UNUSED(lib), Main *main)
for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next)
do_versions_nodetree_image_default_alpha_output(ntree);
}
-
- {
- /* support old particle dupliobject rotation settings */
- ParticleSettings *part;
-
- for (part = main->particle.first; part; part = part->id.next) {
- if (ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR)) {
- part->draw |= PART_DRAW_ROTATE_OB;
-
- if (part->rotmode == 0)
- part->rotmode = PART_ROT_VEL;
- }
- }
- }
}
if (main->versionfile < 260 || (main->versionfile == 260 && main->subversionfile < 1)) {
@@ -1141,16 +1127,6 @@ void blo_do_versions_260(FileData *fd, Library *UNUSED(lib), Main *main)
}
}
-
-
- if (main->versionfile < 263) {
- /* Default for old files is to save particle rotations to pointcache */
- ParticleSettings *part;
- for (part = main->particle.first; part; part = part->id.next) {
- part->flag |= PART_ROTATIONS;
- }
- }
-
if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 1)) {
/* file output node paths are now stored in the file info struct instead socket name */
Scene *sce;
@@ -1444,8 +1420,6 @@ void blo_do_versions_260(FileData *fd, Library *UNUSED(lib), Main *main)
}
if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 14)) {
- ParticleSettings *part;
-
FOREACH_NODETREE(main, ntree, id) {
if (ntree->type == NTREE_COMPOSIT) {
bNode *node;
@@ -1460,12 +1434,6 @@ void blo_do_versions_260(FileData *fd, Library *UNUSED(lib), Main *main)
}
}
} FOREACH_NODETREE_END
-
- /* keep compatibility for dupliobject particle size */
- for (part = main->particle.first; part; part = part->id.next)
- if (ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR))
- if ((part->draw & PART_DRAW_ROTATE_OB) == 0)
- part->draw |= PART_DRAW_NO_SCALE_OB;
}
if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 17)) {
diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c
index 6eb02221c3b..3f1ded5afe4 100644
--- a/source/blender/blenloader/intern/versioning_270.c
+++ b/source/blender/blenloader/intern/versioning_270.c
@@ -48,7 +48,6 @@
#include "DNA_object_types.h"
#include "DNA_mesh_types.h"
#include "DNA_modifier_types.h"
-#include "DNA_particle_types.h"
#include "DNA_linestyle_types.h"
#include "DNA_actuator_types.h"
#include "DNA_view3d_types.h"
@@ -444,22 +443,6 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
}
}
- if (!MAIN_VERSION_ATLEAST(main, 271, 6)) {
- Object *ob;
- for (ob = main->object.first; ob; ob = ob->id.next) {
- ModifierData *md;
-
- for (md = ob->modifiers.first; md; md = md->next) {
- if (md->type == eModifierType_ParticleSystem) {
- ParticleSystemModifierData *pmd = (ParticleSystemModifierData *)md;
- if (pmd->psys && pmd->psys->clmd) {
- pmd->psys->clmd->sim_parms->vel_damping = 1.0f;
- }
- }
- }
- }
- }
-
if (!MAIN_VERSION_ATLEAST(main, 272, 0)) {
if (!DNA_struct_elem_find(fd->filesdna, "RenderData", "int", "preview_start_resolution")) {
Scene *scene;
@@ -540,16 +523,6 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
}
}
- if (!MAIN_VERSION_ATLEAST(main, 273, 3)) {
- ParticleSettings *part;
- for (part = main->particle.first; part; part = part->id.next) {
- if (part->clumpcurve)
- part->child_flag |= PART_CHILD_USE_CLUMP_CURVE;
- if (part->roughcurve)
- part->child_flag |= PART_CHILD_USE_ROUGH_CURVE;
- }
- }
-
if (!MAIN_VERSION_ATLEAST(main, 273, 6)) {
if (!DNA_struct_elem_find(fd->filesdna, "ClothSimSettings", "float", "bending_damping")) {
Object *ob;
@@ -560,39 +533,6 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
ClothModifierData *clmd = (ClothModifierData *)md;
clmd->sim_parms->bending_damping = 0.5f;
}
- else if (md->type == eModifierType_ParticleSystem) {
- ParticleSystemModifierData *pmd = (ParticleSystemModifierData *)md;
- if (pmd->psys->clmd) {
- pmd->psys->clmd->sim_parms->bending_damping = 0.5f;
- }
- }
- }
- }
- }
-
- if (!DNA_struct_elem_find(fd->filesdna, "ParticleSettings", "float", "clump_noise_size")) {
- ParticleSettings *part;
- for (part = main->particle.first; part; part = part->id.next) {
- part->clump_noise_size = 1.0f;
- }
- }
-
- if (!DNA_struct_elem_find(fd->filesdna, "ParticleSettings", "int", "kink_extra_steps")) {
- ParticleSettings *part;
- for (part = main->particle.first; part; part = part->id.next) {
- part->kink_extra_steps = 4;
- }
- }
-
- if (!DNA_struct_elem_find(fd->filesdna, "MTex", "float", "kinkampfac")) {
- ParticleSettings *part;
- for (part = main->particle.first; part; part = part->id.next) {
- int a;
- for (a = 0; a < MAX_MTEX; a++) {
- MTex *mtex = part->mtex[a];
- if (mtex) {
- mtex->kinkampfac = 1.0f;
- }
}
}
}
@@ -679,19 +619,6 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
}
if (!MAIN_VERSION_ATLEAST(main, 274, 1)) {
- /* particle systems need to be forced to redistribute for jitter mode fix */
- {
- Object *ob;
- ParticleSystem *psys;
- for (ob = main->object.first; ob; ob = ob->id.next) {
- for (psys = ob->particlesystem.first; psys; psys = psys->next) {
- if ((psys->pointcache->flag & PTCACHE_BAKED) == 0) {
- psys->recalc |= PSYS_RECALC_RESET;
- }
- }
- }
- }
-
/* hysteresis setted to 10% but not actived */
if (!DNA_struct_elem_find(fd->filesdna, "LodLevel", "int", "obhysteresis")) {
Object *ob;
@@ -1085,39 +1012,7 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
}
}
- /* XXX I don't know against which version I should test */
- if (!MAIN_VERSION_ATLEAST(main, 277, 0)) {
- {
- World *wo;
- for (wo = main->world.first; wo; wo = wo->id.next) {
- wo->probesize = 512;
- wo->probeflags = (WO_PROBE_AUTO_UPDATE | WO_PROBE_COMPUTE_SH);
- wo->probeshres = 64;
- }
- }
-
- {
- Object *ob;
- for (ob = main->object.first; ob; ob = ob->id.next) {
- ob->probesize = 256;
- ob->probeflags = (OB_PROBE_AUTO_UPDATE | OB_PROBE_COMPUTE_SH);
- ob->probeclipsta = 0.1f;
- ob->probeclipend = 1000.0f;
- ob->probeshres = 32;
- }
- }
- }
-
if (!MAIN_VERSION_ATLEAST(main, 277, 1)) {
- for (Scene *scene = main->scene.first; scene; scene = scene->id.next) {
- ParticleEditSettings *pset = &scene->toolsettings->particle;
- for (int a = 0; a < PE_TOT_BRUSH; a++) {
- if (pset->brush[a].strength > 1.0f) {
- pset->brush[a].strength *= 0.01f;
- }
- }
- }
-
for (bScreen *screen = main->screen.first; screen; screen = screen->id.next) {
for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
for (SpaceLink *sl = sa->spacedata.first; sl; sl = sl->next) {
@@ -1275,12 +1170,6 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
ClothModifierData *clmd = (ClothModifierData *)md;
clmd->sim_parms->time_scale = 1.0f;
}
- else if (md->type == eModifierType_ParticleSystem) {
- ParticleSystemModifierData *pmd = (ParticleSystemModifierData *)md;
- if (pmd->psys->clmd) {
- pmd->psys->clmd->sim_parms->time_scale = 1.0f;
- }
- }
}
}
}
@@ -1447,19 +1336,26 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
}
}
}
- }
- {
- for (Scene *scene = main->scene.first; scene != NULL; scene = scene->id.next) {
- if (scene->toolsettings != NULL) {
- ToolSettings *ts = scene->toolsettings;
- ParticleEditSettings *pset = &ts->particle;
- for (int a = 0; a < PE_TOT_BRUSH; a++) {
- if (pset->brush[a].count == 0) {
- pset->brush[a].count = 10;
- }
- }
+
+ if (!DNA_struct_elem_find(fd->filesdna, "World", "ListBase", "gpuprobe")) {
+ World *wo;
+
+ for (wo = main->world.first; wo; wo = wo->id.next) {
+ wo->probesize = 512;
+ wo->probeflags = (WO_PROBE_AUTO_UPDATE | WO_PROBE_COMPUTE_SH);
+ wo->probeshres = 64;
+ }
+
+ Object *ob;
+ for (ob = main->object.first; ob; ob = ob->id.next) {
+ ob->probesize = 256;
+ ob->probeflags = (OB_PROBE_AUTO_UPDATE | OB_PROBE_COMPUTE_SH);
+ ob->probeclipsta = 0.1f;
+ ob->probeclipend = 1000.0f;
+ ob->probeshres = 32;
}
}
+
}
}
diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c
index 99d9e140481..01ef5d6a606 100644
--- a/source/blender/blenloader/intern/versioning_defaults.c
+++ b/source/blender/blenloader/intern/versioning_defaults.c
@@ -143,13 +143,6 @@ void BLO_update_defaults_startup_blend(Main *bmain)
ts->gpencil_v2d_align = GP_PROJECT_VIEWSPACE;
ts->gpencil_seq_align = GP_PROJECT_VIEWSPACE;
ts->gpencil_ima_align = GP_PROJECT_VIEWSPACE;
-
- ParticleEditSettings *pset = &ts->particle;
- for (int a = 0; a < PE_TOT_BRUSH; a++) {
- pset->brush[a].strength = 0.5f;
- pset->brush[a].count = 10;
- }
- pset->brush[PE_BRUSH_CUT].strength = 1.0f;
}
scene->gm.lodflag |= SCE_LOD_USE_HYST;
diff --git a/source/blender/blenloader/intern/versioning_legacy.c b/source/blender/blenloader/intern/versioning_legacy.c
index f2d42849bcc..f5e9fb240dc 100644
--- a/source/blender/blenloader/intern/versioning_legacy.c
+++ b/source/blender/blenloader/intern/versioning_legacy.c
@@ -59,6 +59,7 @@
#include "DNA_nla_types.h"
#include "DNA_node_types.h"
#include "DNA_object_fluidsim.h" // NT
+#include "DNA_object_force.h"
#include "DNA_object_types.h"
#include "DNA_property_types.h"
#include "DNA_view3d_types.h"
@@ -88,8 +89,6 @@
#include "BKE_main.h" // for Main
#include "BKE_mesh.h" // for ME_ defines (patching)
#include "BKE_modifier.h"
-#include "BKE_particle.h"
-#include "BKE_pointcache.h"
#include "BKE_property.h" // for BKE_bproperty_object_get
#include "BKE_scene.h"
#include "BKE_sequencer.h"
@@ -495,27 +494,6 @@ static void do_version_ntree_242_2(bNodeTree *ntree)
}
}
-static void do_version_free_effect_245(Effect *eff)
-{
- PartEff *paf;
-
- if (eff->type == EFF_PARTICLE) {
- paf = (PartEff *)eff;
- if (paf->keys)
- MEM_freeN(paf->keys);
- }
- MEM_freeN(eff);
-}
-
-static void do_version_free_effects_245(ListBase *lb)
-{
- Effect *eff;
-
- while ((eff = BLI_pophead(lb))) {
- do_version_free_effect_245(eff);
- }
-}
-
static void do_version_constraints_245(ListBase *lb)
{
bConstraint *con;
@@ -2687,13 +2665,10 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
Image *ima;
Lamp *la;
Material *ma;
- ParticleSettings *part;
World *wrld;
Mesh *me;
bNodeTree *ntree;
Tex *tex;
- ModifierData *md;
- ParticleSystem *psys;
/* unless the file was created 2.44.3 but not 2.45, update the constraints */
if (!(main->versionfile == 244 && main->subversionfile == 3) &&
@@ -2774,33 +2749,6 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
}
}
- /* add point caches */
- for (ob = main->object.first; ob; ob = ob->id.next) {
- if (ob->soft && !ob->soft->pointcache)
- ob->soft->pointcache = BKE_ptcache_add(&ob->soft->ptcaches);
-
- for (psys = ob->particlesystem.first; psys; psys = psys->next) {
- if (psys->pointcache) {
- if (psys->pointcache->flag & PTCACHE_BAKED && (psys->pointcache->flag & PTCACHE_DISK_CACHE) == 0) {
- printf("Old memory cache isn't supported for particles, so re-bake the simulation!\n");
- psys->pointcache->flag &= ~PTCACHE_BAKED;
- }
- }
- else
- psys->pointcache = BKE_ptcache_add(&psys->ptcaches);
- }
-
- for (md = ob->modifiers.first; md; md = md->next) {
- if (md->type == eModifierType_Cloth) {
- ClothModifierData *clmd = (ClothModifierData*) md;
- if (!clmd->point_cache) {
- clmd->point_cache = BKE_ptcache_add(&clmd->ptcaches);
- clmd->point_cache->step = 1;
- }
- }
- }
- }
-
/* Copy over old per-level multires vertex data
* into a single vertex array in struct Multires */
for (me = main->mesh.first; me; me = me->id.next) {
@@ -2846,18 +2794,6 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
ma->strand_min = 1.0f;
}
- for (part = main->particle.first; part; part = part->id.next) {
- if (part->ren_child_nbr == 0)
- part->ren_child_nbr = part->child_nbr;
-
- if (part->simplify_refsize == 0) {
- part->simplify_refsize = 1920;
- part->simplify_rate = 1.0f;
- part->simplify_transition = 0.1f;
- part->simplify_viewport = 0.8f;
- }
- }
-
for (wrld = main->world.first; wrld; wrld = wrld->id.next) {
if (wrld->ao_approx_error == 0.0f)
wrld->ao_approx_error = 0.25f;
@@ -2997,9 +2933,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
}
if ((main->versionfile < 245) || (main->versionfile == 245 && main->subversionfile < 8)) {
- Scene *sce;
Object *ob;
- PartEff *paf = NULL;
for (ob = main->object.first; ob; ob = ob->id.next) {
if (ob->soft && ob->soft->keys) {
@@ -3016,145 +2950,6 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
sb->keys = NULL;
sb->totkey = 0;
}
-
- /* convert old particles to new system */
- if ((paf = blo_do_version_give_parteff_245(ob))) {
- ParticleSystem *psys;
- ModifierData *md;
- ParticleSystemModifierData *psmd;
- ParticleSettings *part;
-
- /* create new particle system */
- psys = MEM_callocN(sizeof(ParticleSystem), "particle_system");
- psys->pointcache = BKE_ptcache_add(&psys->ptcaches);
-
- part = psys->part = psys_new_settings("ParticleSettings", main);
-
- /* needed for proper libdata lookup */
- blo_do_versions_oldnewmap_insert(fd->libmap, psys->part, psys->part, 0);
- part->id.lib = ob->id.lib;
-
- part->id.us--;
- part->id.tag |= (ob->id.tag & LIB_TAG_NEED_LINK);
-
- psys->totpart = 0;
- psys->flag = PSYS_CURRENT;
-
- BLI_addtail(&ob->particlesystem, psys);
-
- md = modifier_new(eModifierType_ParticleSystem);
- BLI_snprintf(md->name, sizeof(md->name), "ParticleSystem %i", BLI_listbase_count(&ob->particlesystem));
- psmd = (ParticleSystemModifierData*) md;
- psmd->psys = psys;
- BLI_addtail(&ob->modifiers, md);
-
- /* convert settings from old particle system */
- /* general settings */
- part->totpart = MIN2(paf->totpart, 100000);
- part->sta = paf->sta;
- part->end = paf->end;
- part->lifetime = paf->lifetime;
- part->randlife = paf->randlife;
- psys->seed = paf->seed;
- part->disp = paf->disp;
- part->omat = paf->mat[0];
- part->hair_step = paf->totkey;
-
- part->eff_group = paf->group;
-
- /* old system didn't interpolate between keypoints at render time */
- part->draw_step = part->ren_step = 0;
-
- /* physics */
- part->normfac = paf->normfac * 25.0f;
- part->obfac = paf->obfac;
- part->randfac = paf->randfac * 25.0f;
- part->dampfac = paf->damp;
- copy_v3_v3(part->acc, paf->force);
-
- /* flags */
- if (paf->stype & PAF_VECT) {
- if (paf->flag & PAF_STATIC) {
- /* new hair lifetime is always 100.0f */
- float fac = paf->lifetime / 100.0f;
-
- part->draw_as = PART_DRAW_PATH;
- part->type = PART_HAIR;
- psys->recalc |= PSYS_RECALC_REDO;
-
- part->normfac *= fac;
- part->randfac *= fac;
- }
- else {
- part->draw_as = PART_DRAW_LINE;
- part->draw |= PART_DRAW_VEL_LENGTH;
- part->draw_line[1] = 0.04f;
- }
- }
-
- part->rotmode = PART_ROT_VEL;
-
- part->flag |= (paf->flag & PAF_BSPLINE) ? PART_HAIR_BSPLINE : 0;
- part->flag |= (paf->flag & PAF_TRAND) ? PART_TRAND : 0;
- part->flag |= (paf->flag & PAF_EDISTR) ? PART_EDISTR : 0;
- part->flag |= (paf->flag & PAF_UNBORN) ? PART_UNBORN : 0;
- part->flag |= (paf->flag & PAF_DIED) ? PART_DIED : 0;
- part->from |= (paf->flag & PAF_FACE) ? PART_FROM_FACE : 0;
- part->draw |= (paf->flag & PAF_SHOWE) ? PART_DRAW_EMITTER : 0;
-
- psys->vgroup[PSYS_VG_DENSITY] = paf->vertgroup;
- psys->vgroup[PSYS_VG_VEL] = paf->vertgroup_v;
- psys->vgroup[PSYS_VG_LENGTH] = paf->vertgroup_v;
-
- /* dupliobjects */
- if (ob->transflag & OB_DUPLIVERTS) {
- Object *dup = main->object.first;
-
- for (; dup; dup = dup->id.next) {
- if (ob == blo_do_versions_newlibadr(fd, lib, dup->parent)) {
- part->dup_ob = dup;
- ob->transflag |= OB_DUPLIPARTS;
- ob->transflag &= ~OB_DUPLIVERTS;
-
- part->draw_as = PART_DRAW_OB;
-
- /* needed for proper libdata lookup */
- blo_do_versions_oldnewmap_insert(fd->libmap, dup, dup, 0);
- }
- }
- }
-
- {
- FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim);
- if (fluidmd && fluidmd->fss && fluidmd->fss->type == OB_FLUIDSIM_PARTICLE)
- part->type = PART_FLUID;
- }
-
- do_version_free_effects_245(&ob->effect);
-
- printf("Old particle system converted to new system.\n");
- }
- }
-
- for (sce = main->scene.first; sce; sce = sce->id.next) {
- ParticleEditSettings *pset = &sce->toolsettings->particle;
- int a;
-
- if (pset->brush[0].size == 0) {
- pset->flag = PE_KEEP_LENGTHS|PE_LOCK_FIRST|PE_DEFLECT_EMITTER;
- pset->emitterdist = 0.25f;
- pset->totrekey = 5;
- pset->totaddkey = 5;
- pset->brushtype = PE_BRUSH_NONE;
-
- for (a = 0; a < PE_TOT_BRUSH; a++) {
- pset->brush[a].strength = 50;
- pset->brush[a].size = 50;
- pset->brush[a].step = 10;
- }
-
- pset->brush[PE_BRUSH_CUT].strength = 100;
- }
}
}
if ((main->versionfile < 245) || (main->versionfile == 245 && main->subversionfile < 9)) {
@@ -3246,7 +3041,6 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
idproperties_fix_group_lengths(main->action);
idproperties_fix_group_lengths(main->nodetree);
idproperties_fix_group_lengths(main->brush);
- idproperties_fix_group_lengths(main->particle);
}
/* sun/sky */
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index 53d012a8770..3648f60fe5a 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -129,7 +129,6 @@
#include "DNA_object_types.h"
#include "DNA_object_force.h"
#include "DNA_packedFile_types.h"
-#include "DNA_particle_types.h"
#include "DNA_property_types.h"
#include "DNA_rigidbody_types.h"
#include "DNA_scene_types.h"
@@ -170,7 +169,6 @@
#include "BKE_subsurf.h"
#include "BKE_modifier.h"
#include "BKE_fcurve.h"
-#include "BKE_pointcache.h"
#include "BKE_mesh.h"
#ifdef USE_NODE_COMPAT_CUSTOMNODES
@@ -1186,210 +1184,6 @@ static void write_userdef(WriteData *wd)
}
}
-static void write_boid_state(WriteData *wd, BoidState *state)
-{
- BoidRule *rule = state->rules.first;
-
- writestruct(wd, DATA, BoidState, 1, state);
-
- for (; rule; rule = rule->next) {
- switch (rule->type) {
- case eBoidRuleType_Goal:
- case eBoidRuleType_Avoid:
- writestruct(wd, DATA, BoidRuleGoalAvoid, 1, rule);
- break;
- case eBoidRuleType_AvoidCollision:
- writestruct(wd, DATA, BoidRuleAvoidCollision, 1, rule);
- break;
- case eBoidRuleType_FollowLeader:
- writestruct(wd, DATA, BoidRuleFollowLeader, 1, rule);
- break;
- case eBoidRuleType_AverageSpeed:
- writestruct(wd, DATA, BoidRuleAverageSpeed, 1, rule);
- break;
- case eBoidRuleType_Fight:
- writestruct(wd, DATA, BoidRuleFight, 1, rule);
- break;
- default:
- writestruct(wd, DATA, BoidRule, 1, rule);
- break;
- }
- }
-#if 0
- BoidCondition *cond = state->conditions.first;
- for (; cond; cond = cond->next) {
- writestruct(wd, DATA, BoidCondition, 1, cond);
- }
-#endif
-}
-
-/* update this also to readfile.c */
-static const char *ptcache_data_struct[] = {
- "", // BPHYS_DATA_INDEX
- "", // BPHYS_DATA_LOCATION
- "", // BPHYS_DATA_VELOCITY
- "", // BPHYS_DATA_ROTATION
- "", // BPHYS_DATA_AVELOCITY / BPHYS_DATA_XCONST */
- "", // BPHYS_DATA_SIZE:
- "", // BPHYS_DATA_TIMES:
- "BoidData" // case BPHYS_DATA_BOIDS:
-};
-static const char *ptcache_extra_struct[] = {
- "",
- "ParticleSpring"
-};
-static void write_pointcaches(WriteData *wd, ListBase *ptcaches)
-{
- PointCache *cache = ptcaches->first;
- int i;
-
- for (; cache; cache = cache->next) {
- writestruct(wd, DATA, PointCache, 1, cache);
-
- if ((cache->flag & PTCACHE_DISK_CACHE) == 0) {
- PTCacheMem *pm = cache->mem_cache.first;
-
- for (; pm; pm = pm->next) {
- PTCacheExtra *extra = pm->extradata.first;
-
- writestruct(wd, DATA, PTCacheMem, 1, pm);
-
- for (i = 0; i < BPHYS_TOT_DATA; i++) {
- if (pm->data[i] && pm->data_types & (1 << i)) {
- if (ptcache_data_struct[i][0] == '\0') {
- writedata(wd, DATA, MEM_allocN_len(pm->data[i]), pm->data[i]);
- }
- else {
- writestruct_id(wd, DATA, ptcache_data_struct[i], pm->totpoint, pm->data[i]);
- }
- }
- }
-
- for (; extra; extra = extra->next) {
- if (ptcache_extra_struct[extra->type][0] == '\0') {
- continue;
- }
- writestruct(wd, DATA, PTCacheExtra, 1, extra);
- writestruct_id(wd, DATA, ptcache_extra_struct[extra->type], extra->totdata, extra->data);
- }
- }
- }
- }
-}
-static void write_particlesettings(WriteData *wd, ListBase *idbase)
-{
- ParticleSettings *part;
- ParticleDupliWeight *dw;
- GroupObject *go;
- int a;
-
- part = idbase->first;
- while (part) {
- if (part->id.us > 0 || wd->current) {
- /* write LibData */
- writestruct(wd, ID_PA, ParticleSettings, 1, part);
- write_iddata(wd, &part->id);
-
- if (part->adt) {
- write_animdata(wd, part->adt);
- }
- writestruct(wd, DATA, PartDeflect, 1, part->pd);
- writestruct(wd, DATA, PartDeflect, 1, part->pd2);
- writestruct(wd, DATA, EffectorWeights, 1, part->effector_weights);
-
- if (part->clumpcurve) {
- write_curvemapping(wd, part->clumpcurve);
- }
- if (part->roughcurve) {
- write_curvemapping(wd, part->roughcurve);
- }
-
- dw = part->dupliweights.first;
- for (; dw; dw = dw->next) {
- /* update indices, but only if dw->ob is set (can be NULL after loading e.g.) */
- if (dw->ob != NULL) {
- dw->index = 0;
- if (part->dup_group) { /* can be NULL if lining fails or set to None */
- for (go = part->dup_group->gobject.first; go && go->ob != dw->ob; go = go->next, dw->index++);
- }
- }
- writestruct(wd, DATA, ParticleDupliWeight, 1, dw);
- }
-
- if (part->boids && part->phystype == PART_PHYS_BOIDS) {
- BoidState *state = part->boids->states.first;
-
- writestruct(wd, DATA, BoidSettings, 1, part->boids);
-
- for (; state; state = state->next) {
- write_boid_state(wd, state);
- }
- }
- if (part->fluid && part->phystype == PART_PHYS_FLUID) {
- writestruct(wd, DATA, SPHFluidSettings, 1, part->fluid);
- }
-
- for (a = 0; a < MAX_MTEX; a++) {
- if (part->mtex[a]) {
- writestruct(wd, DATA, MTex, 1, part->mtex[a]);
- }
- }
- }
- part = part->id.next;
- }
-}
-static void write_particlesystems(WriteData *wd, ListBase *particles)
-{
- ParticleSystem *psys = particles->first;
- ParticleTarget *pt;
- int a;
-
- for (; psys; psys = psys->next) {
- writestruct(wd, DATA, ParticleSystem, 1, psys);
-
- if (psys->particles) {
- writestruct(wd, DATA, ParticleData, psys->totpart, psys->particles);
-
- if (psys->particles->hair) {
- ParticleData *pa = psys->particles;
-
- for (a = 0; a < psys->totpart; a++, pa++) {
- writestruct(wd, DATA, HairKey, pa->totkey, pa->hair);
- }
- }
-
- if (psys->particles->boid &&
- (psys->part->phystype == PART_PHYS_BOIDS))
- {
- writestruct(wd, DATA, BoidParticle, psys->totpart, psys->particles->boid);
- }
-
- if (psys->part->fluid &&
- (psys->part->phystype == PART_PHYS_FLUID) &&
- (psys->part->fluid->flag & SPH_VISCOELASTIC_SPRINGS))
- {
- writestruct(wd, DATA, ParticleSpring, psys->tot_fluidsprings, psys->fluid_springs);
- }
- }
- pt = psys->targets.first;
- for (; pt; pt = pt->next) {
- writestruct(wd, DATA, ParticleTarget, 1, pt);
- }
-
- if (psys->child) {
- writestruct(wd, DATA, ChildParticle, psys->totchild, psys->child);
- }
-
- if (psys->clmd) {
- writestruct(wd, DATA, ClothModifierData, 1, psys->clmd);
- writestruct(wd, DATA, ClothSimSettings, 1, psys->clmd->sim_parms);
- writestruct(wd, DATA, ClothCollSettings, 1, psys->clmd->coll_parms);
- }
-
- write_pointcaches(wd, &psys->ptcaches);
- }
-}
-
static void write_properties(WriteData *wd, ListBase *lb)
{
bProperty *prop;
@@ -1713,30 +1507,14 @@ static void write_modifiers(WriteData *wd, ListBase *modbase)
writestruct(wd, DATA, ClothSimSettings, 1, clmd->sim_parms);
writestruct(wd, DATA, ClothCollSettings, 1, clmd->coll_parms);
writestruct(wd, DATA, EffectorWeights, 1, clmd->sim_parms->effector_weights);
- write_pointcaches(wd, &clmd->ptcaches);
}
else if (md->type == eModifierType_Smoke) {
SmokeModifierData *smd = (SmokeModifierData *)md;
if (smd->type & MOD_SMOKE_TYPE_DOMAIN) {
- if (smd->domain) {
- write_pointcaches(wd, &(smd->domain->ptcaches[0]));
-
- /* create fake pointcache so that old blender versions can read it */
- smd->domain->point_cache[1] = BKE_ptcache_add(&smd->domain->ptcaches[1]);
- smd->domain->point_cache[1]->flag |= PTCACHE_DISK_CACHE | PTCACHE_FAKE_SMOKE;
- smd->domain->point_cache[1]->step = 1;
-
- write_pointcaches(wd, &(smd->domain->ptcaches[1]));
- }
-
writestruct(wd, DATA, SmokeDomainSettings, 1, smd->domain);
if (smd->domain) {
- /* cleanup the fake pointcache */
- BKE_ptcache_free_list(&smd->domain->ptcaches[1]);
- smd->domain->point_cache[1] = NULL;
-
writestruct(wd, DATA, EffectorWeights, 1, smd->domain->effector_weights);
}
}
@@ -1765,8 +1543,6 @@ static void write_modifiers(WriteData *wd, ListBase *modbase)
}
/* write caches and effector weights */
for (surface = pmd->canvas->surfaces.first; surface; surface = surface->next) {
- write_pointcaches(wd, &(surface->ptcaches));
-
writestruct(wd, DATA, EffectorWeights, 1, surface->effector_weights);
}
}
@@ -1866,7 +1642,6 @@ static void write_objects(WriteData *wd, ListBase *idbase)
writestruct(wd, DATA, PartDeflect, 1, ob->pd);
writestruct(wd, DATA, SoftBody, 1, ob->soft);
if (ob->soft) {
- write_pointcaches(wd, &ob->soft->ptcaches);
writestruct(wd, DATA, EffectorWeights, 1, ob->soft->effector_weights);
}
writestruct(wd, DATA, BulletSoftBody, 1, ob->bsoft);
@@ -1883,7 +1658,6 @@ static void write_objects(WriteData *wd, ListBase *idbase)
writestruct(wd, DATA, ImageUser, 1, ob->iuser);
}
- write_particlesystems(wd, &ob->particlesystem);
write_modifiers(wd, &ob->modifiers);
writelist(wd, DATA, LinkData, &ob->pc_ids);
@@ -2830,7 +2604,6 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
if (sce->rigidbody_world) {
writestruct(wd, DATA, RigidBodyWorld, 1, sce->rigidbody_world);
writestruct(wd, DATA, EffectorWeights, 1, sce->rigidbody_world->effector_weights);
- write_pointcaches(wd, &(sce->rigidbody_world->ptcaches));
}
write_previews(wd, sce->preview);
@@ -4097,7 +3870,6 @@ static bool write_file_handle(
write_materials(wd, &mainvar->mat);
write_textures(wd, &mainvar->tex);
write_meshes(wd, &mainvar->mesh);
- write_particlesettings(wd, &mainvar->particle);
write_nodetrees(wd, &mainvar->nodetree);
write_brushes(wd, &mainvar->brush);
write_palettes(wd, &mainvar->palettes);
diff --git a/source/blender/blentranslation/BLT_translation.h b/source/blender/blentranslation/BLT_translation.h
index 1d76077c9f1..5aa49cddfb0 100644
--- a/source/blender/blentranslation/BLT_translation.h
+++ b/source/blender/blentranslation/BLT_translation.h
@@ -139,7 +139,6 @@ bool BLT_lang_is_ime_supported(void);
#define BLT_I18NCONTEXT_ID_OBJECT "Object"
#define BLT_I18NCONTEXT_ID_PAINTCURVE "PaintCurve"
#define BLT_I18NCONTEXT_ID_PALETTE "Palette"
-#define BLT_I18NCONTEXT_ID_PARTICLESETTINGS "ParticleSettings"
#define BLT_I18NCONTEXT_ID_SCENE "Scene"
#define BLT_I18NCONTEXT_ID_SCREEN "Screen"
#define BLT_I18NCONTEXT_ID_SEQUENCE "Sequence"
@@ -193,7 +192,6 @@ typedef struct {
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_OBJECT, "id_object"), \
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_PAINTCURVE, "id_paintcurve"), \
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_PALETTE, "id_palette"), \
- BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_PARTICLESETTINGS, "id_particlesettings"), \
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"), \
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
index 1812384440f..c470e6fb239 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
@@ -59,7 +59,6 @@ extern "C" {
#include "DNA_mesh_types.h"
#include "DNA_meta_types.h"
#include "DNA_node_types.h"
-#include "DNA_particle_types.h"
#include "DNA_object_types.h"
#include "DNA_rigidbody_types.h"
#include "DNA_scene_types.h"
@@ -86,7 +85,6 @@ extern "C" {
#include "BKE_modifier.h"
#include "BKE_node.h"
#include "BKE_object.h"
-#include "BKE_particle.h"
#include "BKE_rigidbody.h"
#include "BKE_sound.h"
#include "BKE_texture.h"
@@ -486,11 +484,6 @@ void DepsgraphNodeBuilder::build_object(Scene *scene, Base *base, Object *ob)
*/
build_animdata(&ob->id);
- /* particle systems */
- if (ob->particlesystem.first) {
- build_particles(scene, ob);
- }
-
/* grease pencil */
if (ob->gpd) {
build_gpencil(ob->gpd);
@@ -716,46 +709,6 @@ void DepsgraphNodeBuilder::build_rigidbody(Scene *scene)
}
}
-void DepsgraphNodeBuilder::build_particles(Scene *scene, Object *ob)
-{
- /**
- * Particle Systems Nodes
- * ======================
- *
- * There are two types of nodes associated with representing
- * particle systems:
- * 1) Component (EVAL_PARTICLES) - This is the particle-system
- * evaluation context for an object. It acts as the container
- * for all the nodes associated with a particular set of particle
- * systems.
- * 2) Particle System Eval Operation - This operation node acts as a
- * blackbox evaluation step for one particle system referenced by
- * the particle systems stack. All dependencies link to this operation.
- */
-
- /* component for all particle systems */
- ComponentDepsNode *psys_comp = add_component_node(&ob->id, DEPSNODE_TYPE_EVAL_PARTICLES);
-
- /* particle systems */
- for (ParticleSystem *psys = (ParticleSystem *)ob->particlesystem.first; psys; psys = psys->next) {
- ParticleSettings *part = psys->part;
-
- /* particle settings */
- // XXX: what if this is used more than once!
- build_animdata(&part->id);
-
- /* this particle system */
- // TODO: for now, this will just be a placeholder "ubereval" node
- add_operation_node(psys_comp,
- DEPSOP_TYPE_EXEC, function_bind(BKE_particle_system_eval, _1, scene, ob, psys),
- DEG_OPCODE_PSYS_EVAL,
- psys->name);
- }
-
- /* pointcache */
- // TODO...
-}
-
/* IK Solver Eval Steps */
void DepsgraphNodeBuilder::build_ik_pose(Scene *scene, Object *ob, bPoseChannel *pchan, bConstraint *con)
{
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
index 09c7d9ab9de..232c801563e 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
@@ -59,7 +59,6 @@ extern "C" {
#include "DNA_mesh_types.h"
#include "DNA_meta_types.h"
#include "DNA_node_types.h"
-#include "DNA_particle_types.h"
#include "DNA_object_types.h"
#include "DNA_rigidbody_types.h"
#include "DNA_scene_types.h"
@@ -84,7 +83,6 @@ extern "C" {
#include "BKE_modifier.h"
#include "BKE_node.h"
#include "BKE_object.h"
-#include "BKE_particle.h"
#include "BKE_rigidbody.h"
#include "BKE_sound.h"
#include "BKE_texture.h"
@@ -291,9 +289,9 @@ void DepsgraphRelationBuilder::add_collision_relations(const OperationKey &key,
MEM_freeN(collobjs);
}
-void DepsgraphRelationBuilder::add_forcefield_relations(const OperationKey &key, Scene *scene, Object *ob, ParticleSystem *psys, EffectorWeights *eff, bool add_absorption, const char *name)
+void DepsgraphRelationBuilder::add_forcefield_relations(const OperationKey &key, Scene *scene, Object *ob, EffectorWeights *eff, bool add_absorption, const char *name)
{
- ListBase *effectors = pdInitEffectors(scene, ob, psys, eff, false);
+ ListBase *effectors = pdInitEffectors(scene, ob, eff, false);
if (effectors) {
for (EffectorCache *eff = (EffectorCache *)effectors->first; eff; eff = eff->next) {
@@ -302,21 +300,6 @@ void DepsgraphRelationBuilder::add_forcefield_relations(const OperationKey &key,
add_relation(eff_key, key, DEPSREL_TYPE_STANDARD, name);
}
- if (eff->psys) {
- if (eff->ob != ob) {
- ComponentKey eff_key(&eff->ob->id, DEPSNODE_TYPE_EVAL_PARTICLES);
- add_relation(eff_key, key, DEPSREL_TYPE_STANDARD, name);
-
- /* TODO: remove this when/if EVAL_PARTICLES is sufficient for up to date particles */
- ComponentKey mod_key(&eff->ob->id, DEPSNODE_TYPE_GEOMETRY);
- add_relation(mod_key, key, DEPSREL_TYPE_STANDARD, name);
- }
- else if (eff->psys != psys) {
- OperationKey eff_key(&eff->ob->id, DEPSNODE_TYPE_EVAL_PARTICLES, DEG_OPCODE_PSYS_EVAL, eff->psys->name);
- add_relation(eff_key, key, DEPSREL_TYPE_STANDARD, name);
- }
- }
-
if (eff->pd->forcefield == PFIELD_SMOKEFLOW && eff->pd->f_source) {
ComponentKey trf_key(&eff->pd->f_source->id, DEPSNODE_TYPE_TRANSFORM);
add_relation(trf_key, key, DEPSREL_TYPE_STANDARD, "Smoke Force Domain");
@@ -552,11 +535,6 @@ void DepsgraphRelationBuilder::build_object(Main *bmain, Scene *scene, Object *o
}
}
- /* particle systems */
- if (ob->particlesystem.first) {
- build_particles(scene, ob);
- }
-
/* grease pencil */
if (ob->gpd) {
build_gpencil(&ob->id, ob->gpd);
@@ -1163,127 +1141,6 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene)
}
}
-void DepsgraphRelationBuilder::build_particles(Scene *scene, Object *ob)
-{
- TimeSourceKey time_src_key;
- OperationKey obdata_ubereval_key(&ob->id,
- DEPSNODE_TYPE_GEOMETRY,
- DEG_OPCODE_GEOMETRY_UBEREVAL);
-
- /* particle systems */
- for (ParticleSystem *psys = (ParticleSystem *)ob->particlesystem.first; psys; psys = psys->next) {
- ParticleSettings *part = psys->part;
-
- /* particle settings */
- build_animdata(&part->id);
-
- /* this particle system */
- OperationKey psys_key(&ob->id, DEPSNODE_TYPE_EVAL_PARTICLES, DEG_OPCODE_PSYS_EVAL, psys->name);
-
- /* XXX: if particle system is later re-enabled, we must do full rebuild? */
- if (!psys_check_enabled(ob, psys, G.is_rendering))
- continue;
-
- /* TODO(sergey): Are all particle systems depends on time?
- * Hair without dynamics i.e.
- */
- add_relation(time_src_key, psys_key,
- DEPSREL_TYPE_TIME,
- "TimeSrc -> PSys");
-
- /* TODO(sergey): Currently particle update is just a placeholder,
- * hook it to the ubereval node so particle system is getting updated
- * on playback.
- */
- add_relation(psys_key,
- obdata_ubereval_key,
- DEPSREL_TYPE_OPERATION,
- "PSys -> UberEval");
-
-#if 0
- if (ELEM(part->phystype, PART_PHYS_KEYED, PART_PHYS_BOIDS)) {
- ParticleTarget *pt;
-
- for (pt = psys->targets.first; pt; pt = pt->next) {
- if (pt->ob && BLI_findlink(&pt->ob->particlesystem, pt->psys - 1)) {
- node2 = dag_get_node(dag, pt->ob);
- dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Particle Targets");
- }
- }
- }
-
- if (part->ren_as == PART_DRAW_OB && part->dup_ob) {
- node2 = dag_get_node(dag, part->dup_ob);
- /* note that this relation actually runs in the wrong direction, the problem
- * is that dupli system all have this (due to parenting), and the render
- * engine instancing assumes particular ordering of objects in list */
- dag_add_relation(dag, node, node2, DAG_RL_OB_OB, "Particle Object Visualization");
- if (part->dup_ob->type == OB_MBALL)
- dag_add_relation(dag, node, node2, DAG_RL_DATA_DATA, "Particle Object Visualization");
- }
-
- if (part->ren_as == PART_DRAW_GR && part->dup_group) {
- for (go = part->dup_group->gobject.first; go; go = go->next) {
- node2 = dag_get_node(dag, go->ob);
- dag_add_relation(dag, node2, node, DAG_RL_OB_OB, "Particle Group Visualization");
- }
- }
-#endif
-
- /* collisions */
- if (part->type != PART_HAIR) {
- add_collision_relations(psys_key, scene, ob, part->collision_group, ob->lay, true, "Particle Collision");
- }
-
- /* effectors */
- add_forcefield_relations(psys_key, scene, ob, psys, part->effector_weights, part->type == PART_HAIR, "Particle Field");
-
- /* boids */
- if (part->boids) {
- BoidRule *rule = NULL;
- BoidState *state = NULL;
-
- for (state = (BoidState *)part->boids->states.first; state; state = state->next) {
- for (rule = (BoidRule *)state->rules.first; rule; rule = rule->next) {
- Object *ruleob = NULL;
- if (rule->type == eBoidRuleType_Avoid)
- ruleob = ((BoidRuleGoalAvoid *)rule)->ob;
- else if (rule->type == eBoidRuleType_FollowLeader)
- ruleob = ((BoidRuleFollowLeader *)rule)->ob;
-
- if (ruleob) {
- ComponentKey ruleob_key(&ruleob->id, DEPSNODE_TYPE_TRANSFORM);
- add_relation(ruleob_key, psys_key, DEPSREL_TYPE_TRANSFORM, "Boid Rule");
- }
- }
- }
- }
-
- if (part->ren_as == PART_DRAW_OB && part->dup_ob) {
- ComponentKey dup_ob_key(&part->dup_ob->id, DEPSNODE_TYPE_TRANSFORM);
- add_relation(dup_ob_key,
- psys_key,
- DEPSREL_TYPE_TRANSFORM,
- "Particle Object Visualization");
- }
- }
-
- /* Particle depends on the object transform, so that channel is to be ready
- * first.
- *
- * TODO(sergey): This relation should be altered once real granular update
- * is implemented.
- */
- ComponentKey transform_key(&ob->id, DEPSNODE_TYPE_TRANSFORM);
- add_relation(transform_key,
- obdata_ubereval_key,
- DEPSREL_TYPE_GEOMETRY_EVAL,
- "Partcile Eval");
-
- /* pointcache */
- // TODO...
-}
-
/* IK Solver Eval Steps */
void DepsgraphRelationBuilder::build_ik_pose(Object *ob,
bPoseChannel *pchan,
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.h b/source/blender/depsgraph/intern/builder/deg_builder_relations.h
index 5240aa24b54..ac6e6f8f095 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.h
@@ -247,7 +247,7 @@ struct DepsgraphRelationBuilder
void build_gpencil(ID *owner, bGPdata *gpd);
void add_collision_relations(const OperationKey &key, Scene *scene, Object *ob, Group *group, int layer, bool dupli, const char *name);
- void add_forcefield_relations(const OperationKey &key, Scene *scene, Object *ob, ParticleSystem *psys, EffectorWeights *eff, bool add_absorption, const char *name);
+ void add_forcefield_relations(const OperationKey &key, Scene *scene, Object *ob, EffectorWeights *eff, bool add_absorption, const char *name);
template <typename KeyType>
OperationDepsNode *find_operation_node(const KeyType &key);
diff --git a/source/blender/depsgraph/intern/depsgraph_build.cc b/source/blender/depsgraph/intern/depsgraph_build.cc
index 7a3b19e82c6..119b2054d24 100644
--- a/source/blender/depsgraph/intern/depsgraph_build.cc
+++ b/source/blender/depsgraph/intern/depsgraph_build.cc
@@ -329,20 +329,13 @@ void DEG_add_collision_relations(DepsNodeHandle *handle, Scene *scene, Object *o
void DEG_add_forcefield_relations(DepsNodeHandle *handle, Scene *scene, Object *ob, EffectorWeights *effector_weights, bool add_absorption, int skip_forcefield, const char *name)
{
- ListBase *effectors = pdInitEffectors(scene, ob, NULL, effector_weights, false);
+ ListBase *effectors = pdInitEffectors(scene, ob, effector_weights, false);
if (effectors) {
for (EffectorCache *eff = (EffectorCache*)effectors->first; eff; eff = eff->next) {
if (eff->ob != ob && eff->pd->forcefield != skip_forcefield) {
DEG_add_object_relation(handle, eff->ob, DEG_OB_COMP_TRANSFORM, name);
- if (eff->psys) {
- DEG_add_object_relation(handle, eff->ob, DEG_OB_COMP_EVAL_PARTICLES, name);
-
- /* TODO: remove this when/if EVAL_PARTICLES is sufficient for up to date particles */
- DEG_add_object_relation(handle, eff->ob, DEG_OB_COMP_GEOMETRY, name);
- }
-
if (eff->pd->forcefield == PFIELD_SMOKEFLOW && eff->pd->f_source) {
DEG_add_object_relation(handle, eff->pd->f_source, DEG_OB_COMP_TRANSFORM, "Smoke Force Domain");
DEG_add_object_relation(handle, eff->pd->f_source, DEG_OB_COMP_GEOMETRY, "Smoke Force Domain");
diff --git a/source/blender/depsgraph/intern/depsgraph_tag.cc b/source/blender/depsgraph/intern/depsgraph_tag.cc
index b7b62bd59f9..75fb55a1b4d 100644
--- a/source/blender/depsgraph/intern/depsgraph_tag.cc
+++ b/source/blender/depsgraph/intern/depsgraph_tag.cc
@@ -38,7 +38,6 @@ extern "C" {
#include "BLI_utildefines.h"
#include "DNA_object_types.h"
-#include "DNA_particle_types.h"
#include "DNA_screen_types.h"
#include "DNA_windowmanager_types.h"
@@ -74,7 +73,9 @@ extern "C" {
* design of those areas is more clear we'll do the same legacy code here.
* - sergey -
*/
+#if 0
#define DEPSGRAPH_USE_LEGACY_TAGGING
+#endif
namespace {
@@ -116,7 +117,7 @@ void lib_id_recalc_tag_flag(Main *bmain, ID *id, int flag)
if (flag & OB_RECALC_OB)
lib_id_recalc_tag(bmain, id);
- if (flag & (OB_RECALC_DATA | PSYS_RECALC))
+ if (flag & OB_RECALC_DATA)
lib_id_recalc_data_tag(bmain, id);
}
else {
@@ -124,33 +125,6 @@ void lib_id_recalc_tag_flag(Main *bmain, ID *id, int flag)
}
}
-#ifdef DEPSGRAPH_USE_LEGACY_TAGGING
-void depsgraph_legacy_handle_update_tag(Main *bmain, ID *id, short flag)
-{
- if (flag) {
- Object *object;
- short idtype = GS(id->name);
- if (idtype == ID_PA) {
- ParticleSystem *psys;
- for (object = (Object *)bmain->object.first;
- object != NULL;
- object = (Object *)object->id.next)
- {
- for (psys = (ParticleSystem *)object->particlesystem.first;
- psys != NULL;
- psys = (ParticleSystem *)psys->next)
- {
- if (&psys->part->id == id) {
- DEG_id_tag_update_ex(bmain, &object->id, flag & OB_RECALC_ALL);
- psys->recalc |= (flag & PSYS_RECALC);
- }
- }
- }
- }
- }
-}
-#endif
-
} /* namespace */
/* Tag all nodes in ID-block for update.
@@ -237,14 +211,6 @@ void DEG_id_tag_update_ex(Main *bmain, ID *id, short flag)
}
}
}
-
-#ifdef DEPSGRAPH_USE_LEGACY_TAGGING
- /* Special handling from the legacy depsgraph.
- * TODO(sergey): Need to get rid of those once all the areas
- * are re-formulated in terms of franular nodes.
- */
- depsgraph_legacy_handle_update_tag(bmain, id, flag);
-#endif
}
/* Tag given ID type for update. */
diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c
index 57302c18a88..de6a17e9d41 100644
--- a/source/blender/editors/animation/anim_channels_defines.c
+++ b/source/blender/editors/animation/anim_channels_defines.c
@@ -43,7 +43,6 @@
#include "DNA_cachefile_types.h"
#include "DNA_camera_types.h"
#include "DNA_object_types.h"
-#include "DNA_particle_types.h"
#include "DNA_screen_types.h"
#include "DNA_scene_types.h"
#include "DNA_space_types.h"
@@ -119,11 +118,10 @@ static void acf_generic_root_backdrop(bAnimContext *ac, bAnimListElem *ale, floa
/* set backdrop drawing color */
acf->get_backdrop_color(ac, ale, color);
- glColor3fv(color);
/* rounded corners on LHS only - top only when expanded, but bottom too when collapsed */
UI_draw_roundbox_corner_set((expanded) ? UI_CNR_TOP_LEFT : (UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT));
- UI_draw_roundbox_gl_mode(GL_POLYGON, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8);
+ UI_draw_roundbox_gl_mode_3fvAlpha(GL_POLYGON, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8, color, 1.0f);
}
@@ -316,7 +314,7 @@ static short acf_generic_group_offset(bAnimContext *ac, bAnimListElem *ale)
offset += U.widget_unit;
}
/* materials and particles animdata */
- else if (ELEM(GS(ale->id->name), ID_MA, ID_PA))
+ else if (GS(ale->id->name) == ID_MA)
offset += (short)(0.7f * U.widget_unit);
/* if not in Action Editor mode, action-groups (and their children) must carry some offset too... */
@@ -421,14 +419,13 @@ static void acf_summary_backdrop(bAnimContext *ac, bAnimListElem *ale, float ymi
/* set backdrop drawing color */
acf->get_backdrop_color(ac, ale, color);
- glColor3fv(color);
/* rounded corners on LHS only
* - top and bottom
* - special hack: make the top a bit higher, since we are first...
*/
UI_draw_roundbox_corner_set(UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT);
- UI_draw_roundbox_gl_mode(GL_POLYGON, 0, yminc - 2, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8);
+ UI_draw_roundbox_gl_mode_3fvAlpha(GL_POLYGON, 0, yminc - 2, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8, color, 1.0f);
}
/* name for summary entries */
@@ -814,11 +811,10 @@ static void acf_group_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc
/* set backdrop drawing color */
acf->get_backdrop_color(ac, ale, color);
- glColor3fv(color);
/* rounded corners on LHS only - top only when expanded, but bottom too when collapsed */
UI_draw_roundbox_corner_set(expanded ? UI_CNR_TOP_LEFT : (UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT));
- UI_draw_roundbox_gl_mode(GL_POLYGON, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8);
+ UI_draw_roundbox_gl_mode_3fvAlpha(GL_POLYGON, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8, color, 1.0f);
}
/* name for group entries */
@@ -1071,11 +1067,10 @@ static void acf_nla_controls_backdrop(bAnimContext *ac, bAnimListElem *ale, floa
/* set backdrop drawing color */
acf->get_backdrop_color(ac, ale, color);
- glColor3fv(color);
- /* rounded corners on LHS only - top only when expanded, but bottom too when collapsed */
+ /* rounded corners on LHS only - top only when expanded, but bottom too when collapsed */
UI_draw_roundbox_corner_set(expanded ? UI_CNR_TOP_LEFT : (UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT));
- UI_draw_roundbox_gl_mode(GL_POLYGON, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 5);
+ UI_draw_roundbox_gl_mode_3fvAlpha(GL_POLYGON, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 5, color, 1.0f);
}
/* name for nla controls expander entries */
@@ -2002,83 +1997,6 @@ static bAnimChannelType ACF_DSWOR =
acf_dswor_setting_ptr /* pointer for setting */
};
-/* Particle Expander ------------------------------------------- */
-
-// TODO: just get this from RNA?
-static int acf_dspart_icon(bAnimListElem *UNUSED(ale))
-{
- return ICON_PARTICLE_DATA;
-}
-
-/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_dspart_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 PART_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;
- }
-}
-
-/* get pointer to the setting */
-static void *acf_dspart_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
-{
- ParticleSettings *part = (ParticleSettings *)ale->data;
-
- /* clear extra return data first */
- *type = 0;
-
- switch (setting) {
- case ACHANNEL_SETTING_EXPAND: /* expanded */
- return GET_ACF_FLAG_PTR(part->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 (part->adt)
- return GET_ACF_FLAG_PTR(part->adt->flag, type);
- return NULL;
-
- default: /* unsupported */
- return NULL;
- }
-}
-
-/* particle expander type define */
-static bAnimChannelType ACF_DSPART =
-{
- "Particle Data 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_dspart_icon, /* icon */
-
- acf_generic_dataexpand_setting_valid, /* has setting */
- acf_dspart_setting_flag, /* flag for setting */
- acf_dspart_setting_ptr /* pointer for setting */
-};
-
/* MetaBall Expander ------------------------------------------- */
// TODO: just get this from RNA?
@@ -3420,24 +3338,20 @@ static void acf_nlaaction_backdrop(bAnimContext *ac, bAnimListElem *ale, float y
*/
nla_action_get_color(adt, (bAction *)ale->data, color);
- if (adt && (adt->flag & ADT_NLA_EDIT_ON)) {
- /* Yes, the color vector has 4 components, BUT we only want to be using 3 of them! */
- glColor3fv(color);
- }
- else {
- float alpha = (adt && (adt->flag & ADT_NLA_SOLO_TRACK)) ? 0.3f : 1.0f;
- glColor4f(color[0], color[1], color[2], alpha);
- }
-
- /* only on top left corner, to show that this channel sits on top of the preceding ones
+ if (adt && (adt->flag & ADT_NLA_EDIT_ON))
+ color[3] = 1.0f;
+ else
+ color[3] = (adt && (adt->flag & ADT_NLA_SOLO_TRACK)) ? 0.3f : 1.0f;
+
+ /* only on top left corner, to show that this channel sits on top of the preceding ones
* while still linking into the action line strip to the right
*/
UI_draw_roundbox_corner_set(UI_CNR_TOP_LEFT);
-
+
/* draw slightly shifted up vertically to look like it has more separation from other channels,
* but we then need to slightly shorten it so that it doesn't look like it overlaps
*/
- UI_draw_roundbox_gl_mode(GL_POLYGON, offset, yminc + NLACHANNEL_SKIP, (float)v2d->cur.xmax, ymaxc + NLACHANNEL_SKIP - 1, 8);
+ UI_draw_roundbox_gl_mode(GL_POLYGON, offset, yminc + NLACHANNEL_SKIP, (float)v2d->cur.xmax, ymaxc + NLACHANNEL_SKIP - 1, 8, color);
}
/* name for nla action entries */
@@ -3580,7 +3494,6 @@ static void ANIM_init_channel_typeinfo_data(void)
animchannelTypeInfo[type++] = &ACF_DSSKEY; /* ShapeKey Channel */
animchannelTypeInfo[type++] = &ACF_DSWOR; /* World Channel */
animchannelTypeInfo[type++] = &ACF_DSNTREE; /* NodeTree Channel */
- animchannelTypeInfo[type++] = &ACF_DSPART; /* Particle Channel */
animchannelTypeInfo[type++] = &ACF_DSMBALL; /* MetaBall Channel */
animchannelTypeInfo[type++] = &ACF_DSARM; /* Armature Channel */
animchannelTypeInfo[type++] = &ACF_DSMESH; /* Mesh Channel */
diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c
index 117b8549712..ecaadd78dc2 100644
--- a/source/blender/editors/animation/anim_channels_edit.c
+++ b/source/blender/editors/animation/anim_channels_edit.c
@@ -124,7 +124,6 @@ void ANIM_set_active_channel(bAnimContext *ac, void *data, eAnimCont_Types datat
case ANIMTYPE_DSCUR:
case ANIMTYPE_DSSKEY:
case ANIMTYPE_DSWOR:
- case ANIMTYPE_DSPART:
case ANIMTYPE_DSMBALL:
case ANIMTYPE_DSARM:
case ANIMTYPE_DSMESH:
@@ -181,7 +180,6 @@ void ANIM_set_active_channel(bAnimContext *ac, void *data, eAnimCont_Types datat
case ANIMTYPE_DSCUR:
case ANIMTYPE_DSSKEY:
case ANIMTYPE_DSWOR:
- case ANIMTYPE_DSPART:
case ANIMTYPE_DSMBALL:
case ANIMTYPE_DSARM:
case ANIMTYPE_DSMESH:
@@ -283,7 +281,6 @@ void ANIM_deselect_anim_channels(bAnimContext *ac, void *data, eAnimCont_Types d
case ANIMTYPE_DSCUR:
case ANIMTYPE_DSSKEY:
case ANIMTYPE_DSWOR:
- case ANIMTYPE_DSPART:
case ANIMTYPE_DSMBALL:
case ANIMTYPE_DSARM:
case ANIMTYPE_DSMESH:
@@ -380,7 +377,6 @@ void ANIM_deselect_anim_channels(bAnimContext *ac, void *data, eAnimCont_Types d
case ANIMTYPE_DSCUR:
case ANIMTYPE_DSSKEY:
case ANIMTYPE_DSWOR:
- case ANIMTYPE_DSPART:
case ANIMTYPE_DSMBALL:
case ANIMTYPE_DSARM:
case ANIMTYPE_DSMESH:
@@ -2732,7 +2728,6 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index,
case ANIMTYPE_DSCUR:
case ANIMTYPE_DSSKEY:
case ANIMTYPE_DSWOR:
- case ANIMTYPE_DSPART:
case ANIMTYPE_DSMBALL:
case ANIMTYPE_DSARM:
case ANIMTYPE_DSMESH:
diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c
index c12a050e9ba..7bf146aa171 100644
--- a/source/blender/editors/animation/anim_filter.c
+++ b/source/blender/editors/animation/anim_filter.c
@@ -64,7 +64,6 @@
#include "DNA_meta_types.h"
#include "DNA_movieclip_types.h"
#include "DNA_node_types.h"
-#include "DNA_particle_types.h"
#include "DNA_space_types.h"
#include "DNA_sequence_types.h"
#include "DNA_scene_types.h"
@@ -802,19 +801,6 @@ static bAnimListElem *make_new_animlistelem(void *data, short datatype, ID *owne
ale->adt = BKE_animdata_from_id(data);
break;
}
- case ANIMTYPE_DSPART:
- {
- ParticleSettings *part = (ParticleSettings *)ale->data;
- AnimData *adt = part->adt;
-
- ale->flag = FILTER_PART_OBJD(part);
-
- ale->key_data = (adt) ? adt->action : NULL;
- ale->datatype = ALE_ACT;
-
- ale->adt = BKE_animdata_from_id(data);
- break;
- }
case ANIMTYPE_DSTEX:
{
Tex *tex = (Tex *)data;
@@ -2087,12 +2073,6 @@ static size_t animdata_filter_ds_textures(bAnimContext *ac, ListBase *anim_data,
mtex = (MTex **)(&wo->mtex);
break;
}
- case ID_PA:
- {
- ParticleSettings *part = (ParticleSettings *)owner_id;
- mtex = (MTex **)(&part->mtex);
- break;
- }
default:
{
/* invalid/unsupported option */
@@ -2288,53 +2268,6 @@ static size_t animdata_filter_ds_modifiers(bAnimContext *ac, ListBase *anim_data
/* ............ */
-static size_t animdata_filter_ds_particles(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Object *ob, int filter_mode)
-{
- ParticleSystem *psys;
- size_t items = 0;
-
- for (psys = ob->particlesystem.first; psys; psys = psys->next) {
- ListBase tmp_data = {NULL, NULL};
- size_t tmp_items = 0;
-
- /* if no material returned, skip - so that we don't get weird blank entries... */
- if (ELEM(NULL, psys->part, psys->part->adt))
- continue;
-
- /* add particle-system's animation data to temp collection */
- BEGIN_ANIMFILTER_SUBCHANNELS(FILTER_PART_OBJD(psys->part))
- {
- /* particle system's animation data */
- tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)psys->part, filter_mode);
-
- /* textures */
- if (!(ads->filterflag & ADS_FILTER_NOTEX))
- tmp_items += animdata_filter_ds_textures(ac, &tmp_data, ads, (ID *)psys->part, filter_mode);
- }
- END_ANIMFILTER_SUBCHANNELS;
-
- /* did we find anything? */
- if (tmp_items) {
- /* include particle-expand widget first */
- if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
- /* check if filtering by active status */
- if (ANIMCHANNEL_ACTIVEOK(psys->part)) {
- ANIMCHANNEL_NEW_CHANNEL(psys->part, ANIMTYPE_DSPART, psys->part);
- }
- }
-
- /* now add the list of collected channels */
- BLI_movelisttolist(anim_data, &tmp_data);
- BLI_assert(BLI_listbase_is_empty(&tmp_data));
- items += tmp_items;
- }
- }
-
- /* return the number of items added to the list */
- return items;
-}
-
-
static size_t animdata_filter_ds_obdata(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Object *ob, int filter_mode)
{
ListBase tmp_data = {NULL, NULL};
@@ -2610,11 +2543,6 @@ static size_t animdata_filter_dopesheet_ob(bAnimContext *ac, ListBase *anim_data
tmp_items += animdata_filter_ds_obdata(ac, &tmp_data, ads, ob, filter_mode);
}
- /* particles */
- if ((ob->particlesystem.first) && !(ads->filterflag & ADS_FILTER_NOPART)) {
- tmp_items += animdata_filter_ds_particles(ac, &tmp_data, ads, ob, filter_mode);
- }
-
/* grease pencil */
if ((ob->gpd) && !(ads->filterflag & ADS_FILTER_NOGPENCIL)) {
tmp_items += animdata_filter_ds_gpencil(ac, &tmp_data, ads, ob->gpd, filter_mode);
diff --git a/source/blender/editors/gpencil/drawgpencil.c b/source/blender/editors/gpencil/drawgpencil.c
index 48786e08f85..181f85e0909 100644
--- a/source/blender/editors/gpencil/drawgpencil.c
+++ b/source/blender/editors/gpencil/drawgpencil.c
@@ -60,9 +60,11 @@
#include "WM_api.h"
-#include "BIF_gl.h"
#include "BIF_glutil.h"
+#include "GPU_immediate.h"
+#include "GPU_draw.h"
+
#include "ED_gpencil.h"
#include "ED_screen.h"
#include "ED_view3d.h"
@@ -94,97 +96,194 @@ typedef enum eDrawStrokeFlags {
/* thickness above which we should use special drawing */
#define GP_DRAWTHICKNESS_SPECIAL 3
+/* conversion utility (float --> normalized unsigned byte) */
+#define F2UB(x) (unsigned char)(255.0f * x)
+
/* ----- Tool Buffer Drawing ------ */
-/* helper function to set color of buffer point */
-static void gp_set_tpoint_color(tGPspoint *pt, float ink[4])
+/* helper functions to set color of buffer point */
+
+static void gp_set_tpoint_varying_color(const tGPspoint *pt, const float ink[4], unsigned attrib_id)
+{
+ float alpha = ink[3] * pt->strength;
+ CLAMP(alpha, GPENCIL_STRENGTH_MIN, 1.0f);
+ immAttrib4ub(attrib_id, F2UB(ink[0]), F2UB(ink[1]), F2UB(ink[2]), F2UB(alpha));
+}
+
+static void gp_set_point_uniform_color(const bGPDspoint *pt, const float ink[4])
{
float alpha = ink[3] * pt->strength;
CLAMP(alpha, GPENCIL_STRENGTH_MIN, 1.0f);
- glColor4f(ink[0], ink[1], ink[2], alpha);
+ immUniform4f("color", ink[0], ink[1], ink[2], alpha);
}
-/* helper function to set color of point */
-static void gp_set_point_color(bGPDspoint *pt, float ink[4])
+static void gp_set_point_varying_color(const bGPDspoint *pt, const float ink[4], unsigned attrib_id)
{
float alpha = ink[3] * pt->strength;
CLAMP(alpha, GPENCIL_STRENGTH_MIN, 1.0f);
- glColor4f(ink[0], ink[1], ink[2], alpha);
+ immAttrib4ub(attrib_id, F2UB(ink[0]), F2UB(ink[1]), F2UB(ink[2]), F2UB(alpha));
}
-/* helper function to set color and point */
-static void gp_set_color_and_tpoint(tGPspoint *pt, float ink[4])
+/* draw fills for buffer stroke */
+static void gp_draw_stroke_buffer_fill(const tGPspoint *points, int totpoints, float ink[4])
{
- gp_set_tpoint_color(pt, ink);
- glVertex2iv(&pt->x);
+ if (totpoints < 3) {
+ return;
+ }
+ int tot_triangles = totpoints - 2;
+ /* allocate memory for temporary areas */
+ unsigned int(*tmp_triangles)[3] = MEM_mallocN(sizeof(*tmp_triangles) * tot_triangles, "GP Stroke buffer temp triangulation");
+ float(*points2d)[2] = MEM_mallocN(sizeof(*points2d) * totpoints, "GP Stroke buffer temp 2d points");
+
+ /* Convert points to array and triangulate
+ * Here a cache is not used because while drawing the information changes all the time, so the cache
+ * would be recalculated constantly, so it is better to do direct calculation for each function call
+ */
+ for (int i = 0; i < totpoints; i++) {
+ const tGPspoint *pt = &points[i];
+ points2d[i][0] = pt->x;
+ points2d[i][1] = pt->y;
+ }
+ BLI_polyfill_calc((const float(*)[2])points2d, (unsigned int)totpoints, 0, (unsigned int(*)[3])tmp_triangles);
+
+ /* draw triangulation data */
+ if (tot_triangles > 0) {
+ VertexFormat *format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_INT, 2, CONVERT_INT_TO_FLOAT);
+ unsigned color = add_attrib(format, "color", GL_UNSIGNED_BYTE, 4, NORMALIZE_INT_TO_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
+
+ /* Draw all triangles for filling the polygon */
+ immBegin(GL_TRIANGLES, tot_triangles * 3);
+ /* TODO: use batch instead of immediate mode, to share vertices */
+
+ const tGPspoint *pt;
+ for (int i = 0; i < tot_triangles; i++) {
+ /* vertex 1 */
+ pt = &points[tmp_triangles[i][0]];
+ gp_set_tpoint_varying_color(pt, ink, color);
+ immVertex2iv(pos, &pt->x);
+ /* vertex 2 */
+ pt = &points[tmp_triangles[i][1]];
+ gp_set_tpoint_varying_color(pt, ink, color);
+ immVertex2iv(pos, &pt->x);
+ /* vertex 3 */
+ pt = &points[tmp_triangles[i][2]];
+ gp_set_tpoint_varying_color(pt, ink, color);
+ immVertex2iv(pos, &pt->x);
+ }
+
+ immEnd();
+ immUnbindProgram();
+ }
+
+ /* clear memory */
+ if (tmp_triangles) {
+ MEM_freeN(tmp_triangles);
+ }
+ if (points2d) {
+ MEM_freeN(points2d);
+ }
}
/* draw stroke defined in buffer (simple ogl lines/points for now, as dotted lines) */
-static void gp_draw_stroke_buffer(tGPspoint *points, int totpoints, short thickness,
- short dflag, short sflag, float ink[4])
+static void gp_draw_stroke_buffer(const tGPspoint *points, int totpoints, short thickness,
+ short dflag, short sflag, float ink[4], float fill_ink[4])
{
- tGPspoint *pt;
- int i;
-
+ int draw_points = 0;
+
/* error checking */
if ((points == NULL) || (totpoints <= 0))
return;
-
+
/* check if buffer can be drawn */
if (dflag & (GP_DRAWDATA_ONLY3D | GP_DRAWDATA_ONLYV2D))
return;
-
+
+ if (sflag & GP_STROKE_ERASER) {
+ /* don't draw stroke at all! */
+ return;
+ }
+
+ VertexFormat *format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_INT, 2, CONVERT_INT_TO_FLOAT);
+ unsigned color = add_attrib(format, "color", GL_UNSIGNED_BYTE, 4, NORMALIZE_INT_TO_FLOAT);
+
+ const tGPspoint *pt = points;
+
if (totpoints == 1) {
/* if drawing a single point, draw it larger */
glPointSize((float)(thickness + 2) * points->pressure);
- glBegin(GL_POINTS);
-
- gp_set_color_and_tpoint(points, ink);
- glEnd();
- }
- else if (sflag & GP_STROKE_ERASER) {
- /* don't draw stroke at all! */
+ immBindBuiltinProgram(GPU_SHADER_3D_POINT_FIXED_SIZE_VARYING_COLOR);
+ immBegin(GL_POINTS, 1);
+ gp_set_tpoint_varying_color(pt, ink, color);
+ immVertex2iv(pos, &pt->x);
}
else {
float oldpressure = points[0].pressure;
-
+
/* draw stroke curve */
if (G.debug & G_DEBUG) setlinestyle(2);
-
+
glLineWidth(max_ff(oldpressure * thickness, 1.0));
- glBegin(GL_LINE_STRIP);
-
- for (i = 0, pt = points; i < totpoints && pt; i++, pt++) {
+ immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
+ immBeginAtMost(GL_LINE_STRIP, totpoints);
+
+ /* TODO: implement this with a geometry shader to draw one continuous tapered stroke */
+
+ for (int i = 0; i < totpoints; i++, pt++) {
/* if there was a significant pressure change, stop the curve, change the thickness of the stroke,
* and continue drawing again (since line-width cannot change in middle of GL_LINE_STRIP)
*/
if (fabsf(pt->pressure - oldpressure) > 0.2f) {
- glEnd();
+ /* need to have 2 points to avoid immEnd assert error */
+ if (draw_points < 2) {
+ gp_set_tpoint_varying_color(pt - 1, ink, color);
+ immVertex2iv(pos, &(pt - 1)->x);
+ }
+
+ immEnd();
+ draw_points = 0;
+
glLineWidth(max_ff(pt->pressure * thickness, 1.0f));
- glBegin(GL_LINE_STRIP);
-
+ immBeginAtMost(GL_LINE_STRIP, totpoints - i + 1);
+
/* need to roll-back one point to ensure that there are no gaps in the stroke */
if (i != 0) {
- gp_set_color_and_tpoint((pt - 1), ink);
+ gp_set_tpoint_varying_color(pt - 1, ink, color);
+ immVertex2iv(pos, &(pt - 1)->x);
+ ++draw_points;
}
-
- /* now the point we want... */
- gp_set_color_and_tpoint(pt, ink);
-
- oldpressure = pt->pressure;
- }
- else {
- gp_set_color_and_tpoint(pt, ink);
+
+ oldpressure = pt->pressure; /* reset our threshold */
}
+
+ /* now the point we want */
+ gp_set_tpoint_varying_color(pt, ink, color);
+ immVertex2iv(pos, &pt->x);
+ ++draw_points;
+ }
+ /* need to have 2 points to avoid immEnd assert error */
+ if (draw_points < 2) {
+ gp_set_tpoint_varying_color(pt - 1, ink, color);
+ immVertex2iv(pos, &(pt - 1)->x);
}
- glEnd();
if (G.debug & G_DEBUG) setlinestyle(0);
}
+
+ immEnd();
+ immUnbindProgram();
+
+ // draw fill
+ if (fill_ink[3] > GPENCIL_ALPHA_OPACITY_THRESH) {
+ gp_draw_stroke_buffer_fill(points, totpoints, fill_ink);
+ }
}
/* --------- 2D Stroke Drawing Helpers --------- */
/* change in parameter list */
-static void gp_calc_2d_stroke_fxy(float pt[3], short sflag, int offsx, int offsy, int winx, int winy, float r_co[2])
+static void gp_calc_2d_stroke_fxy(const float pt[3], short sflag, int offsx, int offsy, int winx, int winy, float r_co[2])
{
if (sflag & GP_STROKE_2DSPACE) {
r_co[0] = pt[0];
@@ -210,203 +309,141 @@ static void gp_calc_2d_stroke_fxy(float pt[3], short sflag, int offsx, int offsy
/* draw a 2D buffer stroke in "volumetric" style
* NOTE: the stroke buffer doesn't have any coordinate offsets/transforms
*/
-static void gp_draw_stroke_volumetric_buffer(tGPspoint *points, int totpoints, short thickness,
- short dflag, short UNUSED(sflag), float ink[4])
+static void gp_draw_stroke_volumetric_buffer(const tGPspoint *points, int totpoints, short thickness,
+ short dflag, const float ink[4])
{
- GLUquadricObj *qobj = gluNewQuadric();
- float modelview[4][4];
-
- tGPspoint *pt;
- int i;
-
/* error checking */
if ((points == NULL) || (totpoints <= 0))
return;
-
+
/* check if buffer can be drawn */
if (dflag & (GP_DRAWDATA_ONLY3D | GP_DRAWDATA_ONLYV2D))
return;
-
- /* get basic matrix - should be camera space (i.e "identity") */
- glGetFloatv(GL_MODELVIEW_MATRIX, (float *)modelview);
-
- /* draw points */
- glPushMatrix();
-
- for (i = 0, pt = points; i < totpoints; i++, pt++) {
- /* set the transformed position */
- // TODO: scale should change based on zoom level, which requires proper translation mult too!
- modelview[3][0] = pt->x;
- modelview[3][1] = pt->y;
-
- glLoadMatrixf((float *)modelview);
-
- /* draw the disk using the current state... */
- gp_set_tpoint_color(pt, ink);
- gluDisk(qobj, 0.0, pt->pressure * thickness, 32, 1);
-
-
- modelview[3][0] = modelview[3][1] = 0.0f;
+
+ VertexFormat *format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ unsigned size = add_attrib(format, "size", GL_FLOAT, 1, KEEP_FLOAT);
+ unsigned color = add_attrib(format, "color", GL_UNSIGNED_BYTE, 4, NORMALIZE_INT_TO_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR);
+ GPU_enable_program_point_size();
+ immBegin(GL_POINTS, totpoints);
+
+ const tGPspoint *pt = points;
+ for (int i = 0; i < totpoints; i++, pt++) {
+ gp_set_tpoint_varying_color(pt, ink, color);
+ immAttrib1f(size, pt->pressure * thickness); /* TODO: scale based on view transform (zoom level) */
+ immVertex2f(pos, pt->x, pt->y);
}
- glPopMatrix();
- gluDeleteQuadric(qobj);
+ immEnd();
+ immUnbindProgram();
+ GPU_disable_program_point_size();
}
/* draw a 2D strokes in "volumetric" style */
-static void gp_draw_stroke_volumetric_2d(bGPDspoint *points, int totpoints, short thickness,
- short dflag, short sflag,
+static void gp_draw_stroke_volumetric_2d(const bGPDspoint *points, int totpoints, short thickness,
+ short UNUSED(dflag), short sflag,
int offsx, int offsy, int winx, int winy,
- float diff_mat[4][4], float ink[4])
+ const float diff_mat[4][4], const float ink[4])
{
- GLUquadricObj *qobj = gluNewQuadric();
- float modelview[4][4];
- float baseloc[3];
- float scalefac = 1.0f;
-
- bGPDspoint *pt;
- int i;
- float fpt[3];
-
- /* HACK: We need a scale factor for the drawing in the image editor,
- * which seems to use 1 unit as it's maximum size, whereas everything
- * else assumes 1 unit = 1 pixel. Otherwise, we only get a massive blob.
- */
- if ((dflag & GP_DRAWDATA_IEDITHACK) && (dflag & GP_DRAWDATA_ONLYV2D)) {
- scalefac = 0.001f;
- }
-
- /* get basic matrix */
- glGetFloatv(GL_MODELVIEW_MATRIX, (float *)modelview);
- copy_v3_v3(baseloc, modelview[3]);
-
- /* draw points */
- glPushMatrix();
-
- for (i = 0, pt = points; i < totpoints; i++, pt++) {
- /* color of point */
- gp_set_point_color(pt, ink);
-
- /* set the transformed position */
+ VertexFormat *format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ unsigned size = add_attrib(format, "size", GL_FLOAT, 1, KEEP_FLOAT);
+ unsigned color = add_attrib(format, "color", GL_UNSIGNED_BYTE, 4, NORMALIZE_INT_TO_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR);
+ GPU_enable_program_point_size();
+ immBegin(GL_POINTS, totpoints);
+
+ const bGPDspoint *pt = points;
+ for (int i = 0; i < totpoints; i++, pt++) {
+ /* transform position to 2D */
float co[2];
-
+ float fpt[3];
+
mul_v3_m4v3(fpt, diff_mat, &pt->x);
gp_calc_2d_stroke_fxy(fpt, sflag, offsx, offsy, winx, winy, co);
- translate_m4(modelview, co[0], co[1], 0.0f);
-
- glLoadMatrixf((float *)modelview);
-
- /* draw the disk using the current state... */
- gluDisk(qobj, 0.0, pt->pressure * thickness * scalefac, 32, 1);
-
- /* restore matrix */
- copy_v3_v3(modelview[3], baseloc);
+
+ gp_set_point_varying_color(pt, ink, color);
+ immAttrib1f(size, pt->pressure * thickness); /* TODO: scale based on view transform */
+ immVertex2f(pos, co[0], co[1]);
}
-
- glPopMatrix();
- gluDeleteQuadric(qobj);
+
+ immEnd();
+ immUnbindProgram();
+ GPU_disable_program_point_size();
}
/* draw a 3D stroke in "volumetric" style */
static void gp_draw_stroke_volumetric_3d(
- bGPDspoint *points, int totpoints, short thickness,
- short UNUSED(dflag), short UNUSED(sflag), float diff_mat[4][4], float ink[4])
+ const bGPDspoint *points, int totpoints, short thickness,
+ const float ink[4])
{
- GLUquadricObj *qobj = gluNewQuadric();
-
- float base_modelview[4][4], modelview[4][4];
- float base_loc[3];
-
- bGPDspoint *pt;
- int i;
- float fpt[3];
-
- /* Get the basic modelview matrix we use for performing calculations */
- glGetFloatv(GL_MODELVIEW_MATRIX, (float *)base_modelview);
- copy_v3_v3(base_loc, base_modelview[3]);
-
- /* Create the basic view-aligned billboard matrix we're going to actually draw qobj with:
- * - We need to knock out the rotation so that we are
- * simply left with a camera-facing billboard
- * - The scale factors here are chosen so that the thickness
- * is relatively reasonable. Otherwise, it gets far too
- * large!
- */
- scale_m4_fl(modelview, 0.1f);
-
- /* draw each point as a disk... */
- glPushMatrix();
-
- for (i = 0, pt = points; i < totpoints && pt; i++, pt++) {
- /* color of point */
- gp_set_point_color(pt, ink);
-
- mul_v3_m4v3(fpt, diff_mat, &pt->x);
-
- /* apply translation to base_modelview, so that the translated point is put in the right place */
- translate_m4(base_modelview, fpt[0], fpt[1], fpt[2]);
-
- /* copy the translation component to the billboard matrix we're going to use,
- * then reset the base matrix to the original values so that we can do the same
- * for the next point without accumulation/pollution effects
- */
- copy_v3_v3(modelview[3], base_modelview[3]); /* copy offset value */
- copy_v3_v3(base_modelview[3], base_loc); /* restore */
-
- /* apply our billboard matrix for drawing... */
- glLoadMatrixf((float *)modelview);
-
- /* draw the disk using the current state... */
- gluDisk(qobj, 0.0, pt->pressure * thickness, 32, 1);
+ VertexFormat *format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ unsigned size = add_attrib(format, "size", GL_FLOAT, 1, KEEP_FLOAT);
+ unsigned color = add_attrib(format, "color", GL_UNSIGNED_BYTE, 4, NORMALIZE_INT_TO_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR);
+ GPU_enable_program_point_size();
+ immBegin(GL_POINTS, totpoints);
+
+ const bGPDspoint *pt = points;
+ for (int i = 0; i < totpoints && pt; i++, pt++) {
+ gp_set_point_varying_color(pt, ink, color);
+ immAttrib1f(size, pt->pressure * thickness); /* TODO: scale based on view transform */
+ immVertex3fv(pos, &pt->x); /* we can adjust size in vertex shader based on view/projection! */
}
-
- glPopMatrix();
- gluDeleteQuadric(qobj);
+
+ immEnd();
+ immUnbindProgram();
+ GPU_disable_program_point_size();
}
/* --------------- Stroke Fills ----------------- */
/* Get points of stroke always flat to view not affected by camera view or view position */
-static void gp_stroke_2d_flat(bGPDspoint *points, int totpoints, float(*points2d)[2], int *r_direction)
+static void gp_stroke_2d_flat(const bGPDspoint *points, int totpoints, float(*points2d)[2], int *r_direction)
{
- bGPDspoint *pt0 = &points[0];
- bGPDspoint *pt1 = &points[1];
- bGPDspoint *pt3 = &points[(int)(totpoints * 0.75)];
-
+ const bGPDspoint *pt0 = &points[0];
+ const bGPDspoint *pt1 = &points[1];
+ const bGPDspoint *pt3 = &points[(int)(totpoints * 0.75)];
+
float locx[3];
float locy[3];
float loc3[3];
float normal[3];
-
+
/* local X axis (p0 -> p1) */
sub_v3_v3v3(locx, &pt1->x, &pt0->x);
-
+
/* point vector at 3/4 */
sub_v3_v3v3(loc3, &pt3->x, &pt0->x);
-
+
/* vector orthogonal to polygon plane */
cross_v3_v3v3(normal, locx, loc3);
-
+
/* local Y axis (cross to normal/x axis) */
cross_v3_v3v3(locy, normal, locx);
-
+
/* Normalize vectors */
normalize_v3(locx);
normalize_v3(locy);
-
+
/* Get all points in local space */
for (int i = 0; i < totpoints; i++) {
- bGPDspoint *pt = &points[i];
+ const bGPDspoint *pt = &points[i];
float loc[3];
-
+
/* Get local space using first point as origin */
sub_v3_v3v3(loc, &pt->x, &pt0->x);
-
+
points2d[i][0] = dot_v3v3(loc, locx);
points2d[i][1] = dot_v3v3(loc, locy);
}
-
+
/* Concave (-1), Convex (1), or Autodetect (0)? */
*r_direction = (int)locy[2];
}
@@ -416,14 +453,14 @@ static void gp_stroke_2d_flat(bGPDspoint *points, int totpoints, float(*points2d
static void gp_triangulate_stroke_fill(bGPDstroke *gps)
{
BLI_assert(gps->totpoints >= 3);
-
+
/* allocate memory for temporary areas */
gps->tot_triangles = gps->totpoints - 2;
unsigned int (*tmp_triangles)[3] = MEM_mallocN(sizeof(*tmp_triangles) * gps->tot_triangles, "GP Stroke temp triangulation");
float (*points2d)[2] = MEM_mallocN(sizeof(*points2d) * gps->totpoints, "GP Stroke temp 2d points");
-
+
int direction = 0;
-
+
/* convert to 2d and triangulate */
gp_stroke_2d_flat(gps->points, gps->totpoints, points2d, &direction);
BLI_polyfill_calc((const float(*)[2])points2d, (unsigned int)gps->totpoints, direction, (unsigned int(*)[3])tmp_triangles);
@@ -438,7 +475,7 @@ static void gp_triangulate_stroke_fill(bGPDstroke *gps)
else {
gps->triangles = MEM_recallocN(gps->triangles, sizeof(*gps->triangles) * gps->tot_triangles);
}
-
+
for (int i = 0; i < gps->tot_triangles; i++) {
bGPDtriangle *stroke_triangle = &gps->triangles[i];
stroke_triangle->v1 = tmp_triangles[i][0];
@@ -450,15 +487,15 @@ static void gp_triangulate_stroke_fill(bGPDstroke *gps)
/* No triangles needed - Free anything allocated previously */
if (gps->triangles)
MEM_freeN(gps->triangles);
-
+
gps->triangles = NULL;
}
-
+
/* disable recalculation flag */
if (gps->flag & GP_STROKE_RECALC_CACHES) {
gps->flag &= ~GP_STROKE_RECALC_CACHES;
}
-
+
/* clear memory */
if (tmp_triangles) MEM_freeN(tmp_triangles);
if (points2d) MEM_freeN(points2d);
@@ -468,42 +505,55 @@ static void gp_triangulate_stroke_fill(bGPDstroke *gps)
/* draw fills for shapes */
static void gp_draw_stroke_fill(
bGPdata *gpd, bGPDstroke *gps,
- int offsx, int offsy, int winx, int winy, float diff_mat[4][4])
+ int offsx, int offsy, int winx, int winy, const float diff_mat[4][4], const float color[4])
{
- bGPDpalettecolor *palcolor;
- int i;
float fpt[3];
BLI_assert(gps->totpoints >= 3);
- palcolor = ED_gpencil_stroke_getcolor(gpd, gps);
+ bGPDpalettecolor *palcolor = ED_gpencil_stroke_getcolor(gpd, gps);
/* Triangulation fill if high quality flag is enabled */
if (palcolor->flag & PC_COLOR_HQ_FILL) {
- bGPDtriangle *stroke_triangle;
- bGPDspoint *pt;
-
/* Calculate triangles cache for filling area (must be done only after changes) */
if ((gps->flag & GP_STROKE_RECALC_CACHES) || (gps->tot_triangles == 0) || (gps->triangles == NULL)) {
gp_triangulate_stroke_fill(gps);
}
- /* Draw all triangles for filling the polygon (cache must be calculated before) */
BLI_assert(gps->tot_triangles >= 1);
- glBegin(GL_TRIANGLES);
- for (i = 0, stroke_triangle = gps->triangles; i < gps->tot_triangles; i++, stroke_triangle++) {
+
+ unsigned pos;
+ if (gps->flag & GP_STROKE_3DSPACE) {
+ pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ }
+ else {
+ pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ }
+
+ immUniformColor4fv(color);
+
+ /* Draw all triangles for filling the polygon (cache must be calculated before) */
+ immBegin(GL_TRIANGLES, gps->tot_triangles * 3);
+ /* TODO: use batch instead of immediate mode, to share vertices */
+
+ bGPDtriangle *stroke_triangle = gps->triangles;
+ bGPDspoint *pt;
+
+ for (int i = 0; i < gps->tot_triangles; i++, stroke_triangle++) {
if (gps->flag & GP_STROKE_3DSPACE) {
/* vertex 1 */
pt = &gps->points[stroke_triangle->v1];
mul_v3_m4v3(fpt, diff_mat, &pt->x);
- glVertex3fv(fpt);
+ immVertex3fv(pos, fpt);
/* vertex 2 */
pt = &gps->points[stroke_triangle->v2];
mul_v3_m4v3(fpt, diff_mat, &pt->x);
- glVertex3fv(fpt);
+ immVertex3fv(pos, fpt);
/* vertex 3 */
pt = &gps->points[stroke_triangle->v3];
mul_v3_m4v3(fpt, diff_mat, &pt->x);
- glVertex3fv(fpt);
+ immVertex3fv(pos, fpt);
}
else {
float co[2];
@@ -511,21 +561,25 @@ static void gp_draw_stroke_fill(
pt = &gps->points[stroke_triangle->v1];
mul_v3_m4v3(fpt, diff_mat, &pt->x);
gp_calc_2d_stroke_fxy(fpt, gps->flag, offsx, offsy, winx, winy, co);
- glVertex2fv(co);
+ immVertex2fv(pos, co);
/* vertex 2 */
pt = &gps->points[stroke_triangle->v2];
mul_v3_m4v3(fpt, diff_mat, &pt->x);
gp_calc_2d_stroke_fxy(fpt, gps->flag, offsx, offsy, winx, winy, co);
- glVertex2fv(co);
+ immVertex2fv(pos, co);
/* vertex 3 */
pt = &gps->points[stroke_triangle->v3];
mul_v3_m4v3(fpt, diff_mat, &pt->x);
gp_calc_2d_stroke_fxy(fpt, gps->flag, offsx, offsy, winx, winy, co);
- glVertex2fv(co);
+ immVertex2fv(pos, co);
}
}
- glEnd();
+
+ immEnd();
+ immUnbindProgram();
}
+
+#if 0 /* convert to modern GL only if needed */
else {
/* As an initial implementation, we use the OpenGL filled polygon drawing
* here since it's the easiest option to implement for this case. It does
@@ -537,10 +591,10 @@ static void gp_draw_stroke_fill(
* created using old versions of Blender which may have depended on the artifacts
* the old fills created.
*/
- bGPDspoint *pt;
+ bGPDspoint *pt = gps->points;
glBegin(GL_POLYGON);
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ for (int i = 0; i < gps->totpoints; i++, pt++) {
if (gps->flag & GP_STROKE_3DSPACE) {
mul_v3_m4v3(fpt, diff_mat, &pt->x);
glVertex3fv(fpt);
@@ -555,159 +609,186 @@ static void gp_draw_stroke_fill(
glEnd();
}
+#endif
}
/* ----- Existing Strokes Drawing (3D and Point) ------ */
/* draw a given stroke - just a single dot (only one point) */
static void gp_draw_stroke_point(
- bGPDspoint *points, short thickness, short dflag, short sflag,
- int offsx, int offsy, int winx, int winy, float diff_mat[4][4], float ink[4])
+ const bGPDspoint *points, short thickness, short UNUSED(dflag), short sflag,
+ int offsx, int offsy, int winx, int winy, const float diff_mat[4][4], const float ink[4])
{
- float fpt[3];
- bGPDspoint *pt = &points[0];
+ const bGPDspoint *pt = points;
- /* color of point */
- gp_set_point_color(pt, ink);
-
- /* set point thickness (since there's only one of these) */
- glPointSize((float)(thickness + 2) * points->pressure);
-
/* get final position using parent matrix */
+ float fpt[3];
mul_v3_m4v3(fpt, diff_mat, &pt->x);
- /* draw point */
+ VertexFormat *format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+
if (sflag & GP_STROKE_3DSPACE) {
- glBegin(GL_POINTS);
- glVertex3fv(fpt);
- glEnd();
+ immBindBuiltinProgram(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_SMOOTH);
}
else {
- float co[2];
-
- /* get coordinates of point */
+ immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_SMOOTH);
+
+ /* get 2D coordinates of point */
+ float co[3] = { 0.0f };
gp_calc_2d_stroke_fxy(fpt, sflag, offsx, offsy, winx, winy, co);
-
- /* if thickness is less than GP_DRAWTHICKNESS_SPECIAL, simple dot looks ok
- * - also mandatory in if Image Editor 'image-based' dot
- */
- if ((thickness < GP_DRAWTHICKNESS_SPECIAL) ||
- ((dflag & GP_DRAWDATA_IEDITHACK) && (sflag & GP_STROKE_2DSPACE)))
- {
- glBegin(GL_POINTS);
- glVertex2fv(co);
- glEnd();
- }
- else {
- /* draw filled circle as is done in circf (but without the matrix push/pops which screwed things up) */
- GLUquadricObj *qobj = gluNewQuadric();
-
- gluQuadricDrawStyle(qobj, GLU_FILL);
-
- /* need to translate drawing position, but must reset after too! */
- glTranslate2fv(co);
- gluDisk(qobj, 0.0, thickness, 32, 1);
- glTranslatef(-co[0], -co[1], 0.0);
-
- gluDeleteQuadric(qobj);
- }
+ copy_v3_v3(fpt, co);
}
+
+ gp_set_point_uniform_color(pt, ink);
+ /* set point thickness (since there's only one of these) */
+ immUniform1f("size", (float)(thickness + 2) * pt->pressure);
+
+ immBegin(GL_POINTS, 1);
+ immVertex3fv(pos, fpt);
+ immEnd();
+
+ immUnbindProgram();
}
/* draw a given stroke in 3d (i.e. in 3d-space), using simple ogl lines */
-static void gp_draw_stroke_3d(bGPDspoint *points, int totpoints, short thickness, bool debug,
- short UNUSED(sflag), float diff_mat[4][4], float ink[4], bool cyclic)
+static void gp_draw_stroke_3d(const bGPDspoint *points, int totpoints, short thickness, bool UNUSED(debug),
+ short UNUSED(sflag), const float diff_mat[4][4], const float ink[4], bool cyclic)
{
- bGPDspoint *pt, *pt2;
float curpressure = points[0].pressure;
- int i;
float fpt[3];
float cyclic_fpt[3];
+ int draw_points = 0;
+
+ /* if cyclic needs one vertex more */
+ int cyclic_add = 0;
+ if (cyclic) {
+ ++cyclic_add;
+ }
+
+
+ VertexFormat *format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ unsigned color = add_attrib(format, "color", GL_UNSIGNED_BYTE, 4, NORMALIZE_INT_TO_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_SMOOTH_COLOR);
+
+ /* TODO: implement this with a geometry shader to draw one continuous tapered stroke */
/* draw stroke curve */
glLineWidth(max_ff(curpressure * thickness, 1.0f));
- glBegin(GL_LINE_STRIP);
- for (i = 0, pt = points; i < totpoints && pt; i++, pt++) {
- gp_set_point_color(pt, ink);
+ immBeginAtMost(GL_LINE_STRIP, totpoints + cyclic_add);
+ const bGPDspoint *pt = points;
+ for (int i = 0; i < totpoints; i++, pt++) {
+ gp_set_point_varying_color(pt, ink, color);
/* if there was a significant pressure change, stop the curve, change the thickness of the stroke,
* and continue drawing again (since line-width cannot change in middle of GL_LINE_STRIP)
* Note: we want more visible levels of pressures when thickness is bigger.
*/
if (fabsf(pt->pressure - curpressure) > 0.2f / (float)thickness) {
- glEnd();
+ /* if the pressure changes before get at least 2 vertices, need to repeat last point to avoid assert in immEnd() */
+ if (draw_points < 2) {
+ const bGPDspoint *pt2 = pt - 1;
+ mul_v3_m4v3(fpt, diff_mat, &pt2->x);
+ immVertex3fv(pos, fpt);
+ }
+ immEnd();
+ draw_points = 0;
+
curpressure = pt->pressure;
glLineWidth(max_ff(curpressure * thickness, 1.0f));
- glBegin(GL_LINE_STRIP);
-
+ immBeginAtMost(GL_LINE_STRIP, totpoints - i + 1 + cyclic_add);
+
/* need to roll-back one point to ensure that there are no gaps in the stroke */
if (i != 0) {
- pt2 = pt - 1;
+ const bGPDspoint *pt2 = pt - 1;
mul_v3_m4v3(fpt, diff_mat, &pt2->x);
- glVertex3fv(fpt);
+ gp_set_point_varying_color(pt2, ink, color);
+ immVertex3fv(pos, fpt);
+ ++draw_points;
}
-
- /* now the point we want... */
- mul_v3_m4v3(fpt, diff_mat, &pt->x);
- glVertex3fv(fpt);
}
- else {
- mul_v3_m4v3(fpt, diff_mat, &pt->x);
- glVertex3fv(fpt);
- }
- /* saves first point to use in cyclic */
- if (i == 0) {
+
+ /* now the point we want */
+ mul_v3_m4v3(fpt, diff_mat, &pt->x);
+ immVertex3fv(pos, fpt);
+ ++draw_points;
+
+ if (cyclic && i == 0) {
+ /* save first point to use in cyclic */
copy_v3_v3(cyclic_fpt, fpt);
}
}
- /* if cyclic draw line to first point */
+
if (cyclic) {
- glVertex3fv(cyclic_fpt);
+ /* draw line to first point to complete the cycle */
+ immVertex3fv(pos, cyclic_fpt);
+ ++draw_points;
}
- glEnd();
+ /* if less of two points, need to repeat last point to avoid assert in immEnd() */
+ if (draw_points < 2) {
+ const bGPDspoint *pt2 = pt - 1;
+ mul_v3_m4v3(fpt, diff_mat, &pt2->x);
+ gp_set_point_varying_color(pt2, ink, color);
+ immVertex3fv(pos, fpt);
+ }
+
+ immEnd();
+ immUnbindProgram();
+
+#if 0 /* convert to modern GL only if needed */
/* draw debug points of curve on top? */
/* XXX: for now, we represent "selected" strokes in the same way as debug, which isn't used anymore */
if (debug) {
glPointSize((float)(thickness + 2));
-
+
glBegin(GL_POINTS);
- for (i = 0, pt = points; i < totpoints && pt; i++, pt++) {
+ const bGPDspoint *pt = points;
+ for (int i = 0; i < totpoints; i++, pt++) {
mul_v3_m4v3(fpt, diff_mat, &pt->x);
glVertex3fv(fpt);
}
glEnd();
-
}
+#endif
}
/* ----- Fancy 2D-Stroke Drawing ------ */
/* draw a given stroke in 2d */
-static void gp_draw_stroke_2d(bGPDspoint *points, int totpoints, short thickness_s, short dflag, short sflag,
- bool debug, int offsx, int offsy, int winx, int winy, float diff_mat[4][4], float ink[4])
+static void gp_draw_stroke_2d(const bGPDspoint *points, int totpoints, short thickness_s, short dflag, short sflag,
+ bool debug, int offsx, int offsy, int winx, int winy, const float diff_mat[4][4], const float ink[4])
{
/* otherwise thickness is twice that of the 3D view */
float thickness = (float)thickness_s * 0.5f;
-
+
/* strokes in Image Editor need a scale factor, since units there are not pixels! */
float scalefac = 1.0f;
if ((dflag & GP_DRAWDATA_IEDITHACK) && (dflag & GP_DRAWDATA_ONLYV2D)) {
scalefac = 0.001f;
}
-
+
+ /* TODO: fancy++ with the magic of shaders */
+
/* tessellation code - draw stroke as series of connected quads with connection
* edges rotated to minimize shrinking artifacts, and rounded endcaps
*/
{
- bGPDspoint *pt1, *pt2;
+ const bGPDspoint *pt1, *pt2;
float pm[2];
int i;
float fpt[3];
-
- glShadeModel(GL_FLAT);
- glBegin(GL_QUADS);
-
+
+ VertexFormat *format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ unsigned color = add_attrib(format, "color", GL_UNSIGNED_BYTE, 4, NORMALIZE_INT_TO_FLOAT);
+
+ /* this code previously used glShadeModel(GL_FLAT) */
+ immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
+ immBegin(GL_QUADS, (totpoints - 2) * 4 + 12);
+
for (i = 0, pt1 = points, pt2 = points + 1; i < (totpoints - 1); i++, pt1++, pt2++) {
float s0[2], s1[2]; /* segment 'center' points */
float t0[2], t1[2]; /* tessellated coordinates */
@@ -721,19 +802,19 @@ static void gp_draw_stroke_2d(bGPDspoint *points, int totpoints, short thickness
mul_v3_m4v3(fpt, diff_mat, &pt2->x);
gp_calc_2d_stroke_fxy(fpt, sflag, offsx, offsy, winx, winy, s1);
-
+
/* calculate gradient and normal - 'angle'=(ny/nx) */
m1[1] = s1[1] - s0[1];
m1[0] = s1[0] - s0[0];
normalize_v2(m1);
m2[1] = -m1[0];
m2[0] = m1[1];
-
+
/* always use pressure from first point here */
pthick = (pt1->pressure * thickness * scalefac);
-
+
/* color of point */
- gp_set_point_color(pt1, ink);
+ gp_set_point_varying_color(pt1, ink, color);
/* if the first segment, start of segment is segment's normal */
if (i == 0) {
@@ -744,40 +825,40 @@ static void gp_draw_stroke_2d(bGPDspoint *points, int totpoints, short thickness
mt[1] = m2[1] * pthick * 0.5f;
sc[0] = s0[0] - (m1[0] * pthick * 0.75f);
sc[1] = s0[1] - (m1[1] * pthick * 0.75f);
-
+
t0[0] = sc[0] - mt[0];
t0[1] = sc[1] - mt[1];
t1[0] = sc[0] + mt[0];
t1[1] = sc[1] + mt[1];
-
- glVertex2fv(t0);
- glVertex2fv(t1);
-
+
+ immVertex2fv(pos, t0);
+ immVertex2fv(pos, t1);
+
/* calculate points for start of segment */
mt[0] = m2[0] * pthick;
mt[1] = m2[1] * pthick;
-
+
t0[0] = s0[0] - mt[0];
t0[1] = s0[1] - mt[1];
t1[0] = s0[0] + mt[0];
t1[1] = s0[1] + mt[1];
-
+
/* draw this line twice (first to finish off start cap, then for stroke) */
- glVertex2fv(t1);
- glVertex2fv(t0);
- glVertex2fv(t0);
- glVertex2fv(t1);
+ immVertex2fv(pos, t1);
+ immVertex2fv(pos, t0);
+ immVertex2fv(pos, t0);
+ immVertex2fv(pos, t1);
}
/* if not the first segment, use bisector of angle between segments */
else {
float mb[2]; /* bisector normal */
float athick, dfac; /* actual thickness, difference between thicknesses */
-
+
/* calculate gradient of bisector (as average of normals) */
mb[0] = (pm[0] + m2[0]) / 2;
mb[1] = (pm[1] + m2[1]) / 2;
normalize_v2(mb);
-
+
/* calculate gradient to apply
* - as basis, use just pthick * bisector gradient
* - if cross-section not as thick as it should be, add extra padding to fix it
@@ -786,49 +867,48 @@ static void gp_draw_stroke_2d(bGPDspoint *points, int totpoints, short thickness
mt[1] = mb[1] * pthick;
athick = len_v2(mt);
dfac = pthick - (athick * 2);
-
+
if (((athick * 2.0f) < pthick) && (IS_EQF(athick, pthick) == 0)) {
mt[0] += (mb[0] * dfac);
mt[1] += (mb[1] * dfac);
}
-
+
/* calculate points for start of segment */
t0[0] = s0[0] - mt[0];
t0[1] = s0[1] - mt[1];
t1[0] = s0[0] + mt[0];
t1[1] = s0[1] + mt[1];
-
+
/* draw this line twice (once for end of current segment, and once for start of next) */
- glVertex2fv(t1);
- glVertex2fv(t0);
- glVertex2fv(t0);
- glVertex2fv(t1);
+ immVertex2fv(pos, t1);
+ immVertex2fv(pos, t0);
+ immVertex2fv(pos, t0);
+ immVertex2fv(pos, t1);
}
-
+
/* if last segment, also draw end of segment (defined as segment's normal) */
if (i == totpoints - 2) {
/* for once, we use second point's pressure (otherwise it won't be drawn) */
pthick = (pt2->pressure * thickness * scalefac);
-
+
/* color of point */
- gp_set_point_color(pt2, ink);
+ gp_set_point_varying_color(pt2, ink, color);
/* calculate points for end of segment */
mt[0] = m2[0] * pthick;
mt[1] = m2[1] * pthick;
-
+
t0[0] = s1[0] - mt[0];
t0[1] = s1[1] - mt[1];
t1[0] = s1[0] + mt[0];
t1[1] = s1[1] + mt[1];
-
+
/* draw this line twice (once for end of stroke, and once for endcap)*/
- glVertex2fv(t1);
- glVertex2fv(t0);
- glVertex2fv(t0);
- glVertex2fv(t1);
-
-
+ immVertex2fv(pos, t1);
+ immVertex2fv(pos, t0);
+ immVertex2fv(pos, t0);
+ immVertex2fv(pos, t1);
+
/* draw end cap as last step
* - make points slightly closer to center (about halfway across)
*/
@@ -836,34 +916,33 @@ static void gp_draw_stroke_2d(bGPDspoint *points, int totpoints, short thickness
mt[1] = m2[1] * pthick * 0.5f;
sc[0] = s1[0] + (m1[0] * pthick * 0.75f);
sc[1] = s1[1] + (m1[1] * pthick * 0.75f);
-
+
t0[0] = sc[0] - mt[0];
t0[1] = sc[1] - mt[1];
t1[0] = sc[0] + mt[0];
t1[1] = sc[1] + mt[1];
-
- glVertex2fv(t1);
- glVertex2fv(t0);
+
+ immVertex2fv(pos, t1);
+ immVertex2fv(pos, t0);
}
-
+
/* store stroke's 'natural' normal for next stroke to use */
copy_v2_v2(pm, m2);
}
-
- glEnd();
- glShadeModel(GL_SMOOTH);
+
+ immEnd();
+ immUnbindProgram();
}
-
+
+#if 0 /* convert to modern GL only if needed */
/* draw debug points of curve on top? (original stroke points) */
if (debug) {
- bGPDspoint *pt;
- int i;
- float fpt[3];
-
glPointSize((float)(thickness_s + 2));
-
+
glBegin(GL_POINTS);
- for (i = 0, pt = points; i < totpoints && pt; i++, pt++) {
+ const bGPDspoint *pt = points;
+ for (int i = 0; i < totpoints && pt; i++, pt++) {
+ float fpt[3];
float co[2];
mul_v3_m4v3(fpt, diff_mat, &pt->x);
gp_calc_2d_stroke_fxy(fpt, sflag, offsx, offsy, winx, winy, co);
@@ -871,6 +950,9 @@ static void gp_draw_stroke_2d(bGPDspoint *points, int totpoints, short thickness
}
glEnd();
}
+#else
+ UNUSED_VARS(debug);
+#endif
}
/* ----- Strokes Drawing ------ */
@@ -884,41 +966,41 @@ static bool gp_can_draw_stroke(const bGPDstroke *gps, const int dflag)
return false;
if (!(dflag & GP_DRAWDATA_ONLY3D) && (gps->flag & GP_STROKE_3DSPACE))
return false;
-
+
/* 2) Screen Space 2D Strokes */
if ((dflag & GP_DRAWDATA_ONLYV2D) && !(gps->flag & GP_STROKE_2DSPACE))
return false;
if (!(dflag & GP_DRAWDATA_ONLYV2D) && (gps->flag & GP_STROKE_2DSPACE))
return false;
-
+
/* 3) Image Space (2D) */
if ((dflag & GP_DRAWDATA_ONLYI2D) && !(gps->flag & GP_STROKE_2DIMAGE))
return false;
if (!(dflag & GP_DRAWDATA_ONLYI2D) && (gps->flag & GP_STROKE_2DIMAGE))
return false;
-
-
+
/* skip stroke if it doesn't have any valid data */
if ((gps->points == NULL) || (gps->totpoints < 1))
return false;
-
+
/* stroke can be drawn */
return true;
}
/* draw a set of strokes */
static void gp_draw_strokes(
- bGPdata *gpd, bGPDframe *gpf, int offsx, int offsy, int winx, int winy, int dflag,
+ bGPdata *gpd, const bGPDframe *gpf, int offsx, int offsy, int winx, int winy, int dflag,
bool debug, short lthick, const float opacity, const float tintcolor[4],
- const bool onion, const bool custonion, float diff_mat[4][4])
+ const bool onion, const bool custonion, const float diff_mat[4][4])
{
- bGPDstroke *gps;
float tcolor[4];
float tfill[4];
short sthickness;
float ink[4];
- for (gps = gpf->strokes.first; gps; gps = gps->next) {
+ GPU_enable_program_point_size();
+
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
/* check if stroke can be drawn */
if (gp_can_draw_stroke(gps, dflag) == false) {
continue;
@@ -936,6 +1018,10 @@ static void gp_draw_strokes(
/* calculate thickness */
sthickness = gps->thickness + lthick;
+ if (sthickness <= 0) {
+ continue;
+ }
+
/* check which stroke-drawer to use */
if (dflag & GP_DRAWDATA_ONLY3D) {
const int no_xray = (dflag & GP_DRAWDATA_NO_XRAY);
@@ -962,19 +1048,20 @@ static void gp_draw_strokes(
interp_v3_v3v3(tfill, palcolor->fill, tintcolor, tintcolor[3]);
tfill[3] = palcolor->fill[3] * opacity;
if (tfill[3] > GPENCIL_ALPHA_OPACITY_THRESH) {
+ const float *color;
if (!onion) {
- glColor4fv(tfill);
+ color = tfill;
}
else {
if (custonion) {
- glColor4fv(tintcolor);
+ color = tintcolor;
}
else {
ARRAY_SET_ITEMS(tfill, UNPACK3(palcolor->fill), tintcolor[3]);
- glColor4fv(tfill);
+ color = tfill;
}
}
- gp_draw_stroke_fill(gpd, gps, offsx, offsy, winx, winy, diff_mat);
+ gp_draw_stroke_fill(gpd, gps, offsx, offsy, winx, winy, diff_mat, color);
}
}
@@ -996,7 +1083,7 @@ static void gp_draw_strokes(
}
if (palcolor->flag & PC_COLOR_VOLUMETRIC) {
/* volumetric stroke drawing */
- gp_draw_stroke_volumetric_3d(gps->points, gps->totpoints, sthickness, dflag, gps->flag, diff_mat, ink);
+ gp_draw_stroke_volumetric_3d(gps->points, gps->totpoints, sthickness, ink);
}
else {
/* 3D Lines - OpenGL primitives-based */
@@ -1027,20 +1114,21 @@ static void gp_draw_strokes(
interp_v3_v3v3(tfill, palcolor->fill, tintcolor, tintcolor[3]);
tfill[3] = palcolor->fill[3] * opacity;
if (tfill[3] > GPENCIL_ALPHA_OPACITY_THRESH) {
+ const float *color;
if (!onion) {
- glColor4fv(tfill);
+ color = tfill;
}
else {
if (custonion) {
- glColor4fv(tintcolor);
+ color = tintcolor;
}
else {
ARRAY_SET_ITEMS(tfill, palcolor->fill[0], palcolor->fill[1], palcolor->fill[2],
tintcolor[3]);
- glColor4fv(tfill);
+ color = tfill;
}
}
- gp_draw_stroke_fill(gpd, gps, offsx, offsy, winx, winy, diff_mat);
+ gp_draw_stroke_fill(gpd, gps, offsx, offsy, winx, winy, diff_mat, color);
}
}
@@ -1078,15 +1166,15 @@ static void gp_draw_strokes(
}
}
}
+
+ GPU_disable_program_point_size();
}
/* Draw selected verts for strokes being edited */
static void gp_draw_strokes_edit(
- bGPdata *gpd, bGPDframe *gpf, int offsx, int offsy, int winx, int winy, short dflag,
- short lflag, float diff_mat[4][4], float alpha)
+ bGPdata *gpd, const bGPDframe *gpf, int offsx, int offsy, int winx, int winy, short dflag,
+ short lflag, const float diff_mat[4][4], float alpha)
{
- bGPDstroke *gps;
-
/* if alpha 0 do not draw */
if (alpha == 0.0f)
return;
@@ -1100,36 +1188,32 @@ static void gp_draw_strokes_edit(
glGetIntegerv(GL_DEPTH_WRITEMASK, &mask_orig);
glDepthMask(0);
glEnable(GL_DEPTH_TEST);
-
+
/* first arg is normally rv3d->dist, but this isn't
* available here and seems to work quite well without */
bglPolygonOffset(1.0f, 1.0f);
#if 0
- glEnable(GL_POLYGON_OFFSET_LINE);
+ glEnable(GL_POLYGON_OFFSET_LINE); /* do we want LINE or POINT here? (merwin) */
glPolygonOffset(-1.0f, -1.0f);
#endif
}
}
-
-
- /* draw stroke verts */
- for (gps = gpf->strokes.first; gps; gps = gps->next) {
- bGPDspoint *pt;
- float vsize, bsize;
- int i;
- float fpt[3];
+ GPU_enable_program_point_size();
+
+ /* draw stroke verts */
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
/* check if stroke can be drawn */
if (gp_can_draw_stroke(gps, dflag) == false)
continue;
-
+
/* Optimisation: only draw points for selected strokes
* We assume that selected points can only occur in
* strokes that are selected too.
*/
if ((gps->flag & GP_STROKE_SELECT) == 0)
continue;
-
+
/* verify palette color lock */
{
bGPDpalettecolor *palcolor = ED_gpencil_stroke_getcolor(gpd, gps);
@@ -1148,7 +1232,8 @@ static void gp_draw_strokes_edit(
* they stand out more.
* - We use the theme setting for size of the unselected verts
*/
- bsize = UI_GetThemeValuef(TH_GP_VERTEX_SIZE);
+ float bsize = UI_GetThemeValuef(TH_GP_VERTEX_SIZE);
+ float vsize;
if ((int)bsize > 8) {
vsize = 10.0f;
bsize = 8.0f;
@@ -1156,89 +1241,83 @@ static void gp_draw_strokes_edit(
else {
vsize = bsize + 2;
}
-
- /* First Pass: Draw all the verts (i.e. these become the unselected state) */
+
/* for now, we assume that the base color of the points is not too close to the real color */
/* set color using palette */
bGPDpalettecolor *palcolor = ED_gpencil_stroke_getcolor(gpd, gps);
- glColor3fv(palcolor->color);
- glPointSize(bsize);
-
- glBegin(GL_POINTS);
- for (i = 0, pt = gps->points; i < gps->totpoints && pt; i++, pt++) {
+ float selectColor[4];
+ UI_GetThemeColor3fv(TH_GP_VERTEX_SELECT, selectColor);
+ selectColor[3] = alpha;
+
+ VertexFormat *format = immVertexFormat();
+ unsigned pos; /* specified later */
+ unsigned size = add_attrib(format, "size", GL_FLOAT, 1, KEEP_FLOAT);
+ unsigned color = add_attrib(format, "color", GL_FLOAT, 3, KEEP_FLOAT);
+
+ if (gps->flag & GP_STROKE_3DSPACE) {
+ pos = add_attrib(format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR);
+ }
+ else {
+ pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_POINT_VARYING_SIZE_VARYING_COLOR);
+ }
+
+ immBegin(GL_POINTS, gps->totpoints);
+
+ /* Draw start and end point differently if enabled stroke direction hint */
+ bool show_direction_hint = (gpd->flag & GP_DATA_SHOW_DIRECTION) && (gps->totpoints > 1);
+
+ /* Draw all the stroke points (selected or not) */
+ bGPDspoint *pt = gps->points;
+ float fpt[3];
+ for (int i = 0; i < gps->totpoints; i++, pt++) {
+ /* size and color first */
+ if (show_direction_hint && i == 0) {
+ /* start point in green bigger */
+ immAttrib3f(color, 0.0f, 1.0f, 0.0f);
+ immAttrib1f(size, vsize + 4);
+ }
+ else if (show_direction_hint && (i == gps->totpoints - 1)) {
+ /* end point in red smaller */
+ immAttrib3f(color, 1.0f, 0.0f, 0.0f);
+ immAttrib1f(size, vsize + 1);
+ }
+ else if (pt->flag & GP_SPOINT_SELECT) {
+ immAttrib3fv(color, selectColor);
+ immAttrib1f(size, vsize);
+ }
+ else {
+ immAttrib3fv(color, palcolor->color);
+ immAttrib1f(size, bsize);
+ }
+
+ /* then position */
if (gps->flag & GP_STROKE_3DSPACE) {
mul_v3_m4v3(fpt, diff_mat, &pt->x);
- glVertex3fv(fpt);
+ immVertex3fv(pos, fpt);
}
else {
float co[2];
mul_v3_m4v3(fpt, diff_mat, &pt->x);
gp_calc_2d_stroke_fxy(fpt, gps->flag, offsx, offsy, winx, winy, co);
- glVertex2fv(co);
+ immVertex2fv(pos, co);
}
}
- glEnd();
-
-
- /* Second Pass: Draw only verts which are selected */
- float curColor[4];
- UI_GetThemeColor3fv(TH_GP_VERTEX_SELECT, curColor);
- glColor4f(curColor[0], curColor[1], curColor[2], alpha);
- glPointSize(vsize);
-
- glBegin(GL_POINTS);
- for (i = 0, pt = gps->points; i < gps->totpoints && pt; i++, pt++) {
- if (pt->flag & GP_SPOINT_SELECT) {
- if (gps->flag & GP_STROKE_3DSPACE) {
- mul_v3_m4v3(fpt, diff_mat, &pt->x);
- glVertex3fv(fpt);
- }
- else {
- float co[2];
-
- mul_v3_m4v3(fpt, diff_mat, &pt->x);
- gp_calc_2d_stroke_fxy(fpt, gps->flag, offsx, offsy, winx, winy, co);
- glVertex2fv(co);
- }
- }
- }
- glEnd();
-
- /* Draw start and end point if enabled stroke direction hint */
- if ((gpd->flag & GP_DATA_SHOW_DIRECTION) && (gps->totpoints > 1)) {
- bGPDspoint *p;
-
- glPointSize(vsize + 4);
- glBegin(GL_POINTS);
-
- /* start point in green bigger */
- glColor3f(0.0f, 1.0f, 0.0f);
- p = &gps->points[0];
- mul_v3_m4v3(fpt, diff_mat, &p->x);
- glVertex3fv(fpt);
- glEnd();
+ immEnd();
+ immUnbindProgram();
+ }
- /* end point in red smaller */
- glPointSize(vsize + 1);
- glBegin(GL_POINTS);
+ GPU_disable_program_point_size();
- glColor3f(1.0f, 0.0f, 0.0f);
- p = &gps->points[gps->totpoints - 1];
- mul_v3_m4v3(fpt, diff_mat, &p->x);
- glVertex3fv(fpt);
- glEnd();
- }
- }
-
-
/* clear depth mask */
if (dflag & GP_DRAWDATA_ONLY3D) {
if (no_xray) {
glDepthMask(mask_orig);
glDisable(GL_DEPTH_TEST);
-
+
bglPolygonOffset(0.0, 0.0);
#if 0
glDisable(GL_POLYGON_OFFSET_LINE);
@@ -1252,8 +1331,8 @@ static void gp_draw_strokes_edit(
/* draw onion-skinning for a layer */
static void gp_draw_onionskins(
- bGPdata *gpd, bGPDlayer *gpl, bGPDframe *gpf, int offsx, int offsy, int winx, int winy,
- int UNUSED(cfra), int dflag, bool debug, float diff_mat[4][4])
+ bGPdata *gpd, const bGPDlayer *gpl, const bGPDframe *gpf, int offsx, int offsy, int winx, int winy,
+ int UNUSED(cfra), int dflag, bool debug, const float diff_mat[4][4])
{
const float default_color[3] = {UNPACK3(U.gpencil_new_layer_col)};
const float alpha = 1.0f;
@@ -1266,17 +1345,14 @@ static void gp_draw_onionskins(
else {
copy_v3_v3(color, default_color);
}
-
+
if (gpl->gstep > 0) {
- bGPDframe *gf;
- float fac;
-
/* draw previous frames first */
- for (gf = gpf->prev; gf; gf = gf->prev) {
+ for (bGPDframe *gf = gpf->prev; gf; gf = gf->prev) {
/* check if frame is drawable */
if ((gpf->framenum - gf->framenum) <= gpl->gstep) {
/* alpha decreases with distance from curframe index */
- fac = 1.0f - ((float)(gpf->framenum - gf->framenum) / (float)(gpl->gstep + 1));
+ float fac = 1.0f - ((float)(gpf->framenum - gf->framenum) / (float)(gpl->gstep + 1));
color[3] = alpha * fac * 0.66f;
gp_draw_strokes(gpd, gf, offsx, offsy, winx, winy, dflag, debug, gpl->thickness, 1.0f, color,
true, gpl->flag & GP_LAYER_GHOST_PREVCOL, diff_mat);
@@ -1296,8 +1372,7 @@ static void gp_draw_onionskins(
else {
/* don't draw - disabled */
}
-
-
+
/* 2) Now draw next frames */
if (gpl->flag & GP_LAYER_GHOST_NEXTCOL) {
copy_v3_v3(color, gpl->gcolor_next);
@@ -1305,17 +1380,14 @@ static void gp_draw_onionskins(
else {
copy_v3_v3(color, default_color);
}
-
+
if (gpl->gstep_next > 0) {
- bGPDframe *gf;
- float fac;
-
/* now draw next frames */
- for (gf = gpf->next; gf; gf = gf->next) {
+ for (bGPDframe *gf = gpf->next; gf; gf = gf->next) {
/* check if frame is drawable */
if ((gf->framenum - gpf->framenum) <= gpl->gstep_next) {
/* alpha decreases with distance from curframe index */
- fac = 1.0f - ((float)(gf->framenum - gpf->framenum) / (float)(gpl->gstep_next + 1));
+ float fac = 1.0f - ((float)(gf->framenum - gpf->framenum) / (float)(gpl->gstep_next + 1));
color[3] = alpha * fac * 0.66f;
gp_draw_strokes(gpd, gf, offsx, offsy, winx, winy, dflag, debug, gpl->thickness, 1.0f, color,
true, gpl->flag & GP_LAYER_GHOST_NEXTCOL, diff_mat);
@@ -1335,7 +1407,6 @@ static void gp_draw_onionskins(
else {
/* don't draw - disabled */
}
-
}
/* draw interpolate strokes (used only while operator is running) */
@@ -1373,29 +1444,27 @@ void ED_gp_draw_interpolation(tGPDinterpolate *tgpi, const int type)
/* loop over gpencil data layers, drawing them */
static void gp_draw_data_layers(
- bGPDbrush *brush, float alpha, bGPdata *gpd,
+ const bGPDbrush *brush, float alpha, bGPdata *gpd,
int offsx, int offsy, int winx, int winy, int cfra, int dflag)
{
- bGPDlayer *gpl;
float diff_mat[4][4];
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- bGPDframe *gpf;
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
/* calculate parent position */
ED_gpencil_parent_location(gpl, diff_mat);
- bool debug = (gpl->flag & GP_LAYER_DRAWDEBUG) ? true : false;
+ bool debug = (gpl->flag & GP_LAYER_DRAWDEBUG);
short lthick = brush->thickness + gpl->thickness;
-
+
/* don't draw layer if hidden */
if (gpl->flag & GP_LAYER_HIDE)
continue;
-
+
/* get frame to draw */
- gpf = BKE_gpencil_layer_getframe(gpl, cfra, 0);
+ bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, cfra, 0);
if (gpf == NULL)
continue;
-
+
/* set basic stroke thickness */
glLineWidth(lthick);
@@ -1407,10 +1476,10 @@ static void gp_draw_data_layers(
if (condition) dflag |= (draw_flag_value); \
else dflag &= ~(draw_flag_value); \
} (void)0
-
+
/* xray... */
GP_DRAWFLAG_APPLY((gpl->flag & GP_LAYER_NO_XRAY), GP_DRAWDATA_NO_XRAY);
-
+
/* volumetric strokes... */
GP_DRAWFLAG_APPLY((gpl->flag & GP_LAYER_VOLUMETRIC), GP_DRAWDATA_VOLUMETRIC);
@@ -1418,7 +1487,7 @@ static void gp_draw_data_layers(
GP_DRAWFLAG_APPLY((gpl->flag & GP_LAYER_HQ_FILL), GP_DRAWDATA_HQ_FILL);
#undef GP_DRAWFLAG_APPLY
-
+
/* draw 'onionskins' (frame left + right) */
if ((gpl->flag & GP_LAYER_ONIONSKIN) && !(dflag & GP_DRAWDATA_NO_ONIONS)) {
/* Drawing method - only immediately surrounding (gstep = 0),
@@ -1426,11 +1495,11 @@ static void gp_draw_data_layers(
*/
gp_draw_onionskins(gpd, gpl, gpf, offsx, offsy, winx, winy, cfra, dflag, debug, diff_mat);
}
-
+
/* draw the strokes already in active frame */
gp_draw_strokes(gpd, gpf, offsx, offsy, winx, winy, dflag, debug, gpl->thickness,
gpl->opacity, gpl->tintcolor, false, false, diff_mat);
-
+
/* Draw verts of selected strokes
* - when doing OpenGL renders, we don't want to be showing these, as that ends up flickering
* - locked layers can't be edited, so there's no point showing these verts
@@ -1445,16 +1514,13 @@ static void gp_draw_data_layers(
{
gp_draw_strokes_edit(gpd, gpf, offsx, offsy, winx, winy, dflag, gpl->flag, diff_mat, alpha);
}
-
+
/* Check if may need to draw the active stroke cache, only if this layer is the active layer
* that is being edited. (Stroke buffer is currently stored in gp-data)
*/
if (ED_gpencil_session_active() && (gpl->flag & GP_LAYER_ACTIVE) &&
(gpf->flag & GP_FRAME_PAINT))
{
- /* Set color for drawing buffer stroke - since this may not be set yet */
- // glColor4fv(gpl->color);
-
/* Buffer stroke needs to be drawn with a different linestyle
* to help differentiate them from normal strokes.
*
@@ -1463,38 +1529,37 @@ static void gp_draw_data_layers(
*/
if (gpd->sflag & PC_COLOR_VOLUMETRIC) {
gp_draw_stroke_volumetric_buffer(gpd->sbuffer, gpd->sbuffer_size, lthick,
- dflag, gpd->sbuffer_sflag, gpd->scolor);
+ dflag, gpd->scolor);
}
else {
- gp_draw_stroke_buffer(gpd->sbuffer, gpd->sbuffer_size, lthick, dflag, gpd->sbuffer_sflag, gpd->scolor);
+ gp_draw_stroke_buffer(gpd->sbuffer, gpd->sbuffer_size, lthick, dflag, gpd->sbuffer_sflag, gpd->scolor, gpd->sfill);
}
}
}
}
/* draw a short status message in the top-right corner */
-static void gp_draw_status_text(bGPdata *gpd, ARegion *ar)
+static void gp_draw_status_text(const bGPdata *gpd, ARegion *ar)
{
rcti rect;
-
+
/* Cannot draw any status text when drawing OpenGL Renders */
if (G.f & G_RENDER_OGL)
return;
-
+
/* Get bounds of region - Necessary to avoid problems with region overlap */
ED_region_visible_rect(ar, &rect);
-
+
/* for now, this should only be used to indicate when we are in stroke editmode */
if (gpd->flag & GP_DATA_STROKE_EDITMODE) {
const char *printable = IFACE_("GPencil Stroke Editing");
float printable_size[2];
- int xco, yco;
-
+
BLF_width_and_height_default(printable, BLF_DRAW_STR_DUMMY_MAX, &printable_size[0], &printable_size[1]);
- xco = (rect.xmax - U.widget_unit) - (int)printable_size[0];
- yco = (rect.ymax - U.widget_unit);
-
+ int xco = (rect.xmax - U.widget_unit) - (int)printable_size[0];
+ int yco = (rect.ymax - U.widget_unit);
+
/* text label */
UI_ThemeColor(TH_TEXT_HI);
#ifdef WITH_INTERNATIONAL
@@ -1502,50 +1567,54 @@ static void gp_draw_status_text(bGPdata *gpd, ARegion *ar)
#else
BLF_draw_default_ascii(xco, yco, 0.0f, printable, BLF_DRAW_STR_DUMMY_MAX);
#endif
-
+
/* grease pencil icon... */
// XXX: is this too intrusive?
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
-
+
xco -= U.widget_unit;
yco -= (int)printable_size[1] / 2;
UI_icon_draw(xco, yco, ICON_GREASEPENCIL);
-
+
glDisable(GL_BLEND);
}
}
/* draw grease-pencil datablock */
static void gp_draw_data(
- bGPDbrush *brush, float alpha, bGPdata *gpd,
+ const bGPDbrush *brush, float alpha, bGPdata *gpd,
int offsx, int offsy, int winx, int winy, int cfra, int dflag)
{
+#if 0 /* disable to see if really needed. re-enable or delete by Dec 2016 */
/* reset line drawing style (in case previous user didn't reset) */
setlinestyle(0);
-
+#endif
+
/* turn on smooth lines (i.e. anti-aliasing) */
glEnable(GL_LINE_SMOOTH);
-
+
/* XXX: turn on some way of ensuring that the polygon edges get smoothed
* GL_POLYGON_SMOOTH is nasty and shouldn't be used, as it ends up
* creating internal white rays due to the ways it accumulates stuff
*/
-
+
/* turn on alpha-blending */
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
-
+
/* draw! */
gp_draw_data_layers(brush, alpha, gpd, offsx, offsy, winx, winy, cfra, dflag);
-
+
/* turn off alpha blending, then smooth lines */
glDisable(GL_BLEND); // alpha blending
glDisable(GL_LINE_SMOOTH); // smooth lines
-
+
+#if 0 /* disable to see if really needed. re-enable or delete by Dec 2016 */
/* restore initial gl conditions */
glColor4f(0, 0, 0, 1);
+#endif
}
/* if we have strokes for scenes (3d view)/clips (movie clip editor)
@@ -1554,7 +1623,7 @@ static void gp_draw_data_all(Scene *scene, bGPdata *gpd, int offsx, int offsy, i
int cfra, int dflag, const char spacetype)
{
bGPdata *gpd_source = NULL;
-
+
if (scene) {
if (spacetype == SPACE_VIEW3D) {
gpd_source = (scene->gpd ? scene->gpd : NULL);
@@ -1563,7 +1632,7 @@ static void gp_draw_data_all(Scene *scene, bGPdata *gpd, int offsx, int offsy, i
/* currently drawing only gpencil data from either clip or track, but not both - XXX fix logic behind */
gpd_source = (scene->clip->gpd ? scene->clip->gpd : NULL);
}
-
+
if (gpd_source) {
ToolSettings *ts = scene->toolsettings;
bGPDbrush *brush = BKE_gpencil_brush_getactive(ts);
@@ -1571,10 +1640,9 @@ static void gp_draw_data_all(Scene *scene, bGPdata *gpd, int offsx, int offsy, i
gp_draw_data(brush, ts->gp_sculpt.alpha, gpd_source,
offsx, offsy, winx, winy, cfra, dflag);
}
-
}
}
-
+
/* scene/clip data has already been drawn, only object/track data is drawn here
* if gpd_source == gpd, we don't have any object/track data and we can skip */
if (gpd_source == NULL || (gpd_source && gpd_source != gpd)) {
@@ -1602,28 +1670,27 @@ void ED_gpencil_draw_2dimage(const bContext *C)
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = CTX_wm_region(C);
Scene *scene = CTX_data_scene(C);
- bGPdata *gpd;
+
int offsx, offsy, sizex, sizey;
int dflag = GP_DRAWDATA_NOSTATUS;
-
- gpd = ED_gpencil_data_get_active(C); // XXX
+
+ bGPdata *gpd = ED_gpencil_data_get_active(C); // XXX
if (gpd == NULL) return;
-
+
/* calculate rect */
switch (sa->spacetype) {
case SPACE_IMAGE: /* image */
case SPACE_CLIP: /* clip */
{
-
/* just draw using standard scaling (settings here are currently ignored anyways) */
/* FIXME: the opengl poly-strokes don't draw at right thickness when done this way, so disabled */
offsx = 0;
offsy = 0;
sizex = ar->winx;
sizey = ar->winy;
-
+
wmOrtho2(ar->v2d.cur.xmin, ar->v2d.cur.xmax, ar->v2d.cur.ymin, ar->v2d.cur.ymax);
-
+
dflag |= GP_DRAWDATA_ONLYV2D | GP_DRAWDATA_IEDITHACK;
break;
}
@@ -1634,7 +1701,7 @@ void ED_gpencil_draw_2dimage(const bContext *C)
offsy = 0;
sizex = ar->winx;
sizey = ar->winy;
-
+
/* NOTE: I2D was used in 2.4x, but the old settings for that have been deprecated
* and everything moved to standard View2d
*/
@@ -1646,77 +1713,74 @@ void ED_gpencil_draw_2dimage(const bContext *C)
offsy = 0;
sizex = ar->winx;
sizey = ar->winy;
-
+
dflag |= GP_DRAWDATA_ONLYI2D;
break;
}
-
+
if (ED_screen_animation_playing(wm)) {
/* don't show onionskins during animation playback/scrub (i.e. it obscures the poses)
* OpenGL Renders (i.e. final output), or depth buffer (i.e. not real strokes)
*/
dflag |= GP_DRAWDATA_NO_ONIONS;
}
-
-
+
/* draw it! */
gp_draw_data_all(scene, gpd, offsx, offsy, sizex, sizey, CFRA, dflag, sa->spacetype);
}
/* draw grease-pencil sketches to specified 2d-view assuming that matrices are already set correctly
- * Note: this gets called twice - first time with onlyv2d=1 to draw 'canvas' strokes,
- * second time with onlyv2d=0 for screen-aligned strokes */
+ * Note: this gets called twice - first time with onlyv2d=true to draw 'canvas' strokes,
+ * second time with onlyv2d=false for screen-aligned strokes */
void ED_gpencil_draw_view2d(const bContext *C, bool onlyv2d)
{
wmWindowManager *wm = CTX_wm_manager(C);
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = CTX_wm_region(C);
Scene *scene = CTX_data_scene(C);
- bGPdata *gpd;
int dflag = 0;
/* check that we have grease-pencil stuff to draw */
if (sa == NULL) return;
- gpd = ED_gpencil_data_get_active(C); // XXX
+ bGPdata *gpd = ED_gpencil_data_get_active(C); // XXX
if (gpd == NULL) return;
-
+
/* special hack for Image Editor */
/* FIXME: the opengl poly-strokes don't draw at right thickness when done this way, so disabled */
if (ELEM(sa->spacetype, SPACE_IMAGE, SPACE_CLIP))
dflag |= GP_DRAWDATA_IEDITHACK;
-
+
/* draw it! */
if (onlyv2d) dflag |= (GP_DRAWDATA_ONLYV2D | GP_DRAWDATA_NOSTATUS);
if (ED_screen_animation_playing(wm)) dflag |= GP_DRAWDATA_NO_ONIONS;
-
+
gp_draw_data_all(scene, gpd, 0, 0, ar->winx, ar->winy, CFRA, dflag, sa->spacetype);
-
+
/* draw status text (if in screen/pixel-space) */
- if (onlyv2d == false) {
+ if (!onlyv2d) {
gp_draw_status_text(gpd, ar);
}
}
/* draw grease-pencil sketches to specified 3d-view assuming that matrices are already set correctly
- * Note: this gets called twice - first time with only3d=1 to draw 3d-strokes,
- * second time with only3d=0 for screen-aligned strokes */
+ * Note: this gets called twice - first time with only3d=true to draw 3d-strokes,
+ * second time with only3d=false for screen-aligned strokes */
void ED_gpencil_draw_view3d(wmWindowManager *wm, Scene *scene, View3D *v3d, ARegion *ar, bool only3d)
{
- bGPdata *gpd;
int dflag = 0;
RegionView3D *rv3d = ar->regiondata;
int offsx, offsy, winx, winy;
-
+
/* check that we have grease-pencil stuff to draw */
- gpd = ED_gpencil_data_get_active_v3d(scene, v3d);
+ bGPdata *gpd = ED_gpencil_data_get_active_v3d(scene, v3d);
if (gpd == NULL) return;
-
+
/* when rendering to the offscreen buffer we don't want to
* deal with the camera border, otherwise map the coords to the camera border. */
if ((rv3d->persp == RV3D_CAMOB) && !(G.f & G_RENDER_OGL)) {
rctf rectf;
ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &rectf, true); /* no shift */
-
+
offsx = iroundf(rectf.xmin);
offsy = iroundf(rectf.ymin);
winx = iroundf(rectf.xmax - rectf.xmin);
@@ -1728,7 +1792,7 @@ void ED_gpencil_draw_view3d(wmWindowManager *wm, Scene *scene, View3D *v3d, AReg
winx = ar->winx;
winy = ar->winy;
}
-
+
/* set flags */
if (only3d) {
/* 3D strokes/3D space:
@@ -1737,28 +1801,27 @@ void ED_gpencil_draw_view3d(wmWindowManager *wm, Scene *scene, View3D *v3d, AReg
*/
dflag |= (GP_DRAWDATA_ONLY3D | GP_DRAWDATA_NOSTATUS);
}
-
+
if (v3d->flag2 & V3D_RENDER_OVERRIDE) {
/* don't draw status text when "only render" flag is set */
dflag |= GP_DRAWDATA_NOSTATUS;
}
-
+
if ((wm == NULL) || ED_screen_animation_playing(wm)) {
/* don't show onionskins during animation playback/scrub (i.e. it obscures the poses)
* OpenGL Renders (i.e. final output), or depth buffer (i.e. not real strokes)
*/
dflag |= GP_DRAWDATA_NO_ONIONS;
}
-
+
/* draw it! */
- gp_draw_data_all(scene, gpd, offsx, offsy, winx, winy, CFRA, dflag, v3d->spacetype);
-
+ gp_draw_data_all(scene, gpd, offsx, offsy, winx, winy, CFRA, dflag, v3d->spacetype);
}
void ED_gpencil_draw_ex(Scene *scene, bGPdata *gpd, int winx, int winy, const int cfra, const char spacetype)
{
int dflag = GP_DRAWDATA_NOSTATUS | GP_DRAWDATA_ONLYV2D;
-
+
gp_draw_data_all(scene, gpd, 0, 0, winx, winy, cfra, dflag, spacetype);
}
diff --git a/source/blender/editors/gpencil/gpencil_brush.c b/source/blender/editors/gpencil/gpencil_brush.c
index 8576cbca239..7fee8af796a 100644
--- a/source/blender/editors/gpencil/gpencil_brush.c
+++ b/source/blender/editors/gpencil/gpencil_brush.c
@@ -75,9 +75,10 @@
#include "ED_screen.h"
#include "ED_view3d.h"
-#include "BIF_gl.h"
#include "BIF_glutil.h"
+#include "GPU_immediate.h"
+
#include "gpencil_intern.h"
/* ************************************************ */
@@ -958,28 +959,28 @@ static bool gpsculpt_brush_apply_clone(bContext *C, tGP_BrushEditData *gso)
static void gp_brush_drawcursor(bContext *C, int x, int y, void *UNUSED(customdata))
{
GP_EditBrush_Data *brush = gpsculpt_get_brush(CTX_data_scene(C));
-
+
if (brush) {
- glPushMatrix();
-
- glTranslatef((float)x, (float)y, 0.0f);
-
+ VertexFormat *format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
glEnable(GL_LINE_SMOOTH);
glEnable(GL_BLEND);
-
+
/* Inner Ring: Light color for action of the brush */
/* TODO: toggle between add and remove? */
- glColor4ub(255, 255, 255, 200);
- glutil_draw_lined_arc(0.0, M_PI * 2.0, brush->size, 40);
-
+ immUniformColor4ub(255, 255, 255, 200);
+ imm_draw_lined_circle(pos, x, y, brush->size, 40);
+
/* Outer Ring: Dark color for contrast on light backgrounds (e.g. gray on white) */
- glColor3ub(30, 30, 30);
- glutil_draw_lined_arc(0.0, M_PI * 2.0, brush->size + 1, 40);
-
+ immUniformColor3ub(30, 30, 30);
+ imm_draw_lined_circle(pos, x, y, brush->size + 1, 40);
+
+ immUnbindProgram();
+
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
-
- glPopMatrix();
}
}
diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c
index cc45cbd82af..8820c2fa3a4 100644
--- a/source/blender/editors/gpencil/gpencil_paint.c
+++ b/source/blender/editors/gpencil/gpencil_paint.c
@@ -68,9 +68,10 @@
#include "ED_view3d.h"
#include "ED_clip.h"
-#include "BIF_gl.h"
#include "BIF_glutil.h"
+#include "GPU_immediate.h"
+
#include "RNA_access.h"
#include "RNA_define.h"
@@ -1466,6 +1467,7 @@ static bool gp_session_initdata(bContext *C, tGPsdata *p)
bGPDpalettecolor *palcolor = p->palettecolor;
bGPdata *pdata = p->gpd;
copy_v4_v4(pdata->scolor, palcolor->color);
+ copy_v4_v4(pdata->sfill, palcolor->fill);
pdata->sflag = palcolor->flag;
return 1;
@@ -1750,28 +1752,28 @@ static void gp_paint_cleanup(tGPsdata *p)
static void gpencil_draw_eraser(bContext *UNUSED(C), int x, int y, void *p_ptr)
{
tGPsdata *p = (tGPsdata *)p_ptr;
-
+
if (p->paintmode == GP_PAINTMODE_ERASER) {
- glPushMatrix();
-
- glTranslatef((float)x, (float)y, 0.0f);
-
+ VertexFormat *format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
glEnable(GL_LINE_SMOOTH);
glEnable(GL_BLEND);
-
- glColor4ub(255, 100, 100, 20);
- glutil_draw_filled_arc(0.0, M_PI * 2.0, p->radius, 40);
-
- setlinestyle(6);
-
- glColor4ub(255, 100, 100, 200);
- glutil_draw_lined_arc(0.0, M_PI * 2.0, p->radius, 40);
-
+
+ immUniformColor4ub(255, 100, 100, 20);
+ imm_draw_filled_circle(pos, x, y, p->radius, 40);
+
+ setlinestyle(6); /* TODO: handle line stipple in shader */
+
+ immUniformColor4ub(255, 100, 100, 200);
+ imm_draw_lined_circle(pos, x, y, p->radius, 40);
+
+ immUnbindProgram();
+
setlinestyle(0);
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
-
- glPopMatrix();
}
}
diff --git a/source/blender/editors/include/BIF_glutil.h b/source/blender/editors/include/BIF_glutil.h
index d3d2c465d46..30718ccd18d 100644
--- a/source/blender/editors/include/BIF_glutil.h
+++ b/source/blender/editors/include/BIF_glutil.h
@@ -38,20 +38,11 @@ struct bContext;
struct ColorManagedViewSettings;
struct ColorManagedDisplaySettings;
-void fdrawbezier(float vec[4][3]);
void fdrawline(float x1, float y1, float x2, float y2);
void fdrawbox(float x1, float y1, float x2, float y2);
void sdrawline(int x1, int y1, int x2, int y2);
-#if 0
-void sdrawtri(int x1, int y1, int x2, int y2);
-void sdrawtrifill(int x1, int y1, int x2, int y2);
-#endif
void sdrawbox(int x1, int y1, int x2, int y2);
-void sdrawXORline(int x0, int y0, int x1, int y1);
-void sdrawXORline4(int nr, int x0, int y0, int x1, int y1);
-
-void fdrawXORellipse(float xofs, float yofs, float hw, float hh);
void fdrawXORcirc(float xofs, float yofs, float rad);
void fdrawcheckerboard(float x1, float y1, float x2, float y2);
@@ -90,6 +81,48 @@ void glutil_draw_lined_arc(float start, float angle, float radius, int nsegments
void glutil_draw_filled_arc(float start, float angle, float radius, int nsegments);
/**
+ * Draw a circle outline with the given \a radius.
+ * The circle is centered at \a x, \a y and drawn in the XY plane.
+ *
+ * \param pos The vertex attribute number for position.
+ * \param x Horizontal center.
+ * \param y Vertical center.
+ * \param radius The circle's radius.
+ * \param nsegments The number of segments to use in drawing (more = smoother).
+ */
+void imm_draw_lined_circle(unsigned pos, float x, float y, float radius, int nsegments);
+
+/**
+ * Draw a filled circle with the given \a radius.
+ * The circle is centered at \a x, \a y and drawn in the XY plane.
+ *
+ * \param pos The vertex attribute number for position.
+ * \param x Horizontal center.
+ * \param y Vertical center.
+ * \param radius The circle's radius.
+ * \param nsegments The number of segments to use in drawing (more = smoother).
+ */
+void imm_draw_filled_circle(unsigned pos, float x, float y, float radius, int nsegments);
+
+/**
+* Draw a lined box.
+*
+* \param pos The vertex attribute number for position.
+* \param x1 left.
+* \param y1 bottom.
+* \param x2 right.
+* \param y2 top.
+*/
+void imm_draw_line_box(unsigned pos, float x1, float y1, float x2, float y2);
+
+/**
+* Pack color into 3 bytes
+*
+* \param x color.
+*/
+void imm_cpack(unsigned int x);
+
+/**
* Returns a float value as obtained by glGetFloatv.
* The param must cause only one value to be gotten from GL.
*/
@@ -176,12 +209,11 @@ void glaDrawPixelsTexScaled_clipping(float x, float y, int img_w, int img_h, int
*/
void glaDefine2DArea(struct rcti *screen_rect);
-typedef struct gla2DDrawInfo gla2DDrawInfo;
+#if 0 /* UNUSED */
-/* UNUSED */
-#if 0
+typedef struct gla2DDrawInfo gla2DDrawInfo;
-gla2DDrawInfo *glaBegin2DDraw(struct rcti *screen_rect, struct rctf *world_rect);
+gla2DDrawInfo *glaBegin2DDraw(struct rcti *screen_rect, struct rctf *world_rect);
void gla2DDrawTranslatePt(gla2DDrawInfo *di, float wo_x, float wo_y, int *r_sc_x, int *r_sc_y);
void gla2DDrawTranslatePtv(gla2DDrawInfo *di, float world[2], int r_screen[2]);
@@ -190,7 +222,8 @@ void glaEnd2DDraw(gla2DDrawInfo *di);
/** Adjust the transformation mapping of a 2d area */
void gla2DGetMap(gla2DDrawInfo *di, struct rctf *rect);
void gla2DSetMap(gla2DDrawInfo *di, struct rctf *rect);
-#endif
+
+#endif /* UNUSED */
void set_inverted_drawing(int enable);
void setlinestyle(int nr);
diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h
index 4a4ab832b28..4ca7eaf0943 100644
--- a/source/blender/editors/include/ED_anim_api.h
+++ b/source/blender/editors/include/ED_anim_api.h
@@ -161,7 +161,6 @@ typedef enum eAnim_ChannelType {
ANIMTYPE_DSSKEY,
ANIMTYPE_DSWOR,
ANIMTYPE_DSNTREE,
- ANIMTYPE_DSPART,
ANIMTYPE_DSMBALL,
ANIMTYPE_DSARM,
ANIMTYPE_DSMESH,
@@ -279,7 +278,6 @@ typedef enum eAnimFilter_Flags {
#define FILTER_CAM_OBJD(ca) (CHECK_TYPE_INLINE(ca, Camera *), ((ca->flag & CAM_DS_EXPAND)))
#define FILTER_CACHEFILE_OBJD(cf) (CHECK_TYPE_INLINE(cf, CacheFile *), ((cf->flag & CACHEFILE_DS_EXPAND)))
#define FILTER_CUR_OBJD(cu) (CHECK_TYPE_INLINE(cu, Curve *), ((cu->flag & CU_DS_EXPAND)))
-#define FILTER_PART_OBJD(part) (CHECK_TYPE_INLINE(part, ParticleSettings *), ((part->flag & PART_DS_EXPAND)))
#define FILTER_MBALL_OBJD(mb) (CHECK_TYPE_INLINE(mb, MetaBall *), ((mb->flag2 & MB_DS_EXPAND)))
#define FILTER_ARM_OBJD(arm) (CHECK_TYPE_INLINE(arm, bArmature *), ((arm->flag & ARM_DS_EXPAND)))
#define FILTER_MESH_OBJD(me) (CHECK_TYPE_INLINE(me, Mesh *), ((me->flag & ME_DS_EXPAND)))
diff --git a/source/blender/editors/include/ED_buttons.h b/source/blender/editors/include/ED_buttons.h
index 64c16605dec..636c583b828 100644
--- a/source/blender/editors/include/ED_buttons.h
+++ b/source/blender/editors/include/ED_buttons.h
@@ -33,7 +33,6 @@
bool ED_texture_context_check_world(const struct bContext *C);
bool ED_texture_context_check_material(const struct bContext *C);
bool ED_texture_context_check_lamp(const struct bContext *C);
-bool ED_texture_context_check_particles(const struct bContext *C);
bool ED_texture_context_check_linestyle(const struct bContext *C);
bool ED_texture_context_check_others(const struct bContext *C);
diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h
index 04ff5692717..f5c2b1da0cc 100644
--- a/source/blender/editors/include/ED_object.h
+++ b/source/blender/editors/include/ED_object.h
@@ -190,8 +190,6 @@ bool ED_object_modifier_remove(struct ReportList *reports, struct Main *bmain,
void ED_object_modifier_clear(struct Main *bmain, struct Object *ob);
int ED_object_modifier_move_down(struct ReportList *reports, struct Object *ob, struct ModifierData *md);
int ED_object_modifier_move_up(struct ReportList *reports, struct Object *ob, struct ModifierData *md);
-int ED_object_modifier_convert(struct ReportList *reports, struct Main *bmain, struct Scene *scene,
- struct Object *ob, struct ModifierData *md);
int ED_object_modifier_apply(struct ReportList *reports, struct Scene *scene,
struct Object *ob, struct ModifierData *md, int mode);
int ED_object_modifier_copy(struct ReportList *reports, struct Object *ob, struct ModifierData *md);
diff --git a/source/blender/editors/include/ED_particle.h b/source/blender/editors/include/ED_particle.h
deleted file mode 100644
index 6cb8c0cfb19..00000000000
--- a/source/blender/editors/include/ED_particle.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * ***** 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) 2007 by Janne Karhu.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file ED_particle.h
- * \ingroup editors
- */
-
-#ifndef __ED_PARTICLE_H__
-#define __ED_PARTICLE_H__
-
-struct bContext;
-struct Object;
-struct ParticleEditSettings;
-struct rcti;
-struct PTCacheEdit;
-struct Scene;
-
-/* particle edit mode */
-void PE_free_ptcache_edit(struct PTCacheEdit *edit);
-int PE_start_edit(struct PTCacheEdit *edit);
-
-/* access */
-struct PTCacheEdit *PE_get_current(struct Scene *scene, struct Object *ob);
-struct PTCacheEdit *PE_create_current(struct Scene *scene, struct Object *ob);
-void PE_current_changed(struct Scene *scene, struct Object *ob);
-int PE_minmax(struct Scene *scene, float min[3], float max[3]);
-struct ParticleEditSettings *PE_settings(struct Scene *scene);
-
-/* update calls */
-void PE_hide_keys_time(struct Scene *scene, struct PTCacheEdit *edit, float cfra);
-void PE_update_object(struct Scene *scene, struct Object *ob, int useflag);
-
-/* selection tools */
-int PE_mouse_particles(struct bContext *C, const int mval[2], bool extend, bool deselect, bool toggle);
-int PE_border_select(struct bContext *C, struct rcti *rect, bool select, bool extend);
-int PE_circle_select(struct bContext *C, int selecting, const int mval[2], float rad);
-int PE_lasso_select(struct bContext *C, const int mcords[][2], const short moves, bool extend, bool select);
-void PE_deselect_all_visible(struct PTCacheEdit *edit);
-
-/* undo */
-void PE_undo_push(struct Scene *scene, const char *str);
-void PE_undo_step(struct Scene *scene, int step);
-void PE_undo(struct Scene *scene);
-void PE_redo(struct Scene *scene);
-bool PE_undo_is_valid(struct Scene *scene);
-void PE_undo_number(struct Scene *scene, int nr);
-const char *PE_undo_get_name(struct Scene *scene, int nr, bool *r_active);
-
-#endif /* __ED_PARTICLE_H__ */
-
diff --git a/source/blender/editors/include/ED_physics.h b/source/blender/editors/include/ED_physics.h
index fed842c969e..511dae088a0 100644
--- a/source/blender/editors/include/ED_physics.h
+++ b/source/blender/editors/include/ED_physics.h
@@ -39,11 +39,6 @@ struct wmKeyConfig;
struct Scene;
struct Object;
-/* particle_edit.c */
-int PE_poll(struct bContext *C);
-int PE_hair_poll(struct bContext *C);
-int PE_poll_view3d(struct bContext *C);
-
/* rigidbody_object.c */
bool ED_rigidbody_object_add(struct Main *bmain, struct Scene *scene, struct Object *ob, int type, struct ReportList *reports);
void ED_rigidbody_object_remove(struct Main *bmain, struct Scene *scene, struct Object *ob);
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index fd5351394c3..a1289e48da5 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -313,13 +313,15 @@ void UI_draw_roundbox_corner_set(int type);
int UI_draw_roundbox_corner_get(void);
void UI_draw_roundbox_unfilled(float minx, float miny, float maxx, float maxy, float rad);
void UI_draw_box_shadow(unsigned char alpha, float minx, float miny, float maxx, float maxy);
-void UI_draw_roundbox_gl_mode(int mode, float minx, float miny, float maxx, float maxy, float rad);
+void UI_draw_roundbox_gl_mode_3ubAlpha(int mode, float minx, float miny, float maxx, float maxy, float rad, unsigned char col[3], unsigned char alpha);
+void UI_draw_roundbox_gl_mode_3fvAlpha(int mode, float minx, float miny, float maxx, float maxy, float rad, float col[3], float alpha);
+void UI_draw_roundbox_gl_mode(int mode, float minx, float miny, float maxx, float maxy, float rad, float col[4]);
void UI_draw_roundbox_shade_x(int mode, float minx, float miny, float maxx, float maxy, float rad, float shadetop, float shadedown);
void UI_draw_roundbox_shade_y(int mode, float minx, float miny, float maxx, float maxy, float rad, float shadeLeft, float shadeRight);
void UI_draw_text_underline(int pos_x, int pos_y, int len, int height);
void UI_draw_safe_areas(
- float x1, float x2, float y1, float y2,
+ unsigned pos, float x1, float x2, float y1, float y2,
const float title_aspect[2], const float action_aspect[2]);
/* state for scrolldrawing */
diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h
index f8a5f30a596..be03647d6f4 100644
--- a/source/blender/editors/include/UI_resources.h
+++ b/source/blender/editors/include/UI_resources.h
@@ -320,13 +320,13 @@ struct bThemeState {
void UI_ThemeColor(int colorid);
// sets the color plus alpha
-void UI_ThemeColor4(int colorid);
+void UI_ThemeColor4(int colorid);
// sets color plus offset for shade
-void UI_ThemeColorShade(int colorid, int offset);
+void UI_ThemeColorShade(int colorid, int offset);
// sets color plus offset for alpha
-void UI_ThemeColorShadeAlpha(int colorid, int coloffset, int alphaoffset);
+void UI_ThemeColorShadeAlpha(int colorid, int coloffset, int alphaoffset);
// sets color, which is blend between two theme colors
void UI_ThemeColorBlend(int colorid1, int colorid2, float fac);
@@ -352,6 +352,9 @@ void UI_GetThemeColorShade3ubv(int colorid, int offset, unsigned char col[3])
void UI_GetThemeColor4fv(int colorid, float col[4]);
// get four color values, range 0.0-1.0, complete with shading offset for the RGB components
void UI_GetThemeColorShade4fv(int colorid, int offset, float col[4]);
+void UI_GetThemeColorShadeAlpha4fv(int colorid, int coloffset, int alphaoffset, float col[4]);
+// get four color values, range 0.0-1.0, complete with shading offset for the RGB components and blending
+void UI_GetThemeColorBlendShade4fv(int colorid1, int colorid2, float fac, int offset, float col[4]);
// get the 3 or 4 byte values
void UI_GetThemeColor3ubv(int colorid, unsigned char col[3]);
diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c
index 01ea1e953fa..c2c16d31e13 100644
--- a/source/blender/editors/interface/interface_draw.c
+++ b/source/blender/editors/interface/interface_draw.c
@@ -57,6 +57,7 @@
#include "GPU_draw.h"
#include "GPU_basic_shader.h"
+#include "GPU_immediate.h"
#include "UI_interface.h"
@@ -79,68 +80,98 @@ int UI_draw_roundbox_corner_get(void)
return roundboxtype;
}
-void UI_draw_roundbox_gl_mode(int mode, float minx, float miny, float maxx, float maxy, float rad)
+void UI_draw_roundbox_gl_mode_3ubAlpha(int mode, float minx, float miny, float maxx, float maxy, float rad, unsigned char col[3], unsigned char alpha)
+{
+ float colv[4];
+ colv[0] = ((float)col[0]) / 255;
+ colv[1] = ((float)col[1]) / 255;
+ colv[2] = ((float)col[2]) / 255;
+ colv[3] = ((float)alpha) / 255;
+ UI_draw_roundbox_gl_mode(mode, minx, miny, maxx, maxy, rad, colv);
+}
+
+void UI_draw_roundbox_gl_mode_3fvAlpha(int mode, float minx, float miny, float maxx, float maxy, float rad, float col[3], float alpha)
+{
+ float colv[4];
+ colv[0] = col[0];
+ colv[1] = col[1];
+ colv[2] = col[2];
+ colv[3] = alpha;
+ UI_draw_roundbox_gl_mode(mode, minx, miny, maxx, maxy, rad, colv);
+}
+
+void UI_draw_roundbox_gl_mode(int mode, float minx, float miny, float maxx, float maxy, float rad, float col[4])
{
float vec[7][2] = {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, {0.707, 0.293},
{0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}};
int a;
+ VertexFormat *format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+
/* mult */
for (a = 0; a < 7; a++) {
mul_v2_fl(vec[a], rad);
}
- glBegin(mode);
+ if (mode == GL_POLYGON) {
+ mode = GL_TRIANGLE_FAN;
+ }
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4fv(col);
+
+ immBeginAtMost(mode, 36);
/* start with corner right-bottom */
if (roundboxtype & UI_CNR_BOTTOM_RIGHT) {
- glVertex2f(maxx - rad, miny);
+ immVertex2f(pos, maxx - rad, miny);
for (a = 0; a < 7; a++) {
- glVertex2f(maxx - rad + vec[a][0], miny + vec[a][1]);
+ immVertex2f(pos, maxx - rad + vec[a][0], miny + vec[a][1]);
}
- glVertex2f(maxx, miny + rad);
+ immVertex2f(pos, maxx, miny + rad);
}
else {
- glVertex2f(maxx, miny);
+ immVertex2f(pos, maxx, miny);
}
/* corner right-top */
if (roundboxtype & UI_CNR_TOP_RIGHT) {
- glVertex2f(maxx, maxy - rad);
+ immVertex2f(pos, maxx, maxy - rad);
for (a = 0; a < 7; a++) {
- glVertex2f(maxx - vec[a][1], maxy - rad + vec[a][0]);
+ immVertex2f(pos, maxx - vec[a][1], maxy - rad + vec[a][0]);
}
- glVertex2f(maxx - rad, maxy);
+ immVertex2f(pos, maxx - rad, maxy);
}
else {
- glVertex2f(maxx, maxy);
+ immVertex2f(pos, maxx, maxy);
}
/* corner left-top */
if (roundboxtype & UI_CNR_TOP_LEFT) {
- glVertex2f(minx + rad, maxy);
+ immVertex2f(pos, minx + rad, maxy);
for (a = 0; a < 7; a++) {
- glVertex2f(minx + rad - vec[a][0], maxy - vec[a][1]);
+ immVertex2f(pos, minx + rad - vec[a][0], maxy - vec[a][1]);
}
- glVertex2f(minx, maxy - rad);
+ immVertex2f(pos, minx, maxy - rad);
}
else {
- glVertex2f(minx, maxy);
+ immVertex2f(pos, minx, maxy);
}
/* corner left-bottom */
if (roundboxtype & UI_CNR_BOTTOM_LEFT) {
- glVertex2f(minx, miny + rad);
+ immVertex2f(pos, minx, miny + rad);
for (a = 0; a < 7; a++) {
- glVertex2f(minx + vec[a][1], miny + rad - vec[a][0]);
+ immVertex2f(pos, minx + vec[a][1], miny + rad - vec[a][0]);
}
- glVertex2f(minx + rad, miny);
+ immVertex2f(pos, minx + rad, miny);
}
else {
- glVertex2f(minx, miny);
+ immVertex2f(pos, minx, miny);
}
- glEnd();
+ immEnd();
+ immUnbindProgram();
}
static void round_box_shade_col(const float col1[3], float const col2[3], const float fac)
@@ -381,8 +412,7 @@ void UI_draw_roundbox_unfilled(float minx, float miny, float maxx, float maxy, f
/* set antialias line */
glEnable(GL_LINE_SMOOTH);
glEnable(GL_BLEND);
-
- UI_draw_roundbox_gl_mode(GL_LINE_LOOP, minx, miny, maxx, maxy, rad);
+ UI_draw_roundbox_gl_mode(GL_LINE_LOOP, minx, miny, maxx, maxy, rad, color);
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
@@ -451,10 +481,11 @@ void ui_draw_but_IMAGE(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(w
/**
* Draw title and text safe areas.
*
- * The first 4 parameters are the offsets for the view, not the zones.
+ * The first parameter is a GL_FLOAT, 2, KEEP_FLOAT vertex attrib
+ * The next 4 parameters are the offsets for the view, not the zones.
*/
void UI_draw_safe_areas(
- float x1, float x2, float y1, float y2,
+ unsigned pos, float x1, float x2, float y1, float y2,
const float title_aspect[2], const float action_aspect[2])
{
const float size_x_half = (x2 - x1) * 0.5f;
@@ -482,12 +513,7 @@ void UI_draw_safe_areas(
maxx = x2 - margin_x;
maxy = y2 - margin_y;
- glBegin(GL_LINE_LOOP);
- glVertex2f(maxx, miny);
- glVertex2f(maxx, maxy);
- glVertex2f(minx, maxy);
- glVertex2f(minx, miny);
- glEnd();
+ imm_draw_line_box(pos, minx, miny, maxx, maxy);
}
}
}
@@ -501,9 +527,9 @@ static void draw_scope_end(const rctf *rect, GLint *scissor)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
/* outline */
- glColor4f(0.f, 0.f, 0.f, 0.5f);
UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox_gl_mode(GL_LINE_LOOP, rect->xmin - 1, rect->ymin, rect->xmax + 1, rect->ymax + 1, 3.0f);
+ float color[4] = {0.0f, 0.0f, 0.0f, 0.5f};
+ UI_draw_roundbox_gl_mode(GL_LINE_LOOP, rect->xmin - 1, rect->ymin, rect->xmax + 1, rect->ymax + 1, 3.0f, color);
}
static void histogram_draw_one(
@@ -573,9 +599,10 @@ void ui_draw_but_HISTOGRAM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol)
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- UI_ThemeColor4(TH_PREVIEW_BACK);
+ float color[4];
+ UI_GetThemeColor4fv(TH_PREVIEW_BACK, color);
UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f);
+ UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f, color);
/* need scissor test, histogram can draw outside of boundary */
GLint scissor[4];
@@ -660,9 +687,10 @@ void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol),
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- UI_ThemeColor4(TH_PREVIEW_BACK);
+ float color[4];
+ UI_GetThemeColor4fv(TH_PREVIEW_BACK, color);
UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f);
+ UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f, color);
/* need scissor test, waveform can draw outside of boundary */
glGetIntegerv(GL_VIEWPORT, scissor);
@@ -904,9 +932,10 @@ void ui_draw_but_VECTORSCOPE(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wco
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- UI_ThemeColor4(TH_PREVIEW_BACK);
+ float color[4];
+ UI_GetThemeColor4fv(TH_PREVIEW_BACK, color);
UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f);
+ UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f, color);
/* need scissor test, hvectorscope can draw outside of boundary */
GLint scissor[4];
@@ -1189,9 +1218,8 @@ void ui_draw_but_UNITVEC(uiBut *but, uiWidgetColors *wcol, const rcti *rect)
float size;
/* backdrop */
- glColor3ubv((unsigned char *)wcol->inner);
UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox_gl_mode(GL_POLYGON, rect->xmin, rect->ymin, rect->xmax, rect->ymax, 5.0f);
+ UI_draw_roundbox_gl_mode_3ubAlpha(GL_POLYGON, rect->xmin, rect->ymin, rect->xmax, rect->ymax, 5.0f, (unsigned char *)wcol->inner, 255);
/* sphere color */
glCullFace(GL_BACK);
@@ -1513,9 +1541,9 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc
(rect.ymax + 1) - (rect.ymin - 1));
if (scopes->track_disabled) {
- glColor4f(0.7f, 0.3f, 0.3f, 0.3f);
+ float color[4] = {0.7f, 0.3f, 0.3f, 0.3f};
UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f);
+ UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f, color);
ok = true;
}
@@ -1551,9 +1579,9 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc
ImBuf *drawibuf = scopes->track_preview;
if (scopes->use_track_mask) {
- glColor4f(0.0f, 0.0f, 0.0f, 0.3f);
+ float color[4] = {0.0f, 0.0f, 0.0f, 0.3f};
UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f);
+ UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f, color);
}
glaDrawPixelsSafe(rect.xmin, rect.ymin + 1, drawibuf->x, drawibuf->y,
@@ -1595,9 +1623,9 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc
}
if (!ok) {
- glColor4f(0.f, 0.f, 0.f, 0.3f);
+ float color[4] = {0.0f, 0.0f, 0.0f, 0.3f};
UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f);
+ UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f, color);
}
/* outline */
@@ -1671,46 +1699,54 @@ void ui_draw_but_NODESOCKET(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol
/* ****************************************************** */
-static void ui_shadowbox(float minx, float miny, float maxx, float maxy, float shadsize, unsigned char alpha)
+static void ui_shadowbox(unsigned pos, unsigned color, float minx, float miny, float maxx, float maxy, float shadsize, unsigned char alpha)
{
/* right quad */
- glColor4ub(0, 0, 0, alpha);
- glVertex2f(maxx, miny);
- glVertex2f(maxx, maxy - 0.3f * shadsize);
- glColor4ub(0, 0, 0, 0);
- glVertex2f(maxx + shadsize, maxy - 0.75f * shadsize);
- glVertex2f(maxx + shadsize, miny);
+ immAttrib4ub(color, 0, 0, 0, alpha);
+ immVertex2f(pos, maxx, miny);
+ immVertex2f(pos, maxx, maxy - 0.3f * shadsize);
+ immAttrib4ub(color, 0, 0, 0, 0);
+ immVertex2f(pos, maxx + shadsize, maxy - 0.75f * shadsize);
+ immVertex2f(pos, maxx + shadsize, miny);
/* corner shape */
- glColor4ub(0, 0, 0, alpha);
- glVertex2f(maxx, miny);
- glColor4ub(0, 0, 0, 0);
- glVertex2f(maxx + shadsize, miny);
- glVertex2f(maxx + 0.7f * shadsize, miny - 0.7f * shadsize);
- glVertex2f(maxx, miny - shadsize);
+ immAttrib4ub(color, 0, 0, 0, alpha);
+ immVertex2f(pos, maxx, miny);
+ immAttrib4ub(color, 0, 0, 0, 0);
+ immVertex2f(pos, maxx + shadsize, miny);
+ immVertex2f(pos, maxx + 0.7f * shadsize, miny - 0.7f * shadsize);
+ immVertex2f(pos, maxx, miny - shadsize);
/* bottom quad */
- glColor4ub(0, 0, 0, alpha);
- glVertex2f(minx + 0.3f * shadsize, miny);
- glVertex2f(maxx, miny);
- glColor4ub(0, 0, 0, 0);
- glVertex2f(maxx, miny - shadsize);
- glVertex2f(minx + 0.5f * shadsize, miny - shadsize);
+ immAttrib4ub(color, 0, 0, 0, alpha);
+ immVertex2f(pos, minx + 0.3f * shadsize, miny);
+ immVertex2f(pos, maxx, miny);
+ immAttrib4ub(color, 0, 0, 0, 0);
+ immVertex2f(pos, maxx, miny - shadsize);
+ immVertex2f(pos, minx + 0.5f * shadsize, miny - shadsize);
}
void UI_draw_box_shadow(unsigned char alpha, float minx, float miny, float maxx, float maxy)
{
glEnable(GL_BLEND);
-
- glBegin(GL_QUADS);
+
+ VertexFormat *format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ unsigned color = add_attrib(format, "color", GL_UNSIGNED_BYTE, 4, NORMALIZE_INT_TO_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
+
+ immBegin(GL_QUADS, 36);
/* accumulated outline boxes to make shade not linear, is more pleasant */
- ui_shadowbox(minx, miny, maxx, maxy, 11.0, (20 * alpha) >> 8);
- ui_shadowbox(minx, miny, maxx, maxy, 7.0, (40 * alpha) >> 8);
- ui_shadowbox(minx, miny, maxx, maxy, 5.0, (80 * alpha) >> 8);
-
- glEnd();
+ ui_shadowbox(pos, color, minx, miny, maxx, maxy, 11.0, (20 * alpha) >> 8);
+ ui_shadowbox(pos, color, minx, miny, maxx, maxy, 7.0, (40 * alpha) >> 8);
+ ui_shadowbox(pos, color, minx, miny, maxx, maxy, 5.0, (80 * alpha) >> 8);
+ immEnd();
+
+ immUnbindProgram();
+
glDisable(GL_BLEND);
}
@@ -1741,16 +1777,15 @@ void ui_draw_dropshadow(const rctf *rct, float radius, float aspect, float alpha
float calpha = dalpha;
for (; i--; a -= aspect) {
/* alpha ranges from 2 to 20 or so */
- glColor4f(0.0f, 0.0f, 0.0f, calpha);
+ float color[4] = {0.0f, 0.0f, 0.0f, calpha};
+ UI_draw_roundbox_gl_mode(GL_POLYGON, rct->xmin - a, rct->ymin - a, rct->xmax + a, rct->ymax - 10.0f + a, rad + a, color);
calpha += dalpha;
-
- UI_draw_roundbox_gl_mode(GL_POLYGON, rct->xmin - a, rct->ymin - a, rct->xmax + a, rct->ymax - 10.0f + a, rad + a);
}
/* outline emphasis */
glEnable(GL_LINE_SMOOTH);
- glColor4ub(0, 0, 0, 100);
- UI_draw_roundbox_gl_mode(GL_LINE_LOOP, rct->xmin - 0.5f, rct->ymin - 0.5f, rct->xmax + 0.5f, rct->ymax + 0.5f, radius + 0.5f);
+ float color[4] = {0.0f, 0.0f, 0.0f, 0.4f};
+ UI_draw_roundbox_gl_mode(GL_LINE_LOOP, rct->xmin - 0.5f, rct->ymin - 0.5f, rct->xmax + 0.5f, rct->ymax + 0.5f, radius + 0.5f, color);
glDisable(GL_LINE_SMOOTH);
glDisable(GL_BLEND);
diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index 22a450d2523..f82ed82a922 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -728,8 +728,12 @@ static void init_internal_icons(void)
icongltex.id = 0;
}
+#if 0 /* should be a compile-time check (if needed at all) */
/* we only use a texture for cards with non-power of two */
if (GPU_full_non_power_of_two_support()) {
+#else
+ {
+#endif
glGenTextures(1, &icongltex.id);
if (icongltex.id) {
@@ -757,11 +761,6 @@ static void init_internal_icons(void)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
-
- if (glGetError() == GL_OUT_OF_MEMORY) {
- glDeleteTextures(1, &icongltex.id);
- icongltex.id = 0;
- }
}
}
}
@@ -1571,8 +1570,6 @@ int UI_idcode_icon_get(const int idcode)
return ICON_NODETREE;
case ID_OB:
return ICON_OBJECT_DATA;
- case ID_PA:
- return ICON_PARTICLE_DATA;
case ID_PAL:
return ICON_COLOR; /* TODO! this would need its own icon! */
case ID_PC:
diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c
index c131bcb8e14..dd06147f226 100644
--- a/source/blender/editors/interface/interface_panel.c
+++ b/source/blender/editors/interface/interface_panel.c
@@ -65,6 +65,8 @@
#include "UI_interface_icons.h"
#include "UI_resources.h"
+#include "GPU_immediate.h"
+
#include "interface_intern.h"
/*********************** defines and structs ************************/
@@ -1518,7 +1520,8 @@ static void ui_panel_category_draw_tab(
int mode, float minx, float miny, float maxx, float maxy, float rad,
int roundboxtype,
const bool use_highlight, const bool use_shadow,
- const unsigned char highlight_fade[3])
+ const unsigned char highlight_fade[3],
+ const unsigned char col[3])
{
float vec[4][2] = {
{0.195, 0.02},
@@ -1527,74 +1530,88 @@ static void ui_panel_category_draw_tab(
{0.98, 0.805}};
int a;
+ VertexFormat *format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ unsigned color = add_attrib(format, "color", GL_UNSIGNED_BYTE, 3, NORMALIZE_INT_TO_FLOAT);
+
/* mult */
for (a = 0; a < 4; a++) {
mul_v2_fl(vec[a], rad);
}
- glBegin(mode);
+ if (mode == GL_POLYGON) {
+ mode = GL_TRIANGLE_FAN;
+ }
+
+ immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
+
+ immBeginAtMost(mode, 24);
+
+ immAttrib3ubv(color, col);
/* start with corner right-top */
if (use_highlight) {
if (roundboxtype & UI_CNR_TOP_RIGHT) {
- glVertex2f(maxx, maxy - rad);
+ immVertex2f(pos, maxx, maxy - rad);
for (a = 0; a < 4; a++) {
- glVertex2f(maxx - vec[a][1], maxy - rad + vec[a][0]);
+ immVertex2f(pos, maxx - vec[a][1], maxy - rad + vec[a][0]);
}
- glVertex2f(maxx - rad, maxy);
+ immVertex2f(pos, maxx - rad, maxy);
}
else {
- glVertex2f(maxx, maxy);
+ immVertex2f(pos, maxx, maxy);
}
/* corner left-top */
if (roundboxtype & UI_CNR_TOP_LEFT) {
- glVertex2f(minx + rad, maxy);
+ immVertex2f(pos, minx + rad, maxy);
for (a = 0; a < 4; a++) {
- glVertex2f(minx + rad - vec[a][0], maxy - vec[a][1]);
+ immVertex2f(pos, minx + rad - vec[a][0], maxy - vec[a][1]);
}
- glVertex2f(minx, maxy - rad);
+ immVertex2f(pos, minx, maxy - rad);
}
else {
- glVertex2f(minx, maxy);
+ immVertex2f(pos, minx, maxy);
}
}
if (use_highlight && !use_shadow) {
if (highlight_fade) {
- glColor3ubv(highlight_fade);
+ immAttrib3ubv(color, highlight_fade);
}
- glVertex2f(minx, miny + rad);
- glEnd();
+ immVertex2f(pos, minx, miny + rad);
+ immEnd();
+ immUnbindProgram();
return;
}
/* corner left-bottom */
if (roundboxtype & UI_CNR_BOTTOM_LEFT) {
- glVertex2f(minx, miny + rad);
+ immVertex2f(pos, minx, miny + rad);
for (a = 0; a < 4; a++) {
- glVertex2f(minx + vec[a][1], miny + rad - vec[a][0]);
+ immVertex2f(pos, minx + vec[a][1], miny + rad - vec[a][0]);
}
- glVertex2f(minx + rad, miny);
+ immVertex2f(pos, minx + rad, miny);
}
else {
- glVertex2f(minx, miny);
+ immVertex2f(pos, minx, miny);
}
/* corner right-bottom */
if (roundboxtype & UI_CNR_BOTTOM_RIGHT) {
- glVertex2f(maxx - rad, miny);
+ immVertex2f(pos, maxx - rad, miny);
for (a = 0; a < 4; a++) {
- glVertex2f(maxx - rad + vec[a][0], miny + vec[a][1]);
+ immVertex2f(pos, maxx - rad + vec[a][0], miny + vec[a][1]);
}
- glVertex2f(maxx, miny + rad);
+ immVertex2f(pos, maxx, miny + rad);
}
else {
- glVertex2f(maxx, miny);
+ immVertex2f(pos, maxx, miny);
}
- glEnd();
+ immEnd();
+ immUnbindProgram();
}
@@ -1754,19 +1771,19 @@ void UI_panel_category_draw_all(ARegion *ar, const char *category_id_active)
if (is_active)
#endif
{
- glColor3ubv(is_active ? theme_col_tab_active : theme_col_tab_inactive);
ui_panel_category_draw_tab(GL_POLYGON, rct->xmin, rct->ymin, rct->xmax, rct->ymax,
- tab_curve_radius - px, roundboxtype, true, true, NULL);
+ tab_curve_radius - px, roundboxtype, true, true, NULL,
+ is_active ? theme_col_tab_active : theme_col_tab_inactive);
/* tab outline */
- glColor3ubv(theme_col_tab_outline);
ui_panel_category_draw_tab(GL_LINE_STRIP, rct->xmin - px, rct->ymin - px, rct->xmax - px, rct->ymax + px,
- tab_curve_radius, roundboxtype, true, true, NULL);
+ tab_curve_radius, roundboxtype, true, true, NULL, theme_col_tab_outline);
+
/* tab highlight (3d look) */
- glColor3ubv(is_active ? theme_col_tab_highlight : theme_col_tab_highlight_inactive);
ui_panel_category_draw_tab(GL_LINE_STRIP, rct->xmin, rct->ymin, rct->xmax, rct->ymax,
tab_curve_radius, roundboxtype, true, false,
- is_active ? theme_col_back : theme_col_tab_inactive);
+ is_active ? theme_col_back : theme_col_tab_inactive,
+ is_active ? theme_col_tab_highlight : theme_col_tab_highlight_inactive);
}
/* tab blackline */
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 36f65065fa1..462ad34582b 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -64,7 +64,6 @@
#include "BKE_modifier.h"
#include "BKE_object.h"
#include "BKE_packedFile.h"
-#include "BKE_particle.h"
#include "BKE_paint.h"
#include "BKE_report.h"
#include "BKE_sca.h"
@@ -365,7 +364,6 @@ static const char *template_id_browse_tip(StructRNA *type)
case ID_AC: return N_("Browse Action to be linked");
case ID_NT: return N_("Browse Node Tree to be linked");
case ID_BR: return N_("Browse Brush to be linked");
- case ID_PA: return N_("Browse Particle Settings to be linked");
case ID_GD: return N_("Browse Grease Pencil Data to be linked");
case ID_MC: return N_("Browse Movie Clip to be linked");
case ID_MSK: return N_("Browse Mask to be linked");
@@ -522,7 +520,6 @@ static void template_ID(
BLT_I18NCONTEXT_ID_ACTION,
BLT_I18NCONTEXT_ID_NODETREE,
BLT_I18NCONTEXT_ID_BRUSH,
- BLT_I18NCONTEXT_ID_PARTICLESETTINGS,
BLT_I18NCONTEXT_ID_GPENCIL,
BLT_I18NCONTEXT_ID_FREESTYLELINESTYLE,
);
@@ -790,16 +787,6 @@ static void modifiers_convertToReal(bContext *C, void *ob_v, void *md_v)
ED_undo_push(C, "Modifier convert to real");
}
-static int modifier_can_delete(ModifierData *md)
-{
- /* fluid particle modifier can't be deleted here */
- if (md->type == eModifierType_ParticleSystem)
- if (((ParticleSystemModifierData *)md)->psys->part->type == PART_FLUID)
- return 0;
-
- return 1;
-}
-
/* Check whether Modifier is a simulation or not, this is used for switching to the physics/particles context tab */
static int modifier_is_simulation(ModifierData *md)
{
@@ -809,10 +796,6 @@ static int modifier_is_simulation(ModifierData *md)
{
return 1;
}
- /* Particle Tab */
- else if (md->type == eModifierType_ParticleSystem) {
- return 2;
- }
else {
return 0;
}
@@ -927,18 +910,14 @@ static uiLayout *draw_modifier(
UI_block_emboss_set(block, UI_EMBOSS_NONE);
/* When Modifier is a simulation, show button to switch to context rather than the delete button. */
- if (modifier_can_delete(md) &&
- (!modifier_is_simulation(md) ||
- STREQ(scene->r.engine, RE_engine_id_BLENDER_GAME)))
+ if (!modifier_is_simulation(md) ||
+ STREQ(scene->r.engine, RE_engine_id_BLENDER_GAME))
{
uiItemO(row, "", ICON_X, "OBJECT_OT_modifier_remove");
}
else if (modifier_is_simulation(md) == 1) {
uiItemStringO(row, "", ICON_BUTS, "WM_OT_properties_context_change", "context", "PHYSICS");
}
- else if (modifier_is_simulation(md) == 2) {
- uiItemStringO(row, "", ICON_BUTS, "WM_OT_properties_context_change", "context", "PARTICLES");
- }
UI_block_emboss_set(block, UI_EMBOSS);
}
@@ -953,34 +932,20 @@ static uiLayout *draw_modifier(
/* only here obdata, the rest of modifiers is ob level */
UI_block_lock_set(block, BKE_object_obdata_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
- if (md->type == eModifierType_ParticleSystem) {
- ParticleSystem *psys = ((ParticleSystemModifierData *)md)->psys;
-
- if (!(ob->mode & OB_MODE_PARTICLE_EDIT)) {
- if (ELEM(psys->part->ren_as, PART_DRAW_GR, PART_DRAW_OB))
- uiItemO(row, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Convert"), ICON_NONE,
- "OBJECT_OT_duplicates_make_real");
- else if (psys->part->ren_as == PART_DRAW_PATH && psys->pathcache)
- uiItemO(row, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Convert"), ICON_NONE,
- "OBJECT_OT_modifier_convert");
- }
- }
- else {
- uiLayoutSetOperatorContext(row, WM_OP_INVOKE_DEFAULT);
- uiItemEnumO(row, "OBJECT_OT_modifier_apply", CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Apply"),
- 0, "apply_as", MODIFIER_APPLY_DATA);
-
- if (modifier_isSameTopology(md) && !modifier_isNonGeometrical(md)) {
- uiItemEnumO(row, "OBJECT_OT_modifier_apply",
- CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Apply as Shape Key"),
- 0, "apply_as", MODIFIER_APPLY_SHAPE);
- }
+ uiLayoutSetOperatorContext(row, WM_OP_INVOKE_DEFAULT);
+ uiItemEnumO(row, "OBJECT_OT_modifier_apply", CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Apply"),
+ 0, "apply_as", MODIFIER_APPLY_DATA);
+
+ if (modifier_isSameTopology(md) && !modifier_isNonGeometrical(md)) {
+ uiItemEnumO(row, "OBJECT_OT_modifier_apply",
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Apply as Shape Key"),
+ 0, "apply_as", MODIFIER_APPLY_SHAPE);
}
UI_block_lock_clear(block);
UI_block_lock_set(block, ob && ID_IS_LINKED_DATABLOCK(ob), ERROR_LIBDATA_MESSAGE);
- if (!ELEM(md->type, eModifierType_Fluidsim, eModifierType_Softbody, eModifierType_ParticleSystem,
+ if (!ELEM(md->type, eModifierType_Fluidsim, eModifierType_Softbody,
eModifierType_Cloth, eModifierType_Smoke))
{
uiItemO(row, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Copy"), ICON_NONE,
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index c285d753b96..80fc47e25e8 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -58,6 +58,7 @@
#include "interface_intern.h"
#include "GPU_basic_shader.h"
+#include "GPU_immediate.h"
#ifdef WITH_INPUT_IME
# include "WM_types.h"
@@ -217,16 +218,15 @@ void ui_draw_anti_roundbox(int mode, float minx, float miny, float maxx, float m
int j;
glEnable(GL_BLEND);
- glGetFloatv(GL_CURRENT_COLOR, color);
+ glGetFloatv(GL_CURRENT_COLOR, color); // I will make the change in a futur patch, use as it is for now
if (use_alpha) {
color[3] = 0.5f;
}
color[3] *= 0.125f;
- glColor4fv(color);
for (j = 0; j < WIDGET_AA_JITTER; j++) {
glTranslate2fv(jit[j]);
- UI_draw_roundbox_gl_mode(mode, minx, miny, maxx, maxy, rad);
+ UI_draw_roundbox_gl_mode(mode, minx, miny, maxx, maxy, rad, color);
glTranslatef(-jit[j][0], -jit[j][1], 0.0f);
}
@@ -1461,37 +1461,40 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
/* for underline drawing */
float font_xofs, font_yofs;
- UI_fontstyle_draw_ex(fstyle, rect, drawstr + but->ofs,
- drawstr_left_len - but->ofs, &font_xofs, &font_yofs);
+ int drawlen = (drawstr_left_len == INT_MAX) ? strlen(drawstr + but->ofs) : (drawstr_left_len - but->ofs);
- if (but->menu_key != '\0') {
- char fixedbuf[128];
- const char *str;
+ if (drawlen > 0) {
+ UI_fontstyle_draw_ex(fstyle, rect, drawstr + but->ofs, drawlen, &font_xofs, &font_yofs);
- BLI_strncpy(fixedbuf, drawstr + but->ofs, min_ii(sizeof(fixedbuf), drawstr_left_len));
+ if (but->menu_key != '\0') {
+ char fixedbuf[128];
+ const char *str;
- str = strchr(fixedbuf, but->menu_key - 32); /* upper case */
- if (str == NULL)
- str = strchr(fixedbuf, but->menu_key);
+ BLI_strncpy(fixedbuf, drawstr + but->ofs, min_ii(sizeof(fixedbuf), drawlen));
- if (str) {
- int ul_index = -1;
- float ul_advance;
+ str = strchr(fixedbuf, but->menu_key - 32); /* upper case */
+ if (str == NULL)
+ str = strchr(fixedbuf, but->menu_key);
- ul_index = (int)(str - fixedbuf);
+ if (str) {
+ int ul_index = -1;
+ float ul_advance;
- if (fstyle->kerning == 1) {
- BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
- }
+ ul_index = (int)(str - fixedbuf);
- fixedbuf[ul_index] = '\0';
- ul_advance = BLF_width(fstyle->uifont_id, fixedbuf, ul_index);
+ if (fstyle->kerning == 1) {
+ BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
+ }
+
+ fixedbuf[ul_index] = '\0';
+ ul_advance = BLF_width(fstyle->uifont_id, fixedbuf, ul_index);
- BLF_position(fstyle->uifont_id, rect->xmin + font_xofs + ul_advance, rect->ymin + font_yofs, 0.0f);
- BLF_draw(fstyle->uifont_id, "_", 2);
+ BLF_position(fstyle->uifont_id, rect->xmin + font_xofs + ul_advance, rect->ymin + font_yofs, 0.0f);
+ BLF_draw(fstyle->uifont_id, "_", 2);
- if (fstyle->kerning == 1) {
- BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
+ if (fstyle->kerning == 1) {
+ BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT);
+ }
}
}
}
@@ -2266,18 +2269,17 @@ void ui_hsvcircle_pos_from_vals(uiBut *but, const rcti *rect, float *hsv, float
static void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, const rcti *rect)
{
+ /* TODO(merwin): reimplement as shader for pixel-perfect colors */
+
const int tot = 64;
const float radstep = 2.0f * (float)M_PI / (float)tot;
const float centx = BLI_rcti_cent_x_fl(rect);
const float centy = BLI_rcti_cent_y_fl(rect);
float radius = (float)min_ii(BLI_rcti_size_x(rect), BLI_rcti_size_y(rect)) / 2.0f;
- /* gouraud triangle fan */
ColorPicker *cpicker = but->custom_data;
const float *hsv_ptr = cpicker->color_data;
- float xpos, ypos, ang = 0.0f;
float rgb[3], hsvo[3], hsv[3], col[3], colcent[3];
- int a;
bool color_profile = ui_but_is_colorpicker_display_space(but);
/* color */
@@ -2308,11 +2310,18 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, const rcti *
ui_color_picker_to_rgb(0.0f, 0.0f, hsv[2], colcent, colcent + 1, colcent + 2);
- glBegin(GL_TRIANGLE_FAN);
- glColor3fv(colcent);
- glVertex2f(centx, centy);
+ VertexFormat* format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ unsigned color = add_attrib(format, "color", GL_FLOAT, 3, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
+
+ immBegin(GL_TRIANGLE_FAN, tot + 2);
+ immAttrib3fv(color, colcent);
+ immVertex2f(pos, centx, centy);
- for (a = 0; a <= tot; a++, ang += radstep) {
+ float ang = 0.0f;
+ for (int a = 0; a <= tot; a++, ang += radstep) {
float si = sinf(ang);
float co = cosf(ang);
@@ -2320,25 +2329,32 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, const rcti *
ui_color_picker_to_rgb_v(hsv, col);
- glColor3fv(col);
- glVertex2f(centx + co * radius, centy + si * radius);
+ immAttrib3fv(color, col);
+ immVertex2f(pos, centx + co * radius, centy + si * radius);
}
- glEnd();
-
+ immEnd();
+ immUnbindProgram();
+
/* fully rounded outline */
- glPushMatrix();
- glTranslatef(centx, centy, 0.0f);
+ format = immVertexFormat();
+ pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
glEnable(GL_BLEND);
glEnable(GL_LINE_SMOOTH);
- glColor3ubv((unsigned char *)wcol->outline);
- glutil_draw_lined_arc(0.0f, M_PI * 2.0, radius, tot + 1);
+
+ immUniformColor3ubv((unsigned char *)wcol->outline);
+ imm_draw_lined_circle(pos, centx, centy, radius, tot);
+
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
- glPopMatrix();
+
+ immUnbindProgram();
/* cursor */
+ float xpos, ypos;
ui_hsvcircle_pos_from_vals(but, rect, hsvo, &xpos, &ypos);
-
ui_hsv_cursor(xpos, ypos);
}
diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c
index 5e24dc96255..bdd492beb1e 100644
--- a/source/blender/editors/interface/resources.c
+++ b/source/blender/editors/interface/resources.c
@@ -1272,7 +1272,6 @@ void UI_ThemeColor4(int colorid)
cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
glColor4ubv(cp);
-
}
/* set the color with offset for shades */
@@ -1280,7 +1279,7 @@ void UI_ThemeColorShade(int colorid, int offset)
{
int r, g, b;
const unsigned char *cp;
-
+
cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
r = offset + (int) cp[0];
CLAMP(r, 0, 255);
@@ -1304,6 +1303,7 @@ void UI_ThemeColorShadeAlpha(int colorid, int coloffset, int alphaoffset)
CLAMP(b, 0, 255);
a = alphaoffset + (int) cp[3];
CLAMP(a, 0, 255);
+
glColor4ub(r, g, b, a);
}
@@ -1470,6 +1470,53 @@ void UI_GetThemeColorShade3ubv(int colorid, int offset, unsigned char col[3])
col[2] = b;
}
+void UI_GetThemeColorShadeAlpha4fv(int colorid, int coloffset, int alphaoffset, float col[4])
+{
+ int r, g, b, a;
+ const unsigned char *cp;
+
+ cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
+
+ r = coloffset + (int) cp[0];
+ CLAMP(r, 0, 255);
+ g = coloffset + (int) cp[1];
+ CLAMP(g, 0, 255);
+ b = coloffset + (int) cp[2];
+ CLAMP(b, 0, 255);
+ a = alphaoffset + (int) cp[3];
+ CLAMP(b, 0, 255);
+
+ col[0] = ((float)r) / 255.0f;
+ col[1] = ((float)g) / 255.0f;
+ col[2] = ((float)b) / 255.0f;
+ col[3] = ((float)a) / 255.0f;
+}
+
+void UI_GetThemeColorBlendShade4fv(int colorid1, int colorid2, float fac, int offset, float col[4])
+{
+ int r, g, b, a;
+ const unsigned char *cp1, *cp2;
+
+ cp1 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid1);
+ cp2 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid2);
+
+ CLAMP(fac, 0.0f, 1.0f);
+
+ r = offset + floorf((1.0f - fac) * cp1[0] + fac * cp2[0]);
+ CLAMP(r, 0, 255);
+ g = offset + floorf((1.0f - fac) * cp1[1] + fac * cp2[1]);
+ CLAMP(g, 0, 255);
+ b = offset + floorf((1.0f - fac) * cp1[2] + fac * cp2[2]);
+ CLAMP(b, 0, 255);
+ a = offset + floorf((1.0f - fac) * cp1[3] + fac * cp2[3]);
+ CLAMP(a, 0, 255);
+
+ col[0] = ((float)r) / 255.0f;
+ col[1] = ((float)g) / 255.0f;
+ col[2] = ((float)b) / 255.0f;
+ col[3] = ((float)a) / 255.0f;
+}
+
/* get the color, in char pointer */
void UI_GetThemeColor3ubv(int colorid, unsigned char col[3])
{
@@ -1664,6 +1711,8 @@ void init_userdef_do_versions(void)
U.tw_size = 25; /* percentage of window size */
U.tw_handlesize = 16; /* percentage of widget radius */
}
+ if (U.manipulator_scale == 0)
+ U.manipulator_scale = 75;
if (U.pad_rot_angle == 0.0f)
U.pad_rot_angle = 15.0f;
diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c
index c78d97ef86f..482b764117c 100644
--- a/source/blender/editors/interface/view2d.c
+++ b/source/blender/editors/interface/view2d.c
@@ -1100,9 +1100,6 @@ void UI_view2d_view_ortho(View2D *v2d)
/* set matrix on all appropriate axes */
wmOrtho2(curmasked.xmin, curmasked.xmax, curmasked.ymin, curmasked.ymax);
-
- /* XXX is this necessary? */
- glLoadIdentity();
}
/**
@@ -1130,9 +1127,6 @@ void UI_view2d_view_orthoSpecial(ARegion *ar, View2D *v2d, const bool xaxis)
wmOrtho2(curmasked.xmin - xofs, curmasked.xmax - xofs, -yofs, ar->winy - yofs);
else
wmOrtho2(-xofs, ar->winx - xofs, curmasked.ymin - yofs, curmasked.ymax - yofs);
-
- /* XXX is this necessary? */
- glLoadIdentity();
}
@@ -2424,11 +2418,6 @@ void UI_view2d_text_cache_draw(ARegion *ar)
BLI_memarena_free(g_v2d_strings_arena);
g_v2d_strings_arena = NULL;
}
-
- // glMatrixMode(GL_PROJECTION);
- // glPopMatrix();
- // glMatrixMode(GL_MODELVIEW);
- // glPopMatrix();
}
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index 0cb91fd0269..4d31ad439a9 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -82,7 +82,6 @@
#include "BKE_mesh.h"
#include "BKE_nla.h"
#include "BKE_object.h"
-#include "BKE_particle.h"
#include "BKE_report.h"
#include "BKE_sca.h"
#include "BKE_scene.h"
@@ -1967,23 +1966,6 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
}
}
}
- if (dupflag & USER_DUP_PSYS) {
- ParticleSystem *psys;
- for (psys = obn->particlesystem.first; psys; psys = psys->next) {
- id = (ID *) psys->part;
- if (id) {
- ID_NEW_US(psys->part)
- else
- psys->part = BKE_particlesettings_copy(bmain, psys->part);
-
- if (dupflag & USER_DUP_ACT) {
- BKE_animdata_copy_id_action(&psys->part->id);
- }
-
- id_us_min(id);
- }
- }
- }
id = obn->data;
didit = 0;
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index 111afcdc7a7..6b3284fe8b1 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -75,7 +75,6 @@
#include "BKE_mball.h"
#include "BKE_mesh.h"
#include "BKE_object.h"
-#include "BKE_pointcache.h"
#include "BKE_property.h"
#include "BKE_sca.h"
#include "BKE_softbody.h"
@@ -430,22 +429,9 @@ void ED_object_editmode_exit(bContext *C, int flag)
/* freedata only 0 now on file saves and render */
if (freedata) {
- ListBase pidlist;
- PTCacheID *pid;
-
/* for example; displist make is different in editmode */
scene->obedit = NULL; // XXX for context
- /* flag object caches as outdated */
- BKE_ptcache_ids_from_object(&pidlist, obedit, scene, 0);
- for (pid = pidlist.first; pid; pid = pid->next) {
- if (pid->type != PTCACHE_TYPE_PARTICLES) /* particles don't need reset on geometry change */
- pid->cache->flag |= PTCACHE_OUTDATED;
- }
- BLI_freelistN(&pidlist);
-
- BKE_ptcache_object_reset(scene, obedit, PTCACHE_RESET_OUTDATED);
-
/* also flush ob recalc, doesn't take much overhead, but used for particles */
DAG_id_tag_update(&obedit->id, OB_RECALC_OB | OB_RECALC_DATA);
@@ -1583,13 +1569,9 @@ static EnumPropertyItem *object_mode_set_itemsf(bContext *C, PointerRNA *UNUSED(
ob = CTX_data_active_object(C);
if (ob) {
- const bool use_mode_particle_edit = (BLI_listbase_is_empty(&ob->particlesystem) == false) ||
- (ob->soft != NULL) ||
- (modifiers_findByType(ob, eModifierType_Cloth) != NULL);
while (input->identifier) {
if ((input->value == OB_MODE_EDIT && OB_TYPE_SUPPORT_EDITMODE(ob->type)) ||
(input->value == OB_MODE_POSE && (ob->type == OB_ARMATURE)) ||
- (input->value == OB_MODE_PARTICLE_EDIT && use_mode_particle_edit) ||
(ELEM(input->value, OB_MODE_SCULPT, OB_MODE_VERTEX_PAINT,
OB_MODE_WEIGHT_PAINT, OB_MODE_TEXTURE_PAINT) && (ob->type == OB_MESH)) ||
(input->value == OB_MODE_OBJECT))
@@ -1631,8 +1613,6 @@ static const char *object_mode_op_string(int mode)
return "PAINT_OT_weight_paint_toggle";
if (mode == OB_MODE_TEXTURE_PAINT)
return "PAINT_OT_texture_paint_toggle";
- if (mode == OB_MODE_PARTICLE_EDIT)
- return "PARTICLE_OT_particle_edit_toggle";
if (mode == OB_MODE_POSE)
return "OBJECT_OT_posemode_toggle";
if (mode == OB_MODE_GPENCIL)
@@ -1654,7 +1634,7 @@ static bool object_mode_compat_test(Object *ob, ObjectMode mode)
switch (ob->type) {
case OB_MESH:
if (mode & (OB_MODE_EDIT | OB_MODE_SCULPT | OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT |
- OB_MODE_TEXTURE_PAINT | OB_MODE_PARTICLE_EDIT))
+ OB_MODE_TEXTURE_PAINT))
{
return true;
}
diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h
index a599835917c..ff4a58033ac 100644
--- a/source/blender/editors/object/object_intern.h
+++ b/source/blender/editors/object/object_intern.h
@@ -169,7 +169,6 @@ void OBJECT_OT_modifier_remove(struct wmOperatorType *ot);
void OBJECT_OT_modifier_move_up(struct wmOperatorType *ot);
void OBJECT_OT_modifier_move_down(struct wmOperatorType *ot);
void OBJECT_OT_modifier_apply(struct wmOperatorType *ot);
-void OBJECT_OT_modifier_convert(struct wmOperatorType *ot);
void OBJECT_OT_modifier_copy(struct wmOperatorType *ot);
void OBJECT_OT_multires_subdivide(struct wmOperatorType *ot);
void OBJECT_OT_multires_reshape(struct wmOperatorType *ot);
diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c
index b44ddf925a8..9175bd69a28 100644
--- a/source/blender/editors/object/object_modifier.c
+++ b/source/blender/editors/object/object_modifier.c
@@ -41,6 +41,7 @@
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_force.h"
+#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "BLI_bitmap.h"
@@ -71,7 +72,6 @@
#include "BKE_object_deform.h"
#include "BKE_ocean.h"
#include "BKE_paint.h"
-#include "BKE_particle.h"
#include "BKE_softbody.h"
#include "BKE_editmesh.h"
@@ -111,65 +111,57 @@ ModifierData *ED_object_modifier_add(ReportList *reports, Main *bmain, Scene *sc
}
}
- if (type == eModifierType_ParticleSystem) {
- /* don't need to worry about the new modifier's name, since that is set to the number
- * of particle systems which shouldn't have too many duplicates
- */
- new_md = object_add_particle_system(scene, ob, name);
- }
- else {
- /* get new modifier data to add */
- new_md = modifier_new(type);
+ /* get new modifier data to add */
+ new_md = modifier_new(type);
+
+ if (mti->flags & eModifierTypeFlag_RequiresOriginalData) {
+ md = ob->modifiers.first;
- if (mti->flags & eModifierTypeFlag_RequiresOriginalData) {
- md = ob->modifiers.first;
-
- while (md && modifierType_getInfo(md->type)->type == eModifierTypeType_OnlyDeform)
- md = md->next;
-
- BLI_insertlinkbefore(&ob->modifiers, md, new_md);
- }
- else
- BLI_addtail(&ob->modifiers, new_md);
+ while (md && modifierType_getInfo(md->type)->type == eModifierTypeType_OnlyDeform)
+ md = md->next;
+
+ BLI_insertlinkbefore(&ob->modifiers, md, new_md);
+ }
+ else
+ BLI_addtail(&ob->modifiers, new_md);
- if (name) {
- BLI_strncpy_utf8(new_md->name, name, sizeof(new_md->name));
- }
+ if (name) {
+ BLI_strncpy_utf8(new_md->name, name, sizeof(new_md->name));
+ }
- /* make sure modifier data has unique name */
+ /* make sure modifier data has unique name */
- modifier_unique_name(&ob->modifiers, new_md);
-
- /* special cases */
- if (type == eModifierType_Softbody) {
- if (!ob->soft) {
- ob->soft = sbNew(scene);
- ob->softflag |= OB_SB_GOAL | OB_SB_EDGES;
- }
- }
- else if (type == eModifierType_Collision) {
- if (!ob->pd)
- ob->pd = object_add_collision_fields(0);
-
- ob->pd->deflect = 1;
- }
- else if (type == eModifierType_Surface) {
- /* pass */
+ modifier_unique_name(&ob->modifiers, new_md);
+
+ /* special cases */
+ if (type == eModifierType_Softbody) {
+ if (!ob->soft) {
+ ob->soft = sbNew(scene);
+ ob->softflag |= OB_SB_GOAL | OB_SB_EDGES;
}
- else if (type == eModifierType_Multires) {
- /* set totlvl from existing MDISPS layer if object already had it */
- multiresModifier_set_levels_from_disps((MultiresModifierData *)new_md, ob);
+ }
+ else if (type == eModifierType_Collision) {
+ if (!ob->pd)
+ ob->pd = object_add_collision_fields(0);
+
+ ob->pd->deflect = 1;
+ }
+ else if (type == eModifierType_Surface) {
+ /* pass */
+ }
+ else if (type == eModifierType_Multires) {
+ /* set totlvl from existing MDISPS layer if object already had it */
+ multiresModifier_set_levels_from_disps((MultiresModifierData *)new_md, ob);
- if (ob->mode & OB_MODE_SCULPT) {
- /* ensure that grid paint mask layer is created */
- BKE_sculpt_mask_layers_ensure(ob, (MultiresModifierData *)new_md);
- }
- }
- else if (type == eModifierType_Skin) {
- /* ensure skin-node customdata exists */
- BKE_mesh_ensure_skin_customdata(ob->data);
+ if (ob->mode & OB_MODE_SCULPT) {
+ /* ensure that grid paint mask layer is created */
+ BKE_sculpt_mask_layers_ensure(ob, (MultiresModifierData *)new_md);
}
}
+ else if (type == eModifierType_Skin) {
+ /* ensure skin-node customdata exists */
+ BKE_mesh_ensure_skin_customdata(ob->data);
+ }
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
DAG_relations_tag_update(bmain);
@@ -280,14 +272,7 @@ static bool object_modifier_remove(Main *bmain, Object *ob, ModifierData *md,
}
/* special cases */
- if (md->type == eModifierType_ParticleSystem) {
- ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md;
-
- BLI_remlink(&ob->particlesystem, psmd->psys);
- psys_free(ob, psmd->psys);
- psmd->psys = NULL;
- }
- else if (md->type == eModifierType_Softbody) {
+ if (md->type == eModifierType_Softbody) {
if (ob->soft) {
sbFree(ob->soft);
ob->soft = NULL;
@@ -314,12 +299,6 @@ static bool object_modifier_remove(Main *bmain, Object *ob, ModifierData *md,
modifier_skin_customdata_delete(ob);
}
- if (ELEM(md->type, eModifierType_Softbody, eModifierType_Cloth) &&
- BLI_listbase_is_empty(&ob->particlesystem))
- {
- ob->mode &= ~OB_MODE_PARTICLE_EDIT;
- }
-
DAG_relations_tag_update(bmain);
BLI_remlink(&ob->modifiers, md);
@@ -411,115 +390,6 @@ int ED_object_modifier_move_down(ReportList *reports, Object *ob, ModifierData *
return 1;
}
-int ED_object_modifier_convert(ReportList *UNUSED(reports), Main *bmain, Scene *scene, Object *ob, ModifierData *md)
-{
- Object *obn;
- ParticleSystem *psys;
- ParticleCacheKey *key, **cache;
- ParticleSettings *part;
- Mesh *me;
- MVert *mvert;
- MEdge *medge;
- int a, k, kmax;
- int totvert = 0, totedge = 0, cvert = 0;
- int totpart = 0, totchild = 0;
-
- if (md->type != eModifierType_ParticleSystem) return 0;
- if (ob && ob->mode & OB_MODE_PARTICLE_EDIT) return 0;
-
- psys = ((ParticleSystemModifierData *)md)->psys;
- part = psys->part;
-
- if (part->ren_as != PART_DRAW_PATH || psys->pathcache == NULL)
- return 0;
-
- totpart = psys->totcached;
- totchild = psys->totchildcache;
-
- if (totchild && (part->draw & PART_DRAW_PARENT) == 0)
- totpart = 0;
-
- /* count */
- cache = psys->pathcache;
- for (a = 0; a < totpart; a++) {
- key = cache[a];
-
- if (key->segments > 0) {
- totvert += key->segments + 1;
- totedge += key->segments;
- }
- }
-
- cache = psys->childcache;
- for (a = 0; a < totchild; a++) {
- key = cache[a];
-
- if (key->segments > 0) {
- totvert += key->segments + 1;
- totedge += key->segments;
- }
- }
-
- if (totvert == 0) return 0;
-
- /* add new mesh */
- obn = BKE_object_add(bmain, scene, OB_MESH, NULL);
- me = obn->data;
-
- me->totvert = totvert;
- me->totedge = totedge;
-
- me->mvert = CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, totvert);
- me->medge = CustomData_add_layer(&me->edata, CD_MEDGE, CD_CALLOC, NULL, totedge);
- me->mface = CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC, NULL, 0);
-
- mvert = me->mvert;
- medge = me->medge;
-
- /* copy coordinates */
- cache = psys->pathcache;
- for (a = 0; a < totpart; a++) {
- key = cache[a];
- kmax = key->segments;
- for (k = 0; k <= kmax; k++, key++, cvert++, mvert++) {
- copy_v3_v3(mvert->co, key->co);
- if (k) {
- medge->v1 = cvert - 1;
- medge->v2 = cvert;
- medge->flag = ME_EDGEDRAW | ME_EDGERENDER | ME_LOOSEEDGE;
- medge++;
- }
- else {
- /* cheap trick to select the roots */
- mvert->flag |= SELECT;
- }
- }
- }
-
- cache = psys->childcache;
- for (a = 0; a < totchild; a++) {
- key = cache[a];
- kmax = key->segments;
- for (k = 0; k <= kmax; k++, key++, cvert++, mvert++) {
- copy_v3_v3(mvert->co, key->co);
- if (k) {
- medge->v1 = cvert - 1;
- medge->v2 = cvert;
- medge->flag = ME_EDGEDRAW | ME_EDGERENDER | ME_LOOSEEDGE;
- medge++;
- }
- else {
- /* cheap trick to select the roots */
- mvert->flag |= SELECT;
- }
- }
- }
-
- DAG_relations_tag_update(bmain);
-
- return 1;
-}
-
static int modifier_apply_shape(ReportList *reports, Scene *scene, Object *ob, ModifierData *md)
{
const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
@@ -650,20 +520,6 @@ static int modifier_apply_obdata(ReportList *reports, Scene *scene, Object *ob,
return 0;
}
- /* lattice modifier can be applied to particle system too */
- if (ob->particlesystem.first) {
-
- ParticleSystem *psys = ob->particlesystem.first;
-
- for (; psys; psys = psys->next) {
-
- if (psys->part->type != PART_HAIR)
- continue;
-
- psys_apply_hair_lattice(scene, ob, psys);
- }
- }
-
return 1;
}
@@ -872,21 +728,13 @@ ModifierData *edit_modifier_property_get(wmOperator *op, Object *ob, int type)
static int modifier_remove_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
Object *ob = ED_object_active_context(C);
ModifierData *md = edit_modifier_property_get(op, ob, 0);
- int mode_orig = ob->mode;
if (!md || !ED_object_modifier_remove(op->reports, bmain, ob, md))
return OPERATOR_CANCELLED;
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
-
- /* if cloth/softbody was removed, particle mode could be cleared */
- if (mode_orig & OB_MODE_PARTICLE_EDIT)
- if ((ob->mode & OB_MODE_PARTICLE_EDIT) == 0)
- if (scene->basact && scene->basact->object == ob)
- WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, NULL);
return OPERATOR_FINISHED;
}
@@ -1042,47 +890,6 @@ void OBJECT_OT_modifier_apply(wmOperatorType *ot)
edit_modifier_properties(ot);
}
-/************************ convert modifier operator *********************/
-
-static int modifier_convert_exec(bContext *C, wmOperator *op)
-{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- Object *ob = ED_object_active_context(C);
- ModifierData *md = edit_modifier_property_get(op, ob, 0);
-
- if (!md || !ED_object_modifier_convert(op->reports, bmain, scene, ob, md))
- return OPERATOR_CANCELLED;
-
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
-
- return OPERATOR_FINISHED;
-}
-
-static int modifier_convert_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
-{
- if (edit_modifier_invoke_properties(C, op))
- return modifier_convert_exec(C, op);
- else
- return OPERATOR_CANCELLED;
-}
-
-void OBJECT_OT_modifier_convert(wmOperatorType *ot)
-{
- ot->name = "Convert Modifier";
- ot->description = "Convert particles to a mesh object";
- ot->idname = "OBJECT_OT_modifier_convert";
-
- ot->invoke = modifier_convert_invoke;
- ot->exec = modifier_convert_exec;
- ot->poll = edit_modifier_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- edit_modifier_properties(ot);
-}
-
/************************ copy modifier operator *********************/
static int modifier_copy_exec(bContext *C, wmOperator *op)
diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c
index 7c7e80edbf7..f1c4141ad90 100644
--- a/source/blender/editors/object/object_ops.c
+++ b/source/blender/editors/object/object_ops.c
@@ -133,7 +133,6 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_modifier_move_up);
WM_operatortype_append(OBJECT_OT_modifier_move_down);
WM_operatortype_append(OBJECT_OT_modifier_apply);
- WM_operatortype_append(OBJECT_OT_modifier_convert);
WM_operatortype_append(OBJECT_OT_modifier_copy);
WM_operatortype_append(OBJECT_OT_multires_subdivide);
WM_operatortype_append(OBJECT_OT_multires_reshape);
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index 79544f80e95..14cbcfc7fd0 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -43,7 +43,6 @@
#include "DNA_lattice_types.h"
#include "DNA_material_types.h"
#include "DNA_meta_types.h"
-#include "DNA_particle_types.h"
#include "DNA_scene_types.h"
#include "DNA_world_types.h"
#include "DNA_object_types.h"
@@ -2219,7 +2218,6 @@ static int make_local_exec(bContext *C, wmOperator *op)
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
AnimData *adt;
- ParticleSystem *psys;
Material *ma, ***matarar;
Lamp *la;
ID *id;
@@ -2287,9 +2285,6 @@ static int make_local_exec(bContext *C, wmOperator *op)
}
}
- for (psys = ob->particlesystem.first; psys; psys = psys->next)
- id_make_local(bmain, &psys->part->id, false, false);
-
adt = BKE_animdata_from_id(&ob->id);
if (adt) BKE_animdata_make_local(adt);
}
diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c
index f1b7186f8a1..7db32957b42 100644
--- a/source/blender/editors/object/object_select.c
+++ b/source/blender/editors/object/object_select.c
@@ -37,6 +37,7 @@
#include "DNA_group_types.h"
#include "DNA_material_types.h"
#include "DNA_modifier_types.h"
+#include "DNA_object_types.h"
#include "DNA_property_types.h"
#include "DNA_scene_types.h"
#include "DNA_armature_types.h"
@@ -53,7 +54,6 @@
#include "BKE_group.h"
#include "BKE_main.h"
#include "BKE_material.h"
-#include "BKE_particle.h"
#include "BKE_property.h"
#include "BKE_report.h"
#include "BKE_scene.h"
@@ -192,7 +192,6 @@ enum {
OBJECT_SELECT_LINKED_MATERIAL,
OBJECT_SELECT_LINKED_TEXTURE,
OBJECT_SELECT_LINKED_DUPGROUP,
- OBJECT_SELECT_LINKED_PARTICLE,
OBJECT_SELECT_LINKED_LIBRARY,
OBJECT_SELECT_LINKED_LIBRARY_OBDATA
};
@@ -203,7 +202,6 @@ static EnumPropertyItem prop_select_linked_types[] = {
{OBJECT_SELECT_LINKED_MATERIAL, "MATERIAL", 0, "Material", ""},
{OBJECT_SELECT_LINKED_TEXTURE, "TEXTURE", 0, "Texture", ""},
{OBJECT_SELECT_LINKED_DUPGROUP, "DUPGROUP", 0, "Dupligroup", ""},
- {OBJECT_SELECT_LINKED_PARTICLE, "PARTICLE", 0, "Particle System", ""},
{OBJECT_SELECT_LINKED_LIBRARY, "LIBRARY", 0, "Library", ""},
{OBJECT_SELECT_LINKED_LIBRARY_OBDATA, "LIBRARY_OBDATA", 0, "Library (Object Data)", ""},
{0, NULL, 0, NULL, NULL}
@@ -313,37 +311,6 @@ static bool object_select_all_by_dup_group(bContext *C, Object *ob)
return changed;
}
-static bool object_select_all_by_particle(bContext *C, Object *ob)
-{
- ParticleSystem *psys_act = psys_get_current(ob);
- bool changed = false;
-
- CTX_DATA_BEGIN (C, Base *, base, visible_bases)
- {
- if ((base->flag & SELECT) == 0) {
- /* loop through other particles*/
- ParticleSystem *psys;
-
- for (psys = base->object->particlesystem.first; psys; psys = psys->next) {
- if (psys->part == psys_act->part) {
- base->flag |= SELECT;
- changed = true;
- break;
- }
-
- if (base->flag & SELECT) {
- break;
- }
- }
-
- base->object->flag = base->flag;
- }
- }
- CTX_DATA_END;
-
- return changed;
-}
-
static bool object_select_all_by_library(bContext *C, Library *lib)
{
bool changed = false;
@@ -461,12 +428,6 @@ static int object_select_linked_exec(bContext *C, wmOperator *op)
changed = object_select_all_by_dup_group(C, ob);
}
- else if (nr == OBJECT_SELECT_LINKED_PARTICLE) {
- if (BLI_listbase_is_empty(&ob->particlesystem))
- return OPERATOR_CANCELLED;
-
- changed = object_select_all_by_particle(C, ob);
- }
else if (nr == OBJECT_SELECT_LINKED_LIBRARY) {
/* do nothing */
changed = object_select_all_by_library(C, ob->id.lib);
diff --git a/source/blender/editors/physics/CMakeLists.txt b/source/blender/editors/physics/CMakeLists.txt
index 898422dac51..e4513c14413 100644
--- a/source/blender/editors/physics/CMakeLists.txt
+++ b/source/blender/editors/physics/CMakeLists.txt
@@ -38,12 +38,8 @@ set(INC_SYS
set(SRC
dynamicpaint_ops.c
- particle_boids.c
- particle_edit.c
- particle_object.c
physics_fluid.c
physics_ops.c
- physics_pointcache.c
rigidbody_constraint.c
rigidbody_object.c
rigidbody_world.c
diff --git a/source/blender/editors/physics/particle_boids.c b/source/blender/editors/physics/particle_boids.c
deleted file mode 100644
index 14b12497c4a..00000000000
--- a/source/blender/editors/physics/particle_boids.c
+++ /dev/null
@@ -1,371 +0,0 @@
-/*
- * ***** 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) 2009 Janne Karhu.
- * All rights reserved.
- *
- * Contributor(s): Blender Foundation
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/editors/physics/particle_boids.c
- * \ingroup edphys
- */
-
-
-#include <stdlib.h>
-
-#include "MEM_guardedalloc.h"
-
-#include "DNA_particle_types.h"
-
-#include "BLI_listbase.h"
-#include "BLI_utildefines.h"
-
-#include "BKE_boids.h"
-#include "BKE_context.h"
-#include "BKE_depsgraph.h"
-#include "BKE_main.h"
-#include "BKE_particle.h"
-
-#include "RNA_access.h"
-#include "RNA_enum_types.h"
-#include "RNA_define.h"
-
-#include "WM_api.h"
-#include "WM_types.h"
-
-#include "physics_intern.h"
-
-/************************ add/del boid rule operators *********************/
-static int rule_add_exec(bContext *C, wmOperator *op)
-{
- PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_settings", &RNA_ParticleSettings);
- ParticleSettings *part = ptr.data;
- int type= RNA_enum_get(op->ptr, "type");
-
- BoidRule *rule;
- BoidState *state;
-
- if (!part || part->phystype != PART_PHYS_BOIDS)
- return OPERATOR_CANCELLED;
-
- state = boid_get_current_state(part->boids);
-
- for (rule=state->rules.first; rule; rule=rule->next)
- rule->flag &= ~BOIDRULE_CURRENT;
-
- rule = boid_new_rule(type);
- rule->flag |= BOIDRULE_CURRENT;
-
- BLI_addtail(&state->rules, rule);
-
- DAG_id_tag_update(&part->id, OB_RECALC_DATA|PSYS_RECALC_RESET);
-
- return OPERATOR_FINISHED;
-}
-
-void BOID_OT_rule_add(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Add Boid Rule";
- ot->description = "Add a boid rule to the current boid state";
- ot->idname = "BOID_OT_rule_add";
-
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = rule_add_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
-
- ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_boidrule_type_items, 0, "Type", "");
-}
-static int rule_del_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Main *bmain = CTX_data_main(C);
- PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_settings", &RNA_ParticleSettings);
- ParticleSettings *part = ptr.data;
- BoidRule *rule;
- BoidState *state;
-
- if (!part || part->phystype != PART_PHYS_BOIDS)
- return OPERATOR_CANCELLED;
-
- state = boid_get_current_state(part->boids);
-
- for (rule=state->rules.first; rule; rule=rule->next) {
- if (rule->flag & BOIDRULE_CURRENT) {
- BLI_remlink(&state->rules, rule);
- MEM_freeN(rule);
- break;
- }
- }
- rule = state->rules.first;
-
- if (rule)
- rule->flag |= BOIDRULE_CURRENT;
-
- DAG_relations_tag_update(bmain);
- DAG_id_tag_update(&part->id, OB_RECALC_DATA|PSYS_RECALC_RESET);
-
- return OPERATOR_FINISHED;
-}
-
-void BOID_OT_rule_del(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Remove Boid Rule";
- ot->idname = "BOID_OT_rule_del";
- ot->description = "Delete current boid rule";
-
- /* api callbacks */
- ot->exec = rule_del_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
-/************************ move up/down boid rule operators *********************/
-static int rule_move_up_exec(bContext *C, wmOperator *UNUSED(op))
-{
- PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_settings", &RNA_ParticleSettings);
- ParticleSettings *part = ptr.data;
- BoidRule *rule;
- BoidState *state;
-
- if (!part || part->phystype != PART_PHYS_BOIDS)
- return OPERATOR_CANCELLED;
-
- state = boid_get_current_state(part->boids);
- for (rule = state->rules.first; rule; rule=rule->next) {
- if (rule->flag & BOIDRULE_CURRENT && rule->prev) {
- BLI_remlink(&state->rules, rule);
- BLI_insertlinkbefore(&state->rules, rule->prev, rule);
-
- DAG_id_tag_update(&part->id, OB_RECALC_DATA|PSYS_RECALC_RESET);
- break;
- }
- }
-
- return OPERATOR_FINISHED;
-}
-
-void BOID_OT_rule_move_up(wmOperatorType *ot)
-{
- ot->name = "Move Up Boid Rule";
- ot->description = "Move boid rule up in the list";
- ot->idname = "BOID_OT_rule_move_up";
-
- ot->exec = rule_move_up_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
-static int rule_move_down_exec(bContext *C, wmOperator *UNUSED(op))
-{
- PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_settings", &RNA_ParticleSettings);
- ParticleSettings *part = ptr.data;
- BoidRule *rule;
- BoidState *state;
-
- if (!part || part->phystype != PART_PHYS_BOIDS)
- return OPERATOR_CANCELLED;
-
- state = boid_get_current_state(part->boids);
- for (rule = state->rules.first; rule; rule=rule->next) {
- if (rule->flag & BOIDRULE_CURRENT && rule->next) {
- BLI_remlink(&state->rules, rule);
- BLI_insertlinkafter(&state->rules, rule->next, rule);
-
- DAG_id_tag_update(&part->id, OB_RECALC_DATA|PSYS_RECALC_RESET);
- break;
- }
- }
-
- return OPERATOR_FINISHED;
-}
-
-void BOID_OT_rule_move_down(wmOperatorType *ot)
-{
- ot->name = "Move Down Boid Rule";
- ot->description = "Move boid rule down in the list";
- ot->idname = "BOID_OT_rule_move_down";
-
- ot->exec = rule_move_down_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
-
-/************************ add/del boid state operators *********************/
-static int state_add_exec(bContext *C, wmOperator *UNUSED(op))
-{
- PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_settings", &RNA_ParticleSettings);
- ParticleSettings *part = ptr.data;
- BoidState *state;
-
- if (!part || part->phystype != PART_PHYS_BOIDS)
- return OPERATOR_CANCELLED;
-
- for (state=part->boids->states.first; state; state=state->next)
- state->flag &= ~BOIDSTATE_CURRENT;
-
- state = boid_new_state(part->boids);
- state->flag |= BOIDSTATE_CURRENT;
-
- BLI_addtail(&part->boids->states, state);
-
- return OPERATOR_FINISHED;
-}
-
-void BOID_OT_state_add(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Add Boid State";
- ot->description = "Add a boid state to the particle system";
- ot->idname = "BOID_OT_state_add";
-
- /* api callbacks */
- ot->exec = state_add_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-static int state_del_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Main *bmain = CTX_data_main(C);
- PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_settings", &RNA_ParticleSettings);
- ParticleSettings *part = ptr.data;
- BoidState *state;
-
- if (!part || part->phystype != PART_PHYS_BOIDS)
- return OPERATOR_CANCELLED;
-
- for (state=part->boids->states.first; state; state=state->next) {
- if (state->flag & BOIDSTATE_CURRENT) {
- BLI_remlink(&part->boids->states, state);
- MEM_freeN(state);
- break;
- }
- }
-
- /* there must be at least one state */
- if (!part->boids->states.first) {
- state = boid_new_state(part->boids);
- BLI_addtail(&part->boids->states, state);
- }
- else
- state = part->boids->states.first;
-
- state->flag |= BOIDSTATE_CURRENT;
-
- DAG_relations_tag_update(bmain);
- DAG_id_tag_update(&part->id, OB_RECALC_DATA|PSYS_RECALC_RESET);
-
- return OPERATOR_FINISHED;
-}
-
-void BOID_OT_state_del(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Remove Boid State";
- ot->idname = "BOID_OT_state_del";
- ot->description = "Delete current boid state";
-
- /* api callbacks */
- ot->exec = state_del_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
-/************************ move up/down boid state operators *********************/
-static int state_move_up_exec(bContext *C, wmOperator *UNUSED(op))
-{
- PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_settings", &RNA_ParticleSettings);
- ParticleSettings *part = ptr.data;
- BoidSettings *boids;
- BoidState *state;
-
- if (!part || part->phystype != PART_PHYS_BOIDS)
- return OPERATOR_CANCELLED;
-
- boids = part->boids;
-
- for (state = boids->states.first; state; state=state->next) {
- if (state->flag & BOIDSTATE_CURRENT && state->prev) {
- BLI_remlink(&boids->states, state);
- BLI_insertlinkbefore(&boids->states, state->prev, state);
- break;
- }
- }
-
- return OPERATOR_FINISHED;
-}
-
-void BOID_OT_state_move_up(wmOperatorType *ot)
-{
- ot->name = "Move Up Boid State";
- ot->description = "Move boid state up in the list";
- ot->idname = "BOID_OT_state_move_up";
-
- ot->exec = state_move_up_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
-static int state_move_down_exec(bContext *C, wmOperator *UNUSED(op))
-{
- PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_settings", &RNA_ParticleSettings);
- ParticleSettings *part = ptr.data;
- BoidSettings *boids;
- BoidState *state;
-
- if (!part || part->phystype != PART_PHYS_BOIDS)
- return OPERATOR_CANCELLED;
-
- boids = part->boids;
-
- for (state = boids->states.first; state; state=state->next) {
- if (state->flag & BOIDSTATE_CURRENT && state->next) {
- BLI_remlink(&boids->states, state);
- BLI_insertlinkafter(&boids->states, state->next, state);
- DAG_id_tag_update(&part->id, OB_RECALC_DATA|PSYS_RECALC_RESET);
- break;
- }
- }
-
- return OPERATOR_FINISHED;
-}
-
-void BOID_OT_state_move_down(wmOperatorType *ot)
-{
- ot->name = "Move Down Boid State";
- ot->description = "Move boid state down in the list";
- ot->idname = "BOID_OT_state_move_down";
-
- ot->exec = state_move_down_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c
deleted file mode 100644
index e22a145b3a6..00000000000
--- a/source/blender/editors/physics/particle_edit.c
+++ /dev/null
@@ -1,4923 +0,0 @@
-/*
- * ***** 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) 2007 by Janne Karhu.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/editors/physics/particle_edit.c
- * \ingroup edphys
- */
-
-
-#include <stdlib.h>
-#include <math.h>
-#include <string.h>
-#include <assert.h>
-
-#include "MEM_guardedalloc.h"
-
-#include "DNA_scene_types.h"
-#include "DNA_mesh_types.h"
-#include "DNA_meshdata_types.h"
-#include "DNA_view3d_types.h"
-#include "DNA_screen_types.h"
-#include "DNA_space_types.h"
-
-#include "BLI_math.h"
-#include "BLI_lasso.h"
-#include "BLI_listbase.h"
-#include "BLI_string.h"
-#include "BLI_kdtree.h"
-#include "BLI_rand.h"
-#include "BLI_utildefines.h"
-
-#include "BKE_context.h"
-#include "BKE_depsgraph.h"
-#include "BKE_DerivedMesh.h"
-#include "BKE_global.h"
-#include "BKE_object.h"
-#include "BKE_mesh.h"
-#include "BKE_modifier.h"
-#include "BKE_particle.h"
-#include "BKE_report.h"
-#include "BKE_bvhutils.h"
-#include "BKE_pointcache.h"
-
-#include "BIF_gl.h"
-#include "BIF_glutil.h"
-
-#include "ED_object.h"
-#include "ED_physics.h"
-#include "ED_mesh.h"
-#include "ED_particle.h"
-#include "ED_view3d.h"
-
-#include "UI_resources.h"
-
-#include "WM_api.h"
-#include "WM_types.h"
-
-#include "RNA_access.h"
-#include "RNA_define.h"
-
-#include "physics_intern.h"
-
-void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache, ParticleSystem *psys);
-void PTCacheUndo_clear(PTCacheEdit *edit);
-void recalc_lengths(PTCacheEdit *edit);
-void recalc_emitter_field(Object *ob, ParticleSystem *psys);
-void update_world_cos(Object *ob, PTCacheEdit *edit);
-
-#define KEY_K PTCacheEditKey *key; int k
-#define POINT_P PTCacheEditPoint *point; int p
-#define LOOP_POINTS for (p=0, point=edit->points; p<edit->totpoint; p++, point++)
-#define LOOP_VISIBLE_POINTS for (p=0, point=edit->points; p<edit->totpoint; p++, point++) if (!(point->flag & PEP_HIDE))
-#define LOOP_SELECTED_POINTS for (p=0, point=edit->points; p<edit->totpoint; p++, point++) if (point_is_selected(point))
-#define LOOP_UNSELECTED_POINTS for (p=0, point=edit->points; p<edit->totpoint; p++, point++) if (!point_is_selected(point))
-#define LOOP_EDITED_POINTS for (p=0, point=edit->points; p<edit->totpoint; p++, point++) if (point->flag & PEP_EDIT_RECALC)
-#define LOOP_TAGGED_POINTS for (p=0, point=edit->points; p<edit->totpoint; p++, point++) if (point->flag & PEP_TAG)
-#define LOOP_KEYS for (k=0, key=point->keys; k<point->totkey; k++, key++)
-#define LOOP_VISIBLE_KEYS for (k=0, key=point->keys; k<point->totkey; k++, key++) if (!(key->flag & PEK_HIDE))
-#define LOOP_SELECTED_KEYS for (k=0, key=point->keys; k<point->totkey; k++, key++) if ((key->flag & PEK_SELECT) && !(key->flag & PEK_HIDE))
-#define LOOP_TAGGED_KEYS for (k=0, key=point->keys; k<point->totkey; k++, key++) if (key->flag & PEK_TAG)
-
-#define KEY_WCO ((key->flag & PEK_USE_WCO) ? key->world_co : key->co)
-
-/**************************** utilities *******************************/
-
-int PE_poll(bContext *C)
-{
- Scene *scene= CTX_data_scene(C);
- Object *ob= CTX_data_active_object(C);
-
- if (!scene || !ob || !(ob->mode & OB_MODE_PARTICLE_EDIT))
- return 0;
-
- return (PE_get_current(scene, ob) != NULL);
-}
-
-int PE_hair_poll(bContext *C)
-{
- Scene *scene= CTX_data_scene(C);
- Object *ob= CTX_data_active_object(C);
- PTCacheEdit *edit;
-
- if (!scene || !ob || !(ob->mode & OB_MODE_PARTICLE_EDIT))
- return 0;
-
- edit= PE_get_current(scene, ob);
-
- return (edit && edit->psys);
-}
-
-int PE_poll_view3d(bContext *C)
-{
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
-
- return (PE_poll(C) &&
- (sa && sa->spacetype == SPACE_VIEW3D) &&
- (ar && ar->regiontype == RGN_TYPE_WINDOW));
-}
-
-void PE_free_ptcache_edit(PTCacheEdit *edit)
-{
- POINT_P;
-
- if (edit==0) return;
-
- PTCacheUndo_clear(edit);
-
- if (edit->points) {
- LOOP_POINTS {
- if (point->keys)
- MEM_freeN(point->keys);
- }
-
- MEM_freeN(edit->points);
- }
-
- if (edit->mirror_cache)
- MEM_freeN(edit->mirror_cache);
-
- if (edit->emitter_cosnos) {
- MEM_freeN(edit->emitter_cosnos);
- edit->emitter_cosnos= 0;
- }
-
- if (edit->emitter_field) {
- BLI_kdtree_free(edit->emitter_field);
- edit->emitter_field= 0;
- }
-
- psys_free_path_cache(edit->psys, edit);
-
- MEM_freeN(edit);
-}
-
-/************************************************/
-/* Edit Mode Helpers */
-/************************************************/
-
-int PE_start_edit(PTCacheEdit *edit)
-{
- if (edit) {
- edit->edited = 1;
- if (edit->psys)
- edit->psys->flag |= PSYS_EDITED;
- return 1;
- }
-
- return 0;
-}
-
-ParticleEditSettings *PE_settings(Scene *scene)
-{
- return scene->toolsettings ? &scene->toolsettings->particle : NULL;
-}
-
-static float pe_brush_size_get(const Scene *UNUSED(scene), ParticleBrushData *brush)
-{
- // here we can enable unified brush size, needs more work...
- // UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
- // float size = (ups->flag & UNIFIED_PAINT_SIZE) ? ups->size : brush->size;
-
- return brush->size * U.pixelsize;
-}
-
-
-/* always gets at least the first particlesystem even if PSYS_CURRENT flag is not set
- *
- * note: this function runs on poll, therefor it can runs many times a second
- * keep it fast! */
-static PTCacheEdit *pe_get_current(Scene *scene, Object *ob, int create)
-{
- ParticleEditSettings *pset= PE_settings(scene);
- PTCacheEdit *edit = NULL;
- ListBase pidlist;
- PTCacheID *pid;
-
- if (pset==NULL || ob==NULL)
- return NULL;
-
- pset->scene = scene;
- pset->object = ob;
-
- BKE_ptcache_ids_from_object(&pidlist, ob, NULL, 0);
-
- /* in the case of only one editable thing, set pset->edittype accordingly */
- if (BLI_listbase_is_single(&pidlist)) {
- pid = pidlist.first;
- switch (pid->type) {
- case PTCACHE_TYPE_PARTICLES:
- pset->edittype = PE_TYPE_PARTICLES;
- break;
- case PTCACHE_TYPE_SOFTBODY:
- pset->edittype = PE_TYPE_SOFTBODY;
- break;
- case PTCACHE_TYPE_CLOTH:
- pset->edittype = PE_TYPE_CLOTH;
- break;
- }
- }
-
- for (pid=pidlist.first; pid; pid=pid->next) {
- if (pset->edittype == PE_TYPE_PARTICLES && pid->type == PTCACHE_TYPE_PARTICLES) {
- ParticleSystem *psys = pid->calldata;
-
- if (psys->flag & PSYS_CURRENT) {
- if (psys->part && psys->part->type == PART_HAIR) {
- if (psys->flag & PSYS_HAIR_DYNAMICS && psys->pointcache->flag & PTCACHE_BAKED) {
- if (create && !psys->pointcache->edit)
- PE_create_particle_edit(scene, ob, pid->cache, NULL);
- edit = pid->cache->edit;
- }
- else {
- if (create && !psys->edit && psys->flag & PSYS_HAIR_DONE)
- PE_create_particle_edit(scene, ob, NULL, psys);
- edit = psys->edit;
- }
- }
- else {
- if (create && pid->cache->flag & PTCACHE_BAKED && !pid->cache->edit)
- PE_create_particle_edit(scene, ob, pid->cache, psys);
- edit = pid->cache->edit;
- }
-
- break;
- }
- }
- else if (pset->edittype == PE_TYPE_SOFTBODY && pid->type == PTCACHE_TYPE_SOFTBODY) {
- if (create && pid->cache->flag & PTCACHE_BAKED && !pid->cache->edit) {
- pset->flag |= PE_FADE_TIME;
- // NICE TO HAVE but doesn't work: pset->brushtype = PE_BRUSH_COMB;
- PE_create_particle_edit(scene, ob, pid->cache, NULL);
- }
- edit = pid->cache->edit;
- break;
- }
- else if (pset->edittype == PE_TYPE_CLOTH && pid->type == PTCACHE_TYPE_CLOTH) {
- if (create && pid->cache->flag & PTCACHE_BAKED && !pid->cache->edit) {
- pset->flag |= PE_FADE_TIME;
- // NICE TO HAVE but doesn't work: pset->brushtype = PE_BRUSH_COMB;
- PE_create_particle_edit(scene, ob, pid->cache, NULL);
- }
- edit = pid->cache->edit;
- break;
- }
- }
-
- if (edit)
- edit->pid = *pid;
-
- BLI_freelistN(&pidlist);
-
- return edit;
-}
-
-PTCacheEdit *PE_get_current(Scene *scene, Object *ob)
-{
- return pe_get_current(scene, ob, 0);
-}
-
-PTCacheEdit *PE_create_current(Scene *scene, Object *ob)
-{
- return pe_get_current(scene, ob, 1);
-}
-
-void PE_current_changed(Scene *scene, Object *ob)
-{
- if (ob->mode == OB_MODE_PARTICLE_EDIT)
- PE_create_current(scene, ob);
-}
-
-void PE_hide_keys_time(Scene *scene, PTCacheEdit *edit, float cfra)
-{
- ParticleEditSettings *pset=PE_settings(scene);
- POINT_P; KEY_K;
-
-
- if (pset->flag & PE_FADE_TIME && pset->selectmode==SCE_SELECT_POINT) {
- LOOP_POINTS {
- LOOP_KEYS {
- if (fabsf(cfra - *key->time) < pset->fade_frames)
- key->flag &= ~PEK_HIDE;
- else {
- key->flag |= PEK_HIDE;
- //key->flag &= ~PEK_SELECT;
- }
- }
- }
- }
- else {
- LOOP_POINTS {
- LOOP_KEYS {
- key->flag &= ~PEK_HIDE;
- }
- }
- }
-}
-
-static int pe_x_mirror(Object *ob)
-{
- if (ob->type == OB_MESH)
- return (((Mesh *)ob->data)->editflag & ME_EDIT_MIRROR_X);
-
- return 0;
-}
-
-/****************** common struct passed to callbacks ******************/
-
-typedef struct PEData {
- ViewContext vc;
- bglMats mats;
-
- Scene *scene;
- Object *ob;
- DerivedMesh *dm;
- PTCacheEdit *edit;
- BVHTreeFromMesh shape_bvh;
-
- const int *mval;
- rcti *rect;
- float rad;
- float dist;
- float dval;
- int select;
-
- float *dvec;
- float combfac;
- float pufffac;
- float cutfac;
- float smoothfac;
- float weightfac;
- float growfac;
- int totrekey;
-
- int invert;
- int tot;
- float vec[3];
-
- int select_action;
- int select_toggle_action;
-} PEData;
-
-static void PE_set_data(bContext *C, PEData *data)
-{
- memset(data, 0, sizeof(*data));
-
- data->scene= CTX_data_scene(C);
- data->ob= CTX_data_active_object(C);
- data->edit= PE_get_current(data->scene, data->ob);
-}
-
-static void PE_set_view3d_data(bContext *C, PEData *data)
-{
- PE_set_data(C, data);
-
- view3d_set_viewcontext(C, &data->vc);
- /* note, the object argument means the modelview matrix does not account for the objects matrix, use viewmat rather than (obmat * viewmat) */
- view3d_get_transformation(data->vc.ar, data->vc.rv3d, NULL, &data->mats);
-
- if (V3D_IS_ZBUF(data->vc.v3d)) {
- if (data->vc.v3d->flag & V3D_INVALID_BACKBUF) {
- /* needed or else the draw matrix can be incorrect */
- view3d_operator_needs_opengl(C);
-
- ED_view3d_backbuf_validate(&data->vc);
- /* we may need to force an update here by setting the rv3d as dirty
- * for now it seems ok, but take care!:
- * rv3d->depths->dirty = 1; */
- ED_view3d_depth_update(data->vc.ar);
- }
- }
-}
-
-static bool PE_create_shape_tree(PEData *data, Object *shapeob)
-{
- DerivedMesh *dm = shapeob->derivedFinal;
-
- memset(&data->shape_bvh, 0, sizeof(data->shape_bvh));
-
- if (!dm) {
- return false;
- }
-
- DM_ensure_looptri(dm);
- return (bvhtree_from_mesh_looptri(&data->shape_bvh, dm, 0.0f, 4, 8) != NULL);
-}
-
-static void PE_free_shape_tree(PEData *data)
-{
- free_bvhtree_from_mesh(&data->shape_bvh);
-}
-
-/*************************** selection utilities *******************************/
-
-static bool key_test_depth(PEData *data, const float co[3], const int screen_co[2])
-{
- View3D *v3d= data->vc.v3d;
- ViewDepths *vd = data->vc.rv3d->depths;
- double ux, uy, uz;
- float depth;
-
- /* nothing to do */
- if (!V3D_IS_ZBUF(v3d))
- return true;
-
- /* used to calculate here but all callers have the screen_co already, so pass as arg */
-#if 0
- if (ED_view3d_project_int_global(data->vc.ar, co, screen_co,
- V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR) != V3D_PROJ_RET_OK)
- {
- return 0;
- }
-#endif
-
- gluProject(co[0], co[1], co[2], data->mats.modelview, data->mats.projection,
- (GLint *)data->mats.viewport, &ux, &uy, &uz);
-
- /* check if screen_co is within bounds because brush_cut uses out of screen coords */
- if (screen_co[0] >= 0 && screen_co[0] < vd->w && screen_co[1] >= 0 && screen_co[1] < vd->h) {
- BLI_assert(vd && vd->depths);
- /* we know its not clipped */
- depth = vd->depths[screen_co[1] * vd->w + screen_co[0]];
- }
- else
- return 0;
-
- if ((float)uz - 0.00001f > depth)
- return 0;
- else
- return 1;
-}
-
-static bool key_inside_circle(PEData *data, float rad, const float co[3], float *distance)
-{
- float dx, dy, dist;
- int screen_co[2];
-
- /* TODO, should this check V3D_PROJ_TEST_CLIP_BB too? */
- if (ED_view3d_project_int_global(data->vc.ar, co, screen_co, V3D_PROJ_TEST_CLIP_WIN) != V3D_PROJ_RET_OK) {
- return 0;
- }
-
- dx= data->mval[0] - screen_co[0];
- dy= data->mval[1] - screen_co[1];
- dist = sqrtf(dx * dx + dy * dy);
-
- if (dist > rad)
- return 0;
-
- if (key_test_depth(data, co, screen_co)) {
- if (distance)
- *distance=dist;
-
- return 1;
- }
-
- return 0;
-}
-
-static bool key_inside_rect(PEData *data, const float co[3])
-{
- int screen_co[2];
-
- if (ED_view3d_project_int_global(data->vc.ar, co, screen_co, V3D_PROJ_TEST_CLIP_WIN) != V3D_PROJ_RET_OK) {
- return 0;
- }
-
- if (screen_co[0] > data->rect->xmin && screen_co[0] < data->rect->xmax &&
- screen_co[1] > data->rect->ymin && screen_co[1] < data->rect->ymax)
- {
- return key_test_depth(data, co, screen_co);
- }
-
- return 0;
-}
-
-static bool key_inside_test(PEData *data, const float co[3])
-{
- if (data->mval)
- return key_inside_circle(data, data->rad, co, NULL);
- else
- return key_inside_rect(data, co);
-}
-
-static bool point_is_selected(PTCacheEditPoint *point)
-{
- KEY_K;
-
- if (point->flag & PEP_HIDE)
- return 0;
-
- LOOP_SELECTED_KEYS {
- return 1;
- }
-
- return 0;
-}
-
-/*************************** iterators *******************************/
-
-typedef void (*ForPointFunc)(PEData *data, int point_index);
-typedef void (*ForKeyFunc)(PEData *data, int point_index, int key_index);
-typedef void (*ForKeyMatFunc)(PEData *data, float mat[4][4], float imat[4][4], int point_index, int key_index, PTCacheEditKey *key);
-
-static void for_mouse_hit_keys(PEData *data, ForKeyFunc func, int nearest)
-{
- ParticleEditSettings *pset= PE_settings(data->scene);
- PTCacheEdit *edit= data->edit;
- POINT_P; KEY_K;
- int nearest_point, nearest_key;
- float dist= data->rad;
-
- /* in path select mode we have no keys */
- if (pset->selectmode==SCE_SELECT_PATH)
- return;
-
- nearest_point= -1;
- nearest_key= -1;
-
- LOOP_VISIBLE_POINTS {
- if (pset->selectmode == SCE_SELECT_END) {
- if (point->totkey) {
- /* only do end keys */
- key= point->keys + point->totkey-1;
-
- if (nearest) {
- if (key_inside_circle(data, dist, KEY_WCO, &dist)) {
- nearest_point= p;
- nearest_key= point->totkey-1;
- }
- }
- else if (key_inside_test(data, KEY_WCO))
- func(data, p, point->totkey-1);
- }
- }
- else {
- /* do all keys */
- LOOP_VISIBLE_KEYS {
- if (nearest) {
- if (key_inside_circle(data, dist, KEY_WCO, &dist)) {
- nearest_point= p;
- nearest_key= k;
- }
- }
- else if (key_inside_test(data, KEY_WCO))
- func(data, p, k);
- }
- }
- }
-
- /* do nearest only */
- if (nearest && nearest_point > -1)
- func(data, nearest_point, nearest_key);
-}
-
-static void foreach_mouse_hit_point(PEData *data, ForPointFunc func, int selected)
-{
- ParticleEditSettings *pset= PE_settings(data->scene);
- PTCacheEdit *edit= data->edit;
- POINT_P; KEY_K;
-
- /* all is selected in path mode */
- if (pset->selectmode==SCE_SELECT_PATH)
- selected=0;
-
- LOOP_VISIBLE_POINTS {
- if (pset->selectmode==SCE_SELECT_END) {
- if (point->totkey) {
- /* only do end keys */
- key= point->keys + point->totkey - 1;
-
- if (selected==0 || key->flag & PEK_SELECT)
- if (key_inside_circle(data, data->rad, KEY_WCO, &data->dist))
- func(data, p);
- }
- }
- else {
- /* do all keys */
- LOOP_VISIBLE_KEYS {
- if (selected==0 || key->flag & PEK_SELECT) {
- if (key_inside_circle(data, data->rad, KEY_WCO, &data->dist)) {
- func(data, p);
- break;
- }
- }
- }
- }
- }
-}
-
-static void foreach_mouse_hit_key(PEData *data, ForKeyMatFunc func, int selected)
-{
- PTCacheEdit *edit = data->edit;
- ParticleSystem *psys = edit->psys;
- ParticleSystemModifierData *psmd = NULL;
- ParticleEditSettings *pset= PE_settings(data->scene);
- POINT_P; KEY_K;
- float mat[4][4], imat[4][4];
-
- unit_m4(mat);
- unit_m4(imat);
-
- if (edit->psys)
- psmd= psys_get_modifier(data->ob, edit->psys);
-
- /* all is selected in path mode */
- if (pset->selectmode==SCE_SELECT_PATH)
- selected= 0;
-
- LOOP_VISIBLE_POINTS {
- if (pset->selectmode==SCE_SELECT_END) {
- if (point->totkey) {
- /* only do end keys */
- key= point->keys + point->totkey-1;
-
- if (selected==0 || key->flag & PEK_SELECT) {
- if (key_inside_circle(data, data->rad, KEY_WCO, &data->dist)) {
- if (edit->psys && !(edit->psys->flag & PSYS_GLOBAL_HAIR)) {
- psys_mat_hair_to_global(data->ob, psmd->dm_final, psys->part->from, psys->particles + p, mat);
- invert_m4_m4(imat, mat);
- }
-
- func(data, mat, imat, p, point->totkey-1, key);
- }
- }
- }
- }
- else {
- /* do all keys */
- LOOP_VISIBLE_KEYS {
- if (selected==0 || key->flag & PEK_SELECT) {
- if (key_inside_circle(data, data->rad, KEY_WCO, &data->dist)) {
- if (edit->psys && !(edit->psys->flag & PSYS_GLOBAL_HAIR)) {
- psys_mat_hair_to_global(data->ob, psmd->dm_final, psys->part->from, psys->particles + p, mat);
- invert_m4_m4(imat, mat);
- }
-
- func(data, mat, imat, p, k, key);
- }
- }
- }
- }
- }
-}
-
-static void foreach_selected_point(PEData *data, ForPointFunc func)
-{
- PTCacheEdit *edit = data->edit;
- POINT_P;
-
- LOOP_SELECTED_POINTS {
- func(data, p);
- }
-}
-
-static void foreach_selected_key(PEData *data, ForKeyFunc func)
-{
- PTCacheEdit *edit = data->edit;
- POINT_P; KEY_K;
-
- LOOP_VISIBLE_POINTS {
- LOOP_SELECTED_KEYS {
- func(data, p, k);
- }
- }
-}
-
-static void foreach_point(PEData *data, ForPointFunc func)
-{
- PTCacheEdit *edit = data->edit;
- POINT_P;
-
- LOOP_POINTS {
- func(data, p);
- }
-}
-
-static int count_selected_keys(Scene *scene, PTCacheEdit *edit)
-{
- ParticleEditSettings *pset= PE_settings(scene);
- POINT_P; KEY_K;
- int sel= 0;
-
- LOOP_VISIBLE_POINTS {
- if (pset->selectmode==SCE_SELECT_POINT) {
- LOOP_SELECTED_KEYS {
- sel++;
- }
- }
- else if (pset->selectmode==SCE_SELECT_END) {
- if (point->totkey) {
- key = point->keys + point->totkey - 1;
- if (key->flag & PEK_SELECT)
- sel++;
- }
- }
- }
-
- return sel;
-}
-
-/************************************************/
-/* Particle Edit Mirroring */
-/************************************************/
-
-static void PE_update_mirror_cache(Object *ob, ParticleSystem *psys)
-{
- PTCacheEdit *edit;
- ParticleSystemModifierData *psmd;
- KDTree *tree;
- KDTreeNearest nearest;
- HairKey *key;
- PARTICLE_P;
- float mat[4][4], co[3];
- int index, totpart;
-
- edit= psys->edit;
- psmd= psys_get_modifier(ob, psys);
- totpart= psys->totpart;
-
- if (!psmd->dm_final)
- return;
-
- tree= BLI_kdtree_new(totpart);
-
- /* insert particles into kd tree */
- LOOP_PARTICLES {
- key = pa->hair;
- psys_mat_hair_to_orco(ob, psmd->dm_final, psys->part->from, pa, mat);
- copy_v3_v3(co, key->co);
- mul_m4_v3(mat, co);
- BLI_kdtree_insert(tree, p, co);
- }
-
- BLI_kdtree_balance(tree);
-
- /* lookup particles and set in mirror cache */
- if (!edit->mirror_cache)
- edit->mirror_cache= MEM_callocN(sizeof(int)*totpart, "PE mirror cache");
-
- LOOP_PARTICLES {
- key = pa->hair;
- psys_mat_hair_to_orco(ob, psmd->dm_final, psys->part->from, pa, mat);
- copy_v3_v3(co, key->co);
- mul_m4_v3(mat, co);
- co[0] = -co[0];
-
- index= BLI_kdtree_find_nearest(tree, co, &nearest);
-
- /* this needs a custom threshold still, duplicated for editmode mirror */
- if (index != -1 && index != p && (nearest.dist <= 0.0002f))
- edit->mirror_cache[p] = index;
- else
- edit->mirror_cache[p] = -1;
- }
-
- /* make sure mirrors are in two directions */
- LOOP_PARTICLES {
- if (edit->mirror_cache[p]) {
- index= edit->mirror_cache[p];
- if (edit->mirror_cache[index] != p)
- edit->mirror_cache[p] = -1;
- }
- }
-
- BLI_kdtree_free(tree);
-}
-
-static void PE_mirror_particle(Object *ob, DerivedMesh *dm, ParticleSystem *psys, ParticleData *pa, ParticleData *mpa)
-{
- HairKey *hkey, *mhkey;
- PTCacheEditPoint *point, *mpoint;
- PTCacheEditKey *key, *mkey;
- PTCacheEdit *edit;
- float mat[4][4], mmat[4][4], immat[4][4];
- int i, mi, k;
-
- edit= psys->edit;
- i= pa - psys->particles;
-
- /* find mirrored particle if needed */
- if (!mpa) {
- if (!edit->mirror_cache)
- PE_update_mirror_cache(ob, psys);
-
- if (!edit->mirror_cache)
- return; /* something went wrong! */
-
- mi= edit->mirror_cache[i];
- if (mi == -1)
- return;
- mpa= psys->particles + mi;
- }
- else
- mi= mpa - psys->particles;
-
- point = edit->points + i;
- mpoint = edit->points + mi;
-
- /* make sure they have the same amount of keys */
- if (pa->totkey != mpa->totkey) {
- if (mpa->hair) MEM_freeN(mpa->hair);
- if (mpoint->keys) MEM_freeN(mpoint->keys);
-
- mpa->hair= MEM_dupallocN(pa->hair);
- mpa->totkey= pa->totkey;
- mpoint->keys= MEM_dupallocN(point->keys);
- mpoint->totkey= point->totkey;
-
- mhkey= mpa->hair;
- mkey= mpoint->keys;
- for (k=0; k<mpa->totkey; k++, mkey++, mhkey++) {
- mkey->co= mhkey->co;
- mkey->time= &mhkey->time;
- mkey->flag &= ~PEK_SELECT;
- }
- }
-
- /* mirror positions and tags */
- psys_mat_hair_to_orco(ob, dm, psys->part->from, pa, mat);
- psys_mat_hair_to_orco(ob, dm, psys->part->from, mpa, mmat);
- invert_m4_m4(immat, mmat);
-
- hkey=pa->hair;
- mhkey=mpa->hair;
- key= point->keys;
- mkey= mpoint->keys;
- for (k=0; k<pa->totkey; k++, hkey++, mhkey++, key++, mkey++) {
- copy_v3_v3(mhkey->co, hkey->co);
- mul_m4_v3(mat, mhkey->co);
- mhkey->co[0] = -mhkey->co[0];
- mul_m4_v3(immat, mhkey->co);
-
- if (key->flag & PEK_TAG)
- mkey->flag |= PEK_TAG;
-
- mkey->length = key->length;
- }
-
- if (point->flag & PEP_TAG)
- mpoint->flag |= PEP_TAG;
- if (point->flag & PEP_EDIT_RECALC)
- mpoint->flag |= PEP_EDIT_RECALC;
-}
-
-static void PE_apply_mirror(Object *ob, ParticleSystem *psys)
-{
- PTCacheEdit *edit;
- ParticleSystemModifierData *psmd;
- POINT_P;
-
- if (!psys)
- return;
-
- edit= psys->edit;
- psmd= psys_get_modifier(ob, psys);
-
- if (!psmd->dm_final)
- return;
-
- if (!edit->mirror_cache)
- PE_update_mirror_cache(ob, psys);
-
- if (!edit->mirror_cache)
- return; /* something went wrong */
-
- /* we delay settings the PARS_EDIT_RECALC for mirrored particles
- * to avoid doing mirror twice */
- LOOP_POINTS {
- if (point->flag & PEP_EDIT_RECALC) {
- PE_mirror_particle(ob, psmd->dm_final, psys, psys->particles + p, NULL);
-
- if (edit->mirror_cache[p] != -1)
- edit->points[edit->mirror_cache[p]].flag &= ~PEP_EDIT_RECALC;
- }
- }
-
- LOOP_POINTS {
- if (point->flag & PEP_EDIT_RECALC)
- if (edit->mirror_cache[p] != -1)
- edit->points[edit->mirror_cache[p]].flag |= PEP_EDIT_RECALC;
- }
-}
-
-/************************************************/
-/* Edit Calculation */
-/************************************************/
-/* tries to stop edited particles from going through the emitter's surface */
-static void pe_deflect_emitter(Scene *scene, Object *ob, PTCacheEdit *edit)
-{
- ParticleEditSettings *pset= PE_settings(scene);
- ParticleSystem *psys;
- ParticleSystemModifierData *psmd;
- POINT_P; KEY_K;
- int index;
- float *vec, *nor, dvec[3], dot, dist_1st=0.0f;
- float hairimat[4][4], hairmat[4][4];
- const float dist = ED_view3d_select_dist_px() * 0.01f;
-
- if (edit==NULL || edit->psys==NULL || (pset->flag & PE_DEFLECT_EMITTER)==0 || (edit->psys->flag & PSYS_GLOBAL_HAIR))
- return;
-
- psys = edit->psys;
- psmd = psys_get_modifier(ob, psys);
-
- if (!psmd->dm_final)
- return;
-
- LOOP_EDITED_POINTS {
- psys_mat_hair_to_object(ob, psmd->dm_final, psys->part->from, psys->particles + p, hairmat);
-
- LOOP_KEYS {
- mul_m4_v3(hairmat, key->co);
- }
-
- LOOP_KEYS {
- if (k==0) {
- dist_1st = len_v3v3((key+1)->co, key->co);
- dist_1st *= dist * pset->emitterdist;
- }
- else {
- index= BLI_kdtree_find_nearest(edit->emitter_field, key->co, NULL);
-
- vec=edit->emitter_cosnos +index*6;
- nor=vec+3;
-
- sub_v3_v3v3(dvec, key->co, vec);
-
- dot=dot_v3v3(dvec, nor);
- copy_v3_v3(dvec, nor);
-
- if (dot>0.0f) {
- if (dot<dist_1st) {
- normalize_v3(dvec);
- mul_v3_fl(dvec, dist_1st-dot);
- add_v3_v3(key->co, dvec);
- }
- }
- else {
- normalize_v3(dvec);
- mul_v3_fl(dvec, dist_1st-dot);
- add_v3_v3(key->co, dvec);
- }
- if (k==1)
- dist_1st*=1.3333f;
- }
- }
-
- invert_m4_m4(hairimat, hairmat);
-
- LOOP_KEYS {
- mul_m4_v3(hairimat, key->co);
- }
- }
-}
-/* force set distances between neighboring keys */
-static void PE_apply_lengths(Scene *scene, PTCacheEdit *edit)
-{
-
- ParticleEditSettings *pset=PE_settings(scene);
- POINT_P; KEY_K;
- float dv1[3];
-
- if (edit==0 || (pset->flag & PE_KEEP_LENGTHS)==0)
- return;
-
- if (edit->psys && edit->psys->flag & PSYS_GLOBAL_HAIR)
- return;
-
- LOOP_EDITED_POINTS {
- LOOP_KEYS {
- if (k) {
- sub_v3_v3v3(dv1, key->co, (key - 1)->co);
- normalize_v3(dv1);
- mul_v3_fl(dv1, (key - 1)->length);
- add_v3_v3v3(key->co, (key - 1)->co, dv1);
- }
- }
- }
-}
-/* try to find a nice solution to keep distances between neighboring keys */
-static void pe_iterate_lengths(Scene *scene, PTCacheEdit *edit)
-{
- ParticleEditSettings *pset=PE_settings(scene);
- POINT_P;
- PTCacheEditKey *key;
- int j, k;
- float tlen;
- float dv0[3] = {0.0f, 0.0f, 0.0f};
- float dv1[3] = {0.0f, 0.0f, 0.0f};
- float dv2[3] = {0.0f, 0.0f, 0.0f};
-
- if (edit==0 || (pset->flag & PE_KEEP_LENGTHS)==0)
- return;
-
- if (edit->psys && edit->psys->flag & PSYS_GLOBAL_HAIR)
- return;
-
- LOOP_EDITED_POINTS {
- for (j=1; j<point->totkey; j++) {
- float mul= 1.0f / (float)point->totkey;
-
- if (pset->flag & PE_LOCK_FIRST) {
- key= point->keys + 1;
- k= 1;
- dv1[0] = dv1[1] = dv1[2] = 0.0;
- }
- else {
- key= point->keys;
- k= 0;
- dv0[0] = dv0[1] = dv0[2] = 0.0;
- }
-
- for (; k<point->totkey; k++, key++) {
- if (k) {
- sub_v3_v3v3(dv0, (key - 1)->co, key->co);
- tlen= normalize_v3(dv0);
- mul_v3_fl(dv0, (mul * (tlen - (key - 1)->length)));
- }
-
- if (k < point->totkey - 1) {
- sub_v3_v3v3(dv2, (key + 1)->co, key->co);
- tlen= normalize_v3(dv2);
- mul_v3_fl(dv2, mul * (tlen - key->length));
- }
-
- if (k) {
- add_v3_v3((key-1)->co, dv1);
- }
-
- add_v3_v3v3(dv1, dv0, dv2);
- }
- }
- }
-}
-/* set current distances to be kept between neighbouting keys */
-void recalc_lengths(PTCacheEdit *edit)
-{
- POINT_P; KEY_K;
-
- if (edit==0)
- return;
-
- LOOP_EDITED_POINTS {
- key= point->keys;
- for (k=0; k<point->totkey-1; k++, key++) {
- key->length= len_v3v3(key->co, (key + 1)->co);
- }
- }
-}
-
-/* calculate a tree for finding nearest emitter's vertice */
-void recalc_emitter_field(Object *ob, ParticleSystem *psys)
-{
- DerivedMesh *dm=psys_get_modifier(ob, psys)->dm_final;
- PTCacheEdit *edit= psys->edit;
- float *vec, *nor;
- int i, totface /*, totvert*/;
-
- if (!dm)
- return;
-
- if (edit->emitter_cosnos)
- MEM_freeN(edit->emitter_cosnos);
-
- BLI_kdtree_free(edit->emitter_field);
-
- totface=dm->getNumTessFaces(dm);
- /*totvert=dm->getNumVerts(dm);*/ /*UNSUED*/
-
- edit->emitter_cosnos=MEM_callocN(totface*6*sizeof(float), "emitter cosnos");
-
- edit->emitter_field= BLI_kdtree_new(totface);
-
- vec=edit->emitter_cosnos;
- nor=vec+3;
-
- for (i=0; i<totface; i++, vec+=6, nor+=6) {
- MFace *mface=dm->getTessFaceData(dm, i, CD_MFACE);
- MVert *mvert;
-
- mvert=dm->getVertData(dm, mface->v1, CD_MVERT);
- copy_v3_v3(vec, mvert->co);
- VECCOPY(nor, mvert->no);
-
- mvert=dm->getVertData(dm, mface->v2, CD_MVERT);
- add_v3_v3v3(vec, vec, mvert->co);
- VECADD(nor, nor, mvert->no);
-
- mvert=dm->getVertData(dm, mface->v3, CD_MVERT);
- add_v3_v3v3(vec, vec, mvert->co);
- VECADD(nor, nor, mvert->no);
-
- if (mface->v4) {
- mvert=dm->getVertData(dm, mface->v4, CD_MVERT);
- add_v3_v3v3(vec, vec, mvert->co);
- VECADD(nor, nor, mvert->no);
-
- mul_v3_fl(vec, 0.25);
- }
- else
- mul_v3_fl(vec, 1.0f / 3.0f);
-
- normalize_v3(nor);
-
- BLI_kdtree_insert(edit->emitter_field, i, vec);
- }
-
- BLI_kdtree_balance(edit->emitter_field);
-}
-
-static void PE_update_selection(Scene *scene, Object *ob, int useflag)
-{
- PTCacheEdit *edit= PE_get_current(scene, ob);
- HairKey *hkey;
- POINT_P; KEY_K;
-
- /* flag all particles to be updated if not using flag */
- if (!useflag)
- LOOP_POINTS
- point->flag |= PEP_EDIT_RECALC;
-
- /* flush edit key flag to hair key flag to preserve selection
- * on save */
- if (edit->psys) LOOP_POINTS {
- hkey = edit->psys->particles[p].hair;
- LOOP_KEYS {
- hkey->editflag= key->flag;
- hkey++;
- }
- }
-
- psys_cache_edit_paths(scene, ob, edit, CFRA, G.is_rendering);
-
-
- /* disable update flag */
- LOOP_POINTS
- point->flag &= ~PEP_EDIT_RECALC;
-}
-
-void update_world_cos(Object *ob, PTCacheEdit *edit)
-{
- ParticleSystem *psys = edit->psys;
- ParticleSystemModifierData *psmd= psys_get_modifier(ob, psys);
- POINT_P; KEY_K;
- float hairmat[4][4];
-
- if (psys==0 || psys->edit==0 || psmd->dm_final==NULL)
- return;
-
- LOOP_POINTS {
- if (!(psys->flag & PSYS_GLOBAL_HAIR))
- psys_mat_hair_to_global(ob, psmd->dm_final, psys->part->from, psys->particles+p, hairmat);
-
- LOOP_KEYS {
- copy_v3_v3(key->world_co, key->co);
- if (!(psys->flag & PSYS_GLOBAL_HAIR))
- mul_m4_v3(hairmat, key->world_co);
- }
- }
-}
-static void update_velocities(PTCacheEdit *edit)
-{
- /*TODO: get frs_sec properly */
- float vec1[3], vec2[3], frs_sec, dfra;
- POINT_P; KEY_K;
-
- /* hair doesn't use velocities */
- if (edit->psys || !edit->points || !edit->points->keys->vel)
- return;
-
- frs_sec = edit->pid.flag & PTCACHE_VEL_PER_SEC ? 25.0f : 1.0f;
-
- LOOP_EDITED_POINTS {
- LOOP_KEYS {
- if (k==0) {
- dfra = *(key+1)->time - *key->time;
-
- if (dfra <= 0.0f)
- continue;
-
- sub_v3_v3v3(key->vel, (key+1)->co, key->co);
-
- if (point->totkey>2) {
- sub_v3_v3v3(vec1, (key+1)->co, (key+2)->co);
- project_v3_v3v3(vec2, vec1, key->vel);
- sub_v3_v3v3(vec2, vec1, vec2);
- madd_v3_v3fl(key->vel, vec2, 0.5f);
- }
- }
- else if (k==point->totkey-1) {
- dfra = *key->time - *(key-1)->time;
-
- if (dfra <= 0.0f)
- continue;
-
- sub_v3_v3v3(key->vel, key->co, (key-1)->co);
-
- if (point->totkey>2) {
- sub_v3_v3v3(vec1, (key-2)->co, (key-1)->co);
- project_v3_v3v3(vec2, vec1, key->vel);
- sub_v3_v3v3(vec2, vec1, vec2);
- madd_v3_v3fl(key->vel, vec2, 0.5f);
- }
- }
- else {
- dfra = *(key+1)->time - *(key-1)->time;
-
- if (dfra <= 0.0f)
- continue;
-
- sub_v3_v3v3(key->vel, (key+1)->co, (key-1)->co);
- }
- mul_v3_fl(key->vel, frs_sec/dfra);
- }
- }
-}
-
-void PE_update_object(Scene *scene, Object *ob, int useflag)
-{
- /* use this to do partial particle updates, not usable when adding or
- * removing, then a full redo is necessary and calling this may crash */
- ParticleEditSettings *pset= PE_settings(scene);
- PTCacheEdit *edit = PE_get_current(scene, ob);
- POINT_P;
-
- if (!edit)
- return;
-
- /* flag all particles to be updated if not using flag */
- if (!useflag)
- LOOP_POINTS {
- point->flag |= PEP_EDIT_RECALC;
- }
-
- /* do post process on particle edit keys */
- pe_iterate_lengths(scene, edit);
- pe_deflect_emitter(scene, ob, edit);
- PE_apply_lengths(scene, edit);
- if (pe_x_mirror(ob))
- PE_apply_mirror(ob, edit->psys);
- if (edit->psys)
- update_world_cos(ob, edit);
- if (pset->flag & PE_AUTO_VELOCITY)
- update_velocities(edit);
- PE_hide_keys_time(scene, edit, CFRA);
-
- /* regenerate path caches */
- psys_cache_edit_paths(scene, ob, edit, CFRA, G.is_rendering);
-
- /* disable update flag */
- LOOP_POINTS {
- point->flag &= ~PEP_EDIT_RECALC;
- }
-
- if (edit->psys)
- edit->psys->flag &= ~PSYS_HAIR_UPDATED;
-}
-
-/************************************************/
-/* Edit Selections */
-/************************************************/
-
-/*-----selection callbacks-----*/
-
-static void select_key(PEData *data, int point_index, int key_index)
-{
- PTCacheEdit *edit = data->edit;
- PTCacheEditPoint *point = edit->points + point_index;
- PTCacheEditKey *key = point->keys + key_index;
-
- if (data->select)
- key->flag |= PEK_SELECT;
- else
- key->flag &= ~PEK_SELECT;
-
- point->flag |= PEP_EDIT_RECALC;
-}
-
-static void select_keys(PEData *data, int point_index, int UNUSED(key_index))
-{
- PTCacheEdit *edit = data->edit;
- PTCacheEditPoint *point = edit->points + point_index;
- KEY_K;
-
- LOOP_KEYS {
- if (data->select)
- key->flag |= PEK_SELECT;
- else
- key->flag &= ~PEK_SELECT;
- }
-
- point->flag |= PEP_EDIT_RECALC;
-}
-
-static void extend_key_select(PEData *data, int point_index, int key_index)
-{
- PTCacheEdit *edit = data->edit;
- PTCacheEditPoint *point = edit->points + point_index;
- PTCacheEditKey *key = point->keys + key_index;
-
- key->flag |= PEK_SELECT;
- point->flag |= PEP_EDIT_RECALC;
-}
-
-static void deselect_key_select(PEData *data, int point_index, int key_index)
-{
- PTCacheEdit *edit = data->edit;
- PTCacheEditPoint *point = edit->points + point_index;
- PTCacheEditKey *key = point->keys + key_index;
-
- key->flag &= ~PEK_SELECT;
- point->flag |= PEP_EDIT_RECALC;
-}
-
-static void toggle_key_select(PEData *data, int point_index, int key_index)
-{
- PTCacheEdit *edit = data->edit;
- PTCacheEditPoint *point = edit->points + point_index;
- PTCacheEditKey *key = point->keys + key_index;
-
- key->flag ^= PEK_SELECT;
- point->flag |= PEP_EDIT_RECALC;
-}
-
-/************************ de select all operator ************************/
-
-static void select_action_apply(PTCacheEditPoint *point, PTCacheEditKey *key, int action)
-{
- switch (action) {
- case SEL_SELECT:
- if ((key->flag & PEK_SELECT) == 0) {
- key->flag |= PEK_SELECT;
- point->flag |= PEP_EDIT_RECALC;
- }
- break;
- case SEL_DESELECT:
- if (key->flag & PEK_SELECT) {
- key->flag &= ~PEK_SELECT;
- point->flag |= PEP_EDIT_RECALC;
- }
- break;
- case SEL_INVERT:
- if ((key->flag & PEK_SELECT) == 0) {
- key->flag |= PEK_SELECT;
- point->flag |= PEP_EDIT_RECALC;
- }
- else {
- key->flag &= ~PEK_SELECT;
- point->flag |= PEP_EDIT_RECALC;
- }
- break;
- }
-}
-
-static int pe_select_all_exec(bContext *C, wmOperator *op)
-{
- Scene *scene= CTX_data_scene(C);
- Object *ob= CTX_data_active_object(C);
- PTCacheEdit *edit= PE_get_current(scene, ob);
- POINT_P; KEY_K;
- int action = RNA_enum_get(op->ptr, "action");
-
- if (action == SEL_TOGGLE) {
- action = SEL_SELECT;
- LOOP_VISIBLE_POINTS {
- LOOP_SELECTED_KEYS {
- action = SEL_DESELECT;
- break;
- }
-
- if (action == SEL_DESELECT)
- break;
- }
- }
-
- LOOP_VISIBLE_POINTS {
- LOOP_VISIBLE_KEYS {
- select_action_apply(point, key, action);
- }
- }
-
- PE_update_selection(scene, ob, 1);
- WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, ob);
-
- return OPERATOR_FINISHED;
-}
-
-void PARTICLE_OT_select_all(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "(De)select All";
- ot->idname = "PARTICLE_OT_select_all";
- ot->description = "(De)select all particles' keys";
-
- /* api callbacks */
- ot->exec = pe_select_all_exec;
- ot->poll = PE_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
-
- WM_operator_properties_select_all(ot);
-}
-
-/************************ pick select operator ************************/
-
-int PE_mouse_particles(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle)
-{
- PEData data;
- Scene *scene= CTX_data_scene(C);
- Object *ob= CTX_data_active_object(C);
- PTCacheEdit *edit= PE_get_current(scene, ob);
- POINT_P; KEY_K;
-
- if (!PE_start_edit(edit))
- return OPERATOR_CANCELLED;
-
- if (!extend && !deselect && !toggle) {
- LOOP_VISIBLE_POINTS {
- LOOP_SELECTED_KEYS {
- key->flag &= ~PEK_SELECT;
- point->flag |= PEP_EDIT_RECALC;
- }
- }
- }
-
- PE_set_view3d_data(C, &data);
- data.mval= mval;
- data.rad = ED_view3d_select_dist_px();
-
- /* 1 = nearest only */
- if (extend)
- for_mouse_hit_keys(&data, extend_key_select, 1);
- else if (deselect)
- for_mouse_hit_keys(&data, deselect_key_select, 1);
- else
- for_mouse_hit_keys(&data, toggle_key_select, 1);
-
- PE_update_selection(scene, ob, 1);
- WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, data.ob);
-
- return OPERATOR_FINISHED;
-}
-
-/************************ select root operator ************************/
-
-static void select_root(PEData *data, int point_index)
-{
- PTCacheEditPoint *point = data->edit->points + point_index;
- PTCacheEditKey *key = point->keys;
-
- if (point->flag & PEP_HIDE)
- return;
-
- if (data->select_action != SEL_TOGGLE)
- select_action_apply(point, key, data->select_action);
- else if (key->flag & PEK_SELECT)
- data->select_toggle_action = SEL_DESELECT;
-}
-
-static int select_roots_exec(bContext *C, wmOperator *op)
-{
- PEData data;
- int action = RNA_enum_get(op->ptr, "action");
-
- PE_set_data(C, &data);
-
- if (action == SEL_TOGGLE) {
- data.select_action = SEL_TOGGLE;
- data.select_toggle_action = SEL_SELECT;
-
- foreach_point(&data, select_root);
-
- action = data.select_toggle_action;
- }
-
- data.select_action = action;
- foreach_point(&data, select_root);
-
- PE_update_selection(data.scene, data.ob, 1);
- WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, data.ob);
-
- return OPERATOR_FINISHED;
-}
-
-void PARTICLE_OT_select_roots(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Select Roots";
- ot->idname = "PARTICLE_OT_select_roots";
- ot->description = "Select roots of all visible particles";
-
- /* api callbacks */
- ot->exec = select_roots_exec;
- ot->poll = PE_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /* properties */
- WM_operator_properties_select_action(ot, SEL_SELECT);
-}
-
-/************************ select tip operator ************************/
-
-static void select_tip(PEData *data, int point_index)
-{
- PTCacheEditPoint *point = data->edit->points + point_index;
- PTCacheEditKey *key;
-
- if (point->totkey == 0) {
- return;
- }
-
- key = &point->keys[point->totkey - 1];
-
- if (point->flag & PEP_HIDE)
- return;
-
- if (data->select_action != SEL_TOGGLE)
- select_action_apply(point, key, data->select_action);
- else if (key->flag & PEK_SELECT)
- data->select_toggle_action = SEL_DESELECT;
-}
-
-static int select_tips_exec(bContext *C, wmOperator *op)
-{
- PEData data;
- int action = RNA_enum_get(op->ptr, "action");
-
- PE_set_data(C, &data);
-
- if (action == SEL_TOGGLE) {
- data.select_action = SEL_TOGGLE;
- data.select_toggle_action = SEL_SELECT;
-
- foreach_point(&data, select_tip);
-
- action = data.select_toggle_action;
- }
-
- data.select_action = action;
- foreach_point(&data, select_tip);
-
- PE_update_selection(data.scene, data.ob, 1);
- WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, data.ob);
-
- return OPERATOR_FINISHED;
-}
-
-void PARTICLE_OT_select_tips(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Select Tips";
- ot->idname = "PARTICLE_OT_select_tips";
- ot->description = "Select tips of all visible particles";
-
- /* api callbacks */
- ot->exec = select_tips_exec;
- ot->poll = PE_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /* properties */
- WM_operator_properties_select_action(ot, SEL_SELECT);
-}
-
-/*********************** select random operator ************************/
-
-enum { RAN_HAIR, RAN_POINTS };
-
-static EnumPropertyItem select_random_type_items[] = {
- {RAN_HAIR, "HAIR", 0, "Hair", ""},
- {RAN_POINTS, "POINTS", 0, "Points", ""},
- {0, NULL, 0, NULL, NULL}
-};
-
-static int select_random_exec(bContext *C, wmOperator *op)
-{
- PEData data;
- int type;
- Scene *scene;
- Object *ob;
-
- /* used by LOOP_VISIBLE_POINTS, LOOP_VISIBLE_KEYS and LOOP_KEYS */
- PTCacheEdit *edit;
- PTCacheEditPoint *point;
- PTCacheEditKey *key;
- int p;
- int k;
-
- const float randfac = RNA_float_get(op->ptr, "percent") / 100.0f;
- const int seed = WM_operator_properties_select_random_seed_increment_get(op);
- const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT);
- RNG *rng;
-
- type = RNA_enum_get(op->ptr, "type");
-
- PE_set_data(C, &data);
- data.select_action = SEL_SELECT;
- scene = CTX_data_scene(C);
- ob = CTX_data_active_object(C);
- edit = PE_get_current(scene, ob);
-
- rng = BLI_rng_new_srandom(seed);
-
- switch (type) {
- case RAN_HAIR:
- LOOP_VISIBLE_POINTS {
- int flag = ((BLI_rng_get_float(rng) < randfac) == select) ? SEL_SELECT : SEL_DESELECT;
- LOOP_KEYS {
- select_action_apply (point, key, flag);
- }
- }
- break;
- case RAN_POINTS:
- LOOP_VISIBLE_POINTS {
- LOOP_VISIBLE_KEYS {
- int flag = ((BLI_rng_get_float(rng) < randfac) == select) ? SEL_SELECT : SEL_DESELECT;
- select_action_apply (point, key, flag);
- }
- }
- break;
- }
-
- BLI_rng_free(rng);
-
- PE_update_selection(data.scene, data.ob, 1);
- WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, data.ob);
-
- return OPERATOR_FINISHED;
-}
-
-void PARTICLE_OT_select_random(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Select Random";
- ot->idname = "PARTICLE_OT_select_random";
- ot->description = "Select a randomly distributed set of hair or points";
-
- /* api callbacks */
- ot->exec = select_random_exec;
- ot->poll = PE_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /* properties */
- WM_operator_properties_select_random(ot);
- ot->prop = RNA_def_enum (ot->srna, "type", select_random_type_items, RAN_HAIR,
- "Type", "Select either hair or points");
-}
-
-/************************ select linked operator ************************/
-
-static int select_linked_exec(bContext *C, wmOperator *op)
-{
- PEData data;
- int mval[2];
- int location[2];
-
- RNA_int_get_array(op->ptr, "location", location);
- mval[0] = location[0];
- mval[1] = location[1];
-
- PE_set_view3d_data(C, &data);
- data.mval= mval;
- data.rad=75.0f;
- data.select= !RNA_boolean_get(op->ptr, "deselect");
-
- for_mouse_hit_keys(&data, select_keys, 1); /* nearest only */
- PE_update_selection(data.scene, data.ob, 1);
- WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, data.ob);
-
- return OPERATOR_FINISHED;
-}
-
-static int select_linked_invoke(bContext *C, wmOperator *op, const wmEvent *event)
-{
- RNA_int_set_array(op->ptr, "location", event->mval);
- return select_linked_exec(C, op);
-}
-
-void PARTICLE_OT_select_linked(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Select Linked";
- ot->idname = "PARTICLE_OT_select_linked";
- ot->description = "Select nearest particle from mouse pointer";
-
- /* api callbacks */
- ot->exec = select_linked_exec;
- ot->invoke = select_linked_invoke;
- ot->poll = PE_poll_view3d;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "Deselect linked keys rather than selecting them");
- RNA_def_int_vector(ot->srna, "location", 2, NULL, 0, INT_MAX, "Location", "", 0, 16384);
-}
-
-/************************ border select operator ************************/
-void PE_deselect_all_visible(PTCacheEdit *edit)
-{
- POINT_P; KEY_K;
-
- LOOP_VISIBLE_POINTS {
- LOOP_SELECTED_KEYS {
- key->flag &= ~PEK_SELECT;
- point->flag |= PEP_EDIT_RECALC;
- }
- }
-}
-
-int PE_border_select(bContext *C, rcti *rect, bool select, bool extend)
-{
- Scene *scene= CTX_data_scene(C);
- Object *ob= CTX_data_active_object(C);
- PTCacheEdit *edit= PE_get_current(scene, ob);
- PEData data;
-
- if (!PE_start_edit(edit))
- return OPERATOR_CANCELLED;
-
- if (extend == 0 && select)
- PE_deselect_all_visible(edit);
-
- PE_set_view3d_data(C, &data);
- data.rect= rect;
- data.select= select;
-
- for_mouse_hit_keys(&data, select_key, 0);
-
- PE_update_selection(scene, ob, 1);
- WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, ob);
-
- return OPERATOR_FINISHED;
-}
-
-/************************ circle select operator ************************/
-
-int PE_circle_select(bContext *C, int selecting, const int mval[2], float rad)
-{
- Scene *scene= CTX_data_scene(C);
- Object *ob= CTX_data_active_object(C);
- PTCacheEdit *edit= PE_get_current(scene, ob);
- PEData data;
-
- if (!PE_start_edit(edit))
- return OPERATOR_FINISHED;
-
- PE_set_view3d_data(C, &data);
- data.mval= mval;
- data.rad= rad;
- data.select= selecting;
-
- for_mouse_hit_keys(&data, select_key, 0);
-
- PE_update_selection(scene, ob, 1);
- WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, ob);
-
- return OPERATOR_FINISHED;
-}
-
-/************************ lasso select operator ************************/
-
-int PE_lasso_select(bContext *C, const int mcords[][2], const short moves, bool extend, bool select)
-{
- Scene *scene= CTX_data_scene(C);
- Object *ob= CTX_data_active_object(C);
- ARegion *ar= CTX_wm_region(C);
- ParticleEditSettings *pset= PE_settings(scene);
- PTCacheEdit *edit = PE_get_current(scene, ob);
- ParticleSystem *psys = edit->psys;
- ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys);
- POINT_P; KEY_K;
- float co[3], mat[4][4];
- int screen_co[2];
-
- PEData data;
-
- unit_m4(mat);
-
- if (!PE_start_edit(edit))
- return OPERATOR_CANCELLED;
-
- if (extend == 0 && select)
- PE_deselect_all_visible(edit);
-
- /* only for depths */
- PE_set_view3d_data(C, &data);
-
- LOOP_VISIBLE_POINTS {
- if (edit->psys && !(psys->flag & PSYS_GLOBAL_HAIR))
- psys_mat_hair_to_global(ob, psmd->dm_final, psys->part->from, psys->particles + p, mat);
-
- if (pset->selectmode==SCE_SELECT_POINT) {
- LOOP_KEYS {
- copy_v3_v3(co, key->co);
- mul_m4_v3(mat, co);
- if ((ED_view3d_project_int_global(ar, co, screen_co, V3D_PROJ_TEST_CLIP_WIN) == V3D_PROJ_RET_OK) &&
- BLI_lasso_is_point_inside(mcords, moves, screen_co[0], screen_co[1], IS_CLIPPED) &&
- key_test_depth(&data, co, screen_co))
- {
- if (select) {
- if (!(key->flag & PEK_SELECT)) {
- key->flag |= PEK_SELECT;
- point->flag |= PEP_EDIT_RECALC;
- }
- }
- else {
- if (key->flag & PEK_SELECT) {
- key->flag &= ~PEK_SELECT;
- point->flag |= PEP_EDIT_RECALC;
- }
- }
- }
- }
- }
- else if (pset->selectmode==SCE_SELECT_END) {
- if (point->totkey) {
- key= point->keys + point->totkey - 1;
-
- copy_v3_v3(co, key->co);
- mul_m4_v3(mat, co);
- if ((ED_view3d_project_int_global(ar, co, screen_co, V3D_PROJ_TEST_CLIP_WIN) == V3D_PROJ_RET_OK) &&
- BLI_lasso_is_point_inside(mcords, moves, screen_co[0], screen_co[1], IS_CLIPPED) &&
- key_test_depth(&data, co, screen_co))
- {
- if (select) {
- if (!(key->flag & PEK_SELECT)) {
- key->flag |= PEK_SELECT;
- point->flag |= PEP_EDIT_RECALC;
- }
- }
- else {
- if (key->flag & PEK_SELECT) {
- key->flag &= ~PEK_SELECT;
- point->flag |= PEP_EDIT_RECALC;
- }
- }
- }
- }
- }
- }
-
- PE_update_selection(scene, ob, 1);
- WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, ob);
-
- return OPERATOR_FINISHED;
-}
-
-/*************************** hide operator **************************/
-
-static int hide_exec(bContext *C, wmOperator *op)
-{
- Object *ob= CTX_data_active_object(C);
- Scene *scene= CTX_data_scene(C);
- PTCacheEdit *edit= PE_get_current(scene, ob);
- POINT_P; KEY_K;
-
- if (RNA_enum_get(op->ptr, "unselected")) {
- LOOP_UNSELECTED_POINTS {
- point->flag |= PEP_HIDE;
- point->flag |= PEP_EDIT_RECALC;
-
- LOOP_KEYS
- key->flag &= ~PEK_SELECT;
- }
- }
- else {
- LOOP_SELECTED_POINTS {
- point->flag |= PEP_HIDE;
- point->flag |= PEP_EDIT_RECALC;
-
- LOOP_KEYS
- key->flag &= ~PEK_SELECT;
- }
- }
-
- PE_update_selection(scene, ob, 1);
- WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, ob);
-
- return OPERATOR_FINISHED;
-}
-
-void PARTICLE_OT_hide(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Hide Selected";
- ot->idname = "PARTICLE_OT_hide";
- ot->description = "Hide selected particles";
-
- /* api callbacks */
- ot->exec = hide_exec;
- ot->poll = PE_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /* props */
- RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected");
-}
-
-/*************************** reveal operator **************************/
-
-static int reveal_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Object *ob= CTX_data_active_object(C);
- Scene *scene= CTX_data_scene(C);
- PTCacheEdit *edit= PE_get_current(scene, ob);
- POINT_P; KEY_K;
-
- LOOP_POINTS {
- if (point->flag & PEP_HIDE) {
- point->flag &= ~PEP_HIDE;
- point->flag |= PEP_EDIT_RECALC;
-
- LOOP_KEYS
- key->flag |= PEK_SELECT;
- }
- }
-
- PE_update_selection(scene, ob, 1);
- WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, ob);
-
- return OPERATOR_FINISHED;
-}
-
-void PARTICLE_OT_reveal(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Reveal";
- ot->idname = "PARTICLE_OT_reveal";
- ot->description = "Show hidden particles";
-
- /* api callbacks */
- ot->exec = reveal_exec;
- ot->poll = PE_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
-/************************ select less operator ************************/
-
-static void select_less_keys(PEData *data, int point_index)
-{
- PTCacheEdit *edit= data->edit;
- PTCacheEditPoint *point = edit->points + point_index;
- KEY_K;
-
- LOOP_SELECTED_KEYS {
- if (k==0) {
- if (((key+1)->flag&PEK_SELECT)==0)
- key->flag |= PEK_TAG;
- }
- else if (k==point->totkey-1) {
- if (((key-1)->flag&PEK_SELECT)==0)
- key->flag |= PEK_TAG;
- }
- else {
- if ((((key-1)->flag & (key+1)->flag) & PEK_SELECT)==0)
- key->flag |= PEK_TAG;
- }
- }
-
- LOOP_KEYS {
- if (key->flag&PEK_TAG) {
- key->flag &= ~(PEK_TAG|PEK_SELECT);
- point->flag |= PEP_EDIT_RECALC; /* redraw selection only */
- }
- }
-}
-
-static int select_less_exec(bContext *C, wmOperator *UNUSED(op))
-{
- PEData data;
-
- PE_set_data(C, &data);
- foreach_point(&data, select_less_keys);
-
- PE_update_selection(data.scene, data.ob, 1);
- WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, data.ob);
-
- return OPERATOR_FINISHED;
-}
-
-void PARTICLE_OT_select_less(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Select Less";
- ot->idname = "PARTICLE_OT_select_less";
- ot->description = "Deselect boundary selected keys of each particle";
-
- /* api callbacks */
- ot->exec = select_less_exec;
- ot->poll = PE_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
-/************************ select more operator ************************/
-
-static void select_more_keys(PEData *data, int point_index)
-{
- PTCacheEdit *edit= data->edit;
- PTCacheEditPoint *point = edit->points + point_index;
- KEY_K;
-
- LOOP_KEYS {
- if (key->flag & PEK_SELECT) continue;
-
- if (k==0) {
- if ((key+1)->flag&PEK_SELECT)
- key->flag |= PEK_TAG;
- }
- else if (k==point->totkey-1) {
- if ((key-1)->flag&PEK_SELECT)
- key->flag |= PEK_TAG;
- }
- else {
- if (((key-1)->flag | (key+1)->flag) & PEK_SELECT)
- key->flag |= PEK_TAG;
- }
- }
-
- LOOP_KEYS {
- if (key->flag&PEK_TAG) {
- key->flag &= ~PEK_TAG;
- key->flag |= PEK_SELECT;
- point->flag |= PEP_EDIT_RECALC; /* redraw selection only */
- }
- }
-}
-
-static int select_more_exec(bContext *C, wmOperator *UNUSED(op))
-{
- PEData data;
-
- PE_set_data(C, &data);
- foreach_point(&data, select_more_keys);
-
- PE_update_selection(data.scene, data.ob, 1);
- WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, data.ob);
-
- return OPERATOR_FINISHED;
-}
-
-void PARTICLE_OT_select_more(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Select More";
- ot->idname = "PARTICLE_OT_select_more";
- ot->description = "Select keys linked to boundary selected keys of each particle";
-
- /* api callbacks */
- ot->exec = select_more_exec;
- ot->poll = PE_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
-/************************ rekey operator ************************/
-
-static void rekey_particle(PEData *data, int pa_index)
-{
- PTCacheEdit *edit= data->edit;
- ParticleSystem *psys= edit->psys;
- ParticleSimulationData sim= {0};
- ParticleData *pa= psys->particles + pa_index;
- PTCacheEditPoint *point = edit->points + pa_index;
- ParticleKey state;
- HairKey *key, *new_keys, *okey;
- PTCacheEditKey *ekey;
- float dval, sta, end;
- int k;
-
- sim.scene= data->scene;
- sim.ob= data->ob;
- sim.psys= edit->psys;
-
- pa->flag |= PARS_REKEY;
-
- key= new_keys= MEM_callocN(data->totrekey * sizeof(HairKey), "Hair re-key keys");
-
- okey = pa->hair;
- /* root and tip stay the same */
- copy_v3_v3(key->co, okey->co);
- copy_v3_v3((key + data->totrekey - 1)->co, (okey + pa->totkey - 1)->co);
-
- sta= key->time= okey->time;
- end= (key + data->totrekey - 1)->time= (okey + pa->totkey - 1)->time;
- dval= (end - sta) / (float)(data->totrekey - 1);
-
- /* interpolate new keys from old ones */
- for (k=1, key++; k<data->totrekey-1; k++, key++) {
- state.time= (float)k / (float)(data->totrekey-1);
- psys_get_particle_on_path(&sim, pa_index, &state, 0);
- copy_v3_v3(key->co, state.co);
- key->time= sta + k * dval;
- }
-
- /* replace keys */
- if (pa->hair)
- MEM_freeN(pa->hair);
- pa->hair= new_keys;
-
- point->totkey=pa->totkey=data->totrekey;
-
-
- if (point->keys)
- MEM_freeN(point->keys);
- ekey= point->keys= MEM_callocN(pa->totkey * sizeof(PTCacheEditKey), "Hair re-key edit keys");
-
- for (k=0, key=pa->hair; k<pa->totkey; k++, key++, ekey++) {
- ekey->co= key->co;
- ekey->time= &key->time;
- ekey->flag |= PEK_SELECT;
- if (!(psys->flag & PSYS_GLOBAL_HAIR))
- ekey->flag |= PEK_USE_WCO;
- }
-
- pa->flag &= ~PARS_REKEY;
- point->flag |= PEP_EDIT_RECALC;
-}
-
-static int rekey_exec(bContext *C, wmOperator *op)
-{
- PEData data;
-
- PE_set_data(C, &data);
-
- data.dval= 1.0f / (float)(data.totrekey-1);
- data.totrekey= RNA_int_get(op->ptr, "keys_number");
-
- foreach_selected_point(&data, rekey_particle);
-
- recalc_lengths(data.edit);
- PE_update_object(data.scene, data.ob, 1);
- WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, data.ob);
-
- return OPERATOR_FINISHED;
-}
-
-void PARTICLE_OT_rekey(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Rekey";
- ot->idname = "PARTICLE_OT_rekey";
- ot->description = "Change the number of keys of selected particles (root and tip keys included)";
-
- /* api callbacks */
- ot->exec = rekey_exec;
- ot->invoke = WM_operator_props_popup;
- ot->poll = PE_hair_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /* properties */
- RNA_def_int(ot->srna, "keys_number", 2, 2, INT_MAX, "Number of Keys", "", 2, 100);
-}
-
-static void rekey_particle_to_time(Scene *scene, Object *ob, int pa_index, float path_time)
-{
- PTCacheEdit *edit= PE_get_current(scene, ob);
- ParticleSystem *psys;
- ParticleSimulationData sim= {0};
- ParticleData *pa;
- ParticleKey state;
- HairKey *new_keys, *key;
- PTCacheEditKey *ekey;
- int k;
-
- if (!edit || !edit->psys) return;
-
- psys = edit->psys;
-
- sim.scene= scene;
- sim.ob= ob;
- sim.psys= psys;
-
- pa= psys->particles + pa_index;
-
- pa->flag |= PARS_REKEY;
-
- key= new_keys= MEM_dupallocN(pa->hair);
-
- /* interpolate new keys from old ones (roots stay the same) */
- for (k=1, key++; k < pa->totkey; k++, key++) {
- state.time= path_time * (float)k / (float)(pa->totkey-1);
- psys_get_particle_on_path(&sim, pa_index, &state, 0);
- copy_v3_v3(key->co, state.co);
- }
-
- /* replace hair keys */
- if (pa->hair)
- MEM_freeN(pa->hair);
- pa->hair= new_keys;
-
- /* update edit pointers */
- for (k=0, key=pa->hair, ekey=edit->points[pa_index].keys; k<pa->totkey; k++, key++, ekey++) {
- ekey->co= key->co;
- ekey->time= &key->time;
- }
-
- pa->flag &= ~PARS_REKEY;
-}
-
-/************************* utilities **************************/
-
-static int remove_tagged_particles(Object *ob, ParticleSystem *psys, int mirror)
-{
- PTCacheEdit *edit = psys->edit;
- ParticleData *pa, *npa=0, *new_pars=0;
- POINT_P;
- PTCacheEditPoint *npoint=0, *new_points=0;
- ParticleSystemModifierData *psmd;
- int i, new_totpart= psys->totpart, removed= 0;
-
- if (mirror) {
- /* mirror tags */
- psmd= psys_get_modifier(ob, psys);
-
- LOOP_TAGGED_POINTS {
- PE_mirror_particle(ob, psmd->dm_final, psys, psys->particles + p, NULL);
- }
- }
-
- LOOP_TAGGED_POINTS {
- new_totpart--;
- removed++;
- }
-
- if (new_totpart != psys->totpart) {
- if (new_totpart) {
- npa= new_pars= MEM_callocN(new_totpart * sizeof(ParticleData), "ParticleData array");
- npoint= new_points= MEM_callocN(new_totpart * sizeof(PTCacheEditPoint), "PTCacheEditKey array");
-
- if (ELEM(NULL, new_pars, new_points)) {
- /* allocation error! */
- if (new_pars)
- MEM_freeN(new_pars);
- if (new_points)
- MEM_freeN(new_points);
- return 0;
- }
- }
-
- pa= psys->particles;
- point= edit->points;
- for (i=0; i<psys->totpart; i++, pa++, point++) {
- if (point->flag & PEP_TAG) {
- if (point->keys)
- MEM_freeN(point->keys);
- if (pa->hair)
- MEM_freeN(pa->hair);
- }
- else {
- memcpy(npa, pa, sizeof(ParticleData));
- memcpy(npoint, point, sizeof(PTCacheEditPoint));
- npa++;
- npoint++;
- }
- }
-
- if (psys->particles) MEM_freeN(psys->particles);
- psys->particles= new_pars;
-
- if (edit->points) MEM_freeN(edit->points);
- edit->points= new_points;
-
- if (edit->mirror_cache) {
- MEM_freeN(edit->mirror_cache);
- edit->mirror_cache= NULL;
- }
-
- if (psys->child) {
- MEM_freeN(psys->child);
- psys->child= NULL;
- psys->totchild=0;
- }
-
- edit->totpoint= psys->totpart= new_totpart;
- }
-
- return removed;
-}
-
-static void remove_tagged_keys(Object *ob, ParticleSystem *psys)
-{
- PTCacheEdit *edit= psys->edit;
- ParticleData *pa;
- HairKey *hkey, *nhkey, *new_hkeys=0;
- POINT_P; KEY_K;
- PTCacheEditKey *nkey, *new_keys;
- ParticleSystemModifierData *psmd;
- short new_totkey;
-
- if (pe_x_mirror(ob)) {
- /* mirror key tags */
- psmd= psys_get_modifier(ob, psys);
-
- LOOP_POINTS {
- LOOP_TAGGED_KEYS {
- PE_mirror_particle(ob, psmd->dm_final, psys, psys->particles + p, NULL);
- break;
- }
- }
- }
-
- LOOP_POINTS {
- new_totkey= point->totkey;
- LOOP_TAGGED_KEYS {
- new_totkey--;
- }
- /* we can't have elements with less than two keys*/
- if (new_totkey < 2)
- point->flag |= PEP_TAG;
- }
- remove_tagged_particles(ob, psys, pe_x_mirror(ob));
-
- LOOP_POINTS {
- pa = psys->particles + p;
- new_totkey= pa->totkey;
-
- LOOP_TAGGED_KEYS {
- new_totkey--;
- }
-
- if (new_totkey != pa->totkey) {
- nhkey= new_hkeys= MEM_callocN(new_totkey*sizeof(HairKey), "HairKeys");
- nkey= new_keys= MEM_callocN(new_totkey*sizeof(PTCacheEditKey), "particle edit keys");
-
- hkey= pa->hair;
- LOOP_KEYS {
- while (key->flag & PEK_TAG && hkey < pa->hair + pa->totkey) {
- key++;
- hkey++;
- }
-
- if (hkey < pa->hair + pa->totkey) {
- copy_v3_v3(nhkey->co, hkey->co);
- nhkey->editflag = hkey->editflag;
- nhkey->time= hkey->time;
- nhkey->weight= hkey->weight;
-
- nkey->co= nhkey->co;
- nkey->time= &nhkey->time;
- /* these can be copied from old edit keys */
- nkey->flag = key->flag;
- nkey->ftime = key->ftime;
- nkey->length = key->length;
- copy_v3_v3(nkey->world_co, key->world_co);
- }
- nkey++;
- nhkey++;
- hkey++;
- }
-
- if (pa->hair)
- MEM_freeN(pa->hair);
-
- if (point->keys)
- MEM_freeN(point->keys);
-
- pa->hair= new_hkeys;
- point->keys= new_keys;
-
- point->totkey= pa->totkey= new_totkey;
-
- /* flag for recalculating length */
- point->flag |= PEP_EDIT_RECALC;
- }
- }
-}
-
-/************************ subdivide opertor *********************/
-
-/* works like normal edit mode subdivide, inserts keys between neighboring selected keys */
-static void subdivide_particle(PEData *data, int pa_index)
-{
- PTCacheEdit *edit= data->edit;
- ParticleSystem *psys= edit->psys;
- ParticleSimulationData sim= {0};
- ParticleData *pa= psys->particles + pa_index;
- PTCacheEditPoint *point = edit->points + pa_index;
- ParticleKey state;
- HairKey *key, *nkey, *new_keys;
- PTCacheEditKey *ekey, *nekey, *new_ekeys;
-
- int k;
- short totnewkey=0;
- float endtime;
-
- sim.scene= data->scene;
- sim.ob= data->ob;
- sim.psys= edit->psys;
-
- for (k=0, ekey=point->keys; k<pa->totkey-1; k++, ekey++) {
- if (ekey->flag&PEK_SELECT && (ekey+1)->flag&PEK_SELECT)
- totnewkey++;
- }
-
- if (totnewkey==0) return;
-
- pa->flag |= PARS_REKEY;
-
- nkey= new_keys= MEM_callocN((pa->totkey+totnewkey)*(sizeof(HairKey)), "Hair subdivide keys");
- nekey= new_ekeys= MEM_callocN((pa->totkey+totnewkey)*(sizeof(PTCacheEditKey)), "Hair subdivide edit keys");
-
- key = pa->hair;
- endtime= key[pa->totkey-1].time;
-
- for (k=0, ekey=point->keys; k<pa->totkey-1; k++, key++, ekey++) {
-
- memcpy(nkey, key, sizeof(HairKey));
- memcpy(nekey, ekey, sizeof(PTCacheEditKey));
-
- nekey->co= nkey->co;
- nekey->time= &nkey->time;
-
- nkey++;
- nekey++;
-
- if (ekey->flag & PEK_SELECT && (ekey+1)->flag & PEK_SELECT) {
- nkey->time = (key->time + (key + 1)->time) * 0.5f;
- state.time = (endtime != 0.0f) ? nkey->time / endtime: 0.0f;
- psys_get_particle_on_path(&sim, pa_index, &state, 0);
- copy_v3_v3(nkey->co, state.co);
-
- nekey->co= nkey->co;
- nekey->time = &nkey->time;
- nekey->flag |= PEK_SELECT;
- if (!(psys->flag & PSYS_GLOBAL_HAIR))
- nekey->flag |= PEK_USE_WCO;
-
- nekey++;
- nkey++;
- }
- }
- /*tip still not copied*/
- memcpy(nkey, key, sizeof(HairKey));
- memcpy(nekey, ekey, sizeof(PTCacheEditKey));
-
- nekey->co= nkey->co;
- nekey->time= &nkey->time;
-
- if (pa->hair)
- MEM_freeN(pa->hair);
- pa->hair= new_keys;
-
- if (point->keys)
- MEM_freeN(point->keys);
- point->keys= new_ekeys;
-
- point->totkey = pa->totkey = pa->totkey + totnewkey;
- point->flag |= PEP_EDIT_RECALC;
- pa->flag &= ~PARS_REKEY;
-}
-
-static int subdivide_exec(bContext *C, wmOperator *UNUSED(op))
-{
- PEData data;
-
- PE_set_data(C, &data);
- foreach_point(&data, subdivide_particle);
-
- recalc_lengths(data.edit);
- PE_update_object(data.scene, data.ob, 1);
- WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, data.ob);
-
- return OPERATOR_FINISHED;
-}
-
-void PARTICLE_OT_subdivide(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Subdivide";
- ot->idname = "PARTICLE_OT_subdivide";
- ot->description = "Subdivide selected particles segments (adds keys)";
-
- /* api callbacks */
- ot->exec = subdivide_exec;
- ot->poll = PE_hair_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
-/************************ remove doubles opertor *********************/
-
-static int remove_doubles_exec(bContext *C, wmOperator *op)
-{
- Scene *scene= CTX_data_scene(C);
- Object *ob= CTX_data_active_object(C);
- PTCacheEdit *edit= PE_get_current(scene, ob);
- ParticleSystem *psys = edit->psys;
- ParticleSystemModifierData *psmd;
- KDTree *tree;
- KDTreeNearest nearest[10];
- POINT_P;
- float mat[4][4], co[3], threshold= RNA_float_get(op->ptr, "threshold");
- int n, totn, removed, totremoved;
-
- if (psys->flag & PSYS_GLOBAL_HAIR)
- return OPERATOR_CANCELLED;
-
- edit= psys->edit;
- psmd= psys_get_modifier(ob, psys);
- totremoved= 0;
-
- do {
- removed= 0;
-
- tree=BLI_kdtree_new(psys->totpart);
-
- /* insert particles into kd tree */
- LOOP_SELECTED_POINTS {
- psys_mat_hair_to_object(ob, psmd->dm_final, psys->part->from, psys->particles+p, mat);
- copy_v3_v3(co, point->keys->co);
- mul_m4_v3(mat, co);
- BLI_kdtree_insert(tree, p, co);
- }
-
- BLI_kdtree_balance(tree);
-
- /* tag particles to be removed */
- LOOP_SELECTED_POINTS {
- psys_mat_hair_to_object(ob, psmd->dm_final, psys->part->from, psys->particles+p, mat);
- copy_v3_v3(co, point->keys->co);
- mul_m4_v3(mat, co);
-
- totn = BLI_kdtree_find_nearest_n(tree, co, nearest, 10);
-
- for (n=0; n<totn; n++) {
- /* this needs a custom threshold still */
- if (nearest[n].index > p && nearest[n].dist < threshold) {
- if (!(point->flag & PEP_TAG)) {
- point->flag |= PEP_TAG;
- removed++;
- }
- }
- }
- }
-
- BLI_kdtree_free(tree);
-
- /* remove tagged particles - don't do mirror here! */
- remove_tagged_particles(ob, psys, 0);
- totremoved += removed;
- } while (removed);
-
- if (totremoved == 0)
- return OPERATOR_CANCELLED;
-
- BKE_reportf(op->reports, RPT_INFO, "Removed %d double particles", totremoved);
-
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
- WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob);
-
- return OPERATOR_FINISHED;
-}
-
-void PARTICLE_OT_remove_doubles(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Remove Doubles";
- ot->idname = "PARTICLE_OT_remove_doubles";
- ot->description = "Remove selected particles close enough of others";
-
- /* api callbacks */
- ot->exec = remove_doubles_exec;
- ot->poll = PE_hair_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /* properties */
- RNA_def_float(ot->srna, "threshold", 0.0002f, 0.0f, FLT_MAX,
- "Merge Distance", "Threshold distance withing which particles are removed", 0.00001f, 0.1f);
-}
-
-
-static int weight_set_exec(bContext *C, wmOperator *op)
-{
- Scene *scene= CTX_data_scene(C);
- ParticleEditSettings *pset= PE_settings(scene);
- Object *ob= CTX_data_active_object(C);
- PTCacheEdit *edit= PE_get_current(scene, ob);
- ParticleSystem *psys = edit->psys;
- POINT_P;
- KEY_K;
- HairKey *hkey;
- float weight;
- ParticleBrushData *brush= &pset->brush[pset->brushtype];
- float factor= RNA_float_get(op->ptr, "factor");
-
- weight= brush->strength;
- edit= psys->edit;
-
- LOOP_SELECTED_POINTS {
- ParticleData *pa= psys->particles + p;
-
- LOOP_SELECTED_KEYS {
- hkey= pa->hair + k;
- hkey->weight= interpf(weight, hkey->weight, factor);
- }
- }
-
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
- WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob);
-
- return OPERATOR_FINISHED;
-}
-
-void PARTICLE_OT_weight_set(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Weight Set";
- ot->idname = "PARTICLE_OT_weight_set";
- ot->description = "Set the weight of selected keys";
-
- /* api callbacks */
- ot->exec = weight_set_exec;
- ot->poll = PE_hair_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
-
- RNA_def_float(ot->srna, "factor", 1, 0, 1, "Factor",
- "Interpolation factor between current brush weight, and keys' weights", 0, 1);
-}
-
-/************************ cursor drawing *******************************/
-
-static void brush_drawcursor(bContext *C, int x, int y, void *UNUSED(customdata))
-{
- Scene *scene = CTX_data_scene(C);
- ParticleEditSettings *pset= PE_settings(scene);
- ParticleBrushData *brush;
-
- if (pset->brushtype < 0)
- return;
-
- brush= &pset->brush[pset->brushtype];
-
- if (brush) {
- glPushMatrix();
-
- glTranslatef((float)x, (float)y, 0.0f);
-
- glColor4ub(255, 255, 255, 128);
- glEnable(GL_LINE_SMOOTH);
- glEnable(GL_BLEND);
- glutil_draw_lined_arc(0.0, M_PI*2.0, pe_brush_size_get(scene, brush), 40);
- glDisable(GL_BLEND);
- glDisable(GL_LINE_SMOOTH);
-
- glPopMatrix();
- }
-}
-
-static void toggle_particle_cursor(bContext *C, int enable)
-{
- ParticleEditSettings *pset= PE_settings(CTX_data_scene(C));
-
- if (pset->paintcursor && !enable) {
- WM_paint_cursor_end(CTX_wm_manager(C), pset->paintcursor);
- pset->paintcursor = NULL;
- }
- else if (enable)
- pset->paintcursor= WM_paint_cursor_activate(CTX_wm_manager(C), PE_poll_view3d, brush_drawcursor, NULL);
-}
-
-/*************************** delete operator **************************/
-
-enum { DEL_PARTICLE, DEL_KEY };
-
-static EnumPropertyItem delete_type_items[] = {
- {DEL_PARTICLE, "PARTICLE", 0, "Particle", ""},
- {DEL_KEY, "KEY", 0, "Key", ""},
- {0, NULL, 0, NULL, NULL}};
-
-static void set_delete_particle(PEData *data, int pa_index)
-{
- PTCacheEdit *edit= data->edit;
-
- edit->points[pa_index].flag |= PEP_TAG;
-}
-
-static void set_delete_particle_key(PEData *data, int pa_index, int key_index)
-{
- PTCacheEdit *edit= data->edit;
-
- edit->points[pa_index].keys[key_index].flag |= PEK_TAG;
-}
-
-static int delete_exec(bContext *C, wmOperator *op)
-{
- PEData data;
- int type= RNA_enum_get(op->ptr, "type");
-
- PE_set_data(C, &data);
-
- if (type == DEL_KEY) {
- foreach_selected_key(&data, set_delete_particle_key);
- remove_tagged_keys(data.ob, data.edit->psys);
- recalc_lengths(data.edit);
- }
- else if (type == DEL_PARTICLE) {
- foreach_selected_point(&data, set_delete_particle);
- remove_tagged_particles(data.ob, data.edit->psys, pe_x_mirror(data.ob));
- recalc_lengths(data.edit);
- }
-
- DAG_id_tag_update(&data.ob->id, OB_RECALC_DATA);
- WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, data.ob);
-
- return OPERATOR_FINISHED;
-}
-
-void PARTICLE_OT_delete(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Delete";
- ot->idname = "PARTICLE_OT_delete";
- ot->description = "Delete selected particles or keys";
-
- /* api callbacks */
- ot->exec = delete_exec;
- ot->invoke = WM_menu_invoke;
- ot->poll = PE_hair_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", delete_type_items, DEL_PARTICLE, "Type", "Delete a full particle or only keys");
-}
-
-/*************************** mirror operator **************************/
-
-static void PE_mirror_x(Scene *scene, Object *ob, int tagged)
-{
- Mesh *me= (Mesh *)(ob->data);
- ParticleSystemModifierData *psmd;
- PTCacheEdit *edit= PE_get_current(scene, ob);
- ParticleSystem *psys = edit->psys;
- ParticleData *pa, *newpa, *new_pars;
- PTCacheEditPoint *newpoint, *new_points;
- POINT_P; KEY_K;
- HairKey *hkey;
- int *mirrorfaces = NULL;
- int rotation, totpart, newtotpart;
-
- if (psys->flag & PSYS_GLOBAL_HAIR)
- return;
-
- psmd= psys_get_modifier(ob, psys);
- if (!psmd->dm_final)
- return;
-
- const bool use_dm_final_indices = (psys->part->use_modifier_stack && !psmd->dm_final->deformedOnly);
-
- /* NOTE: this is not nice to use tessfaces but hard to avoid since pa->num uses tessfaces */
- BKE_mesh_tessface_ensure(me);
-
- /* Note: In case psys uses DM tessface indices, we mirror final DM itself, not orig mesh. Avoids an (impossible)
- * dm -> orig -> dm tessface indices conversion... */
- mirrorfaces = mesh_get_x_mirror_faces(ob, NULL, use_dm_final_indices ? psmd->dm_final : NULL);
-
- if (!edit->mirror_cache)
- PE_update_mirror_cache(ob, psys);
-
- totpart= psys->totpart;
- newtotpart= psys->totpart;
- LOOP_VISIBLE_POINTS {
- pa = psys->particles + p;
-
- if (!tagged) {
- if (point_is_selected(point)) {
- if (edit->mirror_cache[p] != -1) {
- /* already has a mirror, don't need to duplicate */
- PE_mirror_particle(ob, psmd->dm_final, psys, pa, NULL);
- continue;
- }
- else
- point->flag |= PEP_TAG;
- }
- }
-
- if ((point->flag & PEP_TAG) && mirrorfaces[pa->num*2] != -1)
- newtotpart++;
- }
-
- if (newtotpart != psys->totpart) {
- MFace *mtessface = use_dm_final_indices ? psmd->dm_final->getTessFaceArray(psmd->dm_final) : me->mface;
-
- /* allocate new arrays and copy existing */
- new_pars= MEM_callocN(newtotpart*sizeof(ParticleData), "ParticleData new");
- new_points= MEM_callocN(newtotpart*sizeof(PTCacheEditPoint), "PTCacheEditPoint new");
-
- if (psys->particles) {
- memcpy(new_pars, psys->particles, totpart*sizeof(ParticleData));
- MEM_freeN(psys->particles);
- }
- psys->particles= new_pars;
-
- if (edit->points) {
- memcpy(new_points, edit->points, totpart*sizeof(PTCacheEditPoint));
- MEM_freeN(edit->points);
- }
- edit->points= new_points;
-
- if (edit->mirror_cache) {
- MEM_freeN(edit->mirror_cache);
- edit->mirror_cache= NULL;
- }
-
- edit->totpoint= psys->totpart= newtotpart;
-
- /* create new elements */
- newpa= psys->particles + totpart;
- newpoint= edit->points + totpart;
-
- for (p=0, point=edit->points; p<totpart; p++, point++) {
- pa = psys->particles + p;
- const int pa_num = pa->num;
-
- if (point->flag & PEP_HIDE)
- continue;
-
- if (!(point->flag & PEP_TAG) || mirrorfaces[pa_num * 2] == -1)
- continue;
-
- /* duplicate */
- *newpa= *pa;
- *newpoint= *point;
- if (pa->hair) newpa->hair= MEM_dupallocN(pa->hair);
- if (point->keys) newpoint->keys= MEM_dupallocN(point->keys);
-
- /* rotate weights according to vertex index rotation */
- rotation= mirrorfaces[pa_num * 2 + 1];
- newpa->fuv[0] = pa->fuv[2];
- newpa->fuv[1] = pa->fuv[1];
- newpa->fuv[2] = pa->fuv[0];
- newpa->fuv[3] = pa->fuv[3];
- while (rotation--) {
- if (mtessface[pa_num].v4) {
- SHIFT4(float, newpa->fuv[0], newpa->fuv[1], newpa->fuv[2], newpa->fuv[3]);
- }
- else {
- SHIFT3(float, newpa->fuv[0], newpa->fuv[1], newpa->fuv[2]);
- }
- }
-
- /* assign face index */
- /* NOTE: mesh_get_x_mirror_faces generates -1 for non-found mirror, same as DMCACHE_NOTFOUND... */
- newpa->num = mirrorfaces[pa_num * 2];
-
- if (use_dm_final_indices) {
- newpa->num_dmcache = DMCACHE_ISCHILD;
- }
- else {
- newpa->num_dmcache = psys_particle_dm_face_lookup(
- psmd->dm_final, psmd->dm_deformed, newpa->num, newpa->fuv, NULL);
- }
-
- /* update edit key pointers */
- key= newpoint->keys;
- for (k=0, hkey=newpa->hair; k<newpa->totkey; k++, hkey++, key++) {
- key->co= hkey->co;
- key->time= &hkey->time;
- }
-
- /* map key positions as mirror over x axis */
- PE_mirror_particle(ob, psmd->dm_final, psys, pa, newpa);
-
- newpa++;
- newpoint++;
- }
- }
-
- LOOP_POINTS {
- point->flag &= ~PEP_TAG;
- }
-
- MEM_freeN(mirrorfaces);
-}
-
-static int mirror_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Scene *scene= CTX_data_scene(C);
- Object *ob= CTX_data_active_object(C);
- PTCacheEdit *edit= PE_get_current(scene, ob);
-
- PE_mirror_x(scene, ob, 0);
-
- update_world_cos(ob, edit);
- WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
-
- return OPERATOR_FINISHED;
-}
-
-void PARTICLE_OT_mirror(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Mirror";
- ot->idname = "PARTICLE_OT_mirror";
- ot->description = "Duplicate and mirror the selected particles along the local X axis";
-
- /* api callbacks */
- ot->exec = mirror_exec;
- ot->poll = PE_hair_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
-/************************* brush edit callbacks ********************/
-
-static void brush_comb(PEData *data, float UNUSED(mat[4][4]), float imat[4][4], int point_index, int key_index, PTCacheEditKey *key)
-{
- ParticleEditSettings *pset= PE_settings(data->scene);
- float cvec[3], fac;
-
- if (pset->flag & PE_LOCK_FIRST && key_index == 0) return;
-
- fac= (float)pow((double)(1.0f - data->dist / data->rad), (double)data->combfac);
-
- copy_v3_v3(cvec, data->dvec);
- mul_mat3_m4_v3(imat, cvec);
- mul_v3_fl(cvec, fac);
- add_v3_v3(key->co, cvec);
-
- (data->edit->points + point_index)->flag |= PEP_EDIT_RECALC;
-}
-
-static void brush_cut(PEData *data, int pa_index)
-{
- PTCacheEdit *edit = data->edit;
- ARegion *ar= data->vc.ar;
- Object *ob= data->ob;
- ParticleEditSettings *pset= PE_settings(data->scene);
- ParticleCacheKey *key= edit->pathcache[pa_index];
- float rad2, cut_time= 1.0;
- float x0, x1, v0, v1, o0, o1, xo0, xo1, d, dv;
- int k, cut, keys= (int)pow(2.0, (double)pset->draw_step);
- int screen_co[2];
-
- /* blunt scissors */
- if (BLI_frand() > data->cutfac) return;
-
- /* don't cut hidden */
- if (edit->points[pa_index].flag & PEP_HIDE)
- return;
-
- if (ED_view3d_project_int_global(ar, key->co, screen_co, V3D_PROJ_TEST_CLIP_NEAR) != V3D_PROJ_RET_OK)
- return;
-
- rad2= data->rad * data->rad;
-
- cut=0;
-
- x0 = (float)screen_co[0];
- x1 = (float)screen_co[1];
-
- o0= (float)data->mval[0];
- o1= (float)data->mval[1];
-
- xo0= x0 - o0;
- xo1= x1 - o1;
-
- /* check if root is inside circle */
- if (xo0*xo0 + xo1*xo1 < rad2 && key_test_depth(data, key->co, screen_co)) {
- cut_time= -1.0f;
- cut= 1;
- }
- else {
- /* calculate path time closest to root that was inside the circle */
- for (k=1, key++; k<=keys; k++, key++) {
-
- if ((ED_view3d_project_int_global(ar, key->co, screen_co, V3D_PROJ_TEST_CLIP_NEAR) != V3D_PROJ_RET_OK) ||
- key_test_depth(data, key->co, screen_co) == 0)
- {
- x0 = (float)screen_co[0];
- x1 = (float)screen_co[1];
-
- xo0= x0 - o0;
- xo1= x1 - o1;
- continue;
- }
-
- v0 = (float)screen_co[0] - x0;
- v1 = (float)screen_co[1] - x1;
-
- dv= v0*v0 + v1*v1;
-
- d= (v0*xo1 - v1*xo0);
-
- d= dv * rad2 - d*d;
-
- if (d > 0.0f) {
- d= sqrtf(d);
-
- cut_time= -(v0*xo0 + v1*xo1 + d);
-
- if (cut_time > 0.0f) {
- cut_time /= dv;
-
- if (cut_time < 1.0f) {
- cut_time += (float)(k-1);
- cut_time /= (float)keys;
- cut= 1;
- break;
- }
- }
- }
-
- x0 = (float)screen_co[0];
- x1 = (float)screen_co[1];
-
- xo0= x0 - o0;
- xo1= x1 - o1;
- }
- }
-
- if (cut) {
- if (cut_time < 0.0f) {
- edit->points[pa_index].flag |= PEP_TAG;
- }
- else {
- rekey_particle_to_time(data->scene, ob, pa_index, cut_time);
- edit->points[pa_index].flag |= PEP_EDIT_RECALC;
- }
- }
-}
-
-static void brush_length(PEData *data, int point_index)
-{
- PTCacheEdit *edit= data->edit;
- PTCacheEditPoint *point = edit->points + point_index;
- KEY_K;
- float dvec[3], pvec[3] = {0.0f, 0.0f, 0.0f};
-
- LOOP_KEYS {
- if (k==0) {
- copy_v3_v3(pvec, key->co);
- }
- else {
- sub_v3_v3v3(dvec, key->co, pvec);
- copy_v3_v3(pvec, key->co);
- mul_v3_fl(dvec, data->growfac);
- add_v3_v3v3(key->co, (key-1)->co, dvec);
- }
- }
-
- point->flag |= PEP_EDIT_RECALC;
-}
-
-static void brush_puff(PEData *data, int point_index)
-{
- PTCacheEdit *edit = data->edit;
- ParticleSystem *psys = edit->psys;
- PTCacheEditPoint *point = edit->points + point_index;
- KEY_K;
- float mat[4][4], imat[4][4];
-
- float onor_prev[3]; /* previous normal (particle-space) */
- float ofs_prev[3]; /* accumulate offset for puff_volume (particle-space) */
- float co_root[3], no_root[3]; /* root location and normal (global-space) */
- float co_prev[3], co[3]; /* track key coords as we loop (global-space) */
- float fac = 0.0f, length_accum = 0.0f;
- bool puff_volume = false;
- bool changed = false;
-
- zero_v3(ofs_prev);
-
- {
- ParticleEditSettings *pset= PE_settings(data->scene);
- ParticleBrushData *brush= &pset->brush[pset->brushtype];
- puff_volume = (brush->flag & PE_BRUSH_DATA_PUFF_VOLUME) != 0;
- }
-
- if (psys && !(psys->flag & PSYS_GLOBAL_HAIR)) {
- psys_mat_hair_to_global(data->ob, data->dm, psys->part->from, psys->particles + point_index, mat);
- invert_m4_m4(imat, mat);
- }
- else {
- unit_m4(mat);
- unit_m4(imat);
- }
-
- LOOP_KEYS {
- float kco[3];
-
- if (k==0) {
- /* find root coordinate and normal on emitter */
- copy_v3_v3(co, key->co);
- mul_m4_v3(mat, co);
- mul_v3_m4v3(kco, data->ob->imat, co); /* use 'kco' as the object space version of worldspace 'co', ob->imat is set before calling */
-
- point_index= BLI_kdtree_find_nearest(edit->emitter_field, kco, NULL);
- if (point_index == -1) return;
-
- copy_v3_v3(co_root, co);
- copy_v3_v3(no_root, &edit->emitter_cosnos[point_index * 6 + 3]);
- mul_mat3_m4_v3(data->ob->obmat, no_root); /* normal into global-space */
- normalize_v3(no_root);
-
- if (puff_volume) {
- copy_v3_v3(onor_prev, no_root);
- mul_mat3_m4_v3(imat, onor_prev); /* global-space into particle space */
- normalize_v3(onor_prev);
- }
-
- fac= (float)pow((double)(1.0f - data->dist / data->rad), (double)data->pufffac);
- fac *= 0.025f;
- if (data->invert)
- fac= -fac;
- }
- else {
- /* compute position as if hair was standing up straight.
- * */
- float length;
- copy_v3_v3(co_prev, co);
- copy_v3_v3(co, key->co);
- mul_m4_v3(mat, co);
- length = len_v3v3(co_prev, co);
- length_accum += length;
-
- if ((data->select==0 || (key->flag & PEK_SELECT)) && !(key->flag & PEK_HIDE)) {
- float dco[3]; /* delta temp var */
-
- madd_v3_v3v3fl(kco, co_root, no_root, length_accum);
-
- /* blend between the current and straight position */
- sub_v3_v3v3(dco, kco, co);
- madd_v3_v3fl(co, dco, fac);
- /* keep the same distance from the root or we get glitches [#35406] */
- dist_ensure_v3_v3fl(co, co_root, length_accum);
-
- /* re-use dco to compare before and after translation and add to the offset */
- copy_v3_v3(dco, key->co);
-
- mul_v3_m4v3(key->co, imat, co);
-
- if (puff_volume) {
- /* accumulate the total distance moved to apply to unselected
- * keys that come after */
- sub_v3_v3v3(ofs_prev, key->co, dco);
- }
- changed = true;
- }
- else {
-
- if (puff_volume) {
-#if 0
- /* this is simple but looks bad, adds annoying kinks */
- add_v3_v3(key->co, ofs);
-#else
- /* translate (not rotate) the rest of the hair if its not selected */
- {
-#if 0 /* kindof works but looks worse then whats below */
-
- /* Move the unselected point on a vector based on the
- * hair direction and the offset */
- float c1[3], c2[3];
- sub_v3_v3v3(dco, lastco, co);
- mul_mat3_m4_v3(imat, dco); /* into particle space */
-
- /* move the point along a vector perpendicular to the
- * hairs direction, reduces odd kinks, */
- cross_v3_v3v3(c1, ofs, dco);
- cross_v3_v3v3(c2, c1, dco);
- normalize_v3(c2);
- mul_v3_fl(c2, len_v3(ofs));
- add_v3_v3(key->co, c2);
-#else
- /* Move the unselected point on a vector based on the
- * the normal of the closest geometry */
- float oco[3], onor[3];
- copy_v3_v3(oco, key->co);
- mul_m4_v3(mat, oco);
- mul_v3_m4v3(kco, data->ob->imat, oco); /* use 'kco' as the object space version of worldspace 'co', ob->imat is set before calling */
-
- point_index= BLI_kdtree_find_nearest(edit->emitter_field, kco, NULL);
- if (point_index != -1) {
- copy_v3_v3(onor, &edit->emitter_cosnos[point_index*6+3]);
- mul_mat3_m4_v3(data->ob->obmat, onor); /* normal into worldspace */
- mul_mat3_m4_v3(imat, onor); /* worldspace into particle space */
- normalize_v3(onor);
- }
- else {
- copy_v3_v3(onor, onor_prev);
- }
-
- if (!is_zero_v3(ofs_prev)) {
- mul_v3_fl(onor, len_v3(ofs_prev));
-
- add_v3_v3(key->co, onor);
- }
-
- copy_v3_v3(onor_prev, onor);
-#endif
- }
-#endif
- }
- }
- }
- }
-
- if (changed)
- point->flag |= PEP_EDIT_RECALC;
-}
-
-
-static void BKE_brush_weight_get(PEData *data, float UNUSED(mat[4][4]), float UNUSED(imat[4][4]), int point_index, int key_index, PTCacheEditKey *UNUSED(key))
-{
- /* roots have full weight always */
- if (key_index) {
- PTCacheEdit *edit = data->edit;
- ParticleSystem *psys = edit->psys;
-
- ParticleData *pa= psys->particles + point_index;
- pa->hair[key_index].weight = data->weightfac;
-
- (data->edit->points + point_index)->flag |= PEP_EDIT_RECALC;
- }
-}
-
-static void brush_smooth_get(PEData *data, float mat[4][4], float UNUSED(imat[4][4]), int UNUSED(point_index), int key_index, PTCacheEditKey *key)
-{
- if (key_index) {
- float dvec[3];
-
- sub_v3_v3v3(dvec, key->co, (key-1)->co);
- mul_mat3_m4_v3(mat, dvec);
- add_v3_v3(data->vec, dvec);
- data->tot++;
- }
-}
-
-static void brush_smooth_do(PEData *data, float UNUSED(mat[4][4]), float imat[4][4], int point_index, int key_index, PTCacheEditKey *key)
-{
- float vec[3], dvec[3];
-
- if (key_index) {
- copy_v3_v3(vec, data->vec);
- mul_mat3_m4_v3(imat, vec);
-
- sub_v3_v3v3(dvec, key->co, (key-1)->co);
-
- sub_v3_v3v3(dvec, vec, dvec);
- mul_v3_fl(dvec, data->smoothfac);
-
- add_v3_v3(key->co, dvec);
- }
-
- (data->edit->points + point_index)->flag |= PEP_EDIT_RECALC;
-}
-
-/* convert from triangle barycentric weights to quad mean value weights */
-static void intersect_dm_quad_weights(const float v1[3], const float v2[3], const float v3[3], const float v4[3], float w[4])
-{
- float co[3], vert[4][3];
-
- copy_v3_v3(vert[0], v1);
- copy_v3_v3(vert[1], v2);
- copy_v3_v3(vert[2], v3);
- copy_v3_v3(vert[3], v4);
-
- co[0] = v1[0]*w[0] + v2[0]*w[1] + v3[0]*w[2] + v4[0]*w[3];
- co[1] = v1[1]*w[0] + v2[1]*w[1] + v3[1]*w[2] + v4[1]*w[3];
- co[2] = v1[2]*w[0] + v2[2]*w[1] + v3[2]*w[2] + v4[2]*w[3];
-
- interp_weights_poly_v3(w, vert, 4, co);
-}
-
-/* check intersection with a derivedmesh */
-static int particle_intersect_dm(Scene *scene, Object *ob, DerivedMesh *dm,
- float *vert_cos,
- const float co1[3], const float co2[3],
- float *min_d, int *min_face, float *min_w,
- float *face_minmax, float *pa_minmax,
- float radius, float *ipoint)
-{
- MFace *mface= NULL;
- MVert *mvert= NULL;
- int i, totface, intersect=0;
- float cur_d, cur_uv[2], v1[3], v2[3], v3[3], v4[3], min[3], max[3], p_min[3], p_max[3];
- float cur_ipoint[3];
-
- if (dm == NULL) {
- psys_disable_all(ob);
-
- dm=mesh_get_derived_final(scene, ob, 0);
- if (dm == NULL)
- dm=mesh_get_derived_deform(scene, ob, 0);
-
- psys_enable_all(ob);
-
- if (dm == NULL)
- return 0;
- }
-
- /* BMESH_ONLY, deform dm may not have tessface */
- DM_ensure_tessface(dm);
-
-
- if (pa_minmax==0) {
- INIT_MINMAX(p_min, p_max);
- minmax_v3v3_v3(p_min, p_max, co1);
- minmax_v3v3_v3(p_min, p_max, co2);
- }
- else {
- copy_v3_v3(p_min, pa_minmax);
- copy_v3_v3(p_max, pa_minmax+3);
- }
-
- totface=dm->getNumTessFaces(dm);
- mface=dm->getTessFaceDataArray(dm, CD_MFACE);
- mvert=dm->getVertDataArray(dm, CD_MVERT);
-
- /* lets intersect the faces */
- for (i=0; i<totface; i++, mface++) {
- if (vert_cos) {
- copy_v3_v3(v1, vert_cos+3*mface->v1);
- copy_v3_v3(v2, vert_cos+3*mface->v2);
- copy_v3_v3(v3, vert_cos+3*mface->v3);
- if (mface->v4)
- copy_v3_v3(v4, vert_cos+3*mface->v4);
- }
- else {
- copy_v3_v3(v1, mvert[mface->v1].co);
- copy_v3_v3(v2, mvert[mface->v2].co);
- copy_v3_v3(v3, mvert[mface->v3].co);
- if (mface->v4)
- copy_v3_v3(v4, mvert[mface->v4].co);
- }
-
- if (face_minmax==0) {
- INIT_MINMAX(min, max);
- DO_MINMAX(v1, min, max);
- DO_MINMAX(v2, min, max);
- DO_MINMAX(v3, min, max);
- if (mface->v4)
- DO_MINMAX(v4, min, max);
- if (isect_aabb_aabb_v3(min, max, p_min, p_max)==0)
- continue;
- }
- else {
- copy_v3_v3(min, face_minmax+6*i);
- copy_v3_v3(max, face_minmax+6*i+3);
- if (isect_aabb_aabb_v3(min, max, p_min, p_max)==0)
- continue;
- }
-
- if (radius>0.0f) {
- if (isect_sweeping_sphere_tri_v3(co1, co2, radius, v2, v3, v1, &cur_d, cur_ipoint)) {
- if (cur_d<*min_d) {
- *min_d=cur_d;
- copy_v3_v3(ipoint, cur_ipoint);
- *min_face=i;
- intersect=1;
- }
- }
- if (mface->v4) {
- if (isect_sweeping_sphere_tri_v3(co1, co2, radius, v4, v1, v3, &cur_d, cur_ipoint)) {
- if (cur_d<*min_d) {
- *min_d=cur_d;
- copy_v3_v3(ipoint, cur_ipoint);
- *min_face=i;
- intersect=1;
- }
- }
- }
- }
- else {
- if (isect_line_segment_tri_v3(co1, co2, v1, v2, v3, &cur_d, cur_uv)) {
- if (cur_d<*min_d) {
- *min_d=cur_d;
- min_w[0] = 1.0f - cur_uv[0] - cur_uv[1];
- min_w[1] = cur_uv[0];
- min_w[2] = cur_uv[1];
- min_w[3] = 0.0f;
- if (mface->v4)
- intersect_dm_quad_weights(v1, v2, v3, v4, min_w);
- *min_face=i;
- intersect=1;
- }
- }
- if (mface->v4) {
- if (isect_line_segment_tri_v3(co1, co2, v1, v3, v4, &cur_d, cur_uv)) {
- if (cur_d<*min_d) {
- *min_d=cur_d;
- min_w[0] = 1.0f - cur_uv[0] - cur_uv[1];
- min_w[1] = 0.0f;
- min_w[2] = cur_uv[0];
- min_w[3] = cur_uv[1];
- intersect_dm_quad_weights(v1, v2, v3, v4, min_w);
- *min_face=i;
- intersect=1;
- }
- }
- }
- }
- }
- return intersect;
-}
-
-static int brush_add(PEData *data, short number)
-{
- Scene *scene= data->scene;
- Object *ob= data->ob;
- DerivedMesh *dm;
- PTCacheEdit *edit = data->edit;
- ParticleSystem *psys= edit->psys;
- ParticleData *add_pars;
- ParticleSystemModifierData *psmd= psys_get_modifier(ob, psys);
- ParticleSimulationData sim= {0};
- ParticleEditSettings *pset= PE_settings(scene);
- int i, k, n= 0, totpart= psys->totpart;
- float mco[2];
- float dmx, dmy;
- float co1[3], co2[3], min_d, imat[4][4];
- float framestep, timestep;
- short size= pset->brush[PE_BRUSH_ADD].size;
- short size2= size*size;
- RNG *rng;
-
- invert_m4_m4(imat, ob->obmat);
-
- if (psys->flag & PSYS_GLOBAL_HAIR)
- return 0;
-
- add_pars = MEM_callocN(number * sizeof(ParticleData), "ParticleData add");
-
- rng = BLI_rng_new_srandom(psys->seed+data->mval[0]+data->mval[1]);
-
- sim.scene= scene;
- sim.ob= ob;
- sim.psys= psys;
- sim.psmd= psmd;
-
- timestep= psys_get_timestep(&sim);
-
- if (psys->part->use_modifier_stack || psmd->dm_final->deformedOnly) {
- dm = psmd->dm_final;
- }
- else {
- dm = psmd->dm_deformed;
- }
- BLI_assert(dm);
-
- for (i=0; i<number; i++) {
- if (number>1) {
- dmx = size;
- dmy = size;
-
- /* rejection sampling to get points in circle */
- while (dmx*dmx + dmy*dmy > size2) {
- dmx= (2.0f*BLI_rng_get_float(rng) - 1.0f)*size;
- dmy= (2.0f*BLI_rng_get_float(rng) - 1.0f)*size;
- }
- }
- else {
- dmx = 0.0f;
- dmy = 0.0f;
- }
-
- mco[0] = data->mval[0] + dmx;
- mco[1] = data->mval[1] + dmy;
- ED_view3d_win_to_segment(data->vc.ar, data->vc.v3d, mco, co1, co2, true);
-
- mul_m4_v3(imat, co1);
- mul_m4_v3(imat, co2);
- min_d=2.0;
-
- /* warning, returns the derived mesh face */
- if (particle_intersect_dm(scene, ob, dm, 0, co1, co2, &min_d, &add_pars[n].num_dmcache, add_pars[n].fuv, 0, 0, 0, 0)) {
- if (psys->part->use_modifier_stack && !psmd->dm_final->deformedOnly) {
- add_pars[n].num = add_pars[n].num_dmcache;
- add_pars[n].num_dmcache = DMCACHE_ISCHILD;
- }
- else if (dm == psmd->dm_deformed) {
- /* Final DM is not same topology as orig mesh, we have to map num_dmcache to real final dm. */
- add_pars[n].num = add_pars[n].num_dmcache;
- add_pars[n].num_dmcache = psys_particle_dm_face_lookup(
- psmd->dm_final, psmd->dm_deformed,
- add_pars[n].num, add_pars[n].fuv, NULL);
- }
- else {
- add_pars[n].num = add_pars[n].num_dmcache;
- }
-
- if (add_pars[n].num != DMCACHE_NOTFOUND) {
- n++;
- }
- }
- }
- if (n) {
- int newtotpart=totpart+n;
- float hairmat[4][4], cur_co[3];
- KDTree *tree=0;
- ParticleData *pa, *new_pars = MEM_callocN(newtotpart*sizeof(ParticleData), "ParticleData new");
- PTCacheEditPoint *point, *new_points = MEM_callocN(newtotpart*sizeof(PTCacheEditPoint), "PTCacheEditPoint array new");
- PTCacheEditKey *key;
- HairKey *hkey;
-
- /* save existing elements */
- memcpy(new_pars, psys->particles, totpart * sizeof(ParticleData));
- memcpy(new_points, edit->points, totpart * sizeof(PTCacheEditPoint));
-
- /* change old arrays to new ones */
- if (psys->particles) MEM_freeN(psys->particles);
- psys->particles= new_pars;
-
- if (edit->points) MEM_freeN(edit->points);
- edit->points= new_points;
-
- if (edit->mirror_cache) {
- MEM_freeN(edit->mirror_cache);
- edit->mirror_cache= NULL;
- }
-
- /* create tree for interpolation */
- if (pset->flag & PE_INTERPOLATE_ADDED && psys->totpart) {
- tree=BLI_kdtree_new(psys->totpart);
-
- for (i=0, pa=psys->particles; i<totpart; i++, pa++) {
- psys_particle_on_dm(psmd->dm_final, psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, cur_co, 0, 0, 0, 0, 0);
- BLI_kdtree_insert(tree, i, cur_co);
- }
-
- BLI_kdtree_balance(tree);
- }
-
- edit->totpoint= psys->totpart= newtotpart;
-
- /* create new elements */
- pa = psys->particles + totpart;
- point = edit->points + totpart;
-
- for (i=totpart; i<newtotpart; i++, pa++, point++) {
- memcpy(pa, add_pars + i - totpart, sizeof(ParticleData));
- pa->hair= MEM_callocN(pset->totaddkey * sizeof(HairKey), "BakeKey key add");
- key= point->keys= MEM_callocN(pset->totaddkey * sizeof(PTCacheEditKey), "PTCacheEditKey add");
- point->totkey= pa->totkey= pset->totaddkey;
-
- for (k=0, hkey=pa->hair; k<pa->totkey; k++, hkey++, key++) {
- key->co= hkey->co;
- key->time= &hkey->time;
-
- if (!(psys->flag & PSYS_GLOBAL_HAIR))
- key->flag |= PEK_USE_WCO;
- }
-
- pa->size= 1.0f;
- initialize_particle(&sim, pa);
- reset_particle(&sim, pa, 0.0, 1.0);
- point->flag |= PEP_EDIT_RECALC;
- if (pe_x_mirror(ob))
- point->flag |= PEP_TAG; /* signal for duplicate */
-
- framestep= pa->lifetime/(float)(pset->totaddkey-1);
-
- if (tree) {
- ParticleData *ppa;
- HairKey *thkey;
- ParticleKey key3[3];
- KDTreeNearest ptn[3];
- int w, maxw;
- float maxd, totw=0.0, weight[3];
-
- psys_particle_on_dm(psmd->dm_final, psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, co1, 0, 0, 0, 0, 0);
- maxw = BLI_kdtree_find_nearest_n(tree, co1, ptn, 3);
-
- maxd= ptn[maxw-1].dist;
-
- for (w=0; w<maxw; w++) {
- weight[w] = (float)pow(2.0, (double)(-6.0f * ptn[w].dist / maxd));
- totw += weight[w];
- }
- for (;w<3; w++) {
- weight[w] = 0.0f;
- }
-
- if (totw > 0.0f) {
- for (w=0; w<maxw; w++)
- weight[w] /= totw;
- }
- else {
- for (w=0; w<maxw; w++)
- weight[w] = 1.0f/maxw;
- }
-
- ppa= psys->particles+ptn[0].index;
-
- for (k=0; k<pset->totaddkey; k++) {
- thkey= (HairKey *)pa->hair + k;
- thkey->time= pa->time + k * framestep;
-
- key3[0].time= thkey->time/ 100.0f;
- psys_get_particle_on_path(&sim, ptn[0].index, key3, 0);
- mul_v3_fl(key3[0].co, weight[0]);
-
- /* TODO: interpolating the weight would be nicer */
- thkey->weight= (ppa->hair+MIN2(k, ppa->totkey-1))->weight;
-
- if (maxw>1) {
- key3[1].time= key3[0].time;
- psys_get_particle_on_path(&sim, ptn[1].index, &key3[1], 0);
- mul_v3_fl(key3[1].co, weight[1]);
- add_v3_v3(key3[0].co, key3[1].co);
-
- if (maxw>2) {
- key3[2].time= key3[0].time;
- psys_get_particle_on_path(&sim, ptn[2].index, &key3[2], 0);
- mul_v3_fl(key3[2].co, weight[2]);
- add_v3_v3(key3[0].co, key3[2].co);
- }
- }
-
- if (k==0)
- sub_v3_v3v3(co1, pa->state.co, key3[0].co);
-
- add_v3_v3v3(thkey->co, key3[0].co, co1);
-
- thkey->time= key3[0].time;
- }
- }
- else {
- for (k=0, hkey=pa->hair; k<pset->totaddkey; k++, hkey++) {
- madd_v3_v3v3fl(hkey->co, pa->state.co, pa->state.vel, k * framestep * timestep);
- hkey->time += k * framestep;
- hkey->weight = 1.f - (float)k/(float)(pset->totaddkey-1);
- }
- }
- for (k=0, hkey=pa->hair; k<pset->totaddkey; k++, hkey++) {
- psys_mat_hair_to_global(ob, psmd->dm_final, psys->part->from, pa, hairmat);
- invert_m4_m4(imat, hairmat);
- mul_m4_v3(imat, hkey->co);
- }
- }
-
- if (tree)
- BLI_kdtree_free(tree);
- }
-
- MEM_freeN(add_pars);
-
- BLI_rng_free(rng);
-
- return n;
-}
-
-/************************* brush edit operator ********************/
-
-typedef struct BrushEdit {
- Scene *scene;
- Object *ob;
- PTCacheEdit *edit;
-
- int first;
- int lastmouse[2];
- float zfac;
-
- /* optional cached view settings to avoid setting on every mousemove */
- PEData data;
-} BrushEdit;
-
-static int brush_edit_init(bContext *C, wmOperator *op)
-{
- Scene *scene= CTX_data_scene(C);
- Object *ob= CTX_data_active_object(C);
- ParticleEditSettings *pset= PE_settings(scene);
- PTCacheEdit *edit= PE_get_current(scene, ob);
- ARegion *ar= CTX_wm_region(C);
- BrushEdit *bedit;
- float min[3], max[3];
-
- if (pset->brushtype < 0)
- return 0;
-
- /* set the 'distance factor' for grabbing (used in comb etc) */
- INIT_MINMAX(min, max);
- PE_minmax(scene, min, max);
- mid_v3_v3v3(min, min, max);
-
- bedit= MEM_callocN(sizeof(BrushEdit), "BrushEdit");
- bedit->first= 1;
- op->customdata= bedit;
-
- bedit->scene= scene;
- bedit->ob= ob;
- bedit->edit= edit;
-
- bedit->zfac = ED_view3d_calc_zfac(ar->regiondata, min, NULL);
-
- /* cache view depths and settings for re-use */
- PE_set_view3d_data(C, &bedit->data);
-
- return 1;
-}
-
-static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
-{
- BrushEdit *bedit= op->customdata;
- Scene *scene= bedit->scene;
- Object *ob= bedit->ob;
- PTCacheEdit *edit= bedit->edit;
- ParticleEditSettings *pset= PE_settings(scene);
- ParticleSystemModifierData *psmd= edit->psys ? psys_get_modifier(ob, edit->psys) : NULL;
- ParticleBrushData *brush= &pset->brush[pset->brushtype];
- ARegion *ar= CTX_wm_region(C);
- float vec[3], mousef[2];
- int mval[2];
- int flip, mouse[2], removed= 0, added=0, selected= 0, tot_steps= 1, step= 1;
- float dx, dy, dmax;
- int lock_root = pset->flag & PE_LOCK_FIRST;
-
- if (!PE_start_edit(edit))
- return;
-
- RNA_float_get_array(itemptr, "mouse", mousef);
- mouse[0] = mousef[0];
- mouse[1] = mousef[1];
- flip= RNA_boolean_get(itemptr, "pen_flip");
-
- if (bedit->first) {
- bedit->lastmouse[0] = mouse[0];
- bedit->lastmouse[1] = mouse[1];
- }
-
- dx= mouse[0] - bedit->lastmouse[0];
- dy= mouse[1] - bedit->lastmouse[1];
-
- mval[0] = mouse[0];
- mval[1] = mouse[1];
-
-
- /* disable locking temporatily for disconnected hair */
- if (edit->psys && edit->psys->flag & PSYS_GLOBAL_HAIR)
- pset->flag &= ~PE_LOCK_FIRST;
-
- if (((pset->brushtype == PE_BRUSH_ADD) ?
- (sqrtf(dx * dx + dy * dy) > pset->brush[PE_BRUSH_ADD].step) : (dx != 0 || dy != 0)) || bedit->first)
- {
- PEData data= bedit->data;
-
- view3d_operator_needs_opengl(C);
- selected= (short)count_selected_keys(scene, edit);
-
- dmax = max_ff(fabsf(dx), fabsf(dy));
- tot_steps = dmax/(0.2f * pe_brush_size_get(scene, brush)) + 1;
-
- dx /= (float)tot_steps;
- dy /= (float)tot_steps;
-
- for (step = 1; step<=tot_steps; step++) {
- mval[0] = bedit->lastmouse[0] + step*dx;
- mval[1] = bedit->lastmouse[1] + step*dy;
-
- switch (pset->brushtype) {
- case PE_BRUSH_COMB:
- {
- const float mval_f[2] = {dx, dy};
- data.mval= mval;
- data.rad= pe_brush_size_get(scene, brush);
-
- data.combfac= (brush->strength - 0.5f) * 2.0f;
- if (data.combfac < 0.0f)
- data.combfac= 1.0f - 9.0f * data.combfac;
- else
- data.combfac= 1.0f - data.combfac;
-
- invert_m4_m4(ob->imat, ob->obmat);
-
- ED_view3d_win_to_delta(ar, mval_f, vec, bedit->zfac);
- data.dvec= vec;
-
- foreach_mouse_hit_key(&data, brush_comb, selected);
- break;
- }
- case PE_BRUSH_CUT:
- {
- if (edit->psys && edit->pathcache) {
- data.mval= mval;
- data.rad= pe_brush_size_get(scene, brush);
- data.cutfac= brush->strength;
-
- if (selected)
- foreach_selected_point(&data, brush_cut);
- else
- foreach_point(&data, brush_cut);
-
- removed= remove_tagged_particles(ob, edit->psys, pe_x_mirror(ob));
- if (pset->flag & PE_KEEP_LENGTHS)
- recalc_lengths(edit);
- }
- else
- removed= 0;
-
- break;
- }
- case PE_BRUSH_LENGTH:
- {
- data.mval= mval;
-
- data.rad= pe_brush_size_get(scene, brush);
- data.growfac= brush->strength / 50.0f;
-
- if (brush->invert ^ flip)
- data.growfac= 1.0f - data.growfac;
- else
- data.growfac= 1.0f + data.growfac;
-
- foreach_mouse_hit_point(&data, brush_length, selected);
-
- if (pset->flag & PE_KEEP_LENGTHS)
- recalc_lengths(edit);
- break;
- }
- case PE_BRUSH_PUFF:
- {
- if (edit->psys) {
- data.dm= psmd->dm_final;
- data.mval= mval;
- data.rad= pe_brush_size_get(scene, brush);
- data.select= selected;
-
- data.pufffac= (brush->strength - 0.5f) * 2.0f;
- if (data.pufffac < 0.0f)
- data.pufffac= 1.0f - 9.0f * data.pufffac;
- else
- data.pufffac= 1.0f - data.pufffac;
-
- data.invert= (brush->invert ^ flip);
- invert_m4_m4(ob->imat, ob->obmat);
-
- foreach_mouse_hit_point(&data, brush_puff, selected);
- }
- break;
- }
- case PE_BRUSH_ADD:
- {
- if (edit->psys && edit->psys->part->from==PART_FROM_FACE) {
- data.mval= mval;
-
- added= brush_add(&data, brush->count);
-
- if (pset->flag & PE_KEEP_LENGTHS)
- recalc_lengths(edit);
- }
- else
- added= 0;
- break;
- }
- case PE_BRUSH_SMOOTH:
- {
- data.mval= mval;
- data.rad= pe_brush_size_get(scene, brush);
-
- data.vec[0] = data.vec[1] = data.vec[2] = 0.0f;
- data.tot= 0;
-
- data.smoothfac= brush->strength;
-
- invert_m4_m4(ob->imat, ob->obmat);
-
- foreach_mouse_hit_key(&data, brush_smooth_get, selected);
-
- if (data.tot) {
- mul_v3_fl(data.vec, 1.0f / (float)data.tot);
- foreach_mouse_hit_key(&data, brush_smooth_do, selected);
- }
-
- break;
- }
- case PE_BRUSH_WEIGHT:
- {
- if (edit->psys) {
- data.dm= psmd->dm_final;
- data.mval= mval;
- data.rad= pe_brush_size_get(scene, brush);
-
- data.weightfac = brush->strength; /* note that this will never be zero */
-
- foreach_mouse_hit_key(&data, BKE_brush_weight_get, selected);
- }
-
- break;
- }
- }
- if ((pset->flag & PE_KEEP_LENGTHS)==0)
- recalc_lengths(edit);
-
- if (ELEM(pset->brushtype, PE_BRUSH_ADD, PE_BRUSH_CUT) && (added || removed)) {
- if (pset->brushtype == PE_BRUSH_ADD && pe_x_mirror(ob))
- PE_mirror_x(scene, ob, 1);
-
- update_world_cos(ob, edit);
- psys_free_path_cache(NULL, edit);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
- }
- else
- PE_update_object(scene, ob, 1);
- }
-
- if (edit->psys) {
- WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob);
- }
- else {
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
- WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
- }
-
- bedit->lastmouse[0] = mouse[0];
- bedit->lastmouse[1] = mouse[1];
- bedit->first= 0;
- }
-
- pset->flag |= lock_root;
-}
-
-static void brush_edit_exit(wmOperator *op)
-{
- BrushEdit *bedit= op->customdata;
-
- MEM_freeN(bedit);
-}
-
-static int brush_edit_exec(bContext *C, wmOperator *op)
-{
- if (!brush_edit_init(C, op))
- return OPERATOR_CANCELLED;
-
- RNA_BEGIN (op->ptr, itemptr, "stroke")
- {
- brush_edit_apply(C, op, &itemptr);
- }
- RNA_END;
-
- brush_edit_exit(op);
-
- return OPERATOR_FINISHED;
-}
-
-static void brush_edit_apply_event(bContext *C, wmOperator *op, const wmEvent *event)
-{
- PointerRNA itemptr;
- float mouse[2];
-
- VECCOPY2D(mouse, event->mval);
-
- /* fill in stroke */
- RNA_collection_add(op->ptr, "stroke", &itemptr);
-
- RNA_float_set_array(&itemptr, "mouse", mouse);
- RNA_boolean_set(&itemptr, "pen_flip", event->shift != false); // XXX hardcoded
-
- /* apply */
- brush_edit_apply(C, op, &itemptr);
-}
-
-static int brush_edit_invoke(bContext *C, wmOperator *op, const wmEvent *event)
-{
- if (!brush_edit_init(C, op))
- return OPERATOR_CANCELLED;
-
- brush_edit_apply_event(C, op, event);
-
- WM_event_add_modal_handler(C, op);
-
- return OPERATOR_RUNNING_MODAL;
-}
-
-static int brush_edit_modal(bContext *C, wmOperator *op, const wmEvent *event)
-{
- switch (event->type) {
- case LEFTMOUSE:
- case MIDDLEMOUSE:
- case RIGHTMOUSE: // XXX hardcoded
- brush_edit_exit(op);
- return OPERATOR_FINISHED;
- case MOUSEMOVE:
- brush_edit_apply_event(C, op, event);
- break;
- }
-
- return OPERATOR_RUNNING_MODAL;
-}
-
-static void brush_edit_cancel(bContext *UNUSED(C), wmOperator *op)
-{
- brush_edit_exit(op);
-}
-
-void PARTICLE_OT_brush_edit(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Brush Edit";
- ot->idname = "PARTICLE_OT_brush_edit";
- ot->description = "Apply a stroke of brush to the particles";
-
- /* api callbacks */
- ot->exec = brush_edit_exec;
- ot->invoke = brush_edit_invoke;
- ot->modal = brush_edit_modal;
- ot->cancel = brush_edit_cancel;
- ot->poll = PE_poll_view3d;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING;
-
- /* properties */
- RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", "");
-}
-
-/*********************** cut shape ***************************/
-
-static int shape_cut_poll(bContext *C)
-{
- if (PE_hair_poll(C)) {
- Scene *scene = CTX_data_scene(C);
- ParticleEditSettings *pset = PE_settings(scene);
-
- if (pset->shape_object && (pset->shape_object->type == OB_MESH)) {
- return true;
- }
- }
-
- return false;
-}
-
-typedef struct PointInsideBVH {
- BVHTreeFromMesh bvhdata;
- int num_hits;
-} PointInsideBVH;
-
-static void point_inside_bvh_cb(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
-{
- PointInsideBVH *data = userdata;
-
- data->bvhdata.raycast_callback(&data->bvhdata, index, ray, hit);
-
- if (hit->index != -1)
- ++data->num_hits;
-}
-
-/* true if the point is inside the shape mesh */
-static bool shape_cut_test_point(PEData *data, ParticleCacheKey *key)
-{
- BVHTreeFromMesh *shape_bvh = &data->shape_bvh;
- const float dir[3] = {1.0f, 0.0f, 0.0f};
- PointInsideBVH userdata;
-
- userdata.bvhdata = data->shape_bvh;
- userdata.num_hits = 0;
-
- BLI_bvhtree_ray_cast_all(
- shape_bvh->tree, key->co, dir, 0.0f, BVH_RAYCAST_DIST_MAX,
- point_inside_bvh_cb, &userdata);
-
- /* for any point inside a watertight mesh the number of hits is uneven */
- return (userdata.num_hits % 2) == 1;
-}
-
-static void shape_cut(PEData *data, int pa_index)
-{
- PTCacheEdit *edit = data->edit;
- Object *ob = data->ob;
- ParticleEditSettings *pset = PE_settings(data->scene);
- ParticleCacheKey *key;
-
- bool cut;
- float cut_time = 1.0;
- int k, totkeys = 1 << pset->draw_step;
-
- /* don't cut hidden */
- if (edit->points[pa_index].flag & PEP_HIDE)
- return;
-
- cut = false;
-
- /* check if root is inside the cut shape */
- key = edit->pathcache[pa_index];
- if (!shape_cut_test_point(data, key)) {
- cut_time = -1.0f;
- cut = true;
- }
- else {
- for (k = 0; k < totkeys; k++, key++) {
- BVHTreeRayHit hit;
- float dir[3];
- float len;
-
- sub_v3_v3v3(dir, (key+1)->co, key->co);
- len = normalize_v3(dir);
-
- memset(&hit, 0, sizeof(hit));
- hit.index = -1;
- hit.dist = len;
- BLI_bvhtree_ray_cast(data->shape_bvh.tree, key->co, dir, 0.0f, &hit, data->shape_bvh.raycast_callback, &data->shape_bvh);
- if (hit.index >= 0) {
- if (hit.dist < len) {
- cut_time = (hit.dist / len + (float)k) / (float)totkeys;
- cut = true;
- break;
- }
- }
- }
- }
-
- if (cut) {
- if (cut_time < 0.0f) {
- edit->points[pa_index].flag |= PEP_TAG;
- }
- else {
- rekey_particle_to_time(data->scene, ob, pa_index, cut_time);
- edit->points[pa_index].flag |= PEP_EDIT_RECALC;
- }
- }
-}
-
-static int shape_cut_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Scene *scene = CTX_data_scene(C);
- Object *ob = CTX_data_active_object(C);
- ParticleEditSettings *pset = PE_settings(scene);
- PTCacheEdit *edit = PE_get_current(scene, ob);
- Object *shapeob = pset->shape_object;
- int selected = count_selected_keys(scene, edit);
- int lock_root = pset->flag & PE_LOCK_FIRST;
-
- if (!PE_start_edit(edit))
- return OPERATOR_CANCELLED;
-
- /* disable locking temporatily for disconnected hair */
- if (edit->psys && edit->psys->flag & PSYS_GLOBAL_HAIR)
- pset->flag &= ~PE_LOCK_FIRST;
-
- if (edit->psys && edit->pathcache) {
- PEData data;
- int removed;
-
- PE_set_data(C, &data);
- if (!PE_create_shape_tree(&data, shapeob)) {
- /* shapeob may not have faces... */
- return OPERATOR_CANCELLED;
- }
-
- if (selected)
- foreach_selected_point(&data, shape_cut);
- else
- foreach_point(&data, shape_cut);
-
- removed = remove_tagged_particles(ob, edit->psys, pe_x_mirror(ob));
- recalc_lengths(edit);
-
- if (removed) {
- update_world_cos(ob, edit);
- psys_free_path_cache(NULL, edit);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
- }
- else
- PE_update_object(scene, ob, 1);
-
- if (edit->psys) {
- WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob);
- }
- else {
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
- WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
- }
-
- PE_free_shape_tree(&data);
- }
-
- pset->flag |= lock_root;
-
- return OPERATOR_FINISHED;
-}
-
-void PARTICLE_OT_shape_cut(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Shape Cut";
- ot->idname = "PARTICLE_OT_shape_cut";
- ot->description = "Cut hair to conform to the set shape object";
-
- /* api callbacks */
- ot->exec = shape_cut_exec;
- ot->poll = shape_cut_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
-/*********************** undo ***************************/
-
-static void free_PTCacheUndo(PTCacheUndo *undo)
-{
- PTCacheEditPoint *point;
- int i;
-
- for (i=0, point=undo->points; i<undo->totpoint; i++, point++) {
- if (undo->particles && (undo->particles + i)->hair)
- MEM_freeN((undo->particles + i)->hair);
- if (point->keys)
- MEM_freeN(point->keys);
- }
- if (undo->points)
- MEM_freeN(undo->points);
-
- if (undo->particles)
- MEM_freeN(undo->particles);
-
- BKE_ptcache_free_mem(&undo->mem_cache);
-}
-
-static void make_PTCacheUndo(PTCacheEdit *edit, PTCacheUndo *undo)
-{
- PTCacheEditPoint *point;
- int i;
-
- undo->totpoint= edit->totpoint;
-
- if (edit->psys) {
- ParticleData *pa;
-
- pa= undo->particles= MEM_dupallocN(edit->psys->particles);
-
- for (i=0; i<edit->totpoint; i++, pa++)
- pa->hair= MEM_dupallocN(pa->hair);
-
- undo->psys_flag = edit->psys->flag;
- }
- else {
- PTCacheMem *pm;
-
- BLI_duplicatelist(&undo->mem_cache, &edit->pid.cache->mem_cache);
- pm = undo->mem_cache.first;
-
- for (; pm; pm=pm->next) {
- for (i=0; i<BPHYS_TOT_DATA; i++)
- pm->data[i] = MEM_dupallocN(pm->data[i]);
- }
- }
-
- point= undo->points = MEM_dupallocN(edit->points);
- undo->totpoint = edit->totpoint;
-
- for (i=0; i<edit->totpoint; i++, point++) {
- point->keys= MEM_dupallocN(point->keys);
- /* no need to update edit key->co & key->time pointers here */
- }
-}
-
-static void get_PTCacheUndo(PTCacheEdit *edit, PTCacheUndo *undo)
-{
- ParticleSystem *psys = edit->psys;
- ParticleData *pa;
- HairKey *hkey;
- POINT_P; KEY_K;
-
- LOOP_POINTS {
- if (psys && psys->particles[p].hair)
- MEM_freeN(psys->particles[p].hair);
-
- if (point->keys)
- MEM_freeN(point->keys);
- }
- if (psys && psys->particles)
- MEM_freeN(psys->particles);
- if (edit->points)
- MEM_freeN(edit->points);
- if (edit->mirror_cache) {
- MEM_freeN(edit->mirror_cache);
- edit->mirror_cache= NULL;
- }
-
- edit->points= MEM_dupallocN(undo->points);
- edit->totpoint = undo->totpoint;
-
- LOOP_POINTS {
- point->keys= MEM_dupallocN(point->keys);
- }
-
- if (psys) {
- psys->particles= MEM_dupallocN(undo->particles);
-
- psys->totpart= undo->totpoint;
-
- LOOP_POINTS {
- pa = psys->particles + p;
- hkey= pa->hair = MEM_dupallocN(pa->hair);
-
- LOOP_KEYS {
- key->co= hkey->co;
- key->time= &hkey->time;
- hkey++;
- }
- }
-
- psys->flag = undo->psys_flag;
- }
- else {
- PTCacheMem *pm;
- int i;
-
- BKE_ptcache_free_mem(&edit->pid.cache->mem_cache);
-
- BLI_duplicatelist(&edit->pid.cache->mem_cache, &undo->mem_cache);
-
- pm = edit->pid.cache->mem_cache.first;
-
- for (; pm; pm=pm->next) {
- for (i=0; i<BPHYS_TOT_DATA; i++)
- pm->data[i] = MEM_dupallocN(pm->data[i]);
-
- BKE_ptcache_mem_pointers_init(pm);
-
- LOOP_POINTS {
- LOOP_KEYS {
- if ((int)key->ftime == (int)pm->frame) {
- key->co = pm->cur[BPHYS_DATA_LOCATION];
- key->vel = pm->cur[BPHYS_DATA_VELOCITY];
- key->rot = pm->cur[BPHYS_DATA_ROTATION];
- key->time = &key->ftime;
- }
- }
- BKE_ptcache_mem_pointers_incr(pm);
- }
- }
- }
-}
-
-void PE_undo_push(Scene *scene, const char *str)
-{
- PTCacheEdit *edit= PE_get_current(scene, OBACT);
- PTCacheUndo *undo;
- int nr;
-
- if (!edit) return;
-
- /* remove all undos after (also when curundo==NULL) */
- while (edit->undo.last != edit->curundo) {
- undo= edit->undo.last;
- BLI_remlink(&edit->undo, undo);
- free_PTCacheUndo(undo);
- MEM_freeN(undo);
- }
-
- /* make new */
- edit->curundo= undo= MEM_callocN(sizeof(PTCacheUndo), "particle undo file");
- BLI_strncpy(undo->name, str, sizeof(undo->name));
- BLI_addtail(&edit->undo, undo);
-
- /* and limit amount to the maximum */
- nr= 0;
- undo= edit->undo.last;
- while (undo) {
- nr++;
- if (nr==U.undosteps) break;
- undo= undo->prev;
- }
- if (undo) {
- while (edit->undo.first!=undo) {
- PTCacheUndo *first= edit->undo.first;
- BLI_remlink(&edit->undo, first);
- free_PTCacheUndo(first);
- MEM_freeN(first);
- }
- }
-
- /* copy */
- make_PTCacheUndo(edit, edit->curundo);
-}
-
-void PE_undo_step(Scene *scene, int step)
-{
- PTCacheEdit *edit= PE_get_current(scene, OBACT);
-
- if (!edit) return;
-
- if (step==0) {
- get_PTCacheUndo(edit, edit->curundo);
- }
- else if (step==1) {
-
- if (edit->curundo==NULL || edit->curundo->prev==NULL) {
- /* pass */
- }
- else {
- if (G.debug & G_DEBUG) printf("undo %s\n", edit->curundo->name);
- edit->curundo= edit->curundo->prev;
- get_PTCacheUndo(edit, edit->curundo);
- }
- }
- else {
- /* curundo has to remain current situation! */
-
- if (edit->curundo==NULL || edit->curundo->next==NULL) {
- /* pass */
- }
- else {
- get_PTCacheUndo(edit, edit->curundo->next);
- edit->curundo= edit->curundo->next;
- if (G.debug & G_DEBUG) printf("redo %s\n", edit->curundo->name);
- }
- }
-
- DAG_id_tag_update(&OBACT->id, OB_RECALC_DATA);
-}
-
-bool PE_undo_is_valid(Scene *scene)
-{
- PTCacheEdit *edit= PE_get_current(scene, OBACT);
-
- if (edit) {
- return (edit->undo.last != edit->undo.first);
- }
- return 0;
-}
-
-void PTCacheUndo_clear(PTCacheEdit *edit)
-{
- PTCacheUndo *undo;
-
- if (edit==NULL) return;
-
- undo= edit->undo.first;
- while (undo) {
- free_PTCacheUndo(undo);
- undo= undo->next;
- }
- BLI_freelistN(&edit->undo);
- edit->curundo= NULL;
-}
-
-void PE_undo(Scene *scene)
-{
- PE_undo_step(scene, 1);
-}
-
-void PE_redo(Scene *scene)
-{
- PE_undo_step(scene, -1);
-}
-
-void PE_undo_number(Scene *scene, int nr)
-{
- PTCacheEdit *edit= PE_get_current(scene, OBACT);
- PTCacheUndo *undo;
- int a=0;
-
- for (undo= edit->undo.first; undo; undo= undo->next, a++) {
- if (a==nr) break;
- }
- edit->curundo= undo;
- PE_undo_step(scene, 0);
-}
-
-
-/* get name of undo item, return null if no item with this index */
-/* if active pointer, set it to 1 if true */
-const char *PE_undo_get_name(Scene *scene, int nr, bool *r_active)
-{
- PTCacheEdit *edit= PE_get_current(scene, OBACT);
- PTCacheUndo *undo;
-
- if (r_active) *r_active = false;
-
- if (edit) {
- undo= BLI_findlink(&edit->undo, nr);
- if (undo) {
- if (r_active && (undo == edit->curundo)) {
- *r_active = true;
- }
- return undo->name;
- }
- }
- return NULL;
-}
-
-/************************ utilities ******************************/
-
-int PE_minmax(Scene *scene, float min[3], float max[3])
-{
- Object *ob= OBACT;
- PTCacheEdit *edit= PE_get_current(scene, ob);
- ParticleSystem *psys;
- ParticleSystemModifierData *psmd = NULL;
- POINT_P; KEY_K;
- float co[3], mat[4][4];
- int ok= 0;
-
- if (!edit) return ok;
-
- if ((psys = edit->psys))
- psmd= psys_get_modifier(ob, psys);
- else
- unit_m4(mat);
-
- LOOP_VISIBLE_POINTS {
- if (psys)
- psys_mat_hair_to_global(ob, psmd->dm_final, psys->part->from, psys->particles+p, mat);
-
- LOOP_SELECTED_KEYS {
- copy_v3_v3(co, key->co);
- mul_m4_v3(mat, co);
- DO_MINMAX(co, min, max);
- ok= 1;
- }
- }
-
- if (!ok) {
- BKE_object_minmax(ob, min, max, true);
- ok= 1;
- }
-
- return ok;
-}
-
-/************************ particle edit toggle operator ************************/
-
-/* initialize needed data for bake edit */
-void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache, ParticleSystem *psys)
-{
- PTCacheEdit *edit;
- ParticleSystemModifierData *psmd = (psys) ? psys_get_modifier(ob, psys) : NULL;
- POINT_P; KEY_K;
- ParticleData *pa = NULL;
- HairKey *hkey;
- int totpoint;
-
- /* no psmd->dm happens in case particle system modifier is not enabled */
- if (!(psys && psmd && psmd->dm_final) && !cache)
- return;
-
- if (cache && cache->flag & PTCACHE_DISK_CACHE)
- return;
-
- if (psys == NULL && (cache && BLI_listbase_is_empty(&cache->mem_cache)))
- return;
-
- edit = (psys) ? psys->edit : cache->edit;
-
- if (!edit) {
- totpoint = psys ? psys->totpart : (int)((PTCacheMem *)cache->mem_cache.first)->totpoint;
-
- edit= MEM_callocN(sizeof(PTCacheEdit), "PE_create_particle_edit");
- edit->points=MEM_callocN(totpoint*sizeof(PTCacheEditPoint), "PTCacheEditPoints");
- edit->totpoint = totpoint;
-
- if (psys && !cache) {
- psys->edit= edit;
- edit->psys = psys;
-
- psys->free_edit= PE_free_ptcache_edit;
-
- edit->pathcache = NULL;
- BLI_listbase_clear(&edit->pathcachebufs);
-
- pa = psys->particles;
- LOOP_POINTS {
- point->totkey = pa->totkey;
- point->keys= MEM_callocN(point->totkey*sizeof(PTCacheEditKey), "ParticleEditKeys");
- point->flag |= PEP_EDIT_RECALC;
-
- hkey = pa->hair;
- LOOP_KEYS {
- key->co= hkey->co;
- key->time= &hkey->time;
- key->flag= hkey->editflag;
- if (!(psys->flag & PSYS_GLOBAL_HAIR)) {
- key->flag |= PEK_USE_WCO;
- hkey->editflag |= PEK_USE_WCO;
- }
-
- hkey++;
- }
- pa++;
- }
- update_world_cos(ob, edit);
- }
- else {
- PTCacheMem *pm;
- int totframe=0;
-
- cache->edit= edit;
- cache->free_edit= PE_free_ptcache_edit;
- edit->psys = NULL;
-
- for (pm=cache->mem_cache.first; pm; pm=pm->next)
- totframe++;
-
- for (pm=cache->mem_cache.first; pm; pm=pm->next) {
- LOOP_POINTS {
- if (BKE_ptcache_mem_pointers_seek(p, pm) == 0)
- continue;
-
- if (!point->totkey) {
- key = point->keys = MEM_callocN(totframe*sizeof(PTCacheEditKey), "ParticleEditKeys");
- point->flag |= PEP_EDIT_RECALC;
- }
- else
- key = point->keys + point->totkey;
-
- key->co = pm->cur[BPHYS_DATA_LOCATION];
- key->vel = pm->cur[BPHYS_DATA_VELOCITY];
- key->rot = pm->cur[BPHYS_DATA_ROTATION];
- key->ftime = (float)pm->frame;
- key->time = &key->ftime;
- BKE_ptcache_mem_pointers_incr(pm);
-
- point->totkey++;
- }
- }
- psys = NULL;
- }
-
- UI_GetThemeColor3ubv(TH_EDGE_SELECT, edit->sel_col);
- UI_GetThemeColor3ubv(TH_WIRE, edit->nosel_col);
-
- recalc_lengths(edit);
- if (psys && !cache)
- recalc_emitter_field(ob, psys);
- PE_update_object(scene, ob, 1);
-
- PTCacheUndo_clear(edit);
- PE_undo_push(scene, "Original");
- }
-}
-
-static int particle_edit_toggle_poll(bContext *C)
-{
- Object *ob = CTX_data_active_object(C);
-
- if (ob == NULL || ob->type != OB_MESH)
- return 0;
- if (!ob->data || ID_IS_LINKED_DATABLOCK(ob->data))
- return 0;
- if (CTX_data_edit_object(C))
- return 0;
-
- return (ob->particlesystem.first ||
- modifiers_findByType(ob, eModifierType_Cloth) ||
- modifiers_findByType(ob, eModifierType_Softbody));
-}
-
-static int particle_edit_toggle_exec(bContext *C, wmOperator *op)
-{
- Scene *scene = CTX_data_scene(C);
- Object *ob = CTX_data_active_object(C);
- const int mode_flag = OB_MODE_PARTICLE_EDIT;
- const bool is_mode_set = (ob->mode & mode_flag) != 0;
-
- if (!is_mode_set) {
- if (!ED_object_mode_compat_set(C, ob, mode_flag, op->reports)) {
- return OPERATOR_CANCELLED;
- }
- }
-
- if (!is_mode_set) {
- PTCacheEdit *edit;
- ob->mode |= mode_flag;
- edit= PE_create_current(scene, ob);
-
- /* mesh may have changed since last entering editmode.
- * note, this may have run before if the edit data was just created, so could avoid this and speed up a little */
- if (edit && edit->psys)
- recalc_emitter_field(ob, edit->psys);
-
- toggle_particle_cursor(C, 1);
- WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_MODE_PARTICLE, NULL);
- }
- else {
- ob->mode &= ~mode_flag;
- toggle_particle_cursor(C, 0);
- WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_MODE_OBJECT, NULL);
- }
-
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
-
- return OPERATOR_FINISHED;
-}
-
-void PARTICLE_OT_particle_edit_toggle(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Particle Edit Toggle";
- ot->idname = "PARTICLE_OT_particle_edit_toggle";
- ot->description = "Toggle particle edit mode";
-
- /* api callbacks */
- ot->exec = particle_edit_toggle_exec;
- ot->poll = particle_edit_toggle_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
-
-/************************ set editable operator ************************/
-
-static int clear_edited_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Object *ob= CTX_data_active_object(C);
- ParticleSystem *psys = psys_get_current(ob);
-
- if (psys->edit) {
- if (psys->edit->edited || 1) {
- PE_free_ptcache_edit(psys->edit);
-
- psys->edit = NULL;
- psys->free_edit = NULL;
-
- psys->recalc |= PSYS_RECALC_RESET;
- psys->flag &= ~PSYS_GLOBAL_HAIR;
- psys->flag &= ~PSYS_EDITED;
-
- psys_reset(psys, PSYS_RESET_DEPSGRAPH);
- WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
- }
- }
- else { /* some operation might have protected hair from editing so let's clear the flag */
- psys->recalc |= PSYS_RECALC_RESET;
- psys->flag &= ~PSYS_GLOBAL_HAIR;
- psys->flag &= ~PSYS_EDITED;
- WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
- }
-
- return OPERATOR_FINISHED;
-}
-
-static int clear_edited_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
-{
- return WM_operator_confirm_message(C, op, "Lose changes done in particle mode? (no undo)");
-}
-
-void PARTICLE_OT_edited_clear(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Clear Edited";
- ot->idname = "PARTICLE_OT_edited_clear";
- ot->description = "Undo all edition performed on the particle system";
-
- /* api callbacks */
- ot->exec = clear_edited_exec;
- ot->poll = particle_edit_toggle_poll;
- ot->invoke = clear_edited_invoke;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
-/************************ Unify length operator ************************/
-
-static float calculate_point_length(PTCacheEditPoint *point)
-{
- float length = 0.0f;
- KEY_K;
- LOOP_KEYS {
- if (k > 0) {
- length += len_v3v3((key - 1)->co, key->co);
- }
- }
- return length;
-}
-
-static float calculate_average_length(PTCacheEdit *edit)
-{
- int num_selected = 0;
- float total_length = 0;
- POINT_P;
- LOOP_SELECTED_POINTS {
- total_length += calculate_point_length(point);
- ++num_selected;
- }
- if (num_selected == 0) {
- return 0.0f;
- }
- return total_length / num_selected;
-}
-
-static void scale_point_factor(PTCacheEditPoint *point, float factor)
-{
- float orig_prev_co[3], prev_co[3];
- KEY_K;
- LOOP_KEYS {
- if (k == 0) {
- copy_v3_v3(orig_prev_co, key->co);
- copy_v3_v3(prev_co, key->co);
- }
- else {
- float new_co[3];
- float delta[3];
-
- sub_v3_v3v3(delta, key->co, orig_prev_co);
- mul_v3_fl(delta, factor);
- add_v3_v3v3(new_co, prev_co, delta);
-
- copy_v3_v3(orig_prev_co, key->co);
- copy_v3_v3(key->co, new_co);
- copy_v3_v3(prev_co, key->co);
- }
- }
- point->flag |= PEP_EDIT_RECALC;
-}
-
-static void scale_point_to_length(PTCacheEditPoint *point, float length)
-{
- const float point_length = calculate_point_length(point);
- if (point_length != 0.0f) {
- const float factor = length / point_length;
- scale_point_factor(point, factor);
- }
-}
-
-static void scale_points_to_length(PTCacheEdit *edit, float length)
-{
- POINT_P;
- LOOP_SELECTED_POINTS {
- scale_point_to_length(point, length);
- }
- recalc_lengths(edit);
-}
-
-static int unify_length_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Object *ob = CTX_data_active_object(C);
- Scene *scene = CTX_data_scene(C);
- PTCacheEdit *edit = PE_get_current(scene, ob);
- float average_length = calculate_average_length(edit);
- if (average_length == 0.0f) {
- return OPERATOR_CANCELLED;
- }
- scale_points_to_length(edit, average_length);
-
- PE_update_object(scene, ob, 1);
- if (edit->psys) {
- WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob);
- }
- else {
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
- WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
- }
-
- return OPERATOR_FINISHED;
-}
-
-void PARTICLE_OT_unify_length(struct wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Unify Length";
- ot->idname = "PARTICLE_OT_unify_length";
- ot->description = "Make selected hair the same length";
-
- /* api callbacks */
- ot->exec = unify_length_exec;
- ot->poll = PE_poll_view3d;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c
deleted file mode 100644
index 4a4474868a2..00000000000
--- a/source/blender/editors/physics/particle_object.c
+++ /dev/null
@@ -1,1244 +0,0 @@
-/*
- * ***** 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) 2009 Blender Foundation.
- * All rights reserved.
- *
- * Contributor(s): Blender Foundation
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/editors/physics/particle_object.c
- * \ingroup edphys
- */
-
-
-#include <stdlib.h>
-#include <string.h>
-
-#include "MEM_guardedalloc.h"
-
-#include "DNA_meshdata_types.h"
-#include "DNA_modifier_types.h"
-#include "DNA_scene_types.h"
-
-#include "BLI_math.h"
-#include "BLI_listbase.h"
-#include "BLI_utildefines.h"
-#include "BLI_string.h"
-
-#include "BKE_context.h"
-#include "BKE_depsgraph.h"
-#include "BKE_DerivedMesh.h"
-#include "BKE_cdderivedmesh.h"
-#include "BKE_global.h"
-#include "BKE_library.h"
-#include "BKE_main.h"
-#include "BKE_modifier.h"
-#include "BKE_object.h"
-#include "BKE_particle.h"
-#include "BKE_pointcache.h"
-#include "BKE_report.h"
-
-#include "RNA_access.h"
-#include "RNA_define.h"
-
-#include "WM_api.h"
-#include "WM_types.h"
-
-#include "ED_particle.h"
-#include "ED_screen.h"
-#include "ED_object.h"
-
-#include "UI_resources.h"
-
-#include "physics_intern.h"
-
-extern void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache, ParticleSystem *psys);
-extern void PTCacheUndo_clear(PTCacheEdit *edit);
-extern void recalc_lengths(PTCacheEdit *edit);
-extern void recalc_emitter_field(Object *ob, ParticleSystem *psys);
-extern void update_world_cos(Object *ob, PTCacheEdit *edit);
-
-#define KEY_K PTCacheEditKey *key; int k
-#define POINT_P PTCacheEditPoint *point; int p
-#define LOOP_POINTS for (p=0, point=edit->points; p<edit->totpoint; p++, point++)
-#if 0
-#define LOOP_VISIBLE_POINTS for (p=0, point=edit->points; p<edit->totpoint; p++, point++) if (!(point->flag & PEP_HIDE))
-#define LOOP_SELECTED_POINTS for (p=0, point=edit->points; p<edit->totpoint; p++, point++) if (point_is_selected(point))
-#define LOOP_UNSELECTED_POINTS for (p=0, point=edit->points; p<edit->totpoint; p++, point++) if (!point_is_selected(point))
-#define LOOP_EDITED_POINTS for (p=0, point=edit->points; p<edit->totpoint; p++, point++) if (point->flag & PEP_EDIT_RECALC)
-#define LOOP_TAGGED_POINTS for (p=0, point=edit->points; p<edit->totpoint; p++, point++) if (point->flag & PEP_TAG)
-#endif
-#define LOOP_KEYS for (k=0, key=point->keys; k<point->totkey; k++, key++)
-#if 0
-#define LOOP_VISIBLE_KEYS for (k=0, key=point->keys; k<point->totkey; k++, key++) if (!(key->flag & PEK_HIDE))
-#define LOOP_SELECTED_KEYS for (k=0, key=point->keys; k<point->totkey; k++, key++) if ((key->flag & PEK_SELECT) && !(key->flag & PEK_HIDE))
-#define LOOP_TAGGED_KEYS for (k=0, key=point->keys; k<point->totkey; k++, key++) if (key->flag & PEK_TAG)
-
-#define KEY_WCO (key->flag & PEK_USE_WCO ? key->world_co : key->co)
-#endif
-
-static float I[4][4] = {{1.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 1.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 1.0f}};
-
-/********************** particle system slot operators *********************/
-
-static int particle_system_add_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Object *ob= ED_object_context(C);
- Scene *scene = CTX_data_scene(C);
-
- if (!scene || !ob)
- return OPERATOR_CANCELLED;
-
- object_add_particle_system(scene, ob, NULL);
-
- WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob);
- WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, ob);
-
- return OPERATOR_FINISHED;
-}
-
-void OBJECT_OT_particle_system_add(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Add Particle System Slot";
- ot->idname = "OBJECT_OT_particle_system_add";
- ot->description = "Add a particle system";
-
- /* api callbacks */
- ot->poll = ED_operator_object_active_editable;
- ot->exec = particle_system_add_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
-static int particle_system_remove_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Object *ob = ED_object_context(C);
- Scene *scene = CTX_data_scene(C);
- int mode_orig;
-
- if (!scene || !ob)
- return OPERATOR_CANCELLED;
-
- mode_orig = ob->mode;
- object_remove_particle_system(scene, ob);
-
- /* possible this isn't the active object
- * object_remove_particle_system() clears the mode on the last psys
- */
- if (mode_orig & OB_MODE_PARTICLE_EDIT) {
- if ((ob->mode & OB_MODE_PARTICLE_EDIT) == 0) {
- if (scene->basact && scene->basact->object == ob) {
- WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_MODE_OBJECT, NULL);
- }
- }
- }
-
- WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob);
- WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, ob);
-
- return OPERATOR_FINISHED;
-}
-
-void OBJECT_OT_particle_system_remove(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Remove Particle System Slot";
- ot->idname = "OBJECT_OT_particle_system_remove";
- ot->description = "Remove the selected particle system";
-
- /* api callbacks */
- ot->poll = ED_operator_object_active_editable;
- ot->exec = particle_system_remove_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
-/********************** new particle settings operator *********************/
-
-static int psys_poll(bContext *C)
-{
- PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
- return (ptr.data != NULL);
-}
-
-static int new_particle_settings_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Main *bmain= CTX_data_main(C);
- ParticleSystem *psys;
- ParticleSettings *part = NULL;
- Object *ob;
- PointerRNA ptr;
-
- ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
-
- psys = ptr.data;
-
- /* add or copy particle setting */
- if (psys->part)
- part= BKE_particlesettings_copy(bmain, psys->part);
- else
- part= psys_new_settings("ParticleSettings", bmain);
-
- ob= ptr.id.data;
-
- if (psys->part)
- id_us_min(&psys->part->id);
-
- psys->part = part;
-
- psys_check_boid_data(psys);
-
- DAG_relations_tag_update(bmain);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
-
- WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob);
-
- return OPERATOR_FINISHED;
-}
-
-void PARTICLE_OT_new(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "New Particle Settings";
- ot->idname = "PARTICLE_OT_new";
- ot->description = "Add new particle settings";
-
- /* api callbacks */
- ot->exec = new_particle_settings_exec;
- ot->poll = psys_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
-/********************** keyed particle target operators *********************/
-
-static int new_particle_target_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Main *bmain = CTX_data_main(C);
- PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
- ParticleSystem *psys= ptr.data;
- Object *ob = ptr.id.data;
-
- ParticleTarget *pt;
-
- if (!psys)
- return OPERATOR_CANCELLED;
-
- pt = psys->targets.first;
- for (; pt; pt=pt->next)
- pt->flag &= ~PTARGET_CURRENT;
-
- pt = MEM_callocN(sizeof(ParticleTarget), "keyed particle target");
-
- pt->flag |= PTARGET_CURRENT;
- pt->psys = 1;
-
- BLI_addtail(&psys->targets, pt);
-
- DAG_relations_tag_update(bmain);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
-
- WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob);
-
- return OPERATOR_FINISHED;
-}
-
-void PARTICLE_OT_new_target(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "New Particle Target";
- ot->idname = "PARTICLE_OT_new_target";
- ot->description = "Add a new particle target";
-
- /* api callbacks */
- ot->exec = new_particle_target_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
-static int remove_particle_target_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Main *bmain = CTX_data_main(C);
- PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
- ParticleSystem *psys= ptr.data;
- Object *ob = ptr.id.data;
-
- ParticleTarget *pt;
-
- if (!psys)
- return OPERATOR_CANCELLED;
-
- pt = psys->targets.first;
- for (; pt; pt=pt->next) {
- if (pt->flag & PTARGET_CURRENT) {
- BLI_remlink(&psys->targets, pt);
- MEM_freeN(pt);
- break;
- }
-
- }
- pt = psys->targets.last;
-
- if (pt)
- pt->flag |= PTARGET_CURRENT;
-
- DAG_relations_tag_update(bmain);
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
-
- WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob);
-
- return OPERATOR_FINISHED;
-}
-
-void PARTICLE_OT_target_remove(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Remove Particle Target";
- ot->idname = "PARTICLE_OT_target_remove";
- ot->description = "Remove the selected particle target";
-
- /* api callbacks */
- ot->exec = remove_particle_target_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
-/************************ move up particle target operator *********************/
-
-static int target_move_up_exec(bContext *C, wmOperator *UNUSED(op))
-{
- PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
- ParticleSystem *psys= ptr.data;
- Object *ob = ptr.id.data;
- ParticleTarget *pt;
-
- if (!psys)
- return OPERATOR_CANCELLED;
-
- pt = psys->targets.first;
- for (; pt; pt=pt->next) {
- if (pt->flag & PTARGET_CURRENT && pt->prev) {
- BLI_remlink(&psys->targets, pt);
- BLI_insertlinkbefore(&psys->targets, pt->prev, pt);
-
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
- WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob);
- break;
- }
- }
-
- return OPERATOR_FINISHED;
-}
-
-void PARTICLE_OT_target_move_up(wmOperatorType *ot)
-{
- ot->name = "Move Up Target";
- ot->idname = "PARTICLE_OT_target_move_up";
- ot->description = "Move particle target up in the list";
-
- ot->exec = target_move_up_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
-/************************ move down particle target operator *********************/
-
-static int target_move_down_exec(bContext *C, wmOperator *UNUSED(op))
-{
- PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
- ParticleSystem *psys= ptr.data;
- Object *ob = ptr.id.data;
- ParticleTarget *pt;
-
- if (!psys)
- return OPERATOR_CANCELLED;
- pt = psys->targets.first;
- for (; pt; pt=pt->next) {
- if (pt->flag & PTARGET_CURRENT && pt->next) {
- BLI_remlink(&psys->targets, pt);
- BLI_insertlinkafter(&psys->targets, pt->next, pt);
-
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
- WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob);
- break;
- }
- }
-
- return OPERATOR_FINISHED;
-}
-
-void PARTICLE_OT_target_move_down(wmOperatorType *ot)
-{
- ot->name = "Move Down Target";
- ot->idname = "PARTICLE_OT_target_move_down";
- ot->description = "Move particle target down in the list";
-
- ot->exec = target_move_down_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
-/************************ move up particle dupliweight operator *********************/
-
-static int dupliob_move_up_exec(bContext *C, wmOperator *UNUSED(op))
-{
- PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
- ParticleSystem *psys= ptr.data;
- ParticleSettings *part;
- ParticleDupliWeight *dw;
-
- if (!psys)
- return OPERATOR_CANCELLED;
-
- part = psys->part;
- for (dw=part->dupliweights.first; dw; dw=dw->next) {
- if (dw->flag & PART_DUPLIW_CURRENT && dw->prev) {
- BLI_remlink(&part->dupliweights, dw);
- BLI_insertlinkbefore(&part->dupliweights, dw->prev, dw);
-
- WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, NULL);
- break;
- }
- }
-
- return OPERATOR_FINISHED;
-}
-
-void PARTICLE_OT_dupliob_move_up(wmOperatorType *ot)
-{
- ot->name = "Move Up Dupli Object";
- ot->idname = "PARTICLE_OT_dupliob_move_up";
- ot->description = "Move dupli object up in the list";
-
- ot->exec = dupliob_move_up_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
-/********************** particle dupliweight operators *********************/
-
-static int copy_particle_dupliob_exec(bContext *C, wmOperator *UNUSED(op))
-{
- PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
- ParticleSystem *psys= ptr.data;
- ParticleSettings *part;
- ParticleDupliWeight *dw;
-
- if (!psys)
- return OPERATOR_CANCELLED;
- part = psys->part;
- for (dw=part->dupliweights.first; dw; dw=dw->next) {
- if (dw->flag & PART_DUPLIW_CURRENT) {
- dw->flag &= ~PART_DUPLIW_CURRENT;
- dw = MEM_dupallocN(dw);
- dw->flag |= PART_DUPLIW_CURRENT;
- BLI_addhead(&part->dupliweights, dw);
-
- WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, NULL);
- break;
- }
- }
-
- return OPERATOR_FINISHED;
-}
-
-void PARTICLE_OT_dupliob_copy(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Copy Particle Dupliob";
- ot->idname = "PARTICLE_OT_dupliob_copy";
- ot->description = "Duplicate the current dupliobject";
-
- /* api callbacks */
- ot->exec = copy_particle_dupliob_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
-static int remove_particle_dupliob_exec(bContext *C, wmOperator *UNUSED(op))
-{
- PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
- ParticleSystem *psys= ptr.data;
- ParticleSettings *part;
- ParticleDupliWeight *dw;
-
- if (!psys)
- return OPERATOR_CANCELLED;
-
- part = psys->part;
- for (dw=part->dupliweights.first; dw; dw=dw->next) {
- if (dw->flag & PART_DUPLIW_CURRENT) {
- BLI_remlink(&part->dupliweights, dw);
- MEM_freeN(dw);
- break;
- }
-
- }
- dw = part->dupliweights.last;
-
- if (dw)
- dw->flag |= PART_DUPLIW_CURRENT;
-
- WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, NULL);
-
- return OPERATOR_FINISHED;
-}
-
-void PARTICLE_OT_dupliob_remove(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Remove Particle Dupliobject";
- ot->idname = "PARTICLE_OT_dupliob_remove";
- ot->description = "Remove the selected dupliobject";
-
- /* api callbacks */
- ot->exec = remove_particle_dupliob_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
-/************************ move down particle dupliweight operator *********************/
-
-static int dupliob_move_down_exec(bContext *C, wmOperator *UNUSED(op))
-{
- PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
- ParticleSystem *psys= ptr.data;
- ParticleSettings *part;
- ParticleDupliWeight *dw;
-
- if (!psys)
- return OPERATOR_CANCELLED;
-
- part = psys->part;
- for (dw=part->dupliweights.first; dw; dw=dw->next) {
- if (dw->flag & PART_DUPLIW_CURRENT && dw->next) {
- BLI_remlink(&part->dupliweights, dw);
- BLI_insertlinkafter(&part->dupliweights, dw->next, dw);
-
- WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, NULL);
- break;
- }
- }
-
- return OPERATOR_FINISHED;
-}
-
-void PARTICLE_OT_dupliob_move_down(wmOperatorType *ot)
-{
- ot->name = "Move Down Dupli Object";
- ot->idname = "PARTICLE_OT_dupliob_move_down";
- ot->description = "Move dupli object down in the list";
-
- ot->exec = dupliob_move_down_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
-/************************ connect/disconnect hair operators *********************/
-
-static void disconnect_hair(Scene *scene, Object *ob, ParticleSystem *psys)
-{
- ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys);
- ParticleEditSettings *pset= PE_settings(scene);
- ParticleData *pa;
- PTCacheEdit *edit;
- PTCacheEditPoint *point;
- PTCacheEditKey *ekey = NULL;
- HairKey *key;
- int i, k;
- float hairmat[4][4];
-
- if (!ob || !psys || psys->flag & PSYS_GLOBAL_HAIR)
- return;
-
- if (!psys->part || psys->part->type != PART_HAIR)
- return;
-
- edit = psys->edit;
- point= edit ? edit->points : NULL;
-
- for (i=0, pa=psys->particles; i<psys->totpart; i++, pa++) {
- if (point) {
- ekey = point->keys;
- point++;
- }
-
- psys_mat_hair_to_global(ob, psmd->dm_final, psys->part->from, pa, hairmat);
-
- for (k=0, key=pa->hair; k<pa->totkey; k++, key++) {
- mul_m4_v3(hairmat, key->co);
-
- if (ekey) {
- ekey->flag &= ~PEK_USE_WCO;
- ekey++;
- }
- }
- }
-
- psys_free_path_cache(psys, psys->edit);
-
- psys->flag |= PSYS_GLOBAL_HAIR;
-
- if (ELEM(pset->brushtype, PE_BRUSH_ADD, PE_BRUSH_PUFF))
- pset->brushtype = PE_BRUSH_NONE;
-
- PE_update_object(scene, ob, 0);
-}
-
-static int disconnect_hair_exec(bContext *C, wmOperator *op)
-{
- Scene *scene= CTX_data_scene(C);
- Object *ob= ED_object_context(C);
- ParticleSystem *psys= NULL;
- const bool all = RNA_boolean_get(op->ptr, "all");
-
- if (!ob)
- return OPERATOR_CANCELLED;
-
- if (all) {
- for (psys=ob->particlesystem.first; psys; psys=psys->next) {
- disconnect_hair(scene, ob, psys);
- }
- }
- else {
- psys = psys_get_current(ob);
- disconnect_hair(scene, ob, psys);
- }
-
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
- WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob);
-
- return OPERATOR_FINISHED;
-}
-
-void PARTICLE_OT_disconnect_hair(wmOperatorType *ot)
-{
- ot->name = "Disconnect Hair";
- ot->description = "Disconnect hair from the emitter mesh";
- ot->idname = "PARTICLE_OT_disconnect_hair";
-
- ot->exec = disconnect_hair_exec;
-
- /* flags */
- ot->flag = OPTYPE_UNDO; /* No REGISTER, redo does not work due to missing update, see T47750. */
-
- RNA_def_boolean(ot->srna, "all", 0, "All hair", "Disconnect all hair systems from the emitter mesh");
-}
-
-/* from/to_world_space : whether from/to particles are in world or hair space
- * from/to_mat : additional transform for from/to particles (e.g. for using object space copying)
- */
-static bool remap_hair_emitter(Scene *scene, Object *ob, ParticleSystem *psys,
- Object *target_ob, ParticleSystem *target_psys, PTCacheEdit *target_edit,
- float from_mat[4][4], float to_mat[4][4], bool from_global, bool to_global)
-{
- ParticleSystemModifierData *target_psmd = psys_get_modifier(target_ob, target_psys);
- ParticleData *pa, *tpa;
- PTCacheEditPoint *edit_point;
- PTCacheEditKey *ekey;
- BVHTreeFromMesh bvhtree= {NULL};
- MFace *mface = NULL, *mf;
- MEdge *medge = NULL, *me;
- MVert *mvert;
- DerivedMesh *dm, *target_dm;
- int numverts;
- int i, k;
- float from_ob_imat[4][4], to_ob_imat[4][4];
- float from_imat[4][4], to_imat[4][4];
-
- if (!target_psmd->dm_final)
- return false;
- if (!psys->part || psys->part->type != PART_HAIR)
- return false;
- if (!target_psys->part || target_psys->part->type != PART_HAIR)
- return false;
-
- edit_point = target_edit ? target_edit->points : NULL;
-
- invert_m4_m4(from_ob_imat, ob->obmat);
- invert_m4_m4(to_ob_imat, target_ob->obmat);
- invert_m4_m4(from_imat, from_mat);
- invert_m4_m4(to_imat, to_mat);
-
- if (target_psmd->dm_final->deformedOnly) {
- /* we don't want to mess up target_psmd->dm when converting to global coordinates below */
- dm = target_psmd->dm_final;
- }
- else {
- dm = target_psmd->dm_deformed;
- }
- target_dm = target_psmd->dm_final;
- if (dm == NULL) {
- return false;
- }
- /* don't modify the original vertices */
- dm = CDDM_copy(dm);
-
- /* BMESH_ONLY, deform dm may not have tessface */
- DM_ensure_tessface(dm);
-
- numverts = dm->getNumVerts(dm);
- mvert = dm->getVertArray(dm);
-
- /* convert to global coordinates */
- for (i=0; i<numverts; i++)
- mul_m4_v3(to_mat, mvert[i].co);
-
- if (dm->getNumTessFaces(dm) != 0) {
- mface = dm->getTessFaceArray(dm);
- bvhtree_from_mesh_faces(&bvhtree, dm, 0.0, 2, 6);
- }
- else if (dm->getNumEdges(dm) != 0) {
- medge = dm->getEdgeArray(dm);
- bvhtree_from_mesh_edges(&bvhtree, dm, 0.0, 2, 6);
- }
- else {
- dm->release(dm);
- return false;
- }
-
- for (i = 0, tpa = target_psys->particles, pa = psys->particles;
- i < target_psys->totpart;
- i++, tpa++, pa++) {
-
- float from_co[3];
- BVHTreeNearest nearest;
-
- if (from_global)
- mul_v3_m4v3(from_co, from_ob_imat, pa->hair[0].co);
- else
- mul_v3_m4v3(from_co, from_ob_imat, pa->hair[0].world_co);
- mul_m4_v3(from_mat, from_co);
-
- nearest.index = -1;
- nearest.dist_sq = FLT_MAX;
-
- BLI_bvhtree_find_nearest(bvhtree.tree, from_co, &nearest, bvhtree.nearest_callback, &bvhtree);
-
- if (nearest.index == -1) {
- if (G.debug & G_DEBUG)
- printf("No nearest point found for hair root!");
- continue;
- }
-
- if (mface) {
- float v[4][3];
-
- mf = &mface[nearest.index];
-
- copy_v3_v3(v[0], mvert[mf->v1].co);
- copy_v3_v3(v[1], mvert[mf->v2].co);
- copy_v3_v3(v[2], mvert[mf->v3].co);
- if (mf->v4) {
- copy_v3_v3(v[3], mvert[mf->v4].co);
- interp_weights_poly_v3(tpa->fuv, v, 4, nearest.co);
- }
- else
- interp_weights_poly_v3(tpa->fuv, v, 3, nearest.co);
- tpa->foffset = 0.0f;
-
- tpa->num = nearest.index;
- tpa->num_dmcache = psys_particle_dm_face_lookup(target_dm, dm, tpa->num, tpa->fuv, NULL);
- }
- else {
- me = &medge[nearest.index];
-
- tpa->fuv[1] = line_point_factor_v3(nearest.co,
- mvert[me->v1].co,
- mvert[me->v2].co);
- tpa->fuv[0] = 1.0f - tpa->fuv[1];
- tpa->fuv[2] = tpa->fuv[3] = 0.0f;
- tpa->foffset = 0.0f;
-
- tpa->num = nearest.index;
- tpa->num_dmcache = -1;
- }
-
- /* translate hair keys */
- {
- HairKey *key, *tkey;
- float hairmat[4][4], imat[4][4];
- float offset[3];
-
- if (to_global)
- copy_m4_m4(imat, target_ob->obmat);
- else {
- /* note: using target_dm here, which is in target_ob object space and has full modifiers */
- psys_mat_hair_to_object(target_ob, target_dm, target_psys->part->from, tpa, hairmat);
- invert_m4_m4(imat, hairmat);
- }
- mul_m4_m4m4(imat, imat, to_imat);
-
- /* offset in world space */
- sub_v3_v3v3(offset, nearest.co, from_co);
-
- if (edit_point) {
- for (k=0, key=pa->hair, tkey=tpa->hair, ekey = edit_point->keys; k<tpa->totkey; k++, key++, tkey++, ekey++) {
- float co_orig[3];
-
- if (from_global)
- mul_v3_m4v3(co_orig, from_ob_imat, key->co);
- else
- mul_v3_m4v3(co_orig, from_ob_imat, key->world_co);
- mul_m4_v3(from_mat, co_orig);
-
- add_v3_v3v3(tkey->co, co_orig, offset);
-
- mul_m4_v3(imat, tkey->co);
-
- ekey->flag |= PEK_USE_WCO;
- }
-
- edit_point++;
- }
- else {
- for (k=0, key=pa->hair, tkey=tpa->hair; k<tpa->totkey; k++, key++, tkey++) {
- float co_orig[3];
-
- if (from_global)
- mul_v3_m4v3(co_orig, from_ob_imat, key->co);
- else
- mul_v3_m4v3(co_orig, from_ob_imat, key->world_co);
- mul_m4_v3(from_mat, co_orig);
-
- add_v3_v3v3(tkey->co, co_orig, offset);
-
- mul_m4_v3(imat, tkey->co);
- }
- }
- }
- }
-
- free_bvhtree_from_mesh(&bvhtree);
- dm->release(dm);
-
- psys_free_path_cache(target_psys, target_edit);
-
- PE_update_object(scene, target_ob, 0);
-
- return true;
-}
-
-static bool connect_hair(Scene *scene, Object *ob, ParticleSystem *psys)
-{
- bool ok;
-
- if (!psys)
- return false;
-
- ok = remap_hair_emitter(scene, ob, psys, ob, psys, psys->edit, ob->obmat, ob->obmat, psys->flag & PSYS_GLOBAL_HAIR, false);
- psys->flag &= ~PSYS_GLOBAL_HAIR;
-
- return ok;
-}
-
-static int connect_hair_exec(bContext *C, wmOperator *op)
-{
- Scene *scene= CTX_data_scene(C);
- Object *ob= ED_object_context(C);
- ParticleSystem *psys= NULL;
- const bool all = RNA_boolean_get(op->ptr, "all");
- bool any_connected = false;
-
- if (!ob)
- return OPERATOR_CANCELLED;
-
- if (all) {
- for (psys=ob->particlesystem.first; psys; psys=psys->next) {
- any_connected |= connect_hair(scene, ob, psys);
- }
- }
- else {
- psys = psys_get_current(ob);
- any_connected |= connect_hair(scene, ob, psys);
- }
-
- if (!any_connected) {
- BKE_report(op->reports, RPT_WARNING,
- "No hair connected (can't connect hair if particle system modifier is disabled)");
- return OPERATOR_CANCELLED;
- }
-
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
- WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob);
-
- return OPERATOR_FINISHED;
-}
-
-void PARTICLE_OT_connect_hair(wmOperatorType *ot)
-{
- ot->name = "Connect Hair";
- ot->description = "Connect hair to the emitter mesh";
- ot->idname = "PARTICLE_OT_connect_hair";
-
- ot->exec = connect_hair_exec;
-
- /* flags */
- ot->flag = OPTYPE_UNDO; /* No REGISTER, redo does not work due to missing update, see T47750. */
-
- RNA_def_boolean(ot->srna, "all", 0, "All hair", "Connect all hair systems to the emitter mesh");
-}
-
-/************************ particle system copy operator *********************/
-
-typedef enum eCopyParticlesSpace {
- PAR_COPY_SPACE_OBJECT = 0,
- PAR_COPY_SPACE_WORLD = 1,
-} eCopyParticlesSpace;
-
-static void copy_particle_edit(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSystem *psys_from)
-{
- PTCacheEdit *edit_from = psys_from->edit, *edit;
- ParticleData *pa;
- KEY_K;
- POINT_P;
-
- if (!edit_from)
- return;
-
- edit = MEM_dupallocN(edit_from);
- edit->psys = psys;
- psys->edit = edit;
-
- edit->pathcache = NULL;
- BLI_listbase_clear(&edit->pathcachebufs);
-
- edit->emitter_field = NULL;
- edit->emitter_cosnos = NULL;
-
- BLI_listbase_clear(&edit->undo);
- edit->curundo = NULL;
-
- edit->points = MEM_dupallocN(edit_from->points);
- pa = psys->particles;
- LOOP_POINTS {
- HairKey *hkey = pa->hair;
-
- point->keys= MEM_dupallocN(point->keys);
- LOOP_KEYS {
- key->co = hkey->co;
- key->time = &hkey->time;
- key->flag = hkey->editflag;
- if (!(psys->flag & PSYS_GLOBAL_HAIR)) {
- key->flag |= PEK_USE_WCO;
- hkey->editflag |= PEK_USE_WCO;
- }
-
- hkey++;
- }
-
- pa++;
- }
- update_world_cos(ob, edit);
-
- UI_GetThemeColor3ubv(TH_EDGE_SELECT, edit->sel_col);
- UI_GetThemeColor3ubv(TH_WIRE, edit->nosel_col);
-
- recalc_lengths(edit);
- recalc_emitter_field(ob, psys);
- PE_update_object(scene, ob, true);
-
- PTCacheUndo_clear(edit);
- PE_undo_push(scene, "Original");
-}
-
-static void remove_particle_systems_from_object(Object *ob_to)
-{
- ModifierData *md, *md_next;
-
- if (ob_to->type != OB_MESH)
- return;
- if (!ob_to->data || ID_IS_LINKED_DATABLOCK(ob_to->data))
- return;
-
- for (md = ob_to->modifiers.first; md; md = md_next) {
- md_next = md->next;
-
- /* remove all particle system modifiers as well,
- * these need to sync to the particle system list
- */
- if (ELEM(md->type, eModifierType_ParticleSystem, eModifierType_DynamicPaint, eModifierType_Smoke)) {
- BLI_remlink(&ob_to->modifiers, md);
- modifier_free(md);
- }
- }
-
- BKE_object_free_particlesystems(ob_to);
-}
-
-/* single_psys_from is optional, if NULL all psys of ob_from are copied */
-static bool copy_particle_systems_to_object(Main *bmain,
- Scene *scene,
- Object *ob_from,
- ParticleSystem *single_psys_from,
- Object *ob_to,
- int space,
- bool duplicate_settings)
-{
- ModifierData *md;
- ParticleSystem *psys_start = NULL, *psys, *psys_from;
- ParticleSystem **tmp_psys;
- DerivedMesh *final_dm;
- CustomDataMask cdmask;
- int i, totpsys;
-
- if (ob_to->type != OB_MESH)
- return false;
- if (!ob_to->data || ID_IS_LINKED_DATABLOCK(ob_to->data))
- return false;
-
- /* For remapping we need a valid DM.
- * Because the modifiers are appended at the end it's safe to use
- * the final DM of the object without particles.
- * However, when evaluating the DM all the particle modifiers must be valid,
- * i.e. have the psys assigned already.
- * To break this hen/egg problem we create all psys separately first (to collect required customdata masks),
- * then create the DM, then add them to the object and make the psys modifiers ...
- */
- #define PSYS_FROM_FIRST (single_psys_from ? single_psys_from : ob_from->particlesystem.first)
- #define PSYS_FROM_NEXT(cur) (single_psys_from ? NULL : (cur)->next)
- totpsys = single_psys_from ? 1 : BLI_listbase_count(&ob_from->particlesystem);
-
- tmp_psys = MEM_mallocN(sizeof(ParticleSystem*) * totpsys, "temporary particle system array");
-
- cdmask = 0;
- for (psys_from = PSYS_FROM_FIRST, i = 0;
- psys_from;
- psys_from = PSYS_FROM_NEXT(psys_from), ++i) {
-
- psys = BKE_object_copy_particlesystem(psys_from);
- tmp_psys[i] = psys;
-
- if (psys_start == NULL)
- psys_start = psys;
-
- cdmask |= psys_emitter_customdata_mask(psys);
- }
- /* to iterate source and target psys in sync,
- * we need to know where the newly added psys start
- */
- psys_start = totpsys > 0 ? tmp_psys[0] : NULL;
-
- /* get the DM (psys and their modifiers have not been appended yet) */
- final_dm = mesh_get_derived_final(scene, ob_to, cdmask);
-
- /* now append psys to the object and make modifiers */
- for (i = 0, psys_from = PSYS_FROM_FIRST;
- i < totpsys;
- ++i, psys_from = PSYS_FROM_NEXT(psys_from)) {
-
- ParticleSystemModifierData *psmd;
-
- psys = tmp_psys[i];
-
- /* append to the object */
- BLI_addtail(&ob_to->particlesystem, psys);
-
- /* add a particle system modifier for each system */
- md = modifier_new(eModifierType_ParticleSystem);
- psmd = (ParticleSystemModifierData *)md;
- /* push on top of the stack, no use trying to reproduce old stack order */
- BLI_addtail(&ob_to->modifiers, md);
-
- BLI_snprintf(md->name, sizeof(md->name), "ParticleSystem %i", i);
- modifier_unique_name(&ob_to->modifiers, (ModifierData *)psmd);
-
- psmd->psys = psys;
- psmd->dm_final = CDDM_copy(final_dm);
- CDDM_calc_normals(psmd->dm_final);
- DM_ensure_tessface(psmd->dm_final);
-
- if (psys_from->edit)
- copy_particle_edit(scene, ob_to, psys, psys_from);
-
- if (duplicate_settings) {
- id_us_min(&psys->part->id);
- psys->part = BKE_particlesettings_copy(bmain, psys->part);
- }
- }
- MEM_freeN(tmp_psys);
-
- /* note: do this after creating DM copies for all the particle system modifiers,
- * the remapping otherwise makes final_dm invalid!
- */
- for (psys = psys_start, psys_from = PSYS_FROM_FIRST, i = 0;
- psys;
- psys = psys->next, psys_from = PSYS_FROM_NEXT(psys_from), ++i) {
-
- float (*from_mat)[4], (*to_mat)[4];
-
- switch (space) {
- case PAR_COPY_SPACE_OBJECT:
- from_mat = I;
- to_mat = I;
- break;
- case PAR_COPY_SPACE_WORLD:
- from_mat = ob_from->obmat;
- to_mat = ob_to->obmat;
- break;
- default:
- /* should not happen */
- from_mat = to_mat = NULL;
- BLI_assert(false);
- break;
- }
- if (ob_from != ob_to) {
- remap_hair_emitter(scene, ob_from, psys_from, ob_to, psys, psys->edit, from_mat, to_mat, psys_from->flag & PSYS_GLOBAL_HAIR, psys->flag & PSYS_GLOBAL_HAIR);
- }
-
- /* tag for recalc */
-// psys->recalc |= PSYS_RECALC_RESET;
- }
-
- #undef PSYS_FROM_FIRST
- #undef PSYS_FROM_NEXT
-
- DAG_id_tag_update(&ob_to->id, OB_RECALC_DATA);
- WM_main_add_notifier(NC_OBJECT | ND_PARTICLE | NA_EDITED, ob_to);
- return true;
-}
-
-static int copy_particle_systems_poll(bContext *C)
-{
- Object *ob;
- if (!ED_operator_object_active_editable(C))
- return false;
-
- ob = ED_object_active_context(C);
- if (BLI_listbase_is_empty(&ob->particlesystem))
- return false;
-
- return true;
-}
-
-static int copy_particle_systems_exec(bContext *C, wmOperator *op)
-{
- const int space = RNA_enum_get(op->ptr, "space");
- const bool remove_target_particles = RNA_boolean_get(op->ptr, "remove_target_particles");
- const bool use_active = RNA_boolean_get(op->ptr, "use_active");
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- Object *ob_from = ED_object_active_context(C);
- ParticleSystem *psys_from = use_active ? CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem).data : NULL;
-
- int changed_tot = 0;
- int fail = 0;
-
- CTX_DATA_BEGIN (C, Object *, ob_to, selected_editable_objects)
- {
- if (ob_from != ob_to) {
- bool changed = false;
- if (remove_target_particles) {
- remove_particle_systems_from_object(ob_to);
- changed = true;
- }
- if (copy_particle_systems_to_object(bmain, scene, ob_from, psys_from, ob_to, space, false))
- changed = true;
- else
- fail++;
-
- if (changed)
- changed_tot++;
- }
- }
- CTX_DATA_END;
-
- if ((changed_tot == 0 && fail == 0) || fail) {
- BKE_reportf(op->reports, RPT_ERROR,
- "Copy particle systems to selected: %d done, %d failed",
- changed_tot, fail);
- }
-
- return OPERATOR_FINISHED;
-}
-
-void PARTICLE_OT_copy_particle_systems(wmOperatorType *ot)
-{
- static EnumPropertyItem space_items[] = {
- {PAR_COPY_SPACE_OBJECT, "OBJECT", 0, "Object", "Copy inside each object's local space"},
- {PAR_COPY_SPACE_WORLD, "WORLD", 0, "World", "Copy in world space"},
- {0, NULL, 0, NULL, NULL}
- };
-
- ot->name = "Copy Particle Systems";
- ot->description = "Copy particle systems from the active object to selected objects";
- ot->idname = "PARTICLE_OT_copy_particle_systems";
-
- ot->poll = copy_particle_systems_poll;
- ot->exec = copy_particle_systems_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_enum(ot->srna, "space", space_items, PAR_COPY_SPACE_OBJECT, "Space", "Space transform for copying from one object to another");
- RNA_def_boolean(ot->srna, "remove_target_particles", true, "Remove Target Particles", "Remove particle systems on the target objects");
- RNA_def_boolean(ot->srna, "use_active", false, "Use Active", "Use the active particle system from the context");
-}
-
-static int duplicate_particle_systems_poll(bContext *C)
-{
- if (!ED_operator_object_active_editable(C)) {
- return false;
- }
- Object *ob = ED_object_active_context(C);
- if (BLI_listbase_is_empty(&ob->particlesystem)) {
- return false;
- }
- return true;
-}
-
-static int duplicate_particle_systems_exec(bContext *C, wmOperator *op)
-{
- const bool duplicate_settings = RNA_boolean_get(op->ptr, "use_duplicate_settings");
- Scene *scene = CTX_data_scene(C);
- Object *ob = ED_object_active_context(C);
- ParticleSystem *psys = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem).data;
- copy_particle_systems_to_object(CTX_data_main(C), scene, ob, psys, ob,
- PAR_COPY_SPACE_OBJECT, duplicate_settings);
- return OPERATOR_FINISHED;
-}
-
-void PARTICLE_OT_duplicate_particle_system(wmOperatorType *ot)
-{
- ot->name = "Duplicate Particle Systems";
- ot->description = "Duplicate particle system within the active object";
- ot->idname = "PARTICLE_OT_duplicate_particle_system";
-
- ot->poll = duplicate_particle_systems_poll;
- ot->exec = duplicate_particle_systems_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_boolean(ot->srna, "use_duplicate_settings", false, "Duplicate Settings",
- "Duplicate settings as well, so new particle system uses own settings");
-}
diff --git a/source/blender/editors/physics/physics_intern.h b/source/blender/editors/physics/physics_intern.h
index 6b6df15e987..a5b59feba6b 100644
--- a/source/blender/editors/physics/physics_intern.h
+++ b/source/blender/editors/physics/physics_intern.h
@@ -35,64 +35,6 @@
struct wmOperatorType;
-/* particle_edit.c */
-void PARTICLE_OT_select_all(struct wmOperatorType *ot);
-void PARTICLE_OT_select_roots(struct wmOperatorType *ot);
-void PARTICLE_OT_select_tips(struct wmOperatorType *ot);
-void PARTICLE_OT_select_random(struct wmOperatorType *ot);
-void PARTICLE_OT_select_linked(struct wmOperatorType *ot);
-void PARTICLE_OT_select_less(struct wmOperatorType *ot);
-void PARTICLE_OT_select_more(struct wmOperatorType *ot);
-
-void PARTICLE_OT_hide(struct wmOperatorType *ot);
-void PARTICLE_OT_reveal(struct wmOperatorType *ot);
-
-void PARTICLE_OT_rekey(struct wmOperatorType *ot);
-void PARTICLE_OT_subdivide(struct wmOperatorType *ot);
-void PARTICLE_OT_remove_doubles(struct wmOperatorType *ot);
-void PARTICLE_OT_weight_set(struct wmOperatorType *ot);
-void PARTICLE_OT_delete(struct wmOperatorType *ot);
-void PARTICLE_OT_mirror(struct wmOperatorType *ot);
-
-void PARTICLE_OT_brush_edit(struct wmOperatorType *ot);
-
-void PARTICLE_OT_shape_cut(struct wmOperatorType *ot);
-
-void PARTICLE_OT_particle_edit_toggle(struct wmOperatorType *ot);
-void PARTICLE_OT_edited_clear(struct wmOperatorType *ot);
-
-void PARTICLE_OT_unify_length(struct wmOperatorType *ot);
-
-/* particle_object.c */
-void OBJECT_OT_particle_system_add(struct wmOperatorType *ot);
-void OBJECT_OT_particle_system_remove(struct wmOperatorType *ot);
-
-void PARTICLE_OT_new(struct wmOperatorType *ot);
-void PARTICLE_OT_new_target(struct wmOperatorType *ot);
-void PARTICLE_OT_target_remove(struct wmOperatorType *ot);
-void PARTICLE_OT_target_move_up(struct wmOperatorType *ot);
-void PARTICLE_OT_target_move_down(struct wmOperatorType *ot);
-void PARTICLE_OT_connect_hair(struct wmOperatorType *ot);
-void PARTICLE_OT_disconnect_hair(struct wmOperatorType *ot);
-void PARTICLE_OT_copy_particle_systems(struct wmOperatorType *ot);
-void PARTICLE_OT_duplicate_particle_system(struct wmOperatorType *ot);
-
-void PARTICLE_OT_dupliob_copy(struct wmOperatorType *ot);
-void PARTICLE_OT_dupliob_remove(struct wmOperatorType *ot);
-void PARTICLE_OT_dupliob_move_up(struct wmOperatorType *ot);
-void PARTICLE_OT_dupliob_move_down(struct wmOperatorType *ot);
-
-/* particle_boids.c */
-void BOID_OT_rule_add(struct wmOperatorType *ot);
-void BOID_OT_rule_del(struct wmOperatorType *ot);
-void BOID_OT_rule_move_up(struct wmOperatorType *ot);
-void BOID_OT_rule_move_down(struct wmOperatorType *ot);
-
-void BOID_OT_state_add(struct wmOperatorType *ot);
-void BOID_OT_state_del(struct wmOperatorType *ot);
-void BOID_OT_state_move_up(struct wmOperatorType *ot);
-void BOID_OT_state_move_down(struct wmOperatorType *ot);
-
/* physics_fluid.c */
void FLUID_OT_bake(struct wmOperatorType *ot);
@@ -103,15 +45,6 @@ void DPAINT_OT_surface_slot_remove(struct wmOperatorType *ot);
void DPAINT_OT_type_toggle(struct wmOperatorType *ot);
void DPAINT_OT_output_toggle(struct wmOperatorType *ot);
-/* physics_pointcache.c */
-void PTCACHE_OT_bake_all(struct wmOperatorType *ot);
-void PTCACHE_OT_free_bake_all(struct wmOperatorType *ot);
-void PTCACHE_OT_bake(struct wmOperatorType *ot);
-void PTCACHE_OT_free_bake(struct wmOperatorType *ot);
-void PTCACHE_OT_bake_from_cache(struct wmOperatorType *ot);
-void PTCACHE_OT_add(struct wmOperatorType *ot);
-void PTCACHE_OT_remove(struct wmOperatorType *ot);
-
/* rigidbody_object.c */
void RIGIDBODY_OT_object_add(struct wmOperatorType *ot);
void RIGIDBODY_OT_object_remove(struct wmOperatorType *ot);
diff --git a/source/blender/editors/physics/physics_ops.c b/source/blender/editors/physics/physics_ops.c
index 7ba4b2be43b..d0cb7fd12a9 100644
--- a/source/blender/editors/physics/physics_ops.c
+++ b/source/blender/editors/physics/physics_ops.c
@@ -42,54 +42,8 @@
/***************************** particles ***********************************/
-static void operatortypes_particle(void)
+static void operatortypes_rigidbody(void)
{
- WM_operatortype_append(PARTICLE_OT_select_all);
- WM_operatortype_append(PARTICLE_OT_select_roots);
- WM_operatortype_append(PARTICLE_OT_select_tips);
- WM_operatortype_append(PARTICLE_OT_select_random);
- WM_operatortype_append(PARTICLE_OT_select_linked);
- WM_operatortype_append(PARTICLE_OT_select_less);
- WM_operatortype_append(PARTICLE_OT_select_more);
-
- WM_operatortype_append(PARTICLE_OT_hide);
- WM_operatortype_append(PARTICLE_OT_reveal);
-
- WM_operatortype_append(PARTICLE_OT_rekey);
- WM_operatortype_append(PARTICLE_OT_subdivide);
- WM_operatortype_append(PARTICLE_OT_remove_doubles);
- WM_operatortype_append(PARTICLE_OT_weight_set);
- WM_operatortype_append(PARTICLE_OT_delete);
- WM_operatortype_append(PARTICLE_OT_mirror);
-
- WM_operatortype_append(PARTICLE_OT_brush_edit);
-
- WM_operatortype_append(PARTICLE_OT_shape_cut);
-
- WM_operatortype_append(PARTICLE_OT_particle_edit_toggle);
- WM_operatortype_append(PARTICLE_OT_edited_clear);
-
- WM_operatortype_append(PARTICLE_OT_unify_length);
-
-
- WM_operatortype_append(OBJECT_OT_particle_system_add);
- WM_operatortype_append(OBJECT_OT_particle_system_remove);
-
- WM_operatortype_append(PARTICLE_OT_new);
- WM_operatortype_append(PARTICLE_OT_new_target);
- WM_operatortype_append(PARTICLE_OT_target_remove);
- WM_operatortype_append(PARTICLE_OT_target_move_up);
- WM_operatortype_append(PARTICLE_OT_target_move_down);
- WM_operatortype_append(PARTICLE_OT_connect_hair);
- WM_operatortype_append(PARTICLE_OT_disconnect_hair);
- WM_operatortype_append(PARTICLE_OT_copy_particle_systems);
- WM_operatortype_append(PARTICLE_OT_duplicate_particle_system);
-
- WM_operatortype_append(PARTICLE_OT_dupliob_copy);
- WM_operatortype_append(PARTICLE_OT_dupliob_remove);
- WM_operatortype_append(PARTICLE_OT_dupliob_move_up);
- WM_operatortype_append(PARTICLE_OT_dupliob_move_down);
-
WM_operatortype_append(RIGIDBODY_OT_object_add);
WM_operatortype_append(RIGIDBODY_OT_object_remove);
@@ -107,73 +61,6 @@ static void operatortypes_particle(void)
// WM_operatortype_append(RIGIDBODY_OT_world_export);
}
-static void keymap_particle(wmKeyConfig *keyconf)
-{
- wmKeyMapItem *kmi;
- wmKeyMap *keymap;
-
- keymap = WM_keymap_find(keyconf, "Particle", 0, 0);
- keymap->poll = PE_poll;
-
- kmi = WM_keymap_add_item(keymap, "PARTICLE_OT_select_all", AKEY, KM_PRESS, 0, 0);
- RNA_enum_set(kmi->ptr, "action", SEL_TOGGLE);
- kmi = WM_keymap_add_item(keymap, "PARTICLE_OT_select_all", IKEY, KM_PRESS, KM_CTRL, 0);
- RNA_enum_set(kmi->ptr, "action", SEL_INVERT);
-
- WM_keymap_add_item(keymap, "PARTICLE_OT_select_more", PADPLUSKEY, KM_PRESS, KM_CTRL, 0);
- WM_keymap_add_item(keymap, "PARTICLE_OT_select_less", PADMINUS, KM_PRESS, KM_CTRL, 0);
-
- kmi = WM_keymap_add_item(keymap, "PARTICLE_OT_select_linked", LKEY, KM_PRESS, 0, 0);
- RNA_boolean_set(kmi->ptr, "deselect", false);
- kmi = WM_keymap_add_item(keymap, "PARTICLE_OT_select_linked", LKEY, KM_PRESS, KM_SHIFT, 0);
- RNA_boolean_set(kmi->ptr, "deselect", true);
-
- WM_keymap_add_item(keymap, "PARTICLE_OT_delete", XKEY, KM_PRESS, 0, 0);
- WM_keymap_add_item(keymap, "PARTICLE_OT_delete", DELKEY, KM_PRESS, 0, 0);
-
- WM_keymap_add_item(keymap, "PARTICLE_OT_reveal", HKEY, KM_PRESS, KM_ALT, 0);
- kmi = WM_keymap_add_item(keymap, "PARTICLE_OT_hide", HKEY, KM_PRESS, 0, 0);
- RNA_boolean_set(kmi->ptr, "unselected", false);
- kmi = WM_keymap_add_item(keymap, "PARTICLE_OT_hide", HKEY, KM_PRESS, KM_SHIFT, 0);
- RNA_boolean_set(kmi->ptr, "unselected", true);
-
- kmi = WM_keymap_verify_item(keymap, "VIEW3D_OT_manipulator", LEFTMOUSE, KM_PRESS, KM_ANY, 0);
- RNA_boolean_set(kmi->ptr, "release_confirm", true);
-
- WM_keymap_add_item(keymap, "PARTICLE_OT_brush_edit", LEFTMOUSE, KM_PRESS, 0, 0);
- WM_keymap_add_item(keymap, "PARTICLE_OT_brush_edit", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0);
-
- /* size radial control */
- kmi = WM_keymap_add_item(keymap, "WM_OT_radial_control", FKEY, KM_PRESS, 0, 0);
- RNA_string_set(kmi->ptr, "data_path_primary", "tool_settings.particle_edit.brush.size");
-
- /* size radial control */
- kmi = WM_keymap_add_item(keymap, "WM_OT_radial_control", FKEY, KM_PRESS, KM_SHIFT, 0);
- RNA_string_set(kmi->ptr, "data_path_primary", "tool_settings.particle_edit.brush.strength");
-
- WM_keymap_add_menu(keymap, "VIEW3D_MT_particle_specials", WKEY, KM_PRESS, 0, 0);
-
- WM_keymap_add_item(keymap, "PARTICLE_OT_weight_set", KKEY, KM_PRESS, KM_SHIFT, 0);
-
- ED_keymap_proportional_cycle(keyconf, keymap);
- ED_keymap_proportional_editmode(keyconf, keymap, false);
-}
-
-/******************************* boids *************************************/
-
-static void operatortypes_boids(void)
-{
- WM_operatortype_append(BOID_OT_rule_add);
- WM_operatortype_append(BOID_OT_rule_del);
- WM_operatortype_append(BOID_OT_rule_move_up);
- WM_operatortype_append(BOID_OT_rule_move_down);
-
- WM_operatortype_append(BOID_OT_state_add);
- WM_operatortype_append(BOID_OT_state_del);
- WM_operatortype_append(BOID_OT_state_move_up);
- WM_operatortype_append(BOID_OT_state_move_down);
-}
-
/********************************* fluid ***********************************/
static void operatortypes_fluid(void)
@@ -181,19 +68,6 @@ static void operatortypes_fluid(void)
WM_operatortype_append(FLUID_OT_bake);
}
-/**************************** point cache **********************************/
-
-static void operatortypes_pointcache(void)
-{
- WM_operatortype_append(PTCACHE_OT_bake_all);
- WM_operatortype_append(PTCACHE_OT_free_bake_all);
- WM_operatortype_append(PTCACHE_OT_bake);
- WM_operatortype_append(PTCACHE_OT_free_bake);
- WM_operatortype_append(PTCACHE_OT_bake_from_cache);
- WM_operatortype_append(PTCACHE_OT_add);
- WM_operatortype_append(PTCACHE_OT_remove);
-}
-
/********************************* dynamic paint ***********************************/
static void operatortypes_dynamicpaint(void)
@@ -205,31 +79,17 @@ static void operatortypes_dynamicpaint(void)
WM_operatortype_append(DPAINT_OT_output_toggle);
}
-//static void keymap_pointcache(wmWindowManager *wm)
-//{
-// wmKeyMap *keymap = WM_keymap_find(wm, "Pointcache", 0, 0);
-//
-// WM_keymap_add_item(keymap, "PHYSICS_OT_bake_all", AKEY, KM_PRESS, 0, 0);
-// WM_keymap_add_item(keymap, "PHYSICS_OT_free_all", PADPLUSKEY, KM_PRESS, KM_CTRL, 0);
-// WM_keymap_add_item(keymap, "PHYSICS_OT_bake_particle_system", PADMINUS, KM_PRESS, KM_CTRL, 0);
-// WM_keymap_add_item(keymap, "PHYSICS_OT_free_particle_system", LKEY, KM_PRESS, 0, 0);
-//}
-
/****************************** general ************************************/
void ED_operatortypes_physics(void)
{
- operatortypes_particle();
- operatortypes_boids();
+ operatortypes_rigidbody();
operatortypes_fluid();
- operatortypes_pointcache();
operatortypes_dynamicpaint();
}
-void ED_keymap_physics(wmKeyConfig *keyconf)
+void ED_keymap_physics(wmKeyConfig *UNUSED(keyconf))
{
- keymap_particle(keyconf);
- //keymap_pointcache(keyconf);
}
diff --git a/source/blender/editors/physics/physics_pointcache.c b/source/blender/editors/physics/physics_pointcache.c
deleted file mode 100644
index e81aa584586..00000000000
--- a/source/blender/editors/physics/physics_pointcache.c
+++ /dev/null
@@ -1,469 +0,0 @@
-/*
- * ***** 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) 2007 by Janne Karhu.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/editors/physics/physics_pointcache.c
- * \ingroup edphys
- */
-
-#include <stdlib.h>
-#include <string.h>
-
-#include "MEM_guardedalloc.h"
-
-#include "BLI_blenlib.h"
-#include "BLI_utildefines.h"
-
-#include "DNA_scene_types.h"
-
-#include "BKE_context.h"
-#include "BKE_screen.h"
-#include "BKE_global.h"
-#include "BKE_main.h"
-#include "BKE_particle.h"
-#include "BKE_pointcache.h"
-
-#include "ED_particle.h"
-
-#include "WM_api.h"
-#include "WM_types.h"
-
-#include "RNA_access.h"
-#include "RNA_define.h"
-
-#include "physics_intern.h"
-
-static int ptcache_bake_all_poll(bContext *C)
-{
- return CTX_data_scene(C) != NULL;
-}
-
-static int ptcache_poll(bContext *C)
-{
- PointerRNA ptr= CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache);
- return (ptr.data && ptr.id.data);
-}
-
-typedef struct PointCacheJob {
- void *owner;
- short *stop, *do_update;
- float *progress;
-
- PTCacheBaker *baker;
-} PointCacheJob;
-
-static void ptcache_job_free(void *customdata)
-{
- PointCacheJob *job = customdata;
- MEM_freeN(job->baker);
- MEM_freeN(job);
-}
-
-static int ptcache_job_break(void *customdata)
-{
- PointCacheJob *job = customdata;
-
- if (G.is_break) {
- return 1;
- }
-
- if (job->stop && *(job->stop)) {
- return 1;
- }
-
- return 0;
-}
-
-static void ptcache_job_update(void *customdata, float progress, int *cancel)
-{
- PointCacheJob *job = customdata;
-
- if (ptcache_job_break(job)) {
- *cancel = 1;
- }
-
- *(job->do_update) = true;
- *(job->progress) = progress;
-}
-
-static void ptcache_job_startjob(void *customdata, short *stop, short *do_update, float *progress)
-{
- PointCacheJob *job = customdata;
-
- job->stop = stop;
- job->do_update = do_update;
- job->progress = progress;
-
- G.is_break = false;
-
- /* XXX annoying hack: needed to prevent data corruption when changing
- * scene frame in separate threads
- */
- G.is_rendering = true;
- BKE_spacedata_draw_locks(true);
-
- BKE_ptcache_bake(job->baker);
-
- *do_update = true;
- *stop = 0;
-}
-
-static void ptcache_job_endjob(void *customdata)
-{
- PointCacheJob *job = customdata;
- Scene *scene = job->baker->scene;
-
- G.is_rendering = false;
- BKE_spacedata_draw_locks(false);
-
- WM_set_locked_interface(G.main->wm.first, false);
-
- WM_main_add_notifier(NC_SCENE | ND_FRAME, scene);
- WM_main_add_notifier(NC_OBJECT | ND_POINTCACHE, job->baker->pid.ob);
-}
-
-static void ptcache_free_bake(PointCache *cache)
-{
- if (cache->edit) {
- if (!cache->edit->edited || 1) {// XXX okee("Lose changes done in particle mode?")) {
- PE_free_ptcache_edit(cache->edit);
- cache->edit = NULL;
- cache->flag &= ~PTCACHE_BAKED;
- }
- }
- else {
- cache->flag &= ~PTCACHE_BAKED;
- }
-}
-
-static PTCacheBaker *ptcache_baker_create(bContext *C, wmOperator *op, bool all)
-{
- PTCacheBaker *baker = MEM_callocN(sizeof(PTCacheBaker), "PTCacheBaker");
-
- baker->main = CTX_data_main(C);
- baker->scene = CTX_data_scene(C);
- baker->bake = RNA_boolean_get(op->ptr, "bake");
- baker->render = 0;
- baker->anim_init = 0;
- baker->quick_step = 1;
-
- if (!all) {
- PointerRNA ptr = CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache);
- Object *ob = ptr.id.data;
- PointCache *cache = ptr.data;
-
- ListBase pidlist;
- BKE_ptcache_ids_from_object(&pidlist, ob, baker->scene, MAX_DUPLI_RECUR);
-
- for (PTCacheID *pid = pidlist.first; pid; pid = pid->next) {
- if (pid->cache == cache) {
- baker->pid = *pid;
- break;
- }
- }
-
- BLI_freelistN(&pidlist);
- }
-
- return baker;
-}
-
-static int ptcache_bake_exec(bContext *C, wmOperator *op)
-{
- bool all = STREQ(op->type->idname, "PTCACHE_OT_bake_all");
-
- PTCacheBaker *baker = ptcache_baker_create(C, op, all);
- BKE_ptcache_bake(baker);
- MEM_freeN(baker);
-
- return OPERATOR_FINISHED;
-}
-
-static int ptcache_bake_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
-{
- bool all = STREQ(op->type->idname, "PTCACHE_OT_bake_all");
-
- PointCacheJob *job = MEM_mallocN(sizeof(PointCacheJob), "PointCacheJob");
- job->baker = ptcache_baker_create(C, op, all);
- job->baker->bake_job = job;
- job->baker->update_progress = ptcache_job_update;
-
- wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), CTX_data_scene(C),
- "Point Cache", WM_JOB_PROGRESS, WM_JOB_TYPE_POINTCACHE);
-
- WM_jobs_customdata_set(wm_job, job, ptcache_job_free);
- WM_jobs_timer(wm_job, 0.1, NC_OBJECT | ND_POINTCACHE, NC_OBJECT | ND_POINTCACHE);
- WM_jobs_callbacks(wm_job, ptcache_job_startjob, NULL, NULL, ptcache_job_endjob);
-
- WM_set_locked_interface(CTX_wm_manager(C), true);
-
- WM_jobs_start(CTX_wm_manager(C), wm_job);
-
- WM_event_add_modal_handler(C, op);
-
- /* we must run modal until the bake job is done, otherwise the undo push
- * happens before the job ends, which can lead to race conditions between
- * the baking and file writing code */
- return OPERATOR_RUNNING_MODAL;
-}
-
-static int ptcache_bake_modal(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
-{
- Scene *scene = (Scene *) op->customdata;
-
- /* no running blender, remove handler and pass through */
- if (0 == WM_jobs_test(CTX_wm_manager(C), scene, WM_JOB_TYPE_POINTCACHE)) {
- return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
- }
-
- return OPERATOR_PASS_THROUGH;
-}
-
-static void ptcache_bake_cancel(bContext *C, wmOperator *op)
-{
- wmWindowManager *wm = CTX_wm_manager(C);
- Scene *scene = (Scene *) op->customdata;
-
- /* kill on cancel, because job is using op->reports */
- WM_jobs_kill_type(wm, scene, WM_JOB_TYPE_POINTCACHE);
-}
-
-static int ptcache_free_bake_all_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Scene *scene= CTX_data_scene(C);
- Base *base;
- PTCacheID *pid;
- ListBase pidlist;
-
- for (base=scene->base.first; base; base= base->next) {
- BKE_ptcache_ids_from_object(&pidlist, base->object, scene, MAX_DUPLI_RECUR);
-
- for (pid=pidlist.first; pid; pid=pid->next) {
- ptcache_free_bake(pid->cache);
- }
-
- BLI_freelistN(&pidlist);
-
- WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, base->object);
- }
-
- WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
-
- return OPERATOR_FINISHED;
-}
-
-void PTCACHE_OT_bake_all(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Bake All Physics";
- ot->description = "Bake all physics";
- ot->idname = "PTCACHE_OT_bake_all";
-
- /* api callbacks */
- ot->exec = ptcache_bake_exec;
- ot->invoke = ptcache_bake_invoke;
- ot->modal = ptcache_bake_modal;
- ot->cancel = ptcache_bake_cancel;
- ot->poll = ptcache_bake_all_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
-
- RNA_def_boolean(ot->srna, "bake", 1, "Bake", "");
-}
-void PTCACHE_OT_free_bake_all(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Free All Physics Bakes";
- ot->idname = "PTCACHE_OT_free_bake_all";
- ot->description = "Free all baked caches of all objects in the current scene";
-
- /* api callbacks */
- ot->exec = ptcache_free_bake_all_exec;
- ot->poll = ptcache_bake_all_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
-static int ptcache_free_bake_exec(bContext *C, wmOperator *UNUSED(op))
-{
- PointerRNA ptr= CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache);
- PointCache *cache= ptr.data;
- Object *ob= ptr.id.data;
-
- ptcache_free_bake(cache);
-
- WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, ob);
-
- return OPERATOR_FINISHED;
-}
-static int ptcache_bake_from_cache_exec(bContext *C, wmOperator *UNUSED(op))
-{
- PointerRNA ptr= CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache);
- PointCache *cache= ptr.data;
- Object *ob= ptr.id.data;
-
- cache->flag |= PTCACHE_BAKED;
-
- WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, ob);
-
- return OPERATOR_FINISHED;
-}
-void PTCACHE_OT_bake(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Bake Physics";
- ot->description = "Bake physics";
- ot->idname = "PTCACHE_OT_bake";
-
- /* api callbacks */
- ot->exec = ptcache_bake_exec;
- ot->invoke = ptcache_bake_invoke;
- ot->modal = ptcache_bake_modal;
- ot->cancel = ptcache_bake_cancel;
- ot->poll = ptcache_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
-
- RNA_def_boolean(ot->srna, "bake", 0, "Bake", "");
-}
-void PTCACHE_OT_free_bake(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Free Physics Bake";
- ot->description = "Free physics bake";
- ot->idname = "PTCACHE_OT_free_bake";
-
- /* api callbacks */
- ot->exec = ptcache_free_bake_exec;
- ot->poll = ptcache_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-void PTCACHE_OT_bake_from_cache(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Bake From Cache";
- ot->description = "Bake from cache";
- ot->idname = "PTCACHE_OT_bake_from_cache";
-
- /* api callbacks */
- ot->exec = ptcache_bake_from_cache_exec;
- ot->poll = ptcache_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
-static int ptcache_add_new_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Scene *scene = CTX_data_scene(C);
- PointerRNA ptr= CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache);
- Object *ob= ptr.id.data;
- PointCache *cache= ptr.data;
- PTCacheID *pid;
- ListBase pidlist;
-
- BKE_ptcache_ids_from_object(&pidlist, ob, scene, MAX_DUPLI_RECUR);
-
- for (pid=pidlist.first; pid; pid=pid->next) {
- if (pid->cache == cache) {
- PointCache *cache_new = BKE_ptcache_add(pid->ptcaches);
- cache_new->step = pid->default_step;
- *(pid->cache_ptr) = cache_new;
- break;
- }
- }
-
- BLI_freelistN(&pidlist);
-
- WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
- WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, ob);
-
- return OPERATOR_FINISHED;
-}
-static int ptcache_remove_exec(bContext *C, wmOperator *UNUSED(op))
-{
- PointerRNA ptr= CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache);
- Scene *scene= CTX_data_scene(C);
- Object *ob= ptr.id.data;
- PointCache *cache= ptr.data;
- PTCacheID *pid;
- ListBase pidlist;
-
- BKE_ptcache_ids_from_object(&pidlist, ob, scene, MAX_DUPLI_RECUR);
-
- for (pid=pidlist.first; pid; pid=pid->next) {
- if (pid->cache == cache) {
- if (pid->ptcaches->first == pid->ptcaches->last)
- continue; /* don't delete last cache */
-
- BLI_remlink(pid->ptcaches, pid->cache);
- BKE_ptcache_free(pid->cache);
- *(pid->cache_ptr) = pid->ptcaches->first;
-
- break;
- }
- }
-
- BLI_freelistN(&pidlist);
-
- WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, ob);
-
- return OPERATOR_FINISHED;
-}
-void PTCACHE_OT_add(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Add New Cache";
- ot->description = "Add new cache";
- ot->idname = "PTCACHE_OT_add";
-
- /* api callbacks */
- ot->exec = ptcache_add_new_exec;
- ot->poll = ptcache_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-void PTCACHE_OT_remove(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Delete Current Cache";
- ot->description = "Delete current cache";
- ot->idname = "PTCACHE_OT_remove";
-
- /* api callbacks */
- ot->exec = ptcache_remove_exec;
- ot->poll = ptcache_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c
index 99b33788fdd..9c269fb6116 100644
--- a/source/blender/editors/render/render_shading.c
+++ b/source/blender/editors/render/render_shading.c
@@ -36,7 +36,6 @@
#include "DNA_material_types.h"
#include "DNA_node_types.h"
#include "DNA_object_types.h"
-#include "DNA_particle_types.h"
#include "DNA_scene_types.h"
#include "DNA_space_types.h"
#include "DNA_world_types.h"
@@ -1820,9 +1819,6 @@ static void copy_mtex_copybuf(ID *id)
mtex = &(((World *)id)->mtex[(int)((World *)id)->texact]);
// mtex= wrld->mtex[(int)wrld->texact]; // TODO
break;
- case ID_PA:
- mtex = &(((ParticleSettings *)id)->mtex[(int)((ParticleSettings *)id)->texact]);
- break;
case ID_LS:
mtex = &(((FreestyleLineStyle *)id)->mtex[(int)((FreestyleLineStyle *)id)->texact]);
break;
@@ -1856,9 +1852,6 @@ static void paste_mtex_copybuf(ID *id)
mtex = &(((World *)id)->mtex[(int)((World *)id)->texact]);
// mtex= wrld->mtex[(int)wrld->texact]; // TODO
break;
- case ID_PA:
- mtex = &(((ParticleSettings *)id)->mtex[(int)((ParticleSettings *)id)->texact]);
- break;
case ID_LS:
mtex = &(((FreestyleLineStyle *)id)->mtex[(int)((FreestyleLineStyle *)id)->texact]);
break;
@@ -1927,7 +1920,6 @@ static int paste_mtex_exec(bContext *C, wmOperator *UNUSED(op))
Material *ma = CTX_data_pointer_get_type(C, "material", &RNA_Material).data;
Lamp *la = CTX_data_pointer_get_type(C, "lamp", &RNA_Lamp).data;
World *wo = CTX_data_pointer_get_type(C, "world", &RNA_World).data;
- ParticleSystem *psys = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem).data;
FreestyleLineStyle *linestyle = CTX_data_pointer_get_type(C, "line_style", &RNA_FreestyleLineStyle).data;
if (ma)
@@ -1936,8 +1928,6 @@ static int paste_mtex_exec(bContext *C, wmOperator *UNUSED(op))
id = &la->id;
else if (wo)
id = &wo->id;
- else if (psys)
- id = &psys->part->id;
else if (linestyle)
id = &linestyle->id;
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index e6bb604d387..2acc9e7bfe7 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -57,6 +57,8 @@
#include "ED_screen_types.h"
#include "ED_space_api.h"
+#include "GPU_immediate.h"
+
#include "BIF_gl.h"
#include "BIF_glutil.h"
#include "BLF_api.h"
@@ -89,21 +91,30 @@ static void region_draw_emboss(const ARegion *ar, const rcti *scirct)
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ VertexFormat* format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ unsigned color = add_attrib(format, "color", GL_UNSIGNED_BYTE, 4, NORMALIZE_INT_TO_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
+ immBegin(GL_LINE_STRIP, 5);
+
/* right */
- glColor4ub(0, 0, 0, 30);
- sdrawline(rect.xmax, rect.ymin, rect.xmax, rect.ymax);
+ immAttrib4ub(color, 0, 0, 0, 30);
+ immVertex2f(pos, rect.xmax, rect.ymax);
+ immVertex2f(pos, rect.xmax, rect.ymin);
/* bottom */
- glColor4ub(0, 0, 0, 30);
- sdrawline(rect.xmin, rect.ymin, rect.xmax, rect.ymin);
+ immVertex2f(pos, rect.xmin, rect.ymin);
- /* top */
- glColor4ub(255, 255, 255, 30);
- sdrawline(rect.xmin, rect.ymax, rect.xmax, rect.ymax);
-
/* left */
- glColor4ub(255, 255, 255, 30);
- sdrawline(rect.xmin, rect.ymin, rect.xmin, rect.ymax);
+ immAttrib4ub(color, 255, 255, 255, 30);
+ immVertex2f(pos, rect.xmin, rect.ymax);
+
+ /* top */
+ immVertex2f(pos, rect.xmax, rect.ymax);
+
+ immEnd();
+ immUnbindProgram();
glDisable(GL_BLEND);
}
@@ -206,7 +217,7 @@ static void area_draw_azone_fullscreen(short x1, short y1, short x2, short y2, f
if (G.debug_value == 1) {
rcti click_rect;
float icon_size = UI_DPI_ICON_SIZE + 7 * UI_DPI_FAC;
- char alpha_debug = 255 * alpha;
+ unsigned char alpha_debug = 255 * alpha;
BLI_rcti_init(&click_rect, x, x + icon_size, y, y + icon_size);
@@ -229,59 +240,73 @@ static void area_draw_azone(short x1, short y1, short x2, short y2)
dx = copysign(ceilf(0.3f * abs(dx)), dx);
dy = copysign(ceilf(0.3f * abs(dy)), dy);
- glEnable(GL_BLEND);
glEnable(GL_LINE_SMOOTH);
+
+ VertexFormat* format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ unsigned col = add_attrib(format, "color", GL_UNSIGNED_BYTE, 4, NORMALIZE_INT_TO_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
+ immBegin(GL_LINES, 12);
+
+ immAttrib4ub(col, 255, 255, 255, 180);
+ immVertex2f(pos, x1, y2);
+ immVertex2f(pos, x2, y1);
+
+ immAttrib4ub(col, 255, 255, 255, 130);
+ immVertex2f(pos, x1, y2 - dy);
+ immVertex2f(pos, x2 - dx, y1);
+
+ immAttrib4ub(col, 255, 255, 255, 80);
+ immVertex2f(pos, x1, y2 - 2 * dy);
+ immVertex2f(pos, x2 - 2 * dx, y1);
- glColor4ub(255, 255, 255, 180);
- fdrawline(x1, y2, x2, y1);
- glColor4ub(255, 255, 255, 130);
- fdrawline(x1, y2 - dy, x2 - dx, y1);
- glColor4ub(255, 255, 255, 80);
- fdrawline(x1, y2 - 2 * dy, x2 - 2 * dx, y1);
-
- glColor4ub(0, 0, 0, 210);
- fdrawline(x1, y2 + 1, x2 + 1, y1);
- glColor4ub(0, 0, 0, 180);
- fdrawline(x1, y2 - dy + 1, x2 - dx + 1, y1);
- glColor4ub(0, 0, 0, 150);
- fdrawline(x1, y2 - 2 * dy + 1, x2 - 2 * dx + 1, y1);
+ immAttrib4ub(col, 0, 0, 0, 210);
+ immVertex2f(pos, x1, y2 + 1);
+ immVertex2f(pos, x2 + 1, y1);
+
+ immAttrib4ub(col, 0, 0, 0, 180);
+ immVertex2f(pos, x1, y2 - dy + 1);
+ immVertex2f(pos, x2 - dx + 1, y1);
+
+ immAttrib4ub(col, 0, 0, 0, 150);
+ immVertex2f(pos, x1, y2 - 2 * dy + 1);
+ immVertex2f(pos, x2 - 2 * dx + 1, y1);
+
+ immEnd();
+ immUnbindProgram();
glDisable(GL_LINE_SMOOTH);
- glDisable(GL_BLEND);
}
static void region_draw_azone_icon(AZone *az)
{
- GLUquadricObj *qobj = NULL;
- short midx = az->x1 + (az->x2 - az->x1) / 2;
- short midy = az->y1 + (az->y2 - az->y1) / 2;
-
- qobj = gluNewQuadric();
-
- glPushMatrix();
- glTranslatef(midx, midy, 0.0);
-
- /* outlined circle */
- glEnable(GL_LINE_SMOOTH);
+ float midx = az->x1 + (az->x2 - az->x1) * 0.5f;
+ float midy = az->y1 + (az->y2 - az->y1) * 0.5f;
- glColor4f(1.f, 1.f, 1.f, 0.8f);
+ VertexFormat* format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
- gluQuadricDrawStyle(qobj, GLU_FILL);
- gluDisk(qobj, 0.0, 4.25f, 16, 1);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- glColor4f(0.2f, 0.2f, 0.2f, 0.9f);
-
- gluQuadricDrawStyle(qobj, GLU_SILHOUETTE);
- gluDisk(qobj, 0.0, 4.25f, 16, 1);
-
+ /* outlined circle */
+ immUniform4f("color", 1.0f, 1.0f, 1.0f, 0.8f);
+ imm_draw_filled_circle(pos, midx, midy, 4.25f, 12);
+ /* TODO(merwin): replace this --^ with one round point once shader is ready */
+ glEnable(GL_LINE_SMOOTH);
+ immUniform4f("color", 0.2f, 0.2f, 0.2f, 0.9f);
+ imm_draw_lined_circle(pos, midx, midy, 4.25f, 12);
glDisable(GL_LINE_SMOOTH);
-
- glPopMatrix();
- gluDeleteQuadric(qobj);
-
+
/* + */
- sdrawline(midx, midy - 2, midx, midy + 3);
- sdrawline(midx - 2, midy, midx + 3, midy);
+ immBegin(GL_LINES, 4);
+ immVertex2f(pos, midx, midy - 2);
+ immVertex2f(pos, midx, midy + 3);
+ immVertex2f(pos, midx - 2, midy);
+ immVertex2f(pos, midx + 3, midy);
+ immEnd();
+
+ immUnbindProgram();
}
static void draw_azone_plus(float x1, float y1, float x2, float y2)
diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c
index 93bac3f6660..a7e8c210335 100644
--- a/source/blender/editors/screen/glutil.c
+++ b/source/blender/editors/screen/glutil.c
@@ -49,45 +49,10 @@
#include "IMB_imbuf_types.h"
#include "GPU_basic_shader.h"
+#include "GPU_immediate.h"
#include "UI_interface.h"
-#ifndef GL_CLAMP_TO_EDGE
-#define GL_CLAMP_TO_EDGE 0x812F
-#endif
-
-/* UNUSED */
-#if 0
-void fdrawbezier(float vec[4][3])
-{
- float dist;
- float curve_res = 24, spline_step = 0.0f;
-
- dist = 0.5f * fabsf(vec[0][0] - vec[3][0]);
-
- /* check direction later, for top sockets */
- vec[1][0] = vec[0][0] + dist;
- vec[1][1] = vec[0][1];
-
- vec[2][0] = vec[3][0] - dist;
- vec[2][1] = vec[3][1];
- /* we can reuse the dist variable here to increment the GL curve eval amount */
- dist = 1.0f / curve_res;
-
- cpack(0x0);
- glMap1f(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 4, vec[0]);
- glBegin(GL_LINE_STRIP);
- while (spline_step < 1.000001f) {
-#if 0
- if (do_shaded)
- UI_ThemeColorBlend(th_col1, th_col2, spline_step);
-#endif
- glEvalCoord1f(spline_step);
- spline_step += dist;
- }
- glEnd();
-}
-#endif
void fdrawline(float x1, float y1, float x2, float y2)
{
@@ -99,6 +64,7 @@ void fdrawline(float x1, float y1, float x2, float y2)
void fdrawbox(float x1, float y1, float x2, float y2)
{
+ /* DEPRECATED: use imm_draw_line_box instead */
glBegin(GL_LINE_LOOP);
glVertex2f(x1, y1);
@@ -131,40 +97,9 @@ void sdrawline(int x1, int y1, int x2, int y2)
glEnd();
}
-/* UNUSED */
-#if 0
-/*
- * x1,y2
- * | \
- * | \
- * | \
- * x1,y1-- x2,y1
- */
-
-static void sdrawtripoints(int x1, int y1, int x2, int y2)
-{
- glVertex2i(x1, y1);
- glVertex2i(x1, y2);
- glVertex2i(x2, y1);
-}
-
-void sdrawtri(int x1, int y1, int x2, int y2)
-{
- glBegin(GL_LINE_STRIP);
- sdrawtripoints(x1, y1, x2, y2);
- glEnd();
-}
-
-void sdrawtrifill(int x1, int y1, int x2, int y2)
-{
- glBegin(GL_TRIANGLES);
- sdrawtripoints(x1, y1, x2, y2);
- glEnd();
-}
-#endif
-
void sdrawbox(int x1, int y1, int x2, int y2)
{
+ /* DEPRECATED: use imm_draw_line_box instead */
glBegin(GL_LINE_LOOP);
glVertex2i(x1, y1);
@@ -204,81 +139,6 @@ void set_inverted_drawing(int enable)
GL_TOGGLE(GL_DITHER, !enable);
}
-/* UNUSED */
-#if 0
-void sdrawXORline(int x0, int y0, int x1, int y1)
-{
- if (x0 == x1 && y0 == y1) return;
-
- set_inverted_drawing(1);
-
- glBegin(GL_LINES);
- glVertex2i(x0, y0);
- glVertex2i(x1, y1);
- glEnd();
-
- set_inverted_drawing(0);
-}
-
-void sdrawXORline4(int nr, int x0, int y0, int x1, int y1)
-{
- static int old[4][2][2];
- static char flags[4] = {0, 0, 0, 0};
-
- /* with builtin memory, max 4 lines */
-
- set_inverted_drawing(1);
-
- glBegin(GL_LINES);
- if (nr == -1) { /* flush */
- for (nr = 0; nr < 4; nr++) {
- if (flags[nr]) {
- glVertex2iv(old[nr][0]);
- glVertex2iv(old[nr][1]);
- flags[nr] = 0;
- }
- }
- }
- else {
- if (nr >= 0 && nr < 4) {
- if (flags[nr]) {
- glVertex2iv(old[nr][0]);
- glVertex2iv(old[nr][1]);
- }
-
- old[nr][0][0] = x0;
- old[nr][0][1] = y0;
- old[nr][1][0] = x1;
- old[nr][1][1] = y1;
-
- flags[nr] = 1;
- }
-
- glVertex2i(x0, y0);
- glVertex2i(x1, y1);
- }
- glEnd();
-
- set_inverted_drawing(0);
-}
-
-void fdrawXORellipse(float xofs, float yofs, float hw, float hh)
-{
- if (hw == 0) return;
-
- set_inverted_drawing(1);
-
- glPushMatrix();
- glTranslatef(xofs, yofs, 0.0f);
- glScalef(1.0f, hh / hw, 1.0f);
- glutil_draw_lined_arc(0.0, M_PI * 2.0, hw, 20);
- glPopMatrix();
-
- set_inverted_drawing(0);
-}
-
-#endif
-
void fdrawXORcirc(float xofs, float yofs, float rad)
{
set_inverted_drawing(1);
@@ -293,6 +153,7 @@ void fdrawXORcirc(float xofs, float yofs, float rad)
void glutil_draw_filled_arc(float start, float angle, float radius, int nsegments)
{
+ /* DEPRECATED */
int i;
glBegin(GL_TRIANGLE_FAN);
@@ -308,6 +169,7 @@ void glutil_draw_filled_arc(float start, float angle, float radius, int nsegment
void glutil_draw_lined_arc(float start, float angle, float radius, int nsegments)
{
+ /* DEPRECATED */
int i;
glBegin(GL_LINE_STRIP);
@@ -320,6 +182,44 @@ void glutil_draw_lined_arc(float start, float angle, float radius, int nsegments
glEnd();
}
+static void imm_draw_circle(GLenum prim_type, unsigned pos, float x, float y, float rad, int nsegments)
+{
+ immBegin(prim_type, nsegments);
+ for (int i = 0; i < nsegments; ++i) {
+ float angle = 2 * M_PI * ((float)i / (float)nsegments);
+ immVertex2f(pos, x + rad * cosf(angle),
+ y + rad * sinf(angle));
+ }
+ immEnd();
+}
+
+void imm_draw_lined_circle(unsigned pos, float x, float y, float rad, int nsegments)
+{
+ imm_draw_circle(GL_LINE_LOOP, pos, x, y, rad, nsegments);
+}
+
+void imm_draw_filled_circle(unsigned pos, float x, float y, float rad, int nsegments)
+{
+ imm_draw_circle(GL_TRIANGLE_FAN, pos, x, y, rad, nsegments);
+}
+
+void imm_draw_line_box(unsigned pos, float x1, float y1, float x2, float y2)
+{
+ immBegin(GL_LINE_LOOP, 4);
+ immVertex2f(pos, x1, y1);
+ immVertex2f(pos, x1, y2);
+ immVertex2f(pos, x2, y2);
+ immVertex2f(pos, x2, y1);
+ immEnd();
+}
+
+void imm_cpack(unsigned int x)
+{
+ immUniformColor3ub(((x)& 0xFF),
+ (((x) >> 8) & 0xFF),
+ (((x) >> 16) & 0xFF));
+}
+
float glaGetOneFloat(int param)
{
GLfloat v;
@@ -401,12 +301,6 @@ void glaDrawPixelsTexScaled_clipping(float x, float y, int img_w, int img_h,
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, zoomfilter);
-#if defined(__APPLE__) && 0
- /* [merwin] disable this workaround and see if anyone is affected. If not scrap it! Also at end of this function */
- /* workaround for os x 10.5/10.6 driver bug: http://lists.apple.com/archives/Mac-opengl/2008/Jul/msg00117.html */
- glPixelZoom(1.0f, 1.0f);
-#endif
-
/* setup seamless 2=on, 0=off */
seamless = ((tex_w < img_w || tex_h < img_h) && tex_w > 2 && tex_h > 2) ? 2 : 0;
@@ -514,11 +408,6 @@ void glaDrawPixelsTexScaled_clipping(float x, float y, int img_w, int img_h,
glBindTexture(GL_TEXTURE_2D, 0);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
-
-#if defined(__APPLE__) && 0
- /* workaround for os x 10.5/10.6 driver bug (above) */
- glPixelZoom(xzoom, yzoom);
-#endif
}
void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h,
@@ -673,6 +562,8 @@ void glaDefine2DArea(rcti *screen_rect)
glLoadIdentity();
}
+/* TODO(merwin): put the following 2D code to use, or build new 2D code inspired & informd by it */
+
#if 0 /* UNUSED */
struct gla2DDrawInfo {
@@ -785,7 +676,8 @@ void glaEnd2DDraw(gla2DDrawInfo *di)
MEM_freeN(di);
}
-#endif
+
+#endif /* UNUSED */
/* Uses current OpenGL state to get view matrices for gluProject/gluUnProject */
@@ -999,6 +891,7 @@ void glaDrawImBuf_glsl_ctx(const bContext *C, ImBuf *ibuf, float x, float y, int
void cpack(unsigned int x)
{
+ /* DEPRECATED: use imm_cpack */
glColor3ub(( (x) & 0xFF),
(((x) >> 8) & 0xFF),
(((x) >> 16) & 0xFF));
diff --git a/source/blender/editors/screen/screen_context.c b/source/blender/editors/screen/screen_context.c
index c165bbfd301..2cf0a16f236 100644
--- a/source/blender/editors/screen/screen_context.c
+++ b/source/blender/editors/screen/screen_context.c
@@ -392,12 +392,6 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
return 1;
}
- else if (CTX_data_equals(member, "particle_edit_object")) {
- if (obact && (obact->mode & OB_MODE_PARTICLE_EDIT))
- CTX_data_id_pointer_set(result, &obact->id);
-
- return 1;
- }
else if (CTX_data_equals(member, "sequences")) {
Editing *ed = BKE_sequencer_editing_get(scene, false);
if (ed) {
diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c
index 677a6472c72..5e00d158535 100644
--- a/source/blender/editors/screen/screen_edit.c
+++ b/source/blender/editors/screen/screen_edit.c
@@ -1069,6 +1069,9 @@ static void region_cursor_set(wmWindow *win, int swinid, int swin_changed)
for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) {
if (ar->swinid == swinid) {
if (swin_changed || (ar->type && ar->type->event_cursor)) {
+ if (WM_manipulatormap_cursor_set(ar->manipulator_map, win)) {
+ return;
+ }
ED_region_cursor_set(win, sa, ar);
}
return;
@@ -1274,25 +1277,28 @@ void ED_screens_initialize(wmWindowManager *wm)
void ED_region_exit(bContext *C, ARegion *ar)
{
wmWindowManager *wm = CTX_wm_manager(C);
+ wmWindow *win = CTX_wm_window(C);
ARegion *prevar = CTX_wm_region(C);
if (ar->type && ar->type->exit)
ar->type->exit(wm, ar);
CTX_wm_region_set(C, ar);
+
WM_event_remove_handlers(C, &ar->handlers);
+ WM_event_modal_handler_region_replace(win, ar, NULL);
if (ar->swinid) {
- wm_subwindow_close(CTX_wm_window(C), ar->swinid);
+ wm_subwindow_close(win, ar->swinid);
ar->swinid = 0;
}
-
+
if (ar->headerstr) {
MEM_freeN(ar->headerstr);
ar->headerstr = NULL;
}
if (ar->regiontimer) {
- WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), ar->regiontimer);
+ WM_event_remove_timer(wm, win, ar->regiontimer);
ar->regiontimer = NULL;
}
@@ -1302,6 +1308,7 @@ void ED_region_exit(bContext *C, ARegion *ar)
void ED_area_exit(bContext *C, ScrArea *sa)
{
wmWindowManager *wm = CTX_wm_manager(C);
+ wmWindow *win = CTX_wm_window(C);
ScrArea *prevsa = CTX_wm_area(C);
ARegion *ar;
@@ -1309,10 +1316,13 @@ void ED_area_exit(bContext *C, ScrArea *sa)
sa->type->exit(wm, sa);
CTX_wm_area_set(C, sa);
+
for (ar = sa->regionbase.first; ar; ar = ar->next)
ED_region_exit(C, ar);
WM_event_remove_handlers(C, &sa->handlers);
+ WM_event_modal_handler_area_replace(win, sa, NULL);
+
CTX_wm_area_set(C, prevsa);
}
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index 991025a4d5d..ef99fedbec0 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -43,7 +43,6 @@
#include "DNA_armature_types.h"
#include "DNA_mesh_types.h"
-#include "DNA_particle_types.h"
#include "DNA_scene_types.h"
#include "DNA_brush_types.h"
#include "DNA_object_types.h"
@@ -2422,21 +2421,6 @@ static void wpaint_stroke_done(const bContext *C, struct PaintStroke *stroke)
/* frees prev buffer */
copy_wpaint_prev(ts->wpaint, NULL, 0);
-
- /* and particles too */
- if (ob->particlesystem.first) {
- ParticleSystem *psys;
- int i;
-
- for (psys = ob->particlesystem.first; psys; psys = psys->next) {
- for (i = 0; i < PSYS_TOT_VG; i++) {
- if (psys->vgroup[i] == ob->actdef) {
- psys->recalc |= PSYS_RECALC_RESET;
- break;
- }
- }
- }
- }
DAG_id_tag_update(ob->data, 0);
diff --git a/source/blender/editors/space_api/spacetypes.c b/source/blender/editors/space_api/spacetypes.c
index ac6e3123e4e..5ff1d758563 100644
--- a/source/blender/editors/space_api/spacetypes.c
+++ b/source/blender/editors/space_api/spacetypes.c
@@ -121,12 +121,17 @@ void ED_spacetypes_init(void)
ED_operatortypes_view2d();
ED_operatortypes_ui();
-
- /* register operators */
+
+ /* register types for operators and manipulators */
spacetypes = BKE_spacetypes_list();
for (type = spacetypes->first; type; type = type->next) {
- if (type->operatortypes)
+ /* init manipulator types first, operator-types need them */
+ if (type->manipulators) {
+ type->manipulators();
+ }
+ if (type->operatortypes) {
type->operatortypes();
+ }
}
/* register internal render callbacks */
diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c
index da3364d872d..a1ecb1c4f5c 100644
--- a/source/blender/editors/space_buttons/buttons_context.c
+++ b/source/blender/editors/space_buttons/buttons_context.c
@@ -46,13 +46,13 @@
#include "DNA_world_types.h"
#include "DNA_brush_types.h"
#include "DNA_linestyle_types.h"
+#include "DNA_object_types.h"
#include "BKE_context.h"
#include "BKE_action.h"
#include "BKE_material.h"
#include "BKE_modifier.h"
#include "BKE_paint.h"
-#include "BKE_particle.h"
#include "BKE_screen.h"
#include "BKE_texture.h"
#include "BKE_linestyle.h"
@@ -339,34 +339,6 @@ static int buttons_context_path_pose_bone(ButsContextPath *path)
return 0;
}
-
-static int buttons_context_path_particle(ButsContextPath *path)
-{
- Object *ob;
- ParticleSystem *psys;
- PointerRNA *ptr = &path->ptr[path->len - 1];
-
- /* if we already have (pinned) particle settings, we're done */
- if (RNA_struct_is_a(ptr->type, &RNA_ParticleSettings)) {
- return 1;
- }
- /* if we have an object, get the active particle system */
- if (buttons_context_path_object(path)) {
- ob = path->ptr[path->len - 1].data;
-
- if (ob && ob->type == OB_MESH) {
- psys = psys_get_current(ob);
-
- RNA_pointer_create(&ob->id, &RNA_ParticleSystem, psys, &path->ptr[path->len]);
- path->len++;
- return 1;
- }
- }
-
- /* no path to a particle system possible */
- return 0;
-}
-
static int buttons_context_path_brush(ButsContextPath *path)
{
Scene *scene;
@@ -421,8 +393,6 @@ static int buttons_context_path_texture(ButsContextPath *path, ButsContextTextur
buttons_context_path_world(path);
else if (GS(id->name) == ID_LA)
buttons_context_path_data(path, OB_LAMP);
- else if (GS(id->name) == ID_PA)
- buttons_context_path_particle(path);
else if (GS(id->name) == ID_OB)
buttons_context_path_object(path);
else if (GS(id->name) == ID_LS)
@@ -441,7 +411,6 @@ static int buttons_context_path_texture(ButsContextPath *path, ButsContextTextur
Material *ma;
Lamp *la;
World *wo;
- ParticleSystem *psys;
FreestyleLineStyle *ls;
Tex *tex;
PointerRNA *ptr = &path->ptr[path->len - 1];
@@ -462,28 +431,6 @@ static int buttons_context_path_texture(ButsContextPath *path, ButsContextTextur
return 1;
}
}
- /* try particles */
- else if ((path->tex_ctx == SB_TEXC_PARTICLES) && buttons_context_path_particle(path)) {
- if (path->ptr[path->len - 1].type == &RNA_ParticleSettings) {
- ParticleSettings *part = path->ptr[path->len - 1].data;
-
- tex = give_current_particle_texture(part);
- RNA_id_pointer_create(&tex->id, &path->ptr[path->len]);
- path->len++;
- return 1;
- }
- else {
- psys = path->ptr[path->len - 1].data;
-
- if (psys && psys->part && GS(psys->part->id.name) == ID_PA) {
- tex = give_current_particle_texture(psys->part);
-
- RNA_id_pointer_create(&tex->id, &path->ptr[path->len]);
- path->len++;
- return 1;
- }
- }
- }
/* try material */
else if ((path->tex_ctx == SB_TEXC_MATERIAL) && buttons_context_path_material(path, true, false)) {
ma = path->ptr[path->len - 1].data;
@@ -610,9 +557,6 @@ static int buttons_context_path(const bContext *C, ButsContextPath *path, int ma
case BCONTEXT_DATA:
found = buttons_context_path_data(path, -1);
break;
- case BCONTEXT_PARTICLE:
- found = buttons_context_path_particle(path);
- break;
case BCONTEXT_MATERIAL:
found = buttons_context_path_material(path, false, (sbuts->texuser != NULL));
break;
@@ -900,14 +844,7 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r
ButsContextTexture *ct = sbuts->texuser;
PointerRNA *ptr;
- /* Particles slots are used in both old and new textures handling. */
- if ((ptr = get_pointer_type(path, &RNA_ParticleSystem))) {
- ParticleSettings *part = ((ParticleSystem *)ptr->data)->part;
-
- if (part)
- CTX_data_pointer_set(result, &part->id, &RNA_ParticleSettingsTextureSlot, part->mtex[(int)part->texact]);
- }
- else if (ct) {
+ if (ct) {
return 0; /* new shading system */
}
else if ((ptr = get_pointer_type(path, &RNA_Material))) {
@@ -963,38 +900,6 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r
set_pointer_type(path, result, &RNA_PoseBone);
return 1;
}
- else if (CTX_data_equals(member, "particle_system")) {
- set_pointer_type(path, result, &RNA_ParticleSystem);
- return 1;
- }
- else if (CTX_data_equals(member, "particle_system_editable")) {
- if (PE_poll((bContext *)C))
- set_pointer_type(path, result, &RNA_ParticleSystem);
- else
- CTX_data_pointer_set(result, NULL, &RNA_ParticleSystem, NULL);
- return 1;
- }
- else if (CTX_data_equals(member, "particle_settings")) {
- /* only available when pinned */
- PointerRNA *ptr = get_pointer_type(path, &RNA_ParticleSettings);
-
- if (ptr && ptr->data) {
- CTX_data_pointer_set(result, ptr->id.data, &RNA_ParticleSettings, ptr->data);
- return 1;
- }
- else {
- /* get settings from active particle system instead */
- ptr = get_pointer_type(path, &RNA_ParticleSystem);
-
- if (ptr && ptr->data) {
- ParticleSettings *part = ((ParticleSystem *)ptr->data)->part;
- CTX_data_pointer_set(result, ptr->id.data, &RNA_ParticleSettings, part);
- return 1;
- }
- }
- set_pointer_type(path, result, &RNA_ParticleSettings);
- return 1;
- }
else if (CTX_data_equals(member, "cloth")) {
PointerRNA *ptr = get_pointer_type(path, &RNA_Object);
@@ -1164,14 +1069,6 @@ ID *buttons_context_id_path(const bContext *C)
for (a = path->len - 1; a >= 0; a--) {
ptr = &path->ptr[a];
- /* pin particle settings instead of system, since only settings are an idblock*/
- if (sbuts->mainb == BCONTEXT_PARTICLE && sbuts->flag & SB_PIN_CONTEXT) {
- if (ptr->type == &RNA_ParticleSystem && ptr->data) {
- ParticleSystem *psys = (ParticleSystem *)ptr->data;
- return &psys->part->id;
- }
- }
-
if (ptr->id.data) {
return ptr->id.data;
}
diff --git a/source/blender/editors/space_buttons/buttons_texture.c b/source/blender/editors/space_buttons/buttons_texture.c
index 58c538c4ee5..d72b7dbd8dc 100644
--- a/source/blender/editors/space_buttons/buttons_texture.c
+++ b/source/blender/editors/space_buttons/buttons_texture.c
@@ -46,7 +46,6 @@
#include "DNA_node_types.h"
#include "DNA_object_types.h"
#include "DNA_object_force.h"
-#include "DNA_particle_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
@@ -59,7 +58,6 @@
#include "BKE_modifier.h"
#include "BKE_node.h"
#include "BKE_paint.h"
-#include "BKE_particle.h"
#include "BKE_scene.h"
#ifdef WITH_FREESTYLE
# include "BKE_freestyle.h"
@@ -98,12 +96,6 @@ bool ED_texture_context_check_lamp(const bContext *C)
return (ob && (ob->type == OB_LAMP));
}
-bool ED_texture_context_check_particles(const bContext *C)
-{
- Object *ob = CTX_data_active_object(C);
- return (ob && ob->particlesystem.first);
-}
-
bool ED_texture_context_check_linestyle(const bContext *C)
{
#ifdef WITH_FREESTYLE
@@ -178,7 +170,6 @@ static void set_texture_context(const bContext *C, SpaceButs *sbuts)
bool valid_world = ED_texture_context_check_world(C);
bool valid_material = ED_texture_context_check_material(C);
bool valid_lamp = ED_texture_context_check_lamp(C);
- bool valid_particles = ED_texture_context_check_particles(C);
bool valid_linestyle = ED_texture_context_check_linestyle(C);
bool valid_others = ED_texture_context_check_others(C);
@@ -192,9 +183,6 @@ static void set_texture_context(const bContext *C, SpaceButs *sbuts)
else if ((sbuts->mainb == BCONTEXT_DATA) && valid_lamp) {
sbuts->texture_context = sbuts->texture_context_prev = SB_TEXC_LAMP;
}
- else if ((sbuts->mainb == BCONTEXT_PARTICLE) && valid_particles) {
- sbuts->texture_context = sbuts->texture_context_prev = SB_TEXC_PARTICLES;
- }
else if ((sbuts->mainb == BCONTEXT_RENDER_LAYER) && valid_linestyle) {
sbuts->texture_context = sbuts->texture_context_prev = SB_TEXC_LINESTYLE;
}
@@ -206,7 +194,6 @@ static void set_texture_context(const bContext *C, SpaceButs *sbuts)
(((sbuts->texture_context_prev == SB_TEXC_WORLD) && valid_world) ||
((sbuts->texture_context_prev == SB_TEXC_MATERIAL) && valid_material) ||
((sbuts->texture_context_prev == SB_TEXC_LAMP) && valid_lamp) ||
- ((sbuts->texture_context_prev == SB_TEXC_PARTICLES) && valid_particles) ||
((sbuts->texture_context_prev == SB_TEXC_LINESTYLE) && valid_linestyle) ||
((sbuts->texture_context_prev == SB_TEXC_OTHER) && valid_others)))
{
@@ -216,7 +203,6 @@ static void set_texture_context(const bContext *C, SpaceButs *sbuts)
else if (((sbuts->texture_context == SB_TEXC_WORLD) && !valid_world) ||
((sbuts->texture_context == SB_TEXC_MATERIAL) && !valid_material) ||
((sbuts->texture_context == SB_TEXC_LAMP) && !valid_lamp) ||
- ((sbuts->texture_context == SB_TEXC_PARTICLES) && !valid_particles) ||
((sbuts->texture_context == SB_TEXC_LINESTYLE) && !valid_linestyle) ||
((sbuts->texture_context == SB_TEXC_OTHER) && !valid_others))
{
@@ -228,9 +214,6 @@ static void set_texture_context(const bContext *C, SpaceButs *sbuts)
else if (valid_lamp) {
sbuts->texture_context = SB_TEXC_LAMP;
}
- else if (valid_particles) {
- sbuts->texture_context = SB_TEXC_PARTICLES;
- }
else if (valid_linestyle) {
sbuts->texture_context = SB_TEXC_LINESTYLE;
}
@@ -375,31 +358,9 @@ static void buttons_texture_users_from_context(ListBase *users, const bContext *
buttons_texture_users_find_nodetree(users, &linestyle->id, linestyle->nodetree, N_("Line Style"));
if (ob) {
- ParticleSystem *psys = psys_get_current(ob);
- MTex *mtex;
- int a;
-
/* modifiers */
modifiers_foreachTexLink(ob, buttons_texture_modifier_foreach, users);
- /* particle systems */
- if (psys && !limited_mode) {
- for (a = 0; a < MAX_MTEX; a++) {
- mtex = psys->part->mtex[a];
-
- if (mtex) {
- PointerRNA ptr;
- PropertyRNA *prop;
-
- RNA_pointer_create(&psys->part->id, &RNA_ParticleSettingsTextureSlot, mtex, &ptr);
- prop = RNA_struct_find_property(&ptr, "texture");
-
- buttons_texture_user_property_add(users, &psys->part->id, ptr, prop, N_("Particles"),
- RNA_struct_ui_icon(&RNA_ParticleSettings), psys->name);
- }
- }
- }
-
/* field */
if (ob->pd && ob->pd->forcefield == PFIELD_TEXTURE) {
PointerRNA ptr;
@@ -529,17 +490,6 @@ static void template_texture_select(bContext *C, void *user_p, void *UNUSED(arg)
ct->texture = tex;
- if (user->ptr.type == &RNA_ParticleSettingsTextureSlot) {
- /* stupid exception for particle systems which still uses influence
- * from the old texture system, set the active texture slots as well */
- ParticleSettings *part = user->ptr.id.data;
- int a;
-
- for (a = 0; a < MAX_MTEX; a++)
- if (user->ptr.data == part->mtex[a])
- part->texact = a;
- }
-
if (sbuts && tex)
sbuts->preview = 1;
}
diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c
index e4c23ad74f8..f91a357504d 100644
--- a/source/blender/editors/space_buttons/space_buttons.c
+++ b/source/blender/editors/space_buttons/space_buttons.c
@@ -159,8 +159,6 @@ static void buttons_main_region_draw(const bContext *C, ARegion *ar)
ED_region_panels(C, ar, "material", sbuts->mainb, vertical);
else if (sbuts->mainb == BCONTEXT_TEXTURE)
ED_region_panels(C, ar, "texture", sbuts->mainb, vertical);
- else if (sbuts->mainb == BCONTEXT_PARTICLE)
- ED_region_panels(C, ar, "particle", sbuts->mainb, vertical);
else if (sbuts->mainb == BCONTEXT_PHYSICS)
ED_region_panels(C, ar, "physics", sbuts->mainb, vertical);
else if (sbuts->mainb == BCONTEXT_BONE)
@@ -281,11 +279,6 @@ static void buttons_area_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *
buttons_area_redraw(sa, BCONTEXT_CONSTRAINT);
buttons_area_redraw(sa, BCONTEXT_BONE_CONSTRAINT);
break;
- case ND_PARTICLE:
- if (wmn->action == NA_EDITED)
- buttons_area_redraw(sa, BCONTEXT_PARTICLE);
- sbuts->preview = 1;
- break;
case ND_DRAW:
buttons_area_redraw(sa, BCONTEXT_OBJECT);
buttons_area_redraw(sa, BCONTEXT_DATA);
diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c
index 52d01063175..925efec085d 100644
--- a/source/blender/editors/space_file/file_draw.c
+++ b/source/blender/editors/space_file/file_draw.c
@@ -71,6 +71,10 @@
#include "WM_api.h"
#include "WM_types.h"
+//#include "GPU_draw.h"
+//#include "GPU_basic_shader.h"
+#include "GPU_immediate.h"
+
#include "filelist.h"
#include "file_intern.h" // own include
@@ -467,33 +471,43 @@ static void draw_dividers(FileLayout *layout, View2D *v2d)
const int step = (layout->tile_w + 2 * layout->tile_border_x);
int v1[2], v2[2];
int sx;
+ unsigned int vertex_ct = 0;
unsigned char col_hi[3], col_lo[3];
+ VertexFormat* format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_INT, 2, CONVERT_INT_TO_FLOAT);
+ unsigned color = add_attrib(format, "color", GL_UNSIGNED_BYTE, 3, NORMALIZE_INT_TO_FLOAT);
+
+ vertex_ct = (v2d->cur.xmax - v2d->tot.xmin) / step + 1; /* paint at least 1 divider */
+ vertex_ct *= 4; /* vertex_count = 2 points per divider * 2 lines per divider */
+
UI_GetThemeColorShade3ubv(TH_BACK, 30, col_hi);
UI_GetThemeColorShade3ubv(TH_BACK, -30, col_lo);
v1[1] = v2d->cur.ymax - layout->tile_border_y;
v2[1] = v2d->cur.ymin;
- glBegin(GL_LINES);
+ immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
+ immBegin(GL_LINES, vertex_ct);
/* vertical column dividers */
sx = (int)v2d->tot.xmin;
while (sx < v2d->cur.xmax) {
sx += step;
- glColor3ubv(col_lo);
v1[0] = v2[0] = sx;
- glVertex2iv(v1);
- glVertex2iv(v2);
+ immAttrib3ubv(color, col_lo);
+ immVertex2iv(pos, v1);
+ immVertex2iv(pos, v2);
- glColor3ubv(col_hi);
v1[0] = v2[0] = sx + 1;
- glVertex2iv(v1);
- glVertex2iv(v2);
+ immAttrib3ubv(color, col_hi);
+ immVertex2iv(pos, v1);
+ immVertex2iv(pos, v2);
}
- glEnd();
+ immEnd();
+ immUnbindProgram();
}
void file_draw_list(const bContext *C, ARegion *ar)
diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c
index 7abe5ff5070..5eb261890b2 100644
--- a/source/blender/editors/space_file/filesel.c
+++ b/source/blender/editors/space_file/filesel.c
@@ -214,7 +214,7 @@ short ED_fileselect_set_params(SpaceFile *sfile)
params->filter_id = FILTER_ID_AC | FILTER_ID_AR | FILTER_ID_BR | FILTER_ID_CA | FILTER_ID_CU | FILTER_ID_GD |
FILTER_ID_GR | FILTER_ID_IM | FILTER_ID_LA | FILTER_ID_LS | FILTER_ID_LT | FILTER_ID_MA |
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_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;
if (U.uiflag & USER_HIDE_DOT) {
diff --git a/source/blender/editors/space_graph/graph_draw.c b/source/blender/editors/space_graph/graph_draw.c
index 96a078b2817..9781c909ef6 100644
--- a/source/blender/editors/space_graph/graph_draw.c
+++ b/source/blender/editors/space_graph/graph_draw.c
@@ -50,6 +50,9 @@
#include "BIF_gl.h"
#include "BIF_glutil.h"
+#include "GPU_draw.h"
+#include "GPU_immediate.h"
+
#include "ED_anim_api.h"
#include "graph_intern.h"
@@ -121,16 +124,37 @@ static void draw_fcurve_modifier_controls_envelope(FModifier *fcm, View2D *v2d)
/* Points ---------------- */
-/* helper func - draw keyframe vertices only for an F-Curve */
-static void draw_fcurve_vertices_keyframes(FCurve *fcu, SpaceIpo *UNUSED(sipo), View2D *v2d, short edit, short sel)
+/* helper func - set color to draw F-Curve data with */
+static void set_fcurve_vertex_color(FCurve *fcu, bool sel)
+{
+ /* Fade the 'intensity' of the vertices based on the selection of the curves too */
+ int alphaOffset = (int)((fcurve_display_alpha(fcu) - 1.0f) * 255);
+
+ float color[4];
+
+ /* Set color of curve vertex based on state of curve (i.e. 'Edit' Mode) */
+ if ((fcu->flag & FCURVE_PROTECTED) == 0) {
+ /* Curve's points ARE BEING edited */
+ UI_GetThemeColorShadeAlpha4fv(sel ? TH_VERTEX_SELECT : TH_VERTEX, 0, alphaOffset, color);
+ }
+ else {
+ /* Curve's points CANNOT BE edited */
+ UI_GetThemeColorShadeAlpha4fv(sel ? TH_TEXT_HI : TH_TEXT, 0, alphaOffset, color);
+ }
+
+ immUniformColor4fv(color);
+}
+
+static void draw_fcurve_selected_keyframe_vertices(FCurve *fcu, View2D *v2d, bool edit, bool sel, unsigned pos)
{
- BezTriple *bezt = fcu->bezt;
const float fac = 0.05f * BLI_rctf_size_x(&v2d->cur);
- int i;
-
- glBegin(GL_POINTS);
-
- for (i = 0; i < fcu->totvert; i++, bezt++) {
+
+ set_fcurve_vertex_color(fcu, sel);
+
+ immBeginAtMost(GL_POINTS, fcu->totvert);
+
+ BezTriple *bezt = fcu->bezt;
+ for (int i = 0; i < fcu->totvert; i++, bezt++) {
/* as an optimization step, only draw those in view
* - we apply a correction factor to ensure that points don't pop in/out due to slight twitches of view size
*/
@@ -141,80 +165,50 @@ static void draw_fcurve_vertices_keyframes(FCurve *fcu, SpaceIpo *UNUSED(sipo),
* -
*/
if ((bezt->f2 & SELECT) == sel)
- glVertex3fv(bezt->vec[1]);
+ immVertex2fv(pos, bezt->vec[1]);
}
else {
/* no check for selection here, as curve is not editable... */
/* XXX perhaps we don't want to even draw points? maybe add an option for that later */
- glVertex3fv(bezt->vec[1]);
+ immVertex2fv(pos, bezt->vec[1]);
}
}
}
-
- glEnd();
-}
+ immEnd();
+}
-/* helper func - draw handle vertex for an F-Curve as a round unfilled circle
- * NOTE: the caller MUST HAVE GL_LINE_SMOOTH & GL_BLEND ENABLED, otherwise, the controls don't
- * have a consistent appearance (due to off-pixel alignments)...
- */
-static void draw_fcurve_handle_control(float x, float y, float xscale, float yscale, float hsize)
+/* helper func - draw keyframe vertices only for an F-Curve */
+static void draw_fcurve_keyframe_vertices(FCurve *fcu, View2D *v2d, bool edit, unsigned pos)
{
- static GLuint displist = 0;
-
- /* initialize round circle shape */
- if (displist == 0) {
- GLUquadricObj *qobj;
-
- displist = glGenLists(1);
- glNewList(displist, GL_COMPILE);
-
- qobj = gluNewQuadric();
- gluQuadricDrawStyle(qobj, GLU_SILHOUETTE);
- gluDisk(qobj, 0, 0.7, 8, 1);
- gluDeleteQuadric(qobj);
-
- glEndList();
- }
-
- /* adjust view transform before starting */
- glTranslatef(x, y, 0.0f);
- glScalef(1.0f / xscale * hsize, 1.0f / yscale * hsize, 1.0f);
-
- /* draw! */
- glCallList(displist);
-
- /* restore view transform */
- glScalef(xscale / hsize, yscale / hsize, 1.0);
- glTranslatef(-x, -y, 0.0f);
+ immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_SMOOTH);
+
+ immUniform1f("size", UI_GetThemeValuef(TH_VERTEX_SIZE) * U.pixelsize);
+
+ draw_fcurve_selected_keyframe_vertices(fcu, v2d, edit, false, pos);
+ draw_fcurve_selected_keyframe_vertices(fcu, v2d, edit, true, pos);
+
+ immUnbindProgram();
}
+
/* helper func - draw handle vertices only for an F-Curve (if it is not protected) */
-static void draw_fcurve_vertices_handles(FCurve *fcu, SpaceIpo *sipo, View2D *v2d, short sel, short sel_handle_only, float units_scale)
+static void draw_fcurve_selected_handle_vertices(FCurve *fcu, View2D *v2d, bool sel, bool sel_handle_only, unsigned pos)
{
- BezTriple *bezt = fcu->bezt;
- BezTriple *prevbezt = NULL;
- float hsize, xscale, yscale;
- int i;
-
- /* get view settings */
- hsize = UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE) * U.pixelsize;
- UI_view2d_scale_get(v2d, &xscale, &yscale);
+ (void) v2d; /* TODO: use this to draw only points in view */
- /* Compensate OGL scale sued for unit mapping, so circle will be circle, not ellipse */
- yscale *= units_scale;
-
/* set handle color */
- if (sel) UI_ThemeColor(TH_HANDLE_VERTEX_SELECT);
- else UI_ThemeColor(TH_HANDLE_VERTEX);
-
- /* anti-aliased lines for more consistent appearance */
- if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) glEnable(GL_LINE_SMOOTH);
- glEnable(GL_BLEND);
-
- for (i = 0; i < fcu->totvert; i++, prevbezt = bezt, bezt++) {
- /* Draw the editmode handles for a bezier curve (others don't have handles)
+ float hcolor[3];
+ UI_GetThemeColor3fv(sel ? TH_HANDLE_VERTEX_SELECT : TH_HANDLE_VERTEX, hcolor);
+ immUniform4f("outlineColor", hcolor[0], hcolor[1], hcolor[2], 1.0f);
+ immUniformColor3fvAlpha(hcolor, 0.4f);
+
+ immBeginAtMost(GL_POINTS, fcu->totvert * 2);
+
+ BezTriple *bezt = fcu->bezt;
+ BezTriple *prevbezt = NULL;
+ for (int i = 0; i < fcu->totvert; i++, prevbezt = bezt, bezt++) {
+ /* Draw the editmode handles for a bezier curve (others don't have handles)
* if their selection status matches the selection status we're drawing for
* - first handle only if previous beztriple was bezier-mode
* - second handle only if current beztriple is bezier-mode
@@ -225,68 +219,61 @@ static void draw_fcurve_vertices_handles(FCurve *fcu, SpaceIpo *sipo, View2D *v2
if (!sel_handle_only || BEZT_ISSEL_ANY(bezt)) {
if ((!prevbezt && (bezt->ipo == BEZT_IPO_BEZ)) || (prevbezt && (prevbezt->ipo == BEZT_IPO_BEZ))) {
if ((bezt->f1 & SELECT) == sel) /* && v2d->cur.xmin < bezt->vec[0][0] < v2d->cur.xmax)*/
- draw_fcurve_handle_control(bezt->vec[0][0], bezt->vec[0][1], xscale, yscale, hsize);
+ immVertex2fv(pos, bezt->vec[0]);
}
-
+
if (bezt->ipo == BEZT_IPO_BEZ) {
if ((bezt->f3 & SELECT) == sel) /* && v2d->cur.xmin < bezt->vec[2][0] < v2d->cur.xmax)*/
- draw_fcurve_handle_control(bezt->vec[2][0], bezt->vec[2][1], xscale, yscale, hsize);
+ immVertex2fv(pos, bezt->vec[2]);
}
}
}
-
- if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) glDisable(GL_LINE_SMOOTH);
- glDisable(GL_BLEND);
+
+ immEnd();
}
-/* helper func - set color to draw F-Curve data with */
-static void set_fcurve_vertex_color(FCurve *fcu, short sel)
+/* helper func - draw handle vertices only for an F-Curve (if it is not protected) */
+static void draw_fcurve_handle_vertices(FCurve *fcu, View2D *v2d, bool sel_handle_only, unsigned pos)
{
- /* Fade the 'intensity' of the vertices based on the selection of the curves too */
- int alphaOffset = (int)((fcurve_display_alpha(fcu) - 1.0f) * 255);
-
- /* Set color of curve vertex based on state of curve (i.e. 'Edit' Mode) */
- if ((fcu->flag & FCURVE_PROTECTED) == 0) {
- /* Curve's points ARE BEING edited */
- if (sel) UI_ThemeColorShadeAlpha(TH_VERTEX_SELECT, 0, alphaOffset);
- else UI_ThemeColorShadeAlpha(TH_VERTEX, 0, alphaOffset);
- }
- else {
- /* Curve's points CANNOT BE edited */
- if (sel) UI_ThemeColorShadeAlpha(TH_TEXT_HI, 0, alphaOffset);
- else UI_ThemeColorShadeAlpha(TH_TEXT, 0, alphaOffset);
- }
+ /* smooth outlines for more consistent appearance */
+ immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_SMOOTH);
+
+ /* set handle size */
+ immUniform1f("size", (UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE) + 1.0f) * U.pixelsize);
+ immUniform1f("outlineWidth", 1.0f * U.pixelsize);
+
+ draw_fcurve_selected_handle_vertices(fcu, v2d, false, sel_handle_only, pos);
+ draw_fcurve_selected_handle_vertices(fcu, v2d, true, sel_handle_only, pos);
+
+ immUnbindProgram();
}
-static void draw_fcurve_vertices(SpaceIpo *sipo, ARegion *ar, FCurve *fcu, short do_handles, short sel_handle_only, float units_scale)
+static void draw_fcurve_vertices(ARegion *ar, FCurve *fcu, bool do_handles, bool sel_handle_only)
{
View2D *v2d = &ar->v2d;
-
+
/* only draw points if curve is visible
- * - draw unselected points before selected points as separate passes to minimize color-changing overhead
- * (XXX dunno if this is faster than drawing all in one pass though)
- * and also to make sure in the case of overlapping points that the selected is always visible
+ * - draw unselected points before selected points as separate passes
+ * to make sure in the case of overlapping points that the selected is always visible
* - draw handles before keyframes, so that keyframes will overlap handles (keyframes are more important for users)
*/
-
- glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
-
+
+ unsigned pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+
+ glEnable(GL_BLEND);
+ GPU_enable_program_point_size();
+
/* draw the two handles first (if they're shown, the curve doesn't have just a single keyframe, and the curve is being edited) */
if (do_handles) {
- set_fcurve_vertex_color(fcu, 0);
- draw_fcurve_vertices_handles(fcu, sipo, v2d, 0, sel_handle_only, units_scale);
-
- set_fcurve_vertex_color(fcu, 1);
- draw_fcurve_vertices_handles(fcu, sipo, v2d, 1, sel_handle_only, units_scale);
+ draw_fcurve_handle_vertices(fcu, v2d, sel_handle_only, pos);
}
-
+
/* draw keyframes over the handles */
- set_fcurve_vertex_color(fcu, 0);
- draw_fcurve_vertices_keyframes(fcu, sipo, v2d, !(fcu->flag & FCURVE_PROTECTED), 0);
-
- set_fcurve_vertex_color(fcu, 1);
- draw_fcurve_vertices_keyframes(fcu, sipo, v2d, !(fcu->flag & FCURVE_PROTECTED), 1);
+ draw_fcurve_keyframe_vertices(fcu, v2d, !(fcu->flag & FCURVE_PROTECTED), pos);
+
+ GPU_disable_program_point_size();
+ glDisable(GL_BLEND);
}
/* Handles ---------------- */
@@ -303,10 +290,10 @@ static bool draw_fcurve_handles_check(SpaceIpo *sipo, FCurve *fcu)
(fcu->totvert <= 1) /* do not show handles if there is only 1 keyframe, otherwise they all clump together in an ugly ball */
)
{
- return 0;
+ return false;
}
else {
- return 1;
+ return true;
}
}
@@ -1080,7 +1067,7 @@ void graph_draw_curves(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGrid
glDisable(GL_BLEND);
}
- draw_fcurve_vertices(sipo, ar, fcu, do_handles, (sipo->flag & SIPO_SELVHANDLESONLY), unit_scale);
+ draw_fcurve_vertices(ar, fcu, do_handles, (sipo->flag & SIPO_SELVHANDLESONLY));
}
else {
/* samples: only draw two indicators at either end as indicators */
diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c
index 8dc6c4229b2..6e156750815 100644
--- a/source/blender/editors/space_info/info_stats.c
+++ b/source/blender/editors/space_info/info_stats.c
@@ -35,6 +35,7 @@
#include "DNA_group_types.h"
#include "DNA_lattice_types.h"
#include "DNA_meta_types.h"
+#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "BLI_math.h"
@@ -50,7 +51,6 @@
#include "BKE_DerivedMesh.h"
#include "BKE_key.h"
#include "BKE_paint.h"
-#include "BKE_particle.h"
#include "BKE_editmesh.h"
#include "ED_info.h"
@@ -273,37 +273,7 @@ static void stats_dupli_object(Base *base, Object *ob, SceneStats *stats)
{
if (base->flag & SELECT) stats->totobjsel++;
- if (ob->transflag & OB_DUPLIPARTS) {
- /* Dupli Particles */
- ParticleSystem *psys;
- ParticleSettings *part;
-
- for (psys = ob->particlesystem.first; psys; psys = psys->next) {
- part = psys->part;
-
- if (part->draw_as == PART_DRAW_OB && part->dup_ob) {
- int tot = count_particles(psys);
- stats_object(part->dup_ob, 0, tot, stats);
- }
- else if (part->draw_as == PART_DRAW_GR && part->dup_group) {
- GroupObject *go;
- int tot, totgroup = 0, cur = 0;
-
- for (go = part->dup_group->gobject.first; go; go = go->next)
- totgroup++;
-
- for (go = part->dup_group->gobject.first; go; go = go->next) {
- tot = count_particles_mod(psys, totgroup, cur);
- stats_object(go->ob, 0, tot, stats);
- cur++;
- }
- }
- }
-
- stats_object(ob, base->flag & SELECT, 1, stats);
- stats->totobj++;
- }
- else if (ob->parent && (ob->parent->transflag & (OB_DUPLIVERTS | OB_DUPLIFACES))) {
+ if (ob->parent && (ob->parent->transflag & (OB_DUPLIVERTS | OB_DUPLIFACES))) {
/* Dupli Verts/Faces */
int tot;
diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c
index 3243579f7d0..bb6cf568425 100644
--- a/source/blender/editors/space_nla/nla_buttons.c
+++ b/source/blender/editors/space_nla/nla_buttons.c
@@ -136,7 +136,6 @@ bool nla_panel_context(const bContext *C, PointerRNA *adt_ptr, PointerRNA *nlt_p
case ANIMTYPE_DSSKEY:
case ANIMTYPE_DSWOR:
case ANIMTYPE_DSNTREE:
- case ANIMTYPE_DSPART:
case ANIMTYPE_DSMBALL:
case ANIMTYPE_DSARM:
case ANIMTYPE_DSMESH:
diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c
index e9c46e9d04b..9a8a5df78e4 100644
--- a/source/blender/editors/space_nla/nla_channels.c
+++ b/source/blender/editors/space_nla/nla_channels.c
@@ -175,7 +175,6 @@ static int mouse_nla_channels(bContext *C, bAnimContext *ac, float x, int channe
case ANIMTYPE_DSSKEY:
case ANIMTYPE_DSWOR:
case ANIMTYPE_DSNTREE:
- case ANIMTYPE_DSPART:
case ANIMTYPE_DSMBALL:
case ANIMTYPE_DSARM:
case ANIMTYPE_DSMESH:
@@ -215,7 +214,7 @@ static int mouse_nla_channels(bContext *C, bAnimContext *ac, float x, int channe
/* offset for start of channel (on LHS of channel-list) */
if (ale->id) {
/* special exception for materials and particles */
- if (ELEM(GS(ale->id->name), ID_MA, ID_PA))
+ if (GS(ale->id->name) == ID_MA)
offset = 21 + NLACHANNEL_BUTTON_WIDTH;
else
offset = 14;
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index 7b08b8368ba..774bc0661cc 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -53,6 +53,9 @@
#include "BIF_gl.h"
#include "BIF_glutil.h"
+#include "GPU_draw.h"
+#include "GPU_immediate.h"
+
#include "RNA_access.h"
#include "RNA_define.h"
@@ -62,6 +65,7 @@
#include "WM_types.h"
#include "UI_resources.h"
+#include "UI_view2d.h"
#include "IMB_colormanagement.h"
#include "IMB_imbuf_types.h"
@@ -80,49 +84,6 @@ static void node_socket_button_label(bContext *UNUSED(C), uiLayout *layout, Poin
uiItemL(layout, text, 0);
}
-
-/* ****************** BASE DRAW FUNCTIONS FOR NEW OPERATOR NODES ***************** */
-
-#if 0 /* UNUSED */
-static void node_draw_socket_new(bNodeSocket *sock, float size)
-{
- float x = sock->locx, y = sock->locy;
-
- /* 16 values of sin function */
- static float si[16] = {
- 0.00000000f, 0.39435585f, 0.72479278f, 0.93775213f,
- 0.99871650f, 0.89780453f, 0.65137248f, 0.29936312f,
- -0.10116832f, -0.48530196f, -0.79077573f, -0.96807711f,
- -0.98846832f, -0.84864425f, -0.57126821f, -0.20129852f
- };
- /* 16 values of cos function */
- static float co[16] = {
- 1.00000000f, 0.91895781f, 0.68896691f, 0.34730525f,
- -0.05064916f, -0.44039415f, -0.75875812f, -0.95413925f,
- -0.99486932f, -0.87434661f, -0.61210598f, -0.25065253f,
- 0.15142777f, 0.52896401f, 0.82076344f, 0.97952994f,
- };
- int a;
-
- glColor3ub(180, 180, 180);
-
- glBegin(GL_POLYGON);
- for (a = 0; a < 16; a++)
- glVertex2f(x + size * si[a], y + size * co[a]);
- glEnd();
-
- glColor4ub(0, 0, 0, 150);
- glEnable(GL_BLEND);
- glEnable(GL_LINE_SMOOTH);
- glBegin(GL_LINE_LOOP);
- for (a = 0; a < 16; a++)
- glVertex2f(x + size * si[a], y + size * co[a]);
- glEnd();
- glDisable(GL_LINE_SMOOTH);
- glDisable(GL_BLEND);
-}
-#endif
-
/* ****************** BUTTON CALLBACKS FOR ALL TREES ***************** */
static void node_buts_value(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
@@ -465,7 +426,7 @@ static void node_draw_frame(const bContext *C, ARegion *ar, SpaceNode *snode,
{
rctf *rct = &node->totr;
int color_id = node_get_colorid(node);
- unsigned char color[4];
+ float color[4];
float alpha;
/* skip if out of view */
@@ -475,8 +436,8 @@ static void node_draw_frame(const bContext *C, ARegion *ar, SpaceNode *snode,
return;
}
- UI_GetThemeColor4ubv(TH_NODE_FRAME, color);
- alpha = (float)(color[3]) / 255.0f;
+ UI_GetThemeColor4fv(TH_NODE_FRAME, color);
+ alpha = color[3];
/* shadow */
node_draw_shadow(snode, node, BASIS_RAD, alpha);
@@ -495,16 +456,16 @@ static void node_draw_frame(const bContext *C, ARegion *ar, SpaceNode *snode,
if (node->flag & SELECT) {
glEnable(GL_BLEND);
glEnable(GL_LINE_SMOOTH);
-
+
if (node->flag & NODE_ACTIVE)
- UI_ThemeColorShadeAlpha(TH_ACTIVE, 0, -40);
+ UI_GetThemeColorShadeAlpha4fv(TH_ACTIVE, 0, -40, color);
else
- UI_ThemeColorShadeAlpha(TH_SELECT, 0, -40);
+ UI_GetThemeColorShadeAlpha4fv(TH_SELECT, 0, -40, color);
+
UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox_gl_mode(GL_LINE_LOOP,
- rct->xmin, rct->ymin,
- rct->xmax, rct->ymax, BASIS_RAD);
-
+ UI_draw_roundbox_gl_mode(GL_LINE_LOOP, rct->xmin, rct->ymin, rct->xmax, rct->ymax, BASIS_RAD, color);
+
+
glDisable(GL_LINE_SMOOTH);
glDisable(GL_BLEND);
}
@@ -580,14 +541,12 @@ static void node_draw_reroute_prepare(const bContext *UNUSED(C), bNodeTree *UNUS
static void node_draw_reroute(const bContext *C, ARegion *ar, SpaceNode *UNUSED(snode),
bNodeTree *ntree, bNode *node, bNodeInstanceKey UNUSED(key))
{
- bNodeSocket *sock;
char showname[128]; /* 128 used below */
rctf *rct = &node->totr;
#if 0 /* UNUSED */
float size = NODE_REROUTE_SIZE;
#endif
- float socket_size = NODE_SOCKSIZE;
/* skip if out of view */
if (node->totr.xmax < ar->v2d.cur.xmin || node->totr.xmin > ar->v2d.cur.xmax ||
@@ -637,9 +596,7 @@ static void node_draw_reroute(const bContext *C, ARegion *ar, SpaceNode *UNUSED(
/* only draw input socket. as they all are placed on the same position.
* highlight also if node itself is selected, since we don't display the node body separately!
*/
- for (sock = node->inputs.first; sock; sock = sock->next) {
- node_socket_circle_draw(C, ntree, node, sock, socket_size, (sock->flag & SELECT) || (node->flag & SELECT));
- }
+ node_draw_sockets(&ar->v2d, C, ntree, node, false, node->flag & SELECT);
UI_block_end(C, node->block);
UI_block_draw(C, node->block);
diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c
index ab40c55b59d..c532846d1c4 100644
--- a/source/blender/editors/space_node/node_draw.c
+++ b/source/blender/editors/space_node/node_draw.c
@@ -54,6 +54,9 @@
#include "BIF_gl.h"
#include "BIF_glutil.h"
+#include "GPU_draw.h"
+#include "GPU_immediate.h"
+
#include "WM_api.h"
#include "WM_types.h"
@@ -617,60 +620,16 @@ static void node_draw_mute_line(View2D *v2d, SpaceNode *snode, bNode *node)
glDisable(GL_LINE_SMOOTH);
}
-/* this might have some more generic use */
-static void node_circle_draw(float x, float y, float size, const float col[4], int highlight)
-{
- /* 16 values of sin function */
- static const float si[16] = {
- 0.00000000f, 0.39435585f, 0.72479278f, 0.93775213f,
- 0.99871650f, 0.89780453f, 0.65137248f, 0.29936312f,
- -0.10116832f, -0.48530196f, -0.79077573f, -0.96807711f,
- -0.98846832f, -0.84864425f, -0.57126821f, -0.20129852f
- };
- /* 16 values of cos function */
- static const float co[16] = {
- 1.00000000f, 0.91895781f, 0.68896691f, 0.34730525f,
- -0.05064916f, -0.44039415f, -0.75875812f, -0.95413925f,
- -0.99486932f, -0.87434661f, -0.61210598f, -0.25065253f,
- 0.15142777f, 0.52896401f, 0.82076344f, 0.97952994f,
- };
- int a;
-
- glColor4fv(col);
-
- glEnable(GL_BLEND);
- glBegin(GL_POLYGON);
- for (a = 0; a < 16; a++)
- glVertex2f(x + size * si[a], y + size * co[a]);
- glEnd();
- glDisable(GL_BLEND);
-
- if (highlight) {
- UI_ThemeColor(TH_TEXT_HI);
- glLineWidth(1.5f);
- }
- else {
- glColor4ub(0, 0, 0, 150);
- }
- glEnable(GL_BLEND);
- glEnable(GL_LINE_SMOOTH);
- glBegin(GL_LINE_LOOP);
- for (a = 0; a < 16; a++)
- glVertex2f(x + size * si[a], y + size * co[a]);
- glEnd();
- glDisable(GL_LINE_SMOOTH);
- glDisable(GL_BLEND);
-}
-
-void node_socket_circle_draw(const bContext *C, bNodeTree *ntree, bNode *node, bNodeSocket *sock, float size, int highlight)
+static void node_socket_circle_draw(const bContext *C, bNodeTree *ntree, PointerRNA node_ptr, bNodeSocket *sock, unsigned pos, unsigned col)
{
- PointerRNA ptr, node_ptr;
+ PointerRNA ptr;
float color[4];
RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
- RNA_pointer_create((ID *)ntree, &RNA_Node, node, &node_ptr);
sock->typeinfo->draw_color((bContext *)C, &ptr, &node_ptr, color);
- node_circle_draw(sock->locx, sock->locy, size, color, highlight);
+
+ immAttrib4fv(col, color);
+ immVertex2f(pos, sock->locx, sock->locy);
}
/* ************** Socket callbacks *********** */
@@ -781,15 +740,121 @@ void node_draw_shadow(SpaceNode *snode, bNode *node, float radius, float alpha)
}
}
+void node_draw_sockets(View2D *v2d, const bContext *C, bNodeTree *ntree, bNode *node, bool draw_outputs, bool select_all)
+{
+ PointerRNA node_ptr;
+ RNA_pointer_create((ID *)ntree, &RNA_Node, node, &node_ptr);
+
+ float xscale, yscale;
+ UI_view2d_scale_get(v2d, &xscale, &yscale);
+
+ VertexFormat *format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ unsigned col = add_attrib(format, "color", GL_FLOAT, 4, KEEP_FLOAT);
+
+ glEnable(GL_BLEND);
+ GPU_enable_program_point_size();
+
+ immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_VARYING_COLOR_OUTLINE_SMOOTH);
+
+ /* set handle size */
+ immUniform1f("size", 2.0f * NODE_SOCKSIZE * xscale); // 2 * size to have diameter
+
+ if (!select_all) {
+ /* outline for unselected sockets */
+ immUniform1f("outlineWidth", 1.0f);
+ immUniform4f("outlineColor", 0.0f, 0.0f, 0.0f, 0.6f);
+
+ immBeginAtMost(GL_POINTS, BLI_listbase_count(&node->inputs) + BLI_listbase_count(&node->outputs));
+ }
+
+ /* socket inputs */
+ short selected_input_ct = 0;
+ bNodeSocket *sock;
+ for (sock = node->inputs.first; sock; sock = sock->next) {
+ if (nodeSocketIsHidden(sock))
+ continue;
+ if (select_all || (sock->flag & SELECT)) {
+ ++selected_input_ct;
+ continue;
+ }
+
+ node_socket_circle_draw(C, ntree, node_ptr, sock, pos, col);
+ }
+
+ /* socket outputs */
+ short selected_output_ct = 0;
+ if (draw_outputs) {
+ for (sock = node->outputs.first; sock; sock = sock->next) {
+ if (nodeSocketIsHidden(sock))
+ continue;
+ if (select_all || (sock->flag & SELECT)) {
+ ++selected_output_ct;
+ continue;
+ }
+
+ node_socket_circle_draw(C, ntree, node_ptr, sock, pos, col);
+ }
+ }
+
+ if (!select_all) {
+ immEnd();
+ }
+
+ /* go back and draw selected sockets */
+ if (selected_input_ct + selected_output_ct > 0) {
+ /* outline for selected sockets */
+ float c[3];
+ UI_GetThemeColor3fv(TH_TEXT_HI, c);
+ immUniform4f("outlineColor", c[0], c[1], c[2], 1.0f);
+ immUniform1f("outlineWidth", 1.5f);
+
+ immBegin(GL_POINTS, selected_input_ct + selected_output_ct);
+
+ if (selected_input_ct) {
+ /* socket inputs */
+ for (sock = node->inputs.first; sock; sock = sock->next) {
+ if (nodeSocketIsHidden(sock))
+ continue;
+ if (select_all || (sock->flag & SELECT)) {
+ node_socket_circle_draw(C, ntree, node_ptr, sock, pos, col);
+ if (--selected_input_ct == 0)
+ break; /* stop as soon as last one is drawn */
+ }
+ }
+ }
+
+ if (selected_output_ct) {
+ /* socket outputs */
+ for (sock = node->outputs.first; sock; sock = sock->next) {
+ if (nodeSocketIsHidden(sock))
+ continue;
+ if (select_all || (sock->flag & SELECT)) {
+ node_socket_circle_draw(C, ntree, node_ptr, sock, pos, col);
+ if (--selected_output_ct == 0)
+ break; /* stop as soon as last one is drawn */
+ }
+ }
+ }
+
+ immEnd();
+ }
+
+ immUnbindProgram();
+
+ GPU_disable_program_point_size();
+ glDisable(GL_BLEND);
+}
+
static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node, bNodeInstanceKey key)
{
bNodeInstanceHash *previews = CTX_data_pointer_get(C, "node_previews").data;
- bNodeSocket *sock;
rctf *rct = &node->totr;
float iconofs;
/* float socket_size = NODE_SOCKSIZE*U.dpi/72; */ /* UNUSED */
float iconbutw = 0.8f * UI_UNIT_X;
int color_id = node_get_colorid(node);
+ float color[4];
char showname[128]; /* 128 used below */
View2D *v2d = &ar->v2d;
@@ -798,7 +863,7 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
nodeSynchronizeID(node, false);
/* skip if out of view */
- if (BLI_rctf_isect(&node->totr, &ar->v2d.cur, NULL) == false) {
+ if (BLI_rctf_isect(&node->totr, &v2d->cur, NULL) == false) {
UI_block_end(C, node->block);
node->block = NULL;
return;
@@ -885,12 +950,8 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
UI_draw_icon_tri(rct->xmin + 0.5f * U.widget_unit, rct->ymax - NODE_DY / 2.0f, 'v');
}
- /* this isn't doing anything for the label, so commenting out */
-#if 0
- if (node->flag & SELECT)
- UI_ThemeColor(TH_TEXT_HI);
- else
- UI_ThemeColor(TH_TEXT);
+#if 0 /* this isn't doing anything for the label, so commenting out */
+ UI_ThemeColor((node->flag & SELECT) ? TH_TEXT_HI : TH_TEXT);
#endif
nodeLabel(ntree, node, showname, sizeof(showname));
@@ -917,18 +978,14 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
/* outline active and selected emphasis */
if (node->flag & SELECT) {
-
glEnable(GL_BLEND);
glEnable(GL_LINE_SMOOTH);
-
- if (node->flag & NODE_ACTIVE)
- UI_ThemeColorShadeAlpha(TH_ACTIVE, 0, -40);
- else
- UI_ThemeColorShadeAlpha(TH_SELECT, 0, -40);
-
+
+ UI_GetThemeColorShadeAlpha4fv((node->flag & NODE_ACTIVE) ? TH_ACTIVE : TH_SELECT, 0, -40, color);
+
UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox_gl_mode(GL_LINE_LOOP, rct->xmin, rct->ymin, rct->xmax, rct->ymax, BASIS_RAD);
-
+ UI_draw_roundbox_gl_mode(GL_LINE_LOOP, rct->xmin, rct->ymin, rct->xmax, rct->ymax, BASIS_RAD, color);
+
glDisable(GL_LINE_SMOOTH);
glDisable(GL_BLEND);
}
@@ -937,23 +994,8 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
if (node->flag & NODE_MUTED)
node_draw_mute_line(v2d, snode, node);
-
- /* socket inputs, buttons */
- for (sock = node->inputs.first; sock; sock = sock->next) {
- if (nodeSocketIsHidden(sock))
- continue;
-
- node_socket_circle_draw(C, ntree, node, sock, NODE_SOCKSIZE, sock->flag & SELECT);
- }
-
- /* socket outputs */
- for (sock = node->outputs.first; sock; sock = sock->next) {
- if (nodeSocketIsHidden(sock))
- continue;
-
- node_socket_circle_draw(C, ntree, node, sock, NODE_SOCKSIZE, sock->flag & SELECT);
- }
-
+ node_draw_sockets(v2d, C, ntree, node, true, false);
+
/* preview */
if (node->flag & NODE_PREVIEW && previews) {
bNodePreview *preview = BKE_node_instance_hash_lookup(previews, key);
@@ -973,13 +1015,16 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node, bNodeInstanceKey UNUSED(key))
{
- bNodeSocket *sock;
rctf *rct = &node->totr;
float dx, centy = BLI_rctf_cent_y(rct);
float hiddenrad = BLI_rctf_size_y(rct) / 2.0f;
- float socket_size = NODE_SOCKSIZE;
int color_id = node_get_colorid(node);
+ float color[4];
char showname[128]; /* 128 is used below */
+ View2D *v2d = &ar->v2d;
+ float xscale, yscale;
+
+ UI_view2d_scale_get(v2d, &xscale, &yscale);
/* shadow */
node_draw_shadow(snode, node, hiddenrad, 1.0f);
@@ -1006,12 +1051,10 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b
glEnable(GL_BLEND);
glEnable(GL_LINE_SMOOTH);
- if (node->flag & NODE_ACTIVE)
- UI_ThemeColorShadeAlpha(TH_ACTIVE, 0, -40);
- else
- UI_ThemeColorShadeAlpha(TH_SELECT, 0, -40);
- UI_draw_roundbox_gl_mode(GL_LINE_LOOP, rct->xmin, rct->ymin, rct->xmax, rct->ymax, hiddenrad);
-
+ UI_GetThemeColorShadeAlpha4fv((node->flag & NODE_ACTIVE) ? TH_ACTIVE : TH_SELECT, 0, -40, color);
+
+ UI_draw_roundbox_gl_mode(GL_LINE_LOOP, rct->xmin, rct->ymin, rct->xmax, rct->ymax, hiddenrad, color);
+
glDisable(GL_LINE_SMOOTH);
glDisable(GL_BLEND);
}
@@ -1021,8 +1064,7 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b
glEnable(GL_BLEND);
glEnable(GL_LINE_SMOOTH);
- glColor3fv(node->color);
- UI_draw_roundbox_gl_mode(GL_LINE_LOOP, rct->xmin + 1, rct->ymin + 1, rct->xmax -1, rct->ymax - 1, hiddenrad);
+ UI_draw_roundbox_gl_mode_3fvAlpha(GL_LINE_LOOP, rct->xmin + 1, rct->ymin + 1, rct->xmax -1, rct->ymax - 1, hiddenrad, node->color, 1.0f);
glDisable(GL_LINE_SMOOTH);
glDisable(GL_BLEND);
@@ -1053,12 +1095,9 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b
/* disable lines */
if (node->flag & NODE_MUTED)
node_draw_mute_line(&ar->v2d, snode, node);
-
- if (node->flag & SELECT)
- UI_ThemeColor(TH_SELECT);
- else
- UI_ThemeColor(TH_TEXT);
-
+
+ UI_ThemeColor((node->flag & SELECT) ? TH_SELECT : TH_TEXT);
+
if (node->miniwidth > 0.0f) {
nodeLabel(ntree, node, showname, sizeof(showname));
@@ -1082,17 +1121,8 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b
fdrawline(rct->xmax - dx, centy - 4.0f, rct->xmax - dx, centy + 4.0f);
fdrawline(rct->xmax - dx - 3.0f * snode->aspect, centy - 4.0f, rct->xmax - dx - 3.0f * snode->aspect, centy + 4.0f);
- /* sockets */
- for (sock = node->inputs.first; sock; sock = sock->next) {
- if (!nodeSocketIsHidden(sock))
- node_socket_circle_draw(C, ntree, node, sock, socket_size, sock->flag & SELECT);
- }
-
- for (sock = node->outputs.first; sock; sock = sock->next) {
- if (!nodeSocketIsHidden(sock))
- node_socket_circle_draw(C, ntree, node, sock, socket_size, sock->flag & SELECT);
- }
-
+ node_draw_sockets(v2d, C, ntree, node, true, false);
+
UI_block_end(C, node->block);
UI_block_draw(C, node->block);
node->block = NULL;
@@ -1272,12 +1302,14 @@ static void draw_group_overlay(const bContext *C, ARegion *ar)
View2D *v2d = &ar->v2d;
rctf rect = v2d->cur;
uiBlock *block;
-
+ float color[4];
+
/* shade node groups to separate them visually */
- UI_ThemeColorShadeAlpha(TH_NODE_GROUP, 0, -70);
glEnable(GL_BLEND);
+
+ UI_GetThemeColorShadeAlpha4fv(TH_NODE_GROUP, 0, -70, color);
UI_draw_roundbox_corner_set(UI_CNR_NONE);
- UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin, rect.ymin, rect.xmax, rect.ymax, 0);
+ UI_draw_roundbox_gl_mode(GL_POLYGON, rect.xmin, rect.ymin, rect.xmax, rect.ymax, 0, color);
glDisable(GL_BLEND);
/* set the block bounds to clip mouse events from underlying nodes */
diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h
index 6b8fa0b88fe..3b5d32a432a 100644
--- a/source/blender/editors/space_node/node_intern.h
+++ b/source/blender/editors/space_node/node_intern.h
@@ -67,12 +67,11 @@ void snode_group_offset(struct SpaceNode *snode, float *x, float *y); /* transfo
/* node_draw.c */
int node_get_colorid(struct bNode *node);
-void node_socket_circle_draw(const struct bContext *C, struct bNodeTree *ntree, struct bNode *node,
- struct bNodeSocket *sock, float size, int highlight);
int node_get_resize_cursor(int directions);
void node_draw_shadow(struct SpaceNode *snode, struct bNode *node, float radius, float alpha);
void node_draw_default(const struct bContext *C, struct ARegion *ar, struct SpaceNode *snode,
struct bNodeTree *ntree, struct bNode *node, bNodeInstanceKey key);
+void node_draw_sockets(struct View2D *v2d, const struct bContext *C, struct bNodeTree *ntree, struct bNode *node, bool draw_outputs, bool select_all);
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);
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index 33a5a7ca7b7..ecdab26942a 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -68,6 +68,8 @@
#include "BIF_gl.h"
#include "BIF_glutil.h"
+#include "GPU_immediate.h"
+
#include "UI_interface.h"
#include "UI_interface_icons.h"
#include "UI_resources.h"
@@ -1078,8 +1080,6 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto
UI_icon_draw(x, y, ICON_MODIFIER); break;
case TSE_LINKED_OB:
UI_icon_draw(x, y, ICON_OBJECT_DATA); break;
- case TSE_LINKED_PSYS:
- UI_icon_draw(x, y, ICON_PARTICLES); break;
case TSE_MODIFIER:
{
Object *ob = (Object *)tselem->id;
@@ -1107,10 +1107,6 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto
UI_icon_draw(x, y, ICON_MOD_SOFT); break;
case eModifierType_Boolean:
UI_icon_draw(x, y, ICON_MOD_BOOLEAN); break;
- case eModifierType_ParticleSystem:
- UI_icon_draw(x, y, ICON_MOD_PARTICLES); break;
- case eModifierType_ParticleInstance:
- UI_icon_draw(x, y, ICON_MOD_PARTICLES); break;
case eModifierType_EdgeSplit:
UI_icon_draw(x, y, ICON_MOD_EDGESPLIT); break;
case eModifierType_Array:
@@ -1415,11 +1411,14 @@ static void outliner_draw_iconrow(bContext *C, uiBlock *block, Scene *scene, Spa
static void outliner_set_coord_tree_element(TreeElement *te, int startx, int starty)
{
TreeElement *ten;
-
- /* store coord and continue, we need coordinates for elements outside view too */
- te->xs = startx;
- te->ys = starty;
-
+
+ /* closed items may be displayed in row of parent, don't change their coordinate! */
+ if ((te->flag & TE_ICONROW) == 0) {
+ /* store coord and continue, we need coordinates for elements outside view too */
+ te->xs = startx;
+ te->ys = starty;
+ }
+
for (ten = te->subtree.first; ten; ten = ten->next) {
outliner_set_coord_tree_element(ten, startx + UI_UNIT_X, starty);
}
@@ -1452,23 +1451,8 @@ static void outliner_draw_tree_element(
glEnable(GL_BLEND);
- /* start by highlighting search matches
- * we don't expand items when searching in the datablocks but we
- * still want to highlight any filter matches.
- */
- if ((SEARCHING_OUTLINER(soops) || (soops->outlinevis == SO_DATABLOCKS && soops->search_string[0] != 0)) &&
- (tselem->flag & TSE_SEARCHMATCH))
- {
- char col[4];
- UI_GetThemeColorType4ubv(TH_MATCH, SPACE_OUTLINER, col);
- col[3] = alpha;
- glColor4ubv((GLubyte *)col);
- glRecti(startx, *starty + 1, ar->v2d.cur.xmax, *starty + UI_UNIT_Y - 1);
- }
-
/* colors for active/selected data */
if (tselem->type == 0) {
-
if (te->idcode == ID_SCE) {
if (tselem->id == (ID *)scene) {
glColor4ub(255, 255, 255, alpha);
@@ -1654,7 +1638,7 @@ static void outliner_draw_tree_element(
}
}
-static void outliner_draw_hierarchy(SpaceOops *soops, ListBase *lb, int startx, int *starty)
+static void outliner_draw_hierarchy_lines(SpaceOops *soops, ListBase *lb, int startx, int *starty)
{
TreeElement *te;
TreeStoreElem *tselem;
@@ -1674,7 +1658,7 @@ static void outliner_draw_hierarchy(SpaceOops *soops, ListBase *lb, int startx,
*starty -= UI_UNIT_Y;
if (TSELEM_OPEN(tselem, soops))
- outliner_draw_hierarchy(soops, &te->subtree, startx + UI_UNIT_X, starty);
+ outliner_draw_hierarchy_lines(soops, &te->subtree, startx + UI_UNIT_X, starty);
}
/* vertical line */
@@ -1710,34 +1694,73 @@ static void outliner_draw_struct_marks(ARegion *ar, SpaceOops *soops, ListBase *
}
}
-static void outliner_draw_selection(ARegion *ar, SpaceOops *soops, ListBase *lb, int *starty)
+static void outliner_draw_highlights_recursive(
+ const ARegion *ar, const SpaceOops *soops, const ListBase *lb,
+ const float col_selection[4], const float col_highlight[4], const float col_searchmatch[4],
+ int start_x, int *io_start_y)
{
- TreeElement *te;
- TreeStoreElem *tselem;
-
- for (te = lb->first; te; te = te->next) {
- tselem = TREESTORE(te);
-
+ const bool is_searching = SEARCHING_OUTLINER(soops) ||
+ (soops->outlinevis == SO_DATABLOCKS && soops->search_string[0] != 0);
+
+ for (TreeElement *te = lb->first; te; te = te->next) {
+ const TreeStoreElem *tselem = TREESTORE(te);
+ const int start_y = *io_start_y;
+
/* selection status */
if (tselem->flag & TSE_SELECTED) {
- glRecti(0, *starty + 1, (int)ar->v2d.cur.xmax, *starty + UI_UNIT_Y - 1);
+ glColor4fv(col_selection);
+ glRecti(0, start_y + 1, (int)ar->v2d.cur.xmax, start_y + UI_UNIT_Y - 1);
+ }
+
+ /* search match highlights
+ * we don't expand items when searching in the datablocks but we
+ * still want to highlight any filter matches. */
+ if (is_searching && (tselem->flag & TSE_SEARCHMATCH)) {
+ glColor4fv(col_searchmatch);
+ glRecti(start_x, start_y + 1, ar->v2d.cur.xmax, start_y + UI_UNIT_Y - 1);
+ }
+
+ /* mouse hover highlights */
+ if (tselem->flag & TSE_HIGHLIGHTED) {
+ glColor4fv(col_highlight);
+ glRecti(0, start_y + 1, (int)ar->v2d.cur.xmax, start_y + UI_UNIT_Y - 1);
+ }
+
+ *io_start_y -= UI_UNIT_Y;
+ if (TSELEM_OPEN(tselem, soops)) {
+ outliner_draw_highlights_recursive(
+ ar, soops, &te->subtree, col_selection, col_highlight, col_searchmatch,
+ start_x + UI_UNIT_X, io_start_y);
}
- *starty -= UI_UNIT_Y;
- if (TSELEM_OPEN(tselem, soops)) outliner_draw_selection(ar, soops, &te->subtree, starty);
}
}
+static void outliner_draw_highlights(ARegion *ar, SpaceOops *soops, int startx, int *starty)
+{
+ const float col_highlight[4] = {1.0f, 1.0f, 1.0f, 0.13f};
+ float col_selection[4], col_searchmatch[4];
+
+ UI_GetThemeColor3fv(TH_SELECT_HIGHLIGHT, col_selection);
+ col_selection[3] = 1.0f; /* no alpha */
+ UI_GetThemeColor4fv(TH_MATCH, col_searchmatch);
+ col_searchmatch[3] = 0.5f;
+
+ glEnable(GL_BLEND);
+ outliner_draw_highlights_recursive(ar, soops, &soops->tree, col_selection, col_highlight, col_searchmatch,
+ startx, starty);
+ glDisable(GL_BLEND);
+}
-static void outliner_draw_tree(bContext *C, uiBlock *block, Scene *scene, ARegion *ar,
- SpaceOops *soops, TreeElement **te_edit)
+static void outliner_draw_tree(
+ bContext *C, uiBlock *block, Scene *scene, ARegion *ar,
+ SpaceOops *soops, const bool has_restrict_icons,
+ TreeElement **te_edit)
{
const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
- TreeElement *te;
int starty, startx;
- float col[3];
-
+
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // only once
-
+
if (ELEM(soops->outlinevis, SO_DATABLOCKS, SO_USERDEF)) {
/* struct marks */
UI_ThemeColorShadeAlpha(TH_BACK, -15, -200);
@@ -1745,25 +1768,39 @@ static void outliner_draw_tree(bContext *C, uiBlock *block, Scene *scene, ARegio
starty = (int)ar->v2d.tot.ymax - UI_UNIT_Y - OL_Y_OFFSET;
outliner_draw_struct_marks(ar, soops, &soops->tree, &starty);
}
-
- /* always draw selection fill before hierarchy */
- UI_GetThemeColor3fv(TH_SELECT_HIGHLIGHT, col);
- glColor3fv(col);
+
+ /* draw highlights before hierarchy */
starty = (int)ar->v2d.tot.ymax - UI_UNIT_Y - OL_Y_OFFSET;
- outliner_draw_selection(ar, soops, &soops->tree, &starty);
-
+ startx = 0;
+ outliner_draw_highlights(ar, soops, startx, &starty);
+
+ /* set scissor so tree elements or lines can't overlap restriction icons */
+ GLfloat scissor[4] = {0};
+ if (has_restrict_icons) {
+ int mask_x = BLI_rcti_size_x(&ar->v2d.mask) - (int)OL_TOGW + 1;
+ CLAMP_MIN(mask_x, 0);
+
+ glGetFloatv(GL_SCISSOR_BOX, scissor);
+ glScissor(ar->winrct.xmin, ar->winrct.ymin, mask_x, ar->winy);
+ }
+
// gray hierarchy lines
UI_ThemeColorBlend(TH_BACK, TH_TEXT, 0.4f);
starty = (int)ar->v2d.tot.ymax - UI_UNIT_Y / 2 - OL_Y_OFFSET;
startx = 6;
- outliner_draw_hierarchy(soops, &soops->tree, startx, &starty);
-
+ outliner_draw_hierarchy_lines(soops, &soops->tree, startx, &starty);
+
// items themselves
starty = (int)ar->v2d.tot.ymax - UI_UNIT_Y - OL_Y_OFFSET;
startx = 0;
- for (te = soops->tree.first; te; te = te->next) {
+ for (TreeElement *te = soops->tree.first; te; te = te->next) {
outliner_draw_tree_element(C, block, fstyle, scene, ar, soops, te, startx, &starty, te_edit);
}
+
+ if (has_restrict_icons) {
+ /* reset scissor */
+ glScissor(UNPACK4(scissor));
+ }
}
@@ -1771,34 +1808,36 @@ static void outliner_back(ARegion *ar)
{
int ystart;
- UI_ThemeColorShade(TH_BACK, 6);
ystart = (int)ar->v2d.tot.ymax;
ystart = UI_UNIT_Y * (ystart / (UI_UNIT_Y)) - OL_Y_OFFSET;
-
- while (ystart + 2 * UI_UNIT_Y > ar->v2d.cur.ymin) {
- glRecti(0, ystart, (int)ar->v2d.cur.xmax, ystart + UI_UNIT_Y);
- ystart -= 2 * UI_UNIT_Y;
+
+ VertexFormat *format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColorShade(TH_BACK, 6);
+
+ const float x1 = 0.0f, x2 = ar->v2d.cur.xmax;
+ float y1 = ystart, y2;
+ int tot = (int)floor(ystart - ar->v2d.cur.ymin + 2 * UI_UNIT_Y) / (2 * UI_UNIT_Y);
+
+ if (tot > 0) {
+ immBegin(GL_QUADS, 4 * tot);
+ while (tot--) {
+ y1 -= 2 * UI_UNIT_Y;
+ y2 = y1 + UI_UNIT_Y;
+ immVertex2f(pos, x1, y1);
+ immVertex2f(pos, x2, y1);
+ immVertex2f(pos, x2, y2);
+ immVertex2f(pos, x1, y2);
+ }
+ immEnd();
}
+ immUnbindProgram();
}
static void outliner_draw_restrictcols(ARegion *ar)
{
- int ystart;
-
- /* background underneath */
- UI_ThemeColor(TH_BACK);
- glRecti((int)(ar->v2d.cur.xmax - OL_TOGW),
- (int)(ar->v2d.cur.ymin - 1), (int)ar->v2d.cur.xmax, (int)ar->v2d.cur.ymax);
-
- UI_ThemeColorShade(TH_BACK, 6);
- ystart = (int)ar->v2d.tot.ymax;
- ystart = UI_UNIT_Y * (ystart / (UI_UNIT_Y)) - OL_Y_OFFSET;
-
- while (ystart + 2 * UI_UNIT_Y > ar->v2d.cur.ymin) {
- glRecti((int)ar->v2d.cur.xmax - OL_TOGW, ystart, (int)ar->v2d.cur.xmax, ystart + UI_UNIT_Y);
- ystart -= 2 * UI_UNIT_Y;
- }
-
UI_ThemeColorShadeAlpha(TH_BACK, -15, -200);
/* view */
@@ -1833,6 +1872,7 @@ void draw_outliner(const bContext *C)
uiBlock *block;
int sizey = 0, sizex = 0, sizex_rna = 0;
TreeElement *te_edit = NULL;
+ bool has_restrict_icons;
outliner_build_tree(mainvar, scene, soops); // always
@@ -1854,6 +1894,7 @@ void draw_outliner(const bContext *C)
/* get width of data (for setting 'tot' rect, this is column 1 + column 2 + a bit extra) */
sizex = sizex_rna + OL_RNA_COL_SIZEX + 50;
+ has_restrict_icons = false;
}
else {
/* width must take into account restriction columns (if visible) so that entries will still be visible */
@@ -1865,7 +1906,8 @@ void draw_outliner(const bContext *C)
// XXX this isn't that great yet...
if ((soops->flag & SO_HIDE_RESTRICTCOLS) == 0)
sizex += OL_TOGW * 3;
-
+
+ has_restrict_icons = !(soops->flag & SO_HIDE_RESTRICTCOLS);
}
/* adds vertical offset */
@@ -1882,19 +1924,19 @@ void draw_outliner(const bContext *C)
/* draw outliner stuff (background, hierarchy lines and names) */
outliner_back(ar);
block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
- outliner_draw_tree((bContext *)C, block, scene, ar, soops, &te_edit);
+ outliner_draw_tree((bContext *)C, block, scene, ar, soops, has_restrict_icons, &te_edit);
if (ELEM(soops->outlinevis, SO_DATABLOCKS, SO_USERDEF)) {
/* draw rna buttons */
outliner_draw_rnacols(ar, sizex_rna);
outliner_draw_rnabuts(block, ar, soops, sizex_rna, &soops->tree);
}
- else if ((soops->outlinevis == SO_ID_ORPHANS) && !(soops->flag & SO_HIDE_RESTRICTCOLS)) {
+ else if ((soops->outlinevis == SO_ID_ORPHANS) && has_restrict_icons) {
/* draw user toggle columns */
outliner_draw_restrictcols(ar);
outliner_draw_userbuts(block, ar, soops, &soops->tree);
}
- else if (!(soops->flag & SO_HIDE_RESTRICTCOLS)) {
+ else if (has_restrict_icons) {
/* draw restriction columns */
outliner_draw_restrictcols(ar);
outliner_draw_restrictbuts(block, scene, ar, soops, &soops->tree);
diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c
index 345ac353c11..4dcdcc69d6d 100644
--- a/source/blender/editors/space_outliner/outliner_edit.c
+++ b/source/blender/editors/space_outliner/outliner_edit.c
@@ -148,8 +148,95 @@ TreeElement *outliner_dropzone_find(const SpaceOops *soops, const float fmval[2]
return NULL;
}
+/**
+ * Try to find an item under y-coordinate \a view_co_y (view-space).
+ * \note Recursive
+ */
+TreeElement *outliner_find_item_at_y(const SpaceOops *soops, const ListBase *tree, float view_co_y)
+{
+ for (TreeElement *te_iter = tree->first; te_iter; te_iter = te_iter->next) {
+ if (view_co_y < (te_iter->ys + UI_UNIT_Y)) {
+ if (view_co_y > te_iter->ys) {
+ /* co_y is inside this element */
+ return te_iter;
+ }
+ else if (TSELEM_OPEN(te_iter->store_elem, soops)) {
+ /* co_y is lower than current element, possibly inside children */
+ TreeElement *te_sub = outliner_find_item_at_y(soops, &te_iter->subtree, view_co_y);
+ if (te_sub) {
+ return te_sub;
+ }
+ }
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * Collapsed items can show their children as click-able icons. This function tries to find
+ * such an icon that represents the child item at x-coordinate \a view_co_x (view-space).
+ *
+ * \return a hovered child item or \a parent_te (if no hovered child found).
+ */
+TreeElement *outliner_find_item_at_x_in_row(const SpaceOops *soops, const TreeElement *parent_te, float view_co_x)
+{
+ if (!TSELEM_OPEN(TREESTORE(parent_te), soops)) { /* if parent_te is opened, it doesn't show childs in row */
+ /* no recursion, items can only display their direct children in the row */
+ for (TreeElement *child_te = parent_te->subtree.first;
+ child_te && view_co_x >= child_te->xs; /* don't look further if co_x is smaller than child position*/
+ child_te = child_te->next)
+ {
+ if ((child_te->flag & TE_ICONROW) && (view_co_x > child_te->xs) && (view_co_x < child_te->xend)) {
+ return child_te;
+ }
+ }
+ }
+
+ /* return parent if no child is hovered */
+ return (TreeElement *)parent_te;
+}
+
+
/* ************************************************************** */
-/* Click Activated */
+
+/* Highlight --------------------------------------------------- */
+
+static int outliner_highlight_update(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
+{
+ ARegion *ar = CTX_wm_region(C);
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+ const float my = UI_view2d_region_to_view_y(&ar->v2d, event->mval[1]);
+
+ TreeElement *hovered_te = outliner_find_item_at_y(soops, &soops->tree, my);
+ bool changed = false;
+
+ if (!hovered_te || !(hovered_te->store_elem->flag & TSE_HIGHLIGHTED)) {
+ changed = outliner_set_flag(&soops->tree, TSE_HIGHLIGHTED, false);
+ if (hovered_te) {
+ hovered_te->store_elem->flag |= TSE_HIGHLIGHTED;
+ changed = true;
+ }
+ }
+
+ if (changed) {
+ soops->storeflag |= SO_TREESTORE_REDRAW; /* only needs to redraw, no rebuild */
+ ED_region_tag_redraw(ar);
+ }
+
+ return (OPERATOR_FINISHED | OPERATOR_PASS_THROUGH);
+}
+
+void OUTLINER_OT_highlight_update(wmOperatorType *ot)
+{
+ ot->name = "Update Highlight";
+ ot->idname = "OUTLINER_OT_highlight_update";
+ ot->description = "Update the item highlight based on the current mouse position";
+
+ ot->invoke = outliner_highlight_update;
+
+ ot->poll = ED_operator_outliner_active;
+}
/* Toggle Open/Closed ------------------------------------------- */
@@ -740,17 +827,34 @@ int outliner_has_one_flag(ListBase *lb, short flag, const int curlevel)
return 0;
}
-void outliner_set_flag(ListBase *lb, short flag, short set)
+/**
+ * Set or unset \a flag for all outliner elements in \a lb and sub-trees.
+ * \return if any flag was modified.
+ */
+bool outliner_set_flag(ListBase *lb, short flag, short set)
{
TreeElement *te;
TreeStoreElem *tselem;
-
+ bool changed = false;
+ bool has_flag;
+
for (te = lb->first; te; te = te->next) {
tselem = TREESTORE(te);
- if (set == 0) tselem->flag &= ~flag;
- else tselem->flag |= flag;
- outliner_set_flag(&te->subtree, flag, set);
+ has_flag = (tselem->flag & flag);
+ if (set == 0) {
+ if (has_flag) {
+ tselem->flag &= ~flag;
+ changed = true;
+ }
+ }
+ else if (!has_flag){
+ tselem->flag |= flag;
+ changed = true;
+ }
+ changed |= outliner_set_flag(&te->subtree, flag, set);
}
+
+ return changed;
}
/* Restriction Columns ------------------------------- */
diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h
index ccc52f2dba8..c5dfbf1819b 100644
--- a/source/blender/editors/space_outliner/outliner_intern.h
+++ b/source/blender/editors/space_outliner/outliner_intern.h
@@ -61,14 +61,18 @@ typedef struct TreeElement {
#define TREESTORE_ID_TYPE(_id) \
(ELEM(GS((_id)->name), ID_SCE, ID_LI, ID_OB, ID_ME, ID_CU, ID_MB, ID_NT, ID_MA, ID_TE, ID_IM, ID_LT, ID_LA, ID_CA) || \
- ELEM(GS((_id)->name), ID_KE, ID_WO, ID_SPK, ID_GR, ID_AR, ID_AC, ID_BR, ID_PA, ID_GD, ID_LS) || \
+ ELEM(GS((_id)->name), ID_KE, ID_WO, ID_SPK, ID_GR, ID_AR, ID_AC, ID_BR, ID_GD, ID_LS) || \
ELEM(GS((_id)->name), ID_SCR, ID_WM, ID_TXT, ID_VF, ID_SO, ID_CF, ID_PAL)) /* Only in 'blendfile' mode ... :/ */
/* TreeElement->flag */
-#define TE_ACTIVE 1
-#define TE_ICONROW 2
-#define TE_LAZY_CLOSED 4
-#define TE_FREE_NAME 8
+enum {
+ TE_ACTIVE = (1 << 0),
+ /* Closed items display their children as icon within the row. TE_ICONROW is for
+ * these child-items that are visible but only within the row of the closed parent. */
+ TE_ICONROW = (1 << 1),
+ TE_LAZY_CLOSED = (1 << 2),
+ TE_FREE_NAME = (1 << 3),
+};
/* button events */
#define OL_NAMEBUTTON 1
@@ -150,7 +154,7 @@ eOLDrawState tree_element_type_active(
TreeElement *te, TreeStoreElem *tselem, const eOLSetState set, bool recursive);
eOLDrawState tree_element_active(struct bContext *C, struct Scene *scene, SpaceOops *soops,
TreeElement *te, const eOLSetState set, const bool handle_all_types);
-int outliner_item_do_activate(struct bContext *C, int x, int y, bool extend, bool recursive);
+int outliner_item_activate_or_toggle_closed(struct bContext *C, int x, int y, bool extend, bool recursive);
/* outliner_edit.c ---------------------------------------------- */
typedef void (*outliner_operation_cb)(
@@ -167,7 +171,7 @@ void outliner_do_object_operation(
int common_restrict_check(struct bContext *C, struct Object *ob);
int outliner_has_one_flag(ListBase *lb, short flag, const int curlevel);
-void outliner_set_flag(ListBase *lb, short flag, short set);
+bool outliner_set_flag(ListBase *lb, short flag, short set);
void object_toggle_visibility_cb(
struct bContext *C, struct ReportList *reports, struct Scene *scene,
@@ -208,8 +212,14 @@ void id_remap_cb(
struct TreeStoreElem *tsep, struct TreeStoreElem *tselem, void *user_data);
TreeElement *outliner_dropzone_find(const struct SpaceOops *soops, const float fmval[2], const bool children);
+
+TreeElement *outliner_find_item_at_y(const SpaceOops *soops, const ListBase *tree, float view_co_y);
+TreeElement *outliner_find_item_at_x_in_row(const SpaceOops *soops, const TreeElement *parent_te, float view_co_x);
+
/* ...................................................... */
+void OUTLINER_OT_highlight_update(struct wmOperatorType *ot);
+
void OUTLINER_OT_item_activate(struct wmOperatorType *ot);
void OUTLINER_OT_item_openclose(struct wmOperatorType *ot);
void OUTLINER_OT_item_rename(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_outliner/outliner_ops.c b/source/blender/editors/space_outliner/outliner_ops.c
index 776717c8443..f0c2d848f7a 100644
--- a/source/blender/editors/space_outliner/outliner_ops.c
+++ b/source/blender/editors/space_outliner/outliner_ops.c
@@ -43,6 +43,7 @@
void outliner_operatortypes(void)
{
+ WM_operatortype_append(OUTLINER_OT_highlight_update);
WM_operatortype_append(OUTLINER_OT_item_activate);
WM_operatortype_append(OUTLINER_OT_select_border);
WM_operatortype_append(OUTLINER_OT_item_openclose);
@@ -93,7 +94,9 @@ void outliner_keymap(wmKeyConfig *keyconf)
{
wmKeyMap *keymap = WM_keymap_find(keyconf, "Outliner", SPACE_OUTLINER, 0);
wmKeyMapItem *kmi;
-
+
+ WM_keymap_add_item(keymap, "OUTLINER_OT_highlight_update", MOUSEMOVE, KM_ANY, KM_ANY, 0);
+
WM_keymap_add_item(keymap, "OUTLINER_OT_item_rename", LEFTMOUSE, KM_DBL_CLICK, 0, 0);
kmi = WM_keymap_add_item(keymap, "OUTLINER_OT_item_activate", LEFTMOUSE, KM_CLICK, 0, 0);
diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c
index 89df471990a..a9f834c509f 100644
--- a/source/blender/editors/space_outliner/outliner_select.c
+++ b/source/blender/editors/space_outliner/outliner_select.c
@@ -68,55 +68,6 @@
#include "outliner_intern.h"
-/* ****************************************************** */
-/* Outliner Selection (gray-blue highlight for rows) */
-
-static int outliner_select(SpaceOops *soops, ListBase *lb, int *index, short *selecting)
-{
- TreeElement *te;
- TreeStoreElem *tselem;
- bool changed = false;
-
- for (te = lb->first; te && *index >= 0; te = te->next, (*index)--) {
- tselem = TREESTORE(te);
-
- /* if we've encountered the right item, set its 'Outliner' selection status */
- if (*index == 0) {
- /* this should be the last one, so no need to do anything with index */
- if ((te->flag & TE_ICONROW) == 0) {
- /* -1 value means toggle testing for now... */
- if (*selecting == -1) {
- if (tselem->flag & TSE_SELECTED)
- *selecting = 0;
- else
- *selecting = 1;
- }
-
- /* set selection */
- if (*selecting)
- tselem->flag |= TSE_SELECTED;
- else
- tselem->flag &= ~TSE_SELECTED;
-
- changed |= true;
- }
- }
- else if (TSELEM_OPEN(tselem, soops)) {
- /* Only try selecting sub-elements if we haven't hit the right element yet
- *
- * Hack warning:
- * Index must be reduced before supplying it to the sub-tree to try to do
- * selection, however, we need to increment it again for the next loop to
- * function correctly
- */
- (*index)--;
- changed |= outliner_select(soops, &te->subtree, index, selecting);
- (*index)++;
- }
- }
-
- return changed;
-}
/* ****************************************************** */
/* Outliner Element Selection/Activation on Click */
@@ -666,20 +617,6 @@ static eOLDrawState tree_element_active_modifier(
return OL_DRAWSEL_NONE;
}
-static eOLDrawState tree_element_active_psys(
- bContext *C, Scene *UNUSED(scene), TreeElement *UNUSED(te), TreeStoreElem *tselem, const eOLSetState set)
-{
- if (set != OL_SETSEL_NONE) {
- Object *ob = (Object *)tselem->id;
-
- WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_EDITED, ob);
-
-// XXX extern_set_butspace(F7KEY, 0);
- }
-
- return OL_DRAWSEL_NONE;
-}
-
static int tree_element_active_constraint(
bContext *C, TreeElement *UNUSED(te), TreeStoreElem *tselem, const eOLSetState set)
{
@@ -858,8 +795,6 @@ eOLDrawState tree_element_type_active(
return OL_DRAWSEL_NORMAL;
}
break;
- case TSE_LINKED_PSYS:
- return tree_element_active_psys(C, scene, te, tselem, set);
case TSE_POSE_BASE:
return tree_element_active_pose(C, scene, te, tselem, set);
case TSE_POSE_CHANNEL:
@@ -886,163 +821,164 @@ eOLDrawState tree_element_type_active(
/* ================================================ */
-static bool do_outliner_item_activate(bContext *C, Scene *scene, ARegion *ar, SpaceOops *soops,
- TreeElement *te, bool extend, bool recursive, const float mval[2])
+static void outliner_item_activate(
+ bContext *C, SpaceOops *soops, TreeElement *te,
+ const bool extend, const bool recursive)
{
-
- if (mval[1] > te->ys && mval[1] < te->ys + UI_UNIT_Y) {
- TreeStoreElem *tselem = TREESTORE(te);
- bool openclose = false;
-
- /* open close icon */
- if ((te->flag & TE_ICONROW) == 0) { // hidden icon, no open/close
- if (mval[0] > te->xs && mval[0] < te->xs + UI_UNIT_X)
- openclose = true;
- }
-
- if (openclose) {
- /* all below close/open? */
- if (extend) {
- tselem->flag &= ~TSE_CLOSED;
- outliner_set_flag(&te->subtree, TSE_CLOSED, !outliner_has_one_flag(&te->subtree, TSE_CLOSED, 1));
- }
- else {
- if (tselem->flag & TSE_CLOSED) tselem->flag &= ~TSE_CLOSED;
- else tselem->flag |= TSE_CLOSED;
-
+ Scene *scene = CTX_data_scene(C);
+ TreeStoreElem *tselem = TREESTORE(te);
+
+ /* always makes active object, except for some specific types.
+ * Note about TSE_EBONE: In case of a same ID_AR datablock shared among several objects, we do not want
+ * to switch out of edit mode (see T48328 for details). */
+ if (!ELEM(tselem->type, TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP, TSE_EBONE)) {
+ tree_element_set_active_object(C, scene, soops, te,
+ (extend && tselem->type == 0) ? OL_SETSEL_EXTEND : OL_SETSEL_NORMAL,
+ recursive && tselem->type == 0);
+ }
+
+ if (tselem->type == 0) { // the lib blocks
+ /* editmode? */
+ if (te->idcode == ID_SCE) {
+ if (scene != (Scene *)tselem->id) {
+ ED_screen_set_scene(C, CTX_wm_screen(C), (Scene *)tselem->id);
}
-
- return true;
}
- /* name and first icon */
- else if (mval[0] > te->xs + UI_UNIT_X && mval[0] < te->xend) {
+ else if (te->idcode == ID_GR) {
+ Group *gr = (Group *)tselem->id;
+ GroupObject *gob;
- /* always makes active object, except for some specific types.
- * Note about TSE_EBONE: In case of a same ID_AR datablock shared among several objects, we do not want
- * to switch out of edit mode (see T48328 for details). */
- if (!ELEM(tselem->type, TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP, TSE_EBONE)) {
- tree_element_set_active_object(C, scene, soops, te,
- (extend && tselem->type == 0) ? OL_SETSEL_EXTEND : OL_SETSEL_NORMAL,
- recursive && tselem->type == 0);
- }
-
- if (tselem->type == 0) { // the lib blocks
- /* editmode? */
- if (te->idcode == ID_SCE) {
- if (scene != (Scene *)tselem->id) {
- ED_screen_set_scene(C, CTX_wm_screen(C), (Scene *)tselem->id);
- }
- }
- else if (te->idcode == ID_GR) {
- Group *gr = (Group *)tselem->id;
- GroupObject *gob;
-
- if (extend) {
- int sel = BA_SELECT;
- for (gob = gr->gobject.first; gob; gob = gob->next) {
- if (gob->ob->flag & SELECT) {
- sel = BA_DESELECT;
- break;
- }
- }
-
- for (gob = gr->gobject.first; gob; gob = gob->next) {
- ED_base_object_select(BKE_scene_base_find(scene, gob->ob), sel);
- }
- }
- else {
- BKE_scene_base_deselect_all(scene);
-
- for (gob = gr->gobject.first; gob; gob = gob->next) {
- if ((gob->ob->flag & SELECT) == 0)
- ED_base_object_select(BKE_scene_base_find(scene, gob->ob), BA_SELECT);
- }
+ if (extend) {
+ int sel = BA_SELECT;
+ for (gob = gr->gobject.first; gob; gob = gob->next) {
+ if (gob->ob->flag & SELECT) {
+ sel = BA_DESELECT;
+ break;
}
-
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- }
- else if (ELEM(te->idcode, ID_ME, ID_CU, ID_MB, ID_LT, ID_AR)) {
- WM_operator_name_call(C, "OBJECT_OT_editmode_toggle", WM_OP_INVOKE_REGION_WIN, NULL);
- }
- else { // rest of types
- tree_element_active(C, scene, soops, te, OL_SETSEL_NORMAL, false);
}
+ for (gob = gr->gobject.first; gob; gob = gob->next) {
+ ED_base_object_select(BKE_scene_base_find(scene, gob->ob), sel);
+ }
}
else {
- tree_element_type_active(C, scene, soops, te, tselem,
- extend ? OL_SETSEL_EXTEND : OL_SETSEL_NORMAL,
- recursive);
+ BKE_scene_base_deselect_all(scene);
+
+ for (gob = gr->gobject.first; gob; gob = gob->next) {
+ if ((gob->ob->flag & SELECT) == 0)
+ ED_base_object_select(BKE_scene_base_find(scene, gob->ob), BA_SELECT);
+ }
}
- return true;
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
}
- }
-
- for (te = te->subtree.first; te; te = te->next) {
- if (do_outliner_item_activate(C, scene, ar, soops, te, extend, recursive, mval)) {
- return true;
+ else if (ELEM(te->idcode, ID_ME, ID_CU, ID_MB, ID_LT, ID_AR)) {
+ WM_operator_name_call(C, "OBJECT_OT_editmode_toggle", WM_OP_INVOKE_REGION_WIN, NULL);
}
+ else { // rest of types
+ tree_element_active(C, scene, soops, te, OL_SETSEL_NORMAL, false);
+ }
+
+ }
+ else {
+ tree_element_type_active(C, scene, soops, te, tselem,
+ extend ? OL_SETSEL_EXTEND : OL_SETSEL_NORMAL,
+ recursive);
+ }
+}
+
+/**
+ * \param extend: Don't deselect other items, only modify \a te.
+ * \param toggle: Select \a te when not selected, deselect when selected.
+ */
+static void outliner_item_select(SpaceOops *soops, const TreeElement *te, const bool extend, const bool toggle)
+{
+ TreeStoreElem *tselem = TREESTORE(te);
+ const short new_flag = toggle ? (tselem->flag ^ TSE_SELECTED) : (tselem->flag | TSE_SELECTED);
+
+ if (extend == false) {
+ outliner_set_flag(&soops->tree, TSE_SELECTED, false);
}
- return false;
+ tselem->flag = new_flag;
}
-int outliner_item_do_activate(bContext *C, int x, int y, bool extend, bool recursive)
+static void outliner_item_toggle_closed(TreeElement *te, const bool toggle_children)
+{
+ TreeStoreElem *tselem = TREESTORE(te);
+ if (toggle_children) {
+ tselem->flag &= ~TSE_CLOSED;
+
+ const bool all_opened = !outliner_has_one_flag(&te->subtree, TSE_CLOSED, 1);
+ outliner_set_flag(&te->subtree, TSE_CLOSED, all_opened);
+ }
+ else {
+ tselem->flag ^= TSE_CLOSED;
+ }
+}
+
+static bool outliner_item_is_co_within_close_toggle(TreeElement *te, float view_co_x)
+{
+ return ((te->flag & TE_ICONROW) == 0) && (view_co_x > te->xs) && (view_co_x < te->xs + UI_UNIT_X);
+}
+
+static bool outliner_is_co_within_restrict_columns(const SpaceOops *soops, const ARegion *ar, float view_co_x)
+{
+ return (!ELEM(soops->outlinevis, SO_DATABLOCKS, SO_USERDEF) &&
+ !(soops->flag & SO_HIDE_RESTRICTCOLS) &&
+ (view_co_x > ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX));
+}
+
+int outliner_item_activate_or_toggle_closed(bContext *C, int x, int y, bool extend, bool recursive)
{
- Scene *scene = CTX_data_scene(C);
ARegion *ar = CTX_wm_region(C);
SpaceOops *soops = CTX_wm_space_outliner(C);
TreeElement *te;
- float fmval[2];
+ float view_mval[2];
+ bool changed = false, rebuild_tree = false;
- UI_view2d_region_to_view(&ar->v2d, x, y, &fmval[0], &fmval[1]);
+ UI_view2d_region_to_view(&ar->v2d, x, y, &view_mval[0], &view_mval[1]);
- if (!ELEM(soops->outlinevis, SO_DATABLOCKS, SO_USERDEF) &&
- !(soops->flag & SO_HIDE_RESTRICTCOLS) &&
- (fmval[0] > ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX))
- {
+ if (outliner_is_co_within_restrict_columns(soops, ar, view_mval[0])) {
return OPERATOR_CANCELLED;
}
- for (te = soops->tree.first; te; te = te->next) {
- if (do_outliner_item_activate(C, scene, ar, soops, te, extend, recursive, fmval)) break;
+ if (!(te = outliner_find_item_at_y(soops, &soops->tree, view_mval[1]))) {
+ /* skip */
}
-
- if (te) {
- ED_undo_push(C, "Outliner click event");
+ else if (outliner_item_is_co_within_close_toggle(te, view_mval[0])) {
+ outliner_item_toggle_closed(te, extend);
+ changed = true;
+ rebuild_tree = true;
}
else {
- short selecting = -1;
- int row;
-
- /* get row number - 100 here is just a dummy value since we don't need the column */
- UI_view2d_listview_view_to_cell(&ar->v2d, 1000, UI_UNIT_Y, 0.0f, OL_Y_OFFSET,
- fmval[0], fmval[1], NULL, &row);
-
- /* select relevant row */
- if (outliner_select(soops, &soops->tree, &row, &selecting)) {
-
+ /* the row may also contain children, if one is hovered we want this instead of current te */
+ TreeElement *activate_te = outliner_find_item_at_x_in_row(soops, te, view_mval[0]);
+
+ outliner_item_select(soops, activate_te, extend, extend);
+ outliner_item_activate(C, soops, activate_te, extend, recursive);
+ changed = true;
+ }
+
+ if (changed) {
+ if (!rebuild_tree) {
+ /* only needs to redraw, no rebuild */
soops->storeflag |= SO_TREESTORE_REDRAW;
-
- /* no need for undo push here, only changing outliner data which is
- * scene level - campbell */
- /* ED_undo_push(C, "Outliner selection event"); */
}
+ ED_undo_push(C, "Outliner selection change");
+ ED_region_tag_redraw(ar);
}
-
- ED_region_tag_redraw(ar);
return OPERATOR_FINISHED;
}
/* event can enterkey, then it opens/closes */
-static int outliner_item_activate(bContext *C, wmOperator *op, const wmEvent *event)
+static int outliner_item_activate_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
bool extend = RNA_boolean_get(op->ptr, "extend");
bool recursive = RNA_boolean_get(op->ptr, "recursive");
int x = event->mval[0];
int y = event->mval[1];
- return outliner_item_do_activate(C, x, y, extend, recursive);
+ return outliner_item_activate_or_toggle_closed(C, x, y, extend, recursive);
}
void OUTLINER_OT_item_activate(wmOperatorType *ot)
@@ -1051,7 +987,7 @@ void OUTLINER_OT_item_activate(wmOperatorType *ot)
ot->idname = "OUTLINER_OT_item_activate";
ot->description = "Handle mouse clicks to activate/select items";
- ot->invoke = outliner_item_activate;
+ ot->invoke = outliner_item_activate_invoke;
ot->poll = ED_operator_outliner_active;
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c
index 13200e92e7e..2c678457025 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -380,7 +380,7 @@ static void object_select_hierarchy_cb(
wmWindow *win = CTX_wm_window(C);
int x = win->eventstate->mval[0];
int y = win->eventstate->mval[1];
- outliner_item_do_activate(C, x, y, true, true);
+ outliner_item_activate_or_toggle_closed(C, x, y, true, true);
}
diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c
index 015988efc42..3b499a81831 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -46,7 +46,6 @@
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meta_types.h"
-#include "DNA_particle_types.h"
#include "DNA_scene_types.h"
#include "DNA_world_types.h"
#include "DNA_sequence_types.h"
@@ -622,14 +621,6 @@ static void outliner_add_object_contents(SpaceOops *soops, TreeElement *te, Tree
else if (md->type == eModifierType_Hook) {
outliner_add_element(soops, &ten->subtree, ((HookModifierData *) md)->object, ten, TSE_LINKED_OB, 0);
}
- else if (md->type == eModifierType_ParticleSystem) {
- ParticleSystem *psys = ((ParticleSystemModifierData *) md)->psys;
- TreeElement *ten_psys;
-
- ten_psys = outliner_add_element(soops, &ten->subtree, ob, te, TSE_LINKED_PSYS, 0);
- ten_psys->directdata = psys;
- ten_psys->name = psys->part->id.name + 2;
- }
}
}
diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c
index e1768e4aedc..d7771d06787 100644
--- a/source/blender/editors/space_sequencer/sequencer_draw.c
+++ b/source/blender/editors/space_sequencer/sequencer_draw.c
@@ -59,6 +59,7 @@
#include "BIF_glutil.h"
#include "GPU_basic_shader.h"
+#include "GPU_immediate.h"
#include "ED_anim_api.h"
#include "ED_gpencil.h"
@@ -1048,30 +1049,31 @@ static void sequencer_draw_borders(const SpaceSeq *sseq, const View2D *v2d, cons
/* border */
setlinestyle(3);
- UI_ThemeColorBlendShade(TH_WIRE, TH_BACK, 1.0, 0);
+ VertexFormat *format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
- glBegin(GL_LINE_LOOP);
- glVertex2f(x1 - 0.5f, y1 - 0.5f);
- glVertex2f(x1 - 0.5f, y2 + 0.5f);
- glVertex2f(x2 + 0.5f, y2 + 0.5f);
- glVertex2f(x2 + 0.5f, y1 - 0.5f);
- glEnd();
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColor(TH_BACK);
+
+ imm_draw_line_box(pos, x1 - 0.5f, y1 - 0.5f, x2 + 0.5f, y2 + 0.5f);
/* safety border */
if (sseq->flag & SEQ_SHOW_SAFE_MARGINS) {
UI_draw_safe_areas(
- x1, x2, y1, y2,
+ pos, x1, x2, y1, y2,
scene->safe_areas.title,
scene->safe_areas.action);
if (sseq->flag & SEQ_SHOW_SAFE_CENTER) {
UI_draw_safe_areas(
- x1, x2, y1, y2,
+ pos, x1, x2, y1, y2,
scene->safe_areas.title_center,
scene->safe_areas.action_center);
}
}
+ immUnbindProgram();
+
setlinestyle(0);
}
diff --git a/source/blender/editors/space_time/space_time.c b/source/blender/editors/space_time/space_time.c
index 15eb154c757..f199820dd10 100644
--- a/source/blender/editors/space_time/space_time.c
+++ b/source/blender/editors/space_time/space_time.c
@@ -50,7 +50,6 @@
#include "BKE_main.h"
#include "BKE_modifier.h"
#include "BKE_screen.h"
-#include "BKE_pointcache.h"
#include "ED_anim_api.h"
#include "ED_keyframes_draw.h"
@@ -69,6 +68,8 @@
#include "ED_space_api.h"
#include "ED_markers.h"
+#include "GPU_immediate.h"
+
#include "time_intern.h"
/* ************************ main time area region *********************** */
@@ -80,177 +81,36 @@ static void time_draw_sfra_efra(Scene *scene, View2D *v2d)
*/
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
- glColor4f(0.0f, 0.0f, 0.0f, 0.4f);
-
+
+ VertexFormat *format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4f(0.0f, 0.0f, 0.0f, 0.4f);
+
if (PSFRA < PEFRA) {
- glRectf(v2d->cur.xmin, v2d->cur.ymin, (float)PSFRA, v2d->cur.ymax);
- glRectf((float)PEFRA, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax);
+ immRectf(pos, v2d->cur.xmin, v2d->cur.ymin, (float)PSFRA, v2d->cur.ymax);
+ immRectf(pos, (float)PEFRA, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax);
}
else {
- glRectf(v2d->cur.xmin, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax);
+ immRectf(pos, v2d->cur.xmin, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax);
}
+
glDisable(GL_BLEND);
- UI_ThemeColorShade(TH_BACK, -60);
/* thin lines where the actual frames are */
- fdrawline((float)PSFRA, v2d->cur.ymin, (float)PSFRA, v2d->cur.ymax);
- fdrawline((float)PEFRA, v2d->cur.ymin, (float)PEFRA, v2d->cur.ymax);
-}
+ immUniformThemeColorShade(TH_BACK, -60);
-static void time_draw_cache(SpaceTime *stime, Object *ob, Scene *scene)
-{
- PTCacheID *pid;
- ListBase pidlist;
- SpaceTimeCache *stc = stime->caches.first;
- const float cache_draw_height = (4.0f * UI_DPI_FAC * U.pixelsize);
- float yoffs = 0.f;
-
- if (!(stime->cache_display & TIME_CACHE_DISPLAY) || (!ob))
- return;
-
- BKE_ptcache_ids_from_object(&pidlist, ob, scene, 0);
-
- /* iterate over pointcaches on the active object,
- * add spacetimecache and vertex array for each */
- for (pid = pidlist.first; pid; pid = pid->next) {
- float col[4], *fp;
- int i, sta = pid->cache->startframe, end = pid->cache->endframe;
- int len = (end - sta + 1) * 4;
-
- switch (pid->type) {
- case PTCACHE_TYPE_SOFTBODY:
- if (!(stime->cache_display & TIME_CACHE_SOFTBODY)) continue;
- break;
- case PTCACHE_TYPE_PARTICLES:
- if (!(stime->cache_display & TIME_CACHE_PARTICLES)) continue;
- break;
- case PTCACHE_TYPE_CLOTH:
- if (!(stime->cache_display & TIME_CACHE_CLOTH)) continue;
- break;
- case PTCACHE_TYPE_SMOKE_DOMAIN:
- case PTCACHE_TYPE_SMOKE_HIGHRES:
- if (!(stime->cache_display & TIME_CACHE_SMOKE)) continue;
- break;
- case PTCACHE_TYPE_DYNAMICPAINT:
- if (!(stime->cache_display & TIME_CACHE_DYNAMICPAINT)) continue;
- break;
- case PTCACHE_TYPE_RIGIDBODY:
- if (!(stime->cache_display & TIME_CACHE_RIGIDBODY)) continue;
- break;
- }
-
- if (pid->cache->cached_frames == NULL)
- continue;
+ immBegin(GL_LINES, 4);
- /* make sure we have stc with correct array length */
- if (stc == NULL || MEM_allocN_len(stc->array) != len * 2 * sizeof(float)) {
- if (stc) {
- MEM_freeN(stc->array);
- }
- else {
- stc = MEM_callocN(sizeof(SpaceTimeCache), "spacetimecache");
- BLI_addtail(&stime->caches, stc);
- }
+ immVertex2f(pos, (float)PSFRA, v2d->cur.ymin);
+ immVertex2f(pos, (float)PSFRA, v2d->cur.ymax);
- stc->array = MEM_callocN(len * 2 * sizeof(float), "SpaceTimeCache array");
- }
+ immVertex2f(pos, (float)PEFRA, v2d->cur.ymin);
+ immVertex2f(pos, (float)PEFRA, v2d->cur.ymax);
- /* fill the vertex array with a quad for each cached frame */
- for (i = sta, fp = stc->array; i <= end; i++) {
- if (pid->cache->cached_frames[i - sta]) {
- fp[0] = (float)i - 0.5f;
- fp[1] = 0.0;
- fp += 2;
-
- fp[0] = (float)i - 0.5f;
- fp[1] = 1.0;
- fp += 2;
-
- fp[0] = (float)i + 0.5f;
- fp[1] = 1.0;
- fp += 2;
-
- fp[0] = (float)i + 0.5f;
- fp[1] = 0.0;
- fp += 2;
- }
- }
-
- glPushMatrix();
- glTranslatef(0.0, (float)V2D_SCROLL_HEIGHT + yoffs, 0.0);
- glScalef(1.0, cache_draw_height, 0.0);
-
- switch (pid->type) {
- case PTCACHE_TYPE_SOFTBODY:
- col[0] = 1.0; col[1] = 0.4; col[2] = 0.02;
- col[3] = 0.1;
- break;
- case PTCACHE_TYPE_PARTICLES:
- col[0] = 1.0; col[1] = 0.1; col[2] = 0.02;
- col[3] = 0.1;
- break;
- case PTCACHE_TYPE_CLOTH:
- col[0] = 0.1; col[1] = 0.1; col[2] = 0.75;
- col[3] = 0.1;
- break;
- case PTCACHE_TYPE_SMOKE_DOMAIN:
- case PTCACHE_TYPE_SMOKE_HIGHRES:
- col[0] = 0.2; col[1] = 0.2; col[2] = 0.2;
- col[3] = 0.1;
- break;
- case PTCACHE_TYPE_DYNAMICPAINT:
- col[0] = 1.0; col[1] = 0.1; col[2] = 0.75;
- col[3] = 0.1;
- break;
- case PTCACHE_TYPE_RIGIDBODY:
- col[0] = 1.0; col[1] = 0.6; col[2] = 0.0;
- col[3] = 0.1;
- break;
- default:
- col[0] = 1.0; col[1] = 0.0; col[2] = 1.0;
- col[3] = 0.1;
- BLI_assert(0);
- break;
- }
- glColor4fv(col);
-
- glEnable(GL_BLEND);
-
- glRectf((float)sta, 0.0, (float)end, 1.0);
-
- col[3] = 0.4f;
- if (pid->cache->flag & PTCACHE_BAKED) {
- col[0] -= 0.4f; col[1] -= 0.4f; col[2] -= 0.4f;
- }
- else if (pid->cache->flag & PTCACHE_OUTDATED) {
- col[0] += 0.4f; col[1] += 0.4f; col[2] += 0.4f;
- }
- glColor4fv(col);
-
- glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(2, GL_FLOAT, 0, stc->array);
- glDrawArrays(GL_QUADS, 0, (fp - stc->array) / 2);
- glDisableClientState(GL_VERTEX_ARRAY);
-
- glDisable(GL_BLEND);
-
- glPopMatrix();
-
- yoffs += cache_draw_height;
-
- stc = stc->next;
- }
-
- BLI_freelistN(&pidlist);
-
- /* free excessive caches */
- while (stc) {
- SpaceTimeCache *tmp = stc->next;
- BLI_remlink(&stime->caches, stc);
- MEM_freeN(stc->array);
- MEM_freeN(stc);
- stc = tmp;
- }
+ immEnd();
+ immUnbindProgram();
}
static void time_cache_free(SpaceTime *stime)
@@ -296,7 +156,7 @@ static ActKeyColumn *time_cfra_find_ak(ActKeyColumn *ak, float cframe)
}
/* helper for time_draw_keyframes() */
-static void time_draw_idblock_keyframes(View2D *v2d, ID *id, short onlysel)
+static void time_draw_idblock_keyframes(View2D *v2d, ID *id, short onlysel, const unsigned char color[3])
{
bDopeSheet ads = {NULL};
DLRBT_Tree keys;
@@ -339,21 +199,42 @@ static void time_draw_idblock_keyframes(View2D *v2d, ID *id, short onlysel)
* the first visible keyframe (last one can then be easily checked)
* - draw within a single GL block to be faster
*/
- glBegin(GL_LINES);
- for (ak = time_cfra_find_ak(keys.root, v2d->cur.xmin);
- (ak) && (ak->cfra <= v2d->cur.xmax);
- ak = ak->next)
- {
- glVertex2f(ak->cfra, ymin);
- glVertex2f(ak->cfra, ymax);
+
+ ActKeyColumn *link;
+ int max_len = 0;
+
+ ak = time_cfra_find_ak(keys.root, v2d->cur.xmin);
+
+ for (link = ak; link; link = link->next) {
+ max_len++;
}
- glEnd(); // GL_LINES
-
+
+ if (max_len > 0) {
+
+ VertexFormat *format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor3ubv(color);
+
+ immBeginAtMost(GL_LINES, max_len * 2);
+
+ for (; (ak) && (ak->cfra <= v2d->cur.xmax);
+ ak = ak->next)
+ {
+ immVertex2f(pos, ak->cfra, ymin);
+ immVertex2f(pos, ak->cfra, ymax);
+ }
+
+ immEnd();
+ immUnbindProgram();
+ }
+
/* free temp stuff */
BLI_dlrbTree_free(&keys);
}
-static void time_draw_caches_keyframes(Main *bmain, Scene *scene, View2D *v2d, bool onlysel)
+static void time_draw_caches_keyframes(Main *bmain, Scene *scene, View2D *v2d, bool onlysel, const unsigned char color[3])
{
CacheFile *cache_file;
@@ -380,7 +261,7 @@ static void time_draw_caches_keyframes(Main *bmain, Scene *scene, View2D *v2d, b
cache_file->draw_flag |= CACHEFILE_KEYFRAME_DRAWN;
- time_draw_idblock_keyframes(v2d, (ID *)cache_file, onlysel);
+ time_draw_idblock_keyframes(v2d, (ID *)cache_file, onlysel, color);
}
for (bConstraint *con = ob->constraints.first; con; con = con->next) {
@@ -398,7 +279,7 @@ static void time_draw_caches_keyframes(Main *bmain, Scene *scene, View2D *v2d, b
cache_file->draw_flag |= CACHEFILE_KEYFRAME_DRAWN;
- time_draw_idblock_keyframes(v2d, (ID *)cache_file, onlysel);
+ time_draw_idblock_keyframes(v2d, (ID *)cache_file, onlysel, color);
}
}
}
@@ -410,21 +291,23 @@ static void time_draw_keyframes(const bContext *C, ARegion *ar)
Object *ob = CTX_data_active_object(C);
View2D *v2d = &ar->v2d;
bool onlysel = ((scene->flag & SCE_KEYS_NO_SELONLY) == 0);
+ unsigned char color[3];
/* set this for all keyframe lines once and for all */
glLineWidth(1.0);
/* draw cache files keyframes (if available) */
- UI_ThemeColor(TH_TIME_KEYFRAME);
- time_draw_caches_keyframes(CTX_data_main(C), scene, v2d, onlysel);
+ UI_GetThemeColor3ubv(TH_TIME_KEYFRAME, color);
+ time_draw_caches_keyframes(CTX_data_main(C), scene, v2d, onlysel, color);
/* draw grease pencil keyframes (if available) */
- UI_ThemeColor(TH_TIME_GP_KEYFRAME);
+ UI_GetThemeColor3ubv(TH_TIME_GP_KEYFRAME, color);
+
if (scene->gpd) {
- time_draw_idblock_keyframes(v2d, (ID *)scene->gpd, onlysel);
+ time_draw_idblock_keyframes(v2d, (ID *)scene->gpd, onlysel, color);
}
if (ob && ob->gpd) {
- time_draw_idblock_keyframes(v2d, (ID *)ob->gpd, onlysel);
+ time_draw_idblock_keyframes(v2d, (ID *)ob->gpd, onlysel, color);
}
/* draw scene keyframes first
@@ -433,8 +316,8 @@ static void time_draw_keyframes(const bContext *C, ARegion *ar)
*/
if (onlysel == 0) {
/* set draw color */
- UI_ThemeColorShade(TH_TIME_KEYFRAME, -50);
- time_draw_idblock_keyframes(v2d, (ID *)scene, onlysel);
+ UI_GetThemeColorShade3ubv(TH_TIME_KEYFRAME, -50, color);
+ time_draw_idblock_keyframes(v2d, (ID *)scene, onlysel, color);
}
/* draw keyframes from selected objects
@@ -442,11 +325,11 @@ static void time_draw_keyframes(const bContext *C, ARegion *ar)
* OR the onlysel flag was set, which means that only active object's keyframes should
* be considered
*/
- UI_ThemeColor(TH_TIME_KEYFRAME);
-
+ UI_GetThemeColor3ubv(TH_TIME_KEYFRAME, color);
+
if (ob && ((ob->mode == OB_MODE_POSE) || onlysel)) {
/* draw keyframes for active object only */
- time_draw_idblock_keyframes(v2d, (ID *)ob, onlysel);
+ time_draw_idblock_keyframes(v2d, (ID *)ob, onlysel, color);
}
else {
bool active_done = false;
@@ -455,7 +338,7 @@ static void time_draw_keyframes(const bContext *C, ARegion *ar)
CTX_DATA_BEGIN (C, Object *, obsel, selected_objects)
{
/* last arg is 0, since onlysel doesn't apply here... */
- time_draw_idblock_keyframes(v2d, (ID *)obsel, 0);
+ time_draw_idblock_keyframes(v2d, (ID *)obsel, 0, color);
/* if this object is the active one, set flag so that we don't draw again */
if (obsel == ob)
@@ -465,7 +348,7 @@ static void time_draw_keyframes(const bContext *C, ARegion *ar)
/* if active object hasn't been done yet, draw it... */
if (ob && (active_done == 0))
- time_draw_idblock_keyframes(v2d, (ID *)ob, 0);
+ time_draw_idblock_keyframes(v2d, (ID *)ob, 0, color);
}
}
@@ -494,7 +377,6 @@ static void time_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn)
case ND_BONE_ACTIVE:
case ND_POINTCACHE:
case ND_MODIFIER:
- case ND_PARTICLE:
case ND_KEYS:
ED_area_tag_refresh(sa);
ED_area_tag_redraw(sa);
@@ -569,7 +451,6 @@ static void time_main_region_draw(const bContext *C, ARegion *ar)
/* draw entirely, view changes should be handled here */
Scene *scene = CTX_data_scene(C);
SpaceTime *stime = CTX_wm_space_time(C);
- Object *obact = CTX_data_active_object(C);
View2D *v2d = &ar->v2d;
View2DGrid *grid;
View2DScrollers *scrollers;
@@ -607,9 +488,6 @@ static void time_main_region_draw(const bContext *C, ARegion *ar)
UI_view2d_view_orthoSpecial(ar, v2d, 1);
ED_markers_draw(C, 0);
- /* caches */
- time_draw_cache(stime, obact, scene);
-
/* callback */
UI_view2d_view_ortho(v2d);
ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
diff --git a/source/blender/editors/space_view3d/CMakeLists.txt b/source/blender/editors/space_view3d/CMakeLists.txt
index a5c60248bf1..8fca2ed564e 100644
--- a/source/blender/editors/space_view3d/CMakeLists.txt
+++ b/source/blender/editors/space_view3d/CMakeLists.txt
@@ -52,6 +52,7 @@ set(SRC
view3d_buttons.c
view3d_camera_control.c
view3d_draw.c
+ view3d_draw_legacy.c
view3d_edit.c
view3d_fly.c
view3d_walk.c
diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c
index 1d9a515a5f2..b37a6740891 100644
--- a/source/blender/editors/space_view3d/drawarmature.c
+++ b/source/blender/editors/space_view3d/drawarmature.c
@@ -2161,11 +2161,9 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
bone_matrix_translate_y(bmat, pchan->bone->length);
glMultMatrixf(bmat);
- glColor3ubv(col);
-
float viewmat_pchan[4][4];
mul_m4_m4m4(viewmat_pchan, rv3d->viewmatob, bmat);
- drawaxes(viewmat_pchan, pchan->bone->length * 0.25f, OB_ARROWS);
+ drawaxes(viewmat_pchan, pchan->bone->length * 0.25f, OB_ARROWS, col);
glPopMatrix();
}
@@ -2370,11 +2368,9 @@ static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, const short dt)
bone_matrix_translate_y(bmat, eBone->length);
glMultMatrixf(bmat);
- glColor3ubv(col);
-
float viewmat_ebone[4][4];
mul_m4_m4m4(viewmat_ebone, rv3d->viewmatob, bmat);
- drawaxes(viewmat_ebone, eBone->length * 0.25f, OB_ARROWS);
+ drawaxes(viewmat_ebone, eBone->length * 0.25f, OB_ARROWS, col);
glPopMatrix();
}
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index 96eec0bf48f..9605a84403d 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -37,6 +37,7 @@
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meta_types.h"
+#include "DNA_object_force.h"
#include "DNA_rigidbody_types.h"
#include "DNA_scene_types.h"
#include "DNA_smoke_types.h"
@@ -71,8 +72,6 @@
#include "BKE_movieclip.h"
#include "BKE_object.h"
#include "BKE_paint.h"
-#include "BKE_particle.h"
-#include "BKE_pointcache.h"
#include "BKE_scene.h"
#include "BKE_subsurf.h"
#include "BKE_unit.h"
@@ -90,9 +89,10 @@
#include "GPU_select.h"
#include "GPU_basic_shader.h"
#include "GPU_shader.h"
+#include "GPU_immediate.h"
+#include "GPU_matrix.h"
#include "ED_mesh.h"
-#include "ED_particle.h"
#include "ED_screen.h"
#include "ED_sculpt.h"
#include "ED_types.h"
@@ -210,10 +210,11 @@ typedef struct drawBMSelect_userData {
static void draw_bounding_volume(Object *ob, char type);
-static void drawcube_size(float size);
-static void drawcircle_size(float size);
-static void draw_empty_sphere(float size);
-static void draw_empty_cone(float size);
+static void drawcube_size(float size, unsigned pos);
+static void drawcircle_size(float size, unsigned pos);
+static void draw_empty_sphere(float size, unsigned pos);
+static void draw_empty_cone(float size, unsigned pos);
+
static void draw_box(const float vec[8][3], bool solid);
static void ob_wire_color_blend_theme_id(const unsigned char ob_wire_col[4], const int theme_id, float fac)
@@ -414,7 +415,7 @@ static const float cosval[CIRCLE_RESOL] = {
* \param viewmat_local_unit is typically the 'rv3d->viewmatob'
* copied into a 3x3 matrix and normalized.
*/
-static void draw_xyz_wire(const float viewmat_local_unit[3][3], const float c[3], float size, int axis)
+static void draw_xyz_wire(const float viewmat_local_unit[3][3], const float c[3], float size, int axis, unsigned pos)
{
int line_type;
float buffer[4][3];
@@ -501,18 +502,25 @@ static void draw_xyz_wire(const float viewmat_local_unit[3][3], const float c[3]
return;
}
+ immBegin(line_type, n);
for (int i = 0; i < n; i++) {
mul_transposed_m3_v3((float (*)[3])viewmat_local_unit, buffer[i]);
add_v3_v3(buffer[i], c);
+ immVertex3fv(pos, buffer[i]);
}
+ immEnd();
+
+ /* TODO: recode this function for clarity once we're not in a hurry to modernize GL usage */
+#if 0
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, buffer);
glDrawArrays(line_type, 0, n);
glDisableClientState(GL_VERTEX_ARRAY);
+#endif
}
-void drawaxes(const float viewmat_local[4][4], float size, char drawtype)
+void drawaxes(const float viewmat_local[4][4], float size, char drawtype, const unsigned char color[4])
{
int axis;
float v1[3] = {0.0, 0.0, 0.0};
@@ -521,34 +529,40 @@ void drawaxes(const float viewmat_local[4][4], float size, char drawtype)
glLineWidth(1);
- switch (drawtype) {
+ unsigned pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ if (color) {
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor4ubv(color);
+ }
+ else {
+ immBindBuiltinProgram(GPU_SHADER_3D_DEPTH_ONLY);
+ }
+ switch (drawtype) {
case OB_PLAINAXES:
+ immBegin(GL_LINES, 6);
for (axis = 0; axis < 3; axis++) {
- glBegin(GL_LINES);
-
v1[axis] = size;
v2[axis] = -size;
- glVertex3fv(v1);
- glVertex3fv(v2);
+ immVertex3fv(pos, v1);
+ immVertex3fv(pos, v2);
/* reset v1 & v2 to zero */
v1[axis] = v2[axis] = 0.0f;
-
- glEnd();
}
+ immEnd();
break;
- case OB_SINGLE_ARROW:
- glBegin(GL_LINES);
+ case OB_SINGLE_ARROW:
+ immBegin(GL_LINES, 2);
/* in positive z direction only */
v1[2] = size;
- glVertex3fv(v1);
- glVertex3fv(v2);
- glEnd();
+ immVertex3fv(pos, v1);
+ immVertex3fv(pos, v2);
+ immEnd();
/* square pyramid */
- glBegin(GL_TRIANGLES);
+ immBegin(GL_TRIANGLES, 12);
v2[0] = size * 0.035f; v2[1] = size * 0.035f;
v3[0] = size * -0.035f; v3[1] = size * 0.035f;
@@ -564,28 +578,27 @@ void drawaxes(const float viewmat_local[4][4], float size, char drawtype)
v3[0] = -v3[0];
}
- glVertex3fv(v1);
- glVertex3fv(v2);
- glVertex3fv(v3);
-
+ immVertex3fv(pos, v1);
+ immVertex3fv(pos, v2);
+ immVertex3fv(pos, v3);
}
- glEnd();
-
+ immEnd();
break;
+
case OB_CUBE:
- drawcube_size(size);
+ drawcube_size(size, pos);
break;
case OB_CIRCLE:
- drawcircle_size(size);
+ drawcircle_size(size, pos);
break;
case OB_EMPTY_SPHERE:
- draw_empty_sphere(size);
+ draw_empty_sphere(size, pos);
break;
case OB_EMPTY_CONE:
- draw_empty_cone(size);
+ draw_empty_cone(size, pos);
break;
case OB_ARROWS:
@@ -599,34 +612,34 @@ void drawaxes(const float viewmat_local[4][4], float size, char drawtype)
for (axis = 0; axis < 3; axis++) {
const int arrow_axis = (axis == 0) ? 1 : 0;
- glBegin(GL_LINES);
+ immBegin(GL_LINES, 6);
v2[axis] = size;
- glVertex3fv(v1);
- glVertex3fv(v2);
-
+ immVertex3fv(pos, v1);
+ immVertex3fv(pos, v2);
+
v1[axis] = size * 0.85f;
v1[arrow_axis] = -size * 0.08f;
- glVertex3fv(v1);
- glVertex3fv(v2);
-
+ immVertex3fv(pos, v1);
+ immVertex3fv(pos, v2);
+
v1[arrow_axis] = size * 0.08f;
- glVertex3fv(v1);
- glVertex3fv(v2);
+ immVertex3fv(pos, v1);
+ immVertex3fv(pos, v2);
- glEnd();
-
- v2[axis] += size * 0.125f;
+ immEnd();
- draw_xyz_wire(viewmat_local_unit, v2, size, axis);
+ v2[axis] += size * 0.125f;
+ draw_xyz_wire(viewmat_local_unit, v2, size, axis, pos);
/* reset v1 & v2 to zero */
v1[arrow_axis] = v1[axis] = v2[axis] = 0.0f;
}
- break;
}
}
+
+ immUnbindProgram();
}
@@ -634,92 +647,104 @@ void drawaxes(const float viewmat_local[4][4], float size, char drawtype)
static void draw_empty_image(Object *ob, const short dflag, const unsigned char ob_wire_col[4])
{
Image *ima = ob->data;
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, ob->iuser, NULL);
- if (ibuf && (ibuf->rect == NULL) && (ibuf->rect_float != NULL)) {
- IMB_rect_from_float(ibuf);
- }
+ const float ob_alpha = ob->col[3];
+ float width, height;
+
+ const int texUnit = GL_TEXTURE0;
+ int bindcode = 0;
- int ima_x, ima_y;
+ if (ima) {
+ if (ob_alpha > 0.0f) {
+ glActiveTexture(texUnit);
+ bindcode = GPU_verify_image(ima, ob->iuser, GL_TEXTURE_2D, 0, false, false, false, false);
+ /* don't bother drawing the image if alpha = 0 */
+ }
- /* Get the buffer dimensions so we can fallback to fake ones */
- if (ibuf && ibuf->rect) {
- ima_x = ibuf->x;
- ima_y = ibuf->y;
+ int w, h;
+ BKE_image_get_size(ima, ob->iuser, &w, &h);
+ width = w;
+ height = h;
}
else {
- ima_x = 1;
- ima_y = 1;
+ /* if no image, make it a 1x1 empty square, honor scale & offset */
+ width = height = 1.0f;
}
- float sca_x = 1.0f;
- float sca_y = 1.0f;
+ const float aspect = height / width;
- /* Get the image aspect even if the buffer is invalid */
- if (ima) {
- if (ima->aspx > ima->aspy) {
- sca_y = ima->aspy / ima->aspx;
- }
- else if (ima->aspx < ima->aspy) {
- sca_x = ima->aspx / ima->aspy;
- }
- }
+ float left = ob->ima_ofs[0];
+ float right = ob->ima_ofs[0] + ob->empty_drawsize;
+ float top = ob->ima_ofs[1] + ob->empty_drawsize * aspect;
+ float bottom = ob->ima_ofs[1];
- /* Calculate the scale center based on object's origin */
- float ofs_x = ob->ima_ofs[0] * ima_x;
- float ofs_y = ob->ima_ofs[1] * ima_y;
+ bool use_blend = false;
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
+ if (bindcode) {
+ use_blend = ob_alpha < 1.0f || BKE_image_has_alpha(ima);
+
+ if (use_blend) {
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
- /* Calculate Image scale */
- float scale = ob->empty_drawsize / max_ff((float)ima_x * sca_x, (float)ima_y * sca_y);
+ VertexFormat *format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ unsigned texCoord = add_attrib(format, "texCoord", GL_FLOAT, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_IMAGE_MODULATE_ALPHA);
+ immUniform1f("alpha", ob_alpha);
+ immUniform1i("image", texUnit);
- /* Set the object scale */
- glScalef(scale * sca_x, scale * sca_y, 1.0f);
+ immBegin(GL_TRIANGLE_FAN, 4);
+ immAttrib2f(texCoord, 0.0f, 0.0f);
+ immVertex2f(pos, left, bottom);
- if (ibuf && ibuf->rect) {
- const bool use_clip = (U.glalphaclip != 1.0f);
- int zoomfilter = (U.gameflags & USER_DISABLE_MIPMAP) ? GL_NEAREST : GL_LINEAR;
- /* Setup GL params */
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ immAttrib2f(texCoord, 1.0f, 0.0f);
+ immVertex2f(pos, right, bottom);
- if (use_clip) {
- glEnable(GL_ALPHA_TEST);
- glAlphaFunc(GL_GREATER, U.glalphaclip);
- }
+ immAttrib2f(texCoord, 1.0f, 1.0f);
+ immVertex2f(pos, right, top);
- /* Use the object color and alpha */
- glColor4fv(ob->col);
+ immAttrib2f(texCoord, 0.0f, 1.0f);
+ immVertex2f(pos, left, top);
+ immEnd();
- /* Draw the Image on the screen */
- glaDrawPixelsTex(ofs_x, ofs_y, ima_x, ima_y, GL_RGBA, GL_UNSIGNED_BYTE, zoomfilter, ibuf->rect);
+ immUnbindProgram();
- glDisable(GL_BLEND);
+ glBindTexture(GL_TEXTURE_2D, 0); /* necessary? */
+ }
- if (use_clip) {
- glDisable(GL_ALPHA_TEST);
- glAlphaFunc(GL_ALWAYS, 0.0f);
+ /* Draw the image outline */
+ glLineWidth(1.5f);
+ unsigned pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+
+ const bool picking = dflag & DRAW_CONSTCOLOR;
+ if (picking) {
+ /* TODO: deal with picking separately, use this function just to draw */
+ immBindBuiltinProgram(GPU_SHADER_3D_DEPTH_ONLY);
+ if (use_blend) {
+ glDisable(GL_BLEND);
}
- }
- if ((dflag & DRAW_CONSTCOLOR) == 0) {
- glColor3ubv(ob_wire_col);
+ imm_draw_line_box(pos, left, bottom, right, top);
}
+ else {
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor3ubv(ob_wire_col);
+ glEnable(GL_LINE_SMOOTH);
- /* Calculate the outline vertex positions */
- glBegin(GL_LINE_LOOP);
- glVertex2f(ofs_x, ofs_y);
- glVertex2f(ofs_x + ima_x, ofs_y);
- glVertex2f(ofs_x + ima_x, ofs_y + ima_y);
- glVertex2f(ofs_x, ofs_y + ima_y);
- glEnd();
+ if (!use_blend) {
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
- /* Reset GL settings */
- glPopMatrix();
+ imm_draw_line_box(pos, left, bottom, right, top);
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ glDisable(GL_LINE_SMOOTH);
+ glDisable(GL_BLEND);
+ }
+
+ immUnbindProgram();
}
static void circball_array_fill(float verts[CIRCLE_RESOL][3], const float cent[3], float rad, const float tmat[4][4])
@@ -749,50 +774,65 @@ void drawcircball(int mode, const float cent[3], float rad, const float tmat[4][
glDisableClientState(GL_VERTEX_ARRAY);
}
+void imm_drawcircball(const float cent[3], float rad, const float tmat[4][4], unsigned pos)
+{
+ float verts[CIRCLE_RESOL][3];
+
+ circball_array_fill(verts, cent, rad, tmat);
+
+ immBegin(GL_LINE_LOOP, CIRCLE_RESOL);
+ for (int i = 0; i < CIRCLE_RESOL; ++i) {
+ immVertex3fv(pos, verts[i]);
+ }
+ immEnd();
+}
+
/* circle for object centers, special_color is for library or ob users */
static void drawcentercircle(View3D *v3d, RegionView3D *rv3d, const float co[3], int selstate, bool special_color)
{
- const float size = ED_view3d_pixel_size(rv3d, co) * (float)U.obcenter_dia * 0.5f;
- float verts[CIRCLE_RESOL][3];
+ const float outlineWidth = 1.0f * U.pixelsize;
+ const float size = U.obcenter_dia * U.pixelsize + outlineWidth;
+
+ if (v3d->zbuf) {
+ glDisable(GL_DEPTH_TEST);
+ /* TODO(merwin): fit things like this into plates/buffers design */
+ }
- /* using glDepthFunc guarantees that it does write z values,
- * but not checks for it, so centers remain visible independent of draw order */
- if (v3d->zbuf) glDepthFunc(GL_ALWAYS);
- /* write to near buffer always */
- glDepthRange(0.0, 0.0);
glEnable(GL_BLEND);
-
+ GPU_enable_program_point_size();
+
+ unsigned pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_SMOOTH);
+ immUniform1f("size", size);
+
if (special_color) {
- if (selstate == ACTIVE || selstate == SELECT) glColor4ub(0x88, 0xFF, 0xFF, 155);
- else glColor4ub(0x55, 0xCC, 0xCC, 155);
+ if (selstate == ACTIVE || selstate == SELECT) immUniformColor4ub(0x88, 0xFF, 0xFF, 155);
+ else immUniformColor4ub(0x55, 0xCC, 0xCC, 155);
}
else {
- if (selstate == ACTIVE) UI_ThemeColorShadeAlpha(TH_ACTIVE, 0, -80);
- else if (selstate == SELECT) UI_ThemeColorShadeAlpha(TH_SELECT, 0, -80);
- else if (selstate == DESELECT) UI_ThemeColorShadeAlpha(TH_TRANSFORM, 0, -80);
+ if (selstate == ACTIVE) immUniformThemeColorShadeAlpha(TH_ACTIVE, 0, -80);
+ else if (selstate == SELECT) immUniformThemeColorShadeAlpha(TH_SELECT, 0, -80);
+ else if (selstate == DESELECT) immUniformThemeColorShadeAlpha(TH_TRANSFORM, 0, -80);
}
- circball_array_fill(verts, co, size, rv3d->viewinv);
-
- /* enable vertex array */
- glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(3, GL_FLOAT, 0, verts);
+ /* set up outline */
+ float outlineColor[4];
+ UI_GetThemeColorShadeAlpha4fv(TH_WIRE, 0, -30, outlineColor);
+ immUniform4fv("outlineColor", outlineColor);
+ immUniform1f("outlineWidth", outlineWidth);
- /* 1. draw filled, blended polygon */
- glDrawArrays(GL_POLYGON, 0, CIRCLE_RESOL);
+ immBegin(GL_POINTS, 1);
+ immVertex3fv(pos, co);
+ immEnd();
- /* 2. draw outline */
- glLineWidth(1);
- UI_ThemeColorShadeAlpha(TH_WIRE, 0, -30);
- glDrawArrays(GL_LINE_LOOP, 0, CIRCLE_RESOL);
+ immUnbindProgram();
- /* finish up */
- glDisableClientState(GL_VERTEX_ARRAY);
-
- glDepthRange(0.0, 1.0);
+ GPU_disable_program_point_size();
glDisable(GL_BLEND);
- if (v3d->zbuf) glDepthFunc(GL_LEQUAL);
+ if (v3d->zbuf) {
+ glEnable(GL_DEPTH_TEST);
+ }
}
/* *********** text drawing for object/particles/armature ************* */
@@ -964,9 +1004,9 @@ void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, bool depth_write, flo
/* draws a cube given the scaling of the cube, assuming that
* all required matrices have been set (used for drawing empties)
*/
-static void drawcube_size(float size)
+static void drawcube_size(float size, unsigned pos)
{
- const GLfloat pos[8][3] = {
+ const GLfloat verts[8][3] = {
{-size, -size, -size},
{-size, -size, size},
{-size, size, -size},
@@ -979,10 +1019,18 @@ static void drawcube_size(float size)
const GLubyte indices[24] = {0,1,1,3,3,2,2,0,0,4,4,5,5,7,7,6,6,4,1,5,3,7,2,6};
+#if 0
glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(3, GL_FLOAT, 0, pos);
+ glVertexPointer(3, GL_FLOAT, 0, verts);
glDrawRangeElements(GL_LINES, 0, 7, 24, GL_UNSIGNED_BYTE, indices);
glDisableClientState(GL_VERTEX_ARRAY);
+#else
+ immBegin(GL_LINES, 24);
+ for (int i = 0; i < 24; ++i) {
+ immVertex3fv(pos, verts[indices[i]]);
+ }
+ immEnd();
+#endif
}
static void drawshadbuflimits(Lamp *la, float mat[4][4])
@@ -1170,8 +1218,8 @@ static void draw_transp_sun_volume(Lamp *la)
}
#endif
-static void drawlamp(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
- const char dt, const short dflag, const unsigned char ob_wire_col[4], const bool is_obact)
+void drawlamp(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
+ const char dt, const short dflag, const unsigned char ob_wire_col[4], const bool is_obact)
{
Object *ob = base->object;
const float pixsize = ED_view3d_pixel_size(rv3d, ob->obmat[3]);
@@ -1209,7 +1257,7 @@ static void drawlamp(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
if ((drawcone || drawshadowbox) && !v3d->transp) {
/* in this case we need to draw delayed */
- ED_view3d_after_add(v3d->xray ? &v3d->afterdraw_xraytransp : &v3d->afterdraw_transp, base, dflag);
+ ED_view3d_after_add(&v3d->afterdraw_transp, base, dflag);
return;
}
@@ -1552,36 +1600,38 @@ static void drawlamp(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
glPopMatrix();
}
-static void draw_limit_line(float sta, float end, const short dflag, const unsigned char col[3])
+static void draw_limit_line(float sta, float end, const short dflag, const unsigned char col[3], unsigned pos)
{
- glBegin(GL_LINES);
- glVertex3f(0.0, 0.0, -sta);
- glVertex3f(0.0, 0.0, -end);
- glEnd();
+ immBegin(GL_LINES, 2);
+ immVertex3f(pos, 0.0, 0.0, -sta);
+ immVertex3f(pos, 0.0, 0.0, -end);
+ immEnd();
if (!(dflag & DRAW_PICKING)) {
glPointSize(3.0);
- glBegin(GL_POINTS);
+ /* would like smooth round points here, but that means binding another shader...
+ * if it's really desired, pull these points into their own function to be called after */
+ immBegin(GL_POINTS, 2);
if ((dflag & DRAW_CONSTCOLOR) == 0) {
- glColor3ubv(col);
+ immUniformColor3ubv(col);
}
- glVertex3f(0.0, 0.0, -sta);
- glVertex3f(0.0, 0.0, -end);
- glEnd();
+ immVertex3f(pos, 0.0, 0.0, -sta);
+ immVertex3f(pos, 0.0, 0.0, -end);
+ immEnd();
}
}
/* yafray: draw camera focus point (cross, similar to aqsis code in tuhopuu) */
/* qdn: now also enabled for Blender to set focus point for defocus composite node */
-static void draw_focus_cross(float dist, float size)
+static void draw_focus_cross(float dist, float size, unsigned pos)
{
- glBegin(GL_LINES);
- glVertex3f(-size, 0.0f, -dist);
- glVertex3f(size, 0.0f, -dist);
- glVertex3f(0.0f, -size, -dist);
- glVertex3f(0.0f, size, -dist);
- glEnd();
+ immBegin(GL_LINES, 4);
+ immVertex3f(pos, -size, 0.0f, -dist);
+ immVertex3f(pos, size, 0.0f, -dist);
+ immVertex3f(pos, 0.0f, -size, -dist);
+ immVertex3f(pos, 0.0f, size, -dist);
+ immEnd();
}
#ifdef VIEW3D_CAMERA_BORDER_HACK
@@ -1677,16 +1727,19 @@ static void draw_viewport_object_reconstruction(
const int v3d_drawtype = view3d_effective_drawtype(v3d);
if (v3d_drawtype == OB_WIRE) {
+ unsigned char color[4];
+ const unsigned char *color_ptr = NULL;
if ((dflag & DRAW_CONSTCOLOR) == 0) {
if (selected && (track->flag & TRACK_CUSTOMCOLOR) == 0) {
- glColor3ubv(ob_wire_col);
+ color_ptr = ob_wire_col;
}
else {
- glColor3fv(track->color);
+ rgba_float_to_uchar(color, track->color);
+ color_ptr = color;
}
}
- drawaxes(rv3d->viewmatob, 0.05f, v3d->bundle_drawtype);
+ drawaxes(rv3d->viewmatob, 0.05f, v3d->bundle_drawtype, color_ptr);
}
else if (v3d_drawtype > OB_WIRE) {
if (v3d->bundle_drawtype == OB_EMPTY_SPHERE) {
@@ -1712,17 +1765,21 @@ static void draw_viewport_object_reconstruction(
draw_bundle_sphere();
}
else {
+ unsigned char color[4];
+ const unsigned char *color_ptr = NULL;
if ((dflag & DRAW_CONSTCOLOR) == 0) {
if (selected) {
- glColor3ubv(ob_wire_col);
+ color_ptr = ob_wire_col;
}
else {
- if (track->flag & TRACK_CUSTOMCOLOR) glColor3fv(track->color);
- else UI_ThemeColor(TH_WIRE);
+ if (track->flag & TRACK_CUSTOMCOLOR) rgba_float_to_uchar(color, track->color);
+ else UI_GetThemeColor4ubv(TH_WIRE, color);
+
+ color_ptr = color;
}
}
- drawaxes(rv3d->viewmatob, 0.05f, v3d->bundle_drawtype);
+ drawaxes(rv3d->viewmatob, 0.05f, v3d->bundle_drawtype, color_ptr);
}
}
@@ -1804,59 +1861,68 @@ static void draw_viewport_reconstruction(
GPU_select_load_id(base->selcol);
}
-static void drawcamera_volume(float near_plane[4][3], float far_plane[4][3], const GLenum mode)
-{
- glBegin(mode);
- glVertex3fv(near_plane[0]);
- glVertex3fv(far_plane[0]);
- glVertex3fv(far_plane[1]);
- glVertex3fv(near_plane[1]);
- glEnd();
-
- glBegin(mode);
- glVertex3fv(near_plane[1]);
- glVertex3fv(far_plane[1]);
- glVertex3fv(far_plane[2]);
- glVertex3fv(near_plane[2]);
- glEnd();
-
- glBegin(mode);
- glVertex3fv(near_plane[2]);
- glVertex3fv(near_plane[1]);
- glVertex3fv(far_plane[1]);
- glVertex3fv(far_plane[2]);
- glEnd();
-
- glBegin(mode);
- glVertex3fv(far_plane[0]);
- glVertex3fv(near_plane[0]);
- glVertex3fv(near_plane[3]);
- glVertex3fv(far_plane[3]);
- glEnd();
-}
-
/* camera frame */
-static void drawcamera_frame(float vec[4][3], const GLenum mode)
+static void drawcamera_frame(float vec[4][3], bool filled, unsigned pos)
{
- glBegin(mode);
- glVertex3fv(vec[0]);
- glVertex3fv(vec[1]);
- glVertex3fv(vec[2]);
- glVertex3fv(vec[3]);
- glEnd();
+ immBegin(filled ? GL_QUADS : GL_LINE_LOOP, 4);
+ immVertex3fv(pos, vec[0]);
+ immVertex3fv(pos, vec[1]);
+ immVertex3fv(pos, vec[2]);
+ immVertex3fv(pos, vec[3]);
+ immEnd();
}
/* center point to camera frame */
-static void drawcamera_framelines(float vec[4][3], float origin[3])
-{
- glBegin(GL_LINE_STRIP);
- glVertex3fv(vec[1]);
- glVertex3fv(origin);
- glVertex3fv(vec[0]);
- glVertex3fv(vec[3]);
- glVertex3fv(origin);
- glVertex3fv(vec[2]);
- glEnd();
+static void drawcamera_framelines(float vec[4][3], float origin[3], unsigned pos)
+{
+ immBegin(GL_LINES, 8);
+ immVertex3fv(pos, origin);
+ immVertex3fv(pos, vec[0]);
+ immVertex3fv(pos, origin);
+ immVertex3fv(pos, vec[1]);
+ immVertex3fv(pos, origin);
+ immVertex3fv(pos, vec[2]);
+ immVertex3fv(pos, origin);
+ immVertex3fv(pos, vec[3]);
+ immEnd();
+}
+
+static void drawcamera_volume(float near_plane[4][3], float far_plane[4][3], bool filled, unsigned pos)
+{
+ drawcamera_frame(near_plane, filled, pos);
+ drawcamera_frame(far_plane, filled, pos);
+
+ if (filled) {
+ immBegin(GL_QUADS, 16); /* TODO(merwin): use GL_TRIANGLE_STRIP here */
+ immVertex3fv(pos, near_plane[0]);
+ immVertex3fv(pos, far_plane[0]);
+ immVertex3fv(pos, far_plane[1]);
+ immVertex3fv(pos, near_plane[1]);
+
+ immVertex3fv(pos, near_plane[1]);
+ immVertex3fv(pos, far_plane[1]);
+ immVertex3fv(pos, far_plane[2]);
+ immVertex3fv(pos, near_plane[2]);
+
+ immVertex3fv(pos, near_plane[2]);
+ immVertex3fv(pos, near_plane[1]);
+ immVertex3fv(pos, far_plane[1]);
+ immVertex3fv(pos, far_plane[2]);
+
+ immVertex3fv(pos, far_plane[0]);
+ immVertex3fv(pos, near_plane[0]);
+ immVertex3fv(pos, near_plane[3]);
+ immVertex3fv(pos, far_plane[3]);
+ immEnd();
+ }
+ else {
+ immBegin(GL_LINES, 8);
+ for (int i = 0; i < 4; ++i) {
+ immVertex3fv(pos, near_plane[i]);
+ immVertex3fv(pos, far_plane[i]);
+ }
+ immEnd();
+ }
}
static bool drawcamera_is_stereo3d(Scene *scene, View3D *v3d, Object *ob)
@@ -1868,7 +1934,7 @@ static bool drawcamera_is_stereo3d(Scene *scene, View3D *v3d, Object *ob)
static void drawcamera_stereo3d(
Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, const Camera *cam,
- float vec[4][3], float drawsize, const float scale[3])
+ float vec[4][3], float drawsize, const float scale[3], unsigned pos)
{
float obmat[4][4];
float vec_lr[2][4][3];
@@ -1884,15 +1950,15 @@ static void drawcamera_stereo3d(
zero_v3(tvec);
- glPushMatrix();
+ /* caller bound GPU_SHADER_3D_UNIFORM_COLOR, passed in pos attribute ID */
for (int i = 0; i < 2; i++) {
ob = BKE_camera_multiview_render(scene, ob, names[i]);
cam_lr[i] = ob->data;
- glLoadMatrixf(rv3d->viewmat);
+ gpuLoadMatrix3D(rv3d->viewmat);
BKE_camera_multiview_model_matrix(&scene->r, ob, names[i], obmat);
- glMultMatrixf(obmat);
+ gpuMultMatrix3D(obmat);
copy_m3_m3(vec_lr[i], vec);
copy_v3_v3(vec_lr[i][3], vec[3]);
@@ -1909,10 +1975,10 @@ static void drawcamera_stereo3d(
if (is_stereo3d_cameras) {
/* camera frame */
- drawcamera_frame(vec_lr[i], GL_LINE_LOOP);
+ drawcamera_frame(vec_lr[i], false, pos);
/* center point to camera frame */
- drawcamera_framelines(vec_lr[i], tvec);
+ drawcamera_framelines(vec_lr[i], tvec, pos);
}
/* connecting line */
@@ -1926,21 +1992,21 @@ static void drawcamera_stereo3d(
}
}
-
/* the remaining drawing takes place in the view space */
- glLoadMatrixf(rv3d->viewmat);
+ gpuLoadMatrix3D(rv3d->viewmat);
if (is_stereo3d_cameras) {
/* draw connecting lines */
- GPU_basic_shader_bind_enable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
- GPU_basic_shader_line_stipple(2, 0xAAAA);
+ glPushAttrib(GL_ENABLE_BIT); /* TODO(merwin): new state tracking! */
+ glLineStipple(2, 0xAAAA);
+ glEnable(GL_LINE_STIPPLE);
- glBegin(GL_LINES);
- glVertex3fv(origin[0]);
- glVertex3fv(origin[1]);
- glEnd();
+ immBegin(GL_LINES, 2);
+ immVertex3fv(pos, origin[0]);
+ immVertex3fv(pos, origin[1]);
+ immEnd();
- GPU_basic_shader_bind_disable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
+ glPopAttrib();
}
/* draw convergence plane */
@@ -1965,18 +2031,18 @@ static void drawcamera_stereo3d(
add_v3_v3(local_plane[i], axis_center);
}
- glColor3f(0.0f, 0.0f, 0.0f);
+ immUniformColor3f(0.0f, 0.0f, 0.0f);
/* camera frame */
- drawcamera_frame(local_plane, GL_LINE_LOOP);
+ drawcamera_frame(local_plane, false, pos);
if (v3d->stereo3d_convergence_alpha > 0.0f) {
glEnable(GL_BLEND);
glDepthMask(0); /* disable write in zbuffer, needed for nice transp */
- glColor4f(0.0f, 0.0f, 0.0f, v3d->stereo3d_convergence_alpha);
+ immUniformColor4f(0.0f, 0.0f, 0.0f, v3d->stereo3d_convergence_alpha);
- drawcamera_frame(local_plane, GL_QUADS);
+ drawcamera_frame(local_plane, true, pos);
glDisable(GL_BLEND);
glDepthMask(1); /* restore write in zbuffer */
@@ -2004,32 +2070,26 @@ static void drawcamera_stereo3d(
}
/* camera frame */
- glColor3f(0.0f, 0.0f, 0.0f);
+ immUniformColor3f(0.0f, 0.0f, 0.0f);
- drawcamera_frame(near_plane, GL_LINE_LOOP);
- drawcamera_frame(far_plane, GL_LINE_LOOP);
- drawcamera_volume(near_plane, far_plane, GL_LINE_LOOP);
+ drawcamera_volume(near_plane, far_plane, false, pos);
if (v3d->stereo3d_volume_alpha > 0.0f) {
glEnable(GL_BLEND);
glDepthMask(0); /* disable write in zbuffer, needed for nice transp */
if (i == 0)
- glColor4f(0.0f, 1.0f, 1.0f, v3d->stereo3d_volume_alpha);
+ immUniformColor4f(0.0f, 1.0f, 1.0f, v3d->stereo3d_volume_alpha);
else
- glColor4f(1.0f, 0.0f, 0.0f, v3d->stereo3d_volume_alpha);
+ immUniformColor4f(1.0f, 0.0f, 0.0f, v3d->stereo3d_volume_alpha);
- drawcamera_frame(near_plane, GL_QUADS);
- drawcamera_frame(far_plane, GL_QUADS);
- drawcamera_volume(near_plane, far_plane, GL_QUADS);
+ drawcamera_volume(near_plane, far_plane, true, pos);
glDisable(GL_BLEND);
glDepthMask(1); /* restore write in zbuffer */
}
}
}
-
- glPopMatrix();
}
/* flag similar to draw_object() */
@@ -2097,6 +2157,13 @@ static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base
BKE_camera_view_frame_ex(scene, cam, cam->drawsize, is_view, scale,
asp, shift, &drawsize, vec);
+ gpuMatrixBegin3D_legacy();
+
+ unsigned pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ if (ob_wire_col) {
+ immUniformColor3ubv(ob_wire_col);
+ }
glDisable(GL_CULL_FACE);
glLineWidth(1);
@@ -2107,27 +2174,30 @@ static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base
float obmat[4][4];
bool is_left = v3d->multiview_eye == STEREO_LEFT_ID;
- glPushMatrix();
- glLoadMatrixf(rv3d->viewmat);
+ gpuPushMatrix();
+ gpuLoadMatrix3D(rv3d->viewmat);
BKE_camera_multiview_model_matrix(&scene->r, ob, is_left ? STEREO_LEFT_NAME : STEREO_RIGHT_NAME, obmat);
- glMultMatrixf(obmat);
+ gpuMultMatrix3D(obmat);
- drawcamera_frame(vec, GL_LINE_LOOP);
- glPopMatrix();
+ drawcamera_frame(vec, false, pos);
+ gpuPopMatrix();
}
else {
- drawcamera_frame(vec, GL_LINE_LOOP);
+ drawcamera_frame(vec, false, pos);
}
}
- if (is_view)
+ if (is_view) {
+ immUnbindProgram();
+ gpuMatrixEnd();
return;
+ }
zero_v3(tvec);
/* center point to camera frame */
if (!is_stereo3d_cameras)
- drawcamera_framelines(vec, tvec);
+ drawcamera_framelines(vec, tvec, pos);
/* arrow on top */
tvec[2] = vec[1][2]; /* copy the depth */
@@ -2136,22 +2206,22 @@ static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base
* for active cameras. We actually draw both outline+filled
* for active cameras so the wire can be seen side-on */
for (int i = 0; i < 2; i++) {
- if (i == 0) glBegin(GL_LINE_LOOP);
- else if (i == 1 && is_active) glBegin(GL_TRIANGLES);
+ if (i == 0) immBegin(GL_LINE_LOOP, 3);
+ else if (i == 1 && is_active) immBegin(GL_TRIANGLES, 3);
else break;
tvec[0] = shift[0] + ((-0.7f * drawsize) * scale[0]);
tvec[1] = shift[1] + ((drawsize * (asp[1] + 0.1f)) * scale[1]);
- glVertex3fv(tvec); /* left */
+ immVertex3fv(pos, tvec); /* left */
tvec[0] = shift[0] + ((0.7f * drawsize) * scale[0]);
- glVertex3fv(tvec); /* right */
+ immVertex3fv(pos, tvec); /* right */
tvec[0] = shift[0];
tvec[1] = shift[1] + ((1.1f * drawsize * (asp[1] + 0.7f)) * scale[1]);
- glVertex3fv(tvec); /* top */
+ immVertex3fv(pos, tvec); /* top */
- glEnd();
+ immEnd();
}
if ((dflag & DRAW_SCENESET) == 0) {
@@ -2162,16 +2232,15 @@ static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base
copy_m4_m4(nobmat, ob->obmat);
normalize_m4(nobmat);
- glPushMatrix();
- glLoadMatrixf(rv3d->viewmat);
- glMultMatrixf(nobmat);
+ gpuLoadMatrix3D(rv3d->viewmat);
+ gpuMultMatrix3D(nobmat);
if (cam->flag & CAM_SHOWLIMITS) {
const unsigned char col[3] = {128, 128, 60}, col_hi[3] = {255, 255, 120};
- draw_limit_line(cam->clipsta, cam->clipend, dflag, (is_active ? col_hi : col));
+ draw_limit_line(cam->clipsta, cam->clipend, dflag, (is_active ? col_hi : col), pos);
/* qdn: was yafray only, now also enabled for Blender to be used with defocus composite node */
- draw_focus_cross(BKE_camera_object_dof_distance(ob), cam->drawsize);
+ draw_focus_cross(BKE_camera_object_dof_distance(ob), cam->drawsize, pos);
}
if (cam->flag & CAM_SHOWMIST) {
@@ -2180,57 +2249,66 @@ static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base
if (world) {
draw_limit_line(world->miststa, world->miststa + world->mistdist,
- dflag, (is_active ? col_hi : col));
+ dflag, (is_active ? col_hi : col), pos);
}
}
- glPopMatrix();
}
}
/* stereo cameras drawing */
if (is_stereo3d) {
- drawcamera_stereo3d(scene, v3d, rv3d, ob, cam, vec, drawsize, scale);
+ drawcamera_stereo3d(scene, v3d, rv3d, ob, cam, vec, drawsize, scale, pos);
}
+
+ immUnbindProgram();
+ gpuMatrixEnd();
}
/* flag similar to draw_object() */
-static void drawspeaker(Scene *UNUSED(scene), View3D *UNUSED(v3d), RegionView3D *UNUSED(rv3d),
- Object *UNUSED(ob), int UNUSED(flag))
+static void drawspeaker(const unsigned char ob_wire_col[3])
{
- float vec[3];
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+
+ if (ob_wire_col) {
+ immUniformColor3ubv(ob_wire_col);
+ }
- glEnable(GL_BLEND);
glLineWidth(1);
+ const int segments = 16;
+
for (int j = 0; j < 3; j++) {
- vec[2] = 0.25f * j - 0.125f;
+ float z = 0.25f * j - 0.125f;
- glBegin(GL_LINE_LOOP);
- for (int i = 0; i < 16; i++) {
- vec[0] = cosf((float)M_PI * i / 8.0f) * (j == 0 ? 0.5f : 0.25f);
- vec[1] = sinf((float)M_PI * i / 8.0f) * (j == 0 ? 0.5f : 0.25f);
- glVertex3fv(vec);
+ immBegin(GL_LINE_LOOP, segments);
+ for (int i = 0; i < segments; i++) {
+ float x = cosf((float)M_PI * i / 8.0f) * (j == 0 ? 0.5f : 0.25f);
+ float y = sinf((float)M_PI * i / 8.0f) * (j == 0 ? 0.5f : 0.25f);
+ immVertex3f(pos, x, y, z);
}
- glEnd();
+ immEnd();
}
for (int j = 0; j < 4; j++) {
- vec[0] = (((j + 1) % 2) * (j - 1)) * 0.5f;
- vec[1] = ((j % 2) * (j - 2)) * 0.5f;
- glBegin(GL_LINE_STRIP);
+ float x = (((j + 1) % 2) * (j - 1)) * 0.5f;
+ float y = ((j % 2) * (j - 2)) * 0.5f;
+ immBegin(GL_LINE_STRIP, 3);
for (int i = 0; i < 3; i++) {
if (i == 1) {
- vec[0] *= 0.5f;
- vec[1] *= 0.5f;
+ x *= 0.5f;
+ y *= 0.5f;
}
- vec[2] = 0.25f * i - 0.125f;
- glVertex3fv(vec);
+ float z = 0.25f * i - 0.125f;
+ immVertex3f(pos, x, y, z);
}
- glEnd();
+ immEnd();
}
- glDisable(GL_BLEND);
+ immUnbindProgram();
}
static void lattice_draw_verts(Lattice *lt, DispList *dl, BPoint *actbp, short sel)
@@ -3930,7 +4008,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d,
/* Mesh drawing routines */
-static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm)
+void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm)
{
if ((v3d->transp == false) && /* not when we draw the transparent pass */
(ob->mode & OB_MODE_ALL_PAINT) == false) /* not when painting (its distracting) - campbell */
@@ -4177,12 +4255,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
* with the background. */
if ((dflag & DRAW_CONSTCOLOR) == 0) {
- if (is_obact && (ob->mode & OB_MODE_PARTICLE_EDIT)) {
- ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.15f);
- }
- else {
- glColor3ubv(ob_wire_col);
- }
+ glColor3ubv(ob_wire_col);
}
/* If drawing wire and drawtype is not OB_WIRE then we are
@@ -4235,7 +4308,7 @@ static bool draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3
/* If we are drawing shadows and any of the materials don't cast a shadow,
* then don't draw the object */
if (v3d->flag2 & V3D_RENDER_SHADOW) {
- for (int i = 1; i <= ob->totcol; ++i) {
+ for (int i = 0; i < ob->totcol; ++i) {
Material *ma = give_current_material(ob, i);
if (ma && !(ma->mode2 & MA_CASTSHADOW)) {
return true;
@@ -4780,1113 +4853,6 @@ static bool drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *ba
}
/* *********** drawing for particles ************* */
-static void draw_particle_arrays(int draw_as, int totpoint, int ob_dt, int select)
-{
- /* draw created data arrays */
- switch (draw_as) {
- case PART_DRAW_AXIS:
- case PART_DRAW_CROSS:
- glDrawArrays(GL_LINES, 0, 6 * totpoint);
- break;
- case PART_DRAW_LINE:
- glDrawArrays(GL_LINES, 0, 2 * totpoint);
- break;
- case PART_DRAW_BB:
- if (ob_dt <= OB_WIRE || select)
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
- else
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
-
- glDrawArrays(GL_QUADS, 0, 4 * totpoint);
- break;
- default:
- glDrawArrays(GL_POINTS, 0, totpoint);
- break;
- }
-}
-static void draw_particle(ParticleKey *state, int draw_as, short draw, float pixsize,
- float imat[4][4], const float draw_line[2], ParticleBillboardData *bb, ParticleDrawData *pdd)
-{
- float vec[3], vec2[3];
- float *vd = NULL;
- float *cd = NULL;
- float ma_col[3] = {0.0f, 0.0f, 0.0f};
-
- /* null only for PART_DRAW_CIRC */
- if (pdd) {
- vd = pdd->vd;
- cd = pdd->cd;
-
- if (pdd->ma_col) {
- copy_v3_v3(ma_col, pdd->ma_col);
- }
- }
-
- switch (draw_as) {
- case PART_DRAW_DOT:
- {
- if (vd) {
- copy_v3_v3(vd, state->co); pdd->vd += 3;
- }
- if (cd) {
- copy_v3_v3(cd, pdd->ma_col);
- pdd->cd += 3;
- }
- break;
- }
- case PART_DRAW_CROSS:
- case PART_DRAW_AXIS:
- {
- vec[0] = 2.0f * pixsize;
- vec[1] = vec[2] = 0.0;
- mul_qt_v3(state->rot, vec);
- if (draw_as == PART_DRAW_AXIS) {
- if (cd) {
- cd[1] = cd[2] = cd[4] = cd[5] = 0.0;
- cd[0] = cd[3] = 1.0;
- cd[6] = cd[8] = cd[9] = cd[11] = 0.0;
- cd[7] = cd[10] = 1.0;
- cd[13] = cd[12] = cd[15] = cd[16] = 0.0;
- cd[14] = cd[17] = 1.0;
- pdd->cd += 18;
- }
-
- copy_v3_v3(vec2, state->co);
- }
- else {
- if (cd) {
- cd[0] = cd[3] = cd[6] = cd[9] = cd[12] = cd[15] = ma_col[0];
- cd[1] = cd[4] = cd[7] = cd[10] = cd[13] = cd[16] = ma_col[1];
- cd[2] = cd[5] = cd[8] = cd[11] = cd[14] = cd[17] = ma_col[2];
- pdd->cd += 18;
- }
- sub_v3_v3v3(vec2, state->co, vec);
- }
-
- add_v3_v3(vec, state->co);
- copy_v3_v3(pdd->vd, vec); pdd->vd += 3;
- copy_v3_v3(pdd->vd, vec2); pdd->vd += 3;
-
- vec[1] = 2.0f * pixsize;
- vec[0] = vec[2] = 0.0;
- mul_qt_v3(state->rot, vec);
- if (draw_as == PART_DRAW_AXIS) {
- copy_v3_v3(vec2, state->co);
- }
- else {
- sub_v3_v3v3(vec2, state->co, vec);
- }
-
- add_v3_v3(vec, state->co);
- copy_v3_v3(pdd->vd, vec); pdd->vd += 3;
- copy_v3_v3(pdd->vd, vec2); pdd->vd += 3;
-
- vec[2] = 2.0f * pixsize;
- vec[0] = vec[1] = 0.0f;
- mul_qt_v3(state->rot, vec);
- if (draw_as == PART_DRAW_AXIS) {
- copy_v3_v3(vec2, state->co);
- }
- else {
- sub_v3_v3v3(vec2, state->co, vec);
- }
-
- add_v3_v3(vec, state->co);
-
- copy_v3_v3(pdd->vd, vec); pdd->vd += 3;
- copy_v3_v3(pdd->vd, vec2); pdd->vd += 3;
- break;
- }
- case PART_DRAW_LINE:
- {
- copy_v3_v3(vec, state->vel);
- normalize_v3(vec);
- if (draw & PART_DRAW_VEL_LENGTH)
- mul_v3_fl(vec, len_v3(state->vel));
- madd_v3_v3v3fl(pdd->vd, state->co, vec, -draw_line[0]); pdd->vd += 3;
- madd_v3_v3v3fl(pdd->vd, state->co, vec, draw_line[1]); pdd->vd += 3;
- if (cd) {
- cd[0] = cd[3] = ma_col[0];
- cd[1] = cd[4] = ma_col[1];
- cd[2] = cd[5] = ma_col[2];
- pdd->cd += 6;
- }
- break;
- }
- case PART_DRAW_CIRC:
- {
- drawcircball(GL_LINE_LOOP, state->co, pixsize, imat);
- break;
- }
- case PART_DRAW_BB:
- {
- float xvec[3], yvec[3], zvec[3], bb_center[3];
- if (cd) {
- cd[0] = cd[3] = cd[6] = cd[9] = ma_col[0];
- cd[1] = cd[4] = cd[7] = cd[10] = ma_col[1];
- cd[2] = cd[5] = cd[8] = cd[11] = ma_col[2];
- pdd->cd += 12;
- }
-
- copy_v3_v3(bb->vec, state->co);
- copy_v3_v3(bb->vel, state->vel);
-
- psys_make_billboard(bb, xvec, yvec, zvec, bb_center);
-
- add_v3_v3v3(pdd->vd, bb_center, xvec);
- add_v3_v3(pdd->vd, yvec); pdd->vd += 3;
-
- sub_v3_v3v3(pdd->vd, bb_center, xvec);
- add_v3_v3(pdd->vd, yvec); pdd->vd += 3;
-
- sub_v3_v3v3(pdd->vd, bb_center, xvec);
- sub_v3_v3v3(pdd->vd, pdd->vd, yvec); pdd->vd += 3;
-
- add_v3_v3v3(pdd->vd, bb_center, xvec);
- sub_v3_v3v3(pdd->vd, pdd->vd, yvec); pdd->vd += 3;
-
- copy_v3_v3(pdd->nd, zvec); pdd->nd += 3;
- copy_v3_v3(pdd->nd, zvec); pdd->nd += 3;
- copy_v3_v3(pdd->nd, zvec); pdd->nd += 3;
- copy_v3_v3(pdd->nd, zvec); pdd->nd += 3;
- break;
- }
- }
-}
-static void draw_particle_data(ParticleSystem *psys, RegionView3D *rv3d,
- ParticleKey *state, int draw_as,
- float imat[4][4], ParticleBillboardData *bb, ParticleDrawData *pdd,
- const float ct, const float pa_size, const float r_tilt, const float pixsize_scale)
-{
- ParticleSettings *part = psys->part;
- float pixsize;
-
- if (psys->parent)
- mul_m4_v3(psys->parent->obmat, state->co);
-
- /* create actual particle data */
- if (draw_as == PART_DRAW_BB) {
- bb->offset[0] = part->bb_offset[0];
- bb->offset[1] = part->bb_offset[1];
- bb->size[0] = part->bb_size[0] * pa_size;
- if (part->bb_align == PART_BB_VEL) {
- float pa_vel = len_v3(state->vel);
- float head = part->bb_vel_head * pa_vel;
- float tail = part->bb_vel_tail * pa_vel;
- bb->size[1] = part->bb_size[1] * pa_size + head + tail;
- /* use offset to adjust the particle center. this is relative to size, so need to divide! */
- if (bb->size[1] > 0.0f)
- bb->offset[1] += (head - tail) / bb->size[1];
- }
- else {
- bb->size[1] = part->bb_size[1] * pa_size;
- }
- bb->tilt = part->bb_tilt * (1.0f - part->bb_rand_tilt * r_tilt);
- bb->time = ct;
- }
-
- pixsize = ED_view3d_pixel_size(rv3d, state->co) * pixsize_scale;
-
- draw_particle(state, draw_as, part->draw, pixsize, imat, part->draw_line, bb, pdd);
-}
-/* unified drawing of all new particle systems draw types except dupli ob & group
- * mostly tries to use vertex arrays for speed
- *
- * 1. check that everything is ok & updated
- * 2. start initializing things
- * 3. initialize according to draw type
- * 4. allocate drawing data arrays
- * 5. start filling the arrays
- * 6. draw the arrays
- * 7. clean up
- */
-static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv3d,
- Base *base, ParticleSystem *psys,
- const char ob_dt, const short dflag)
-{
- Object *ob = base->object;
- ParticleEditSettings *pset = PE_settings(scene);
- ParticleSettings *part = psys->part;
- ParticleData *pars = psys->particles;
- ParticleData *pa;
- ParticleKey state, *states = NULL;
- ParticleBillboardData bb;
- ParticleSimulationData sim = {NULL};
- ParticleDrawData *pdd = psys->pdd;
- Material *ma;
- float vel[3], imat[4][4];
- float timestep, pixsize_scale = 1.0f, pa_size, r_tilt, r_length;
- float pa_time, pa_birthtime, pa_dietime, pa_health, intensity;
- float cfra;
- float ma_col[3] = {0.0f, 0.0f, 0.0f};
- int a, totpart, totpoint = 0, totve = 0, drawn, draw_as, totchild = 0;
- bool select = (ob->flag & SELECT) != 0, create_cdata = false, need_v = false;
- GLint polygonmode[2];
- char numstr[32];
- unsigned char tcol[4] = {0, 0, 0, 255};
-
-/* 1. */
- if (part == NULL || !psys_check_enabled(ob, psys, G.is_rendering))
- return;
-
- if (pars == NULL) return;
-
- /* don't draw normal paths in edit mode */
- if (psys_in_edit_mode(scene, psys) && (pset->flag & PE_DRAW_PART) == 0)
- return;
-
- if (part->draw_as == PART_DRAW_REND)
- draw_as = part->ren_as;
- else
- draw_as = part->draw_as;
-
- if (draw_as == PART_DRAW_NOT)
- return;
-
- /* prepare curvemapping tables */
- if ((psys->part->child_flag & PART_CHILD_USE_CLUMP_CURVE) && psys->part->clumpcurve)
- curvemapping_changed_all(psys->part->clumpcurve);
- if ((psys->part->child_flag & PART_CHILD_USE_ROUGH_CURVE) && psys->part->roughcurve)
- curvemapping_changed_all(psys->part->roughcurve);
-
-/* 2. */
- sim.scene = scene;
- sim.ob = ob;
- sim.psys = psys;
- sim.psmd = psys_get_modifier(ob, psys);
-
- if (part->phystype == PART_PHYS_KEYED) {
- if (psys->flag & PSYS_KEYED) {
- psys_count_keyed_targets(&sim);
- if (psys->totkeyed == 0)
- return;
- }
- }
-
- if (select) {
- select = false;
- if (psys_get_current(ob) == psys)
- select = true;
- }
-
- psys->flag |= PSYS_DRAWING;
-
- if (part->type == PART_HAIR && !psys->childcache)
- totchild = 0;
- else
- totchild = psys->totchild * part->disp / 100;
-
- ma = give_current_material(ob, part->omat);
-
- if (v3d->zbuf) glDepthMask(1);
-
- if ((ma) && (part->draw_col == PART_DRAW_COL_MAT)) {
- rgb_float_to_uchar(tcol, &(ma->r));
- copy_v3_v3(ma_col, &ma->r);
- }
-
- if ((dflag & DRAW_CONSTCOLOR) == 0) {
- glColor3ubv(tcol);
- }
-
- timestep = psys_get_timestep(&sim);
-
- if ((base->flag & OB_FROMDUPLI) && (ob->flag & OB_FROMGROUP)) {
- float mat[4][4];
- mul_m4_m4m4(mat, ob->obmat, psys->imat);
- glMultMatrixf(mat);
- }
-
- /* needed for text display */
- invert_m4_m4(ob->imat, ob->obmat);
-
- totpart = psys->totpart;
-
- cfra = BKE_scene_frame_get(scene);
-
- if (draw_as == PART_DRAW_PATH && psys->pathcache == NULL && psys->childcache == NULL)
- draw_as = PART_DRAW_DOT;
-
-/* 3. */
- glLineWidth(1.0f);
-
- switch (draw_as) {
- case PART_DRAW_DOT:
- if (part->draw_size)
- glPointSize(part->draw_size);
- else
- glPointSize(2.0); /* default dot size */
- break;
- case PART_DRAW_CIRC:
- /* calculate view aligned matrix: */
- copy_m4_m4(imat, rv3d->viewinv);
- normalize_v3(imat[0]);
- normalize_v3(imat[1]);
- /* fall-through */
- case PART_DRAW_CROSS:
- case PART_DRAW_AXIS:
- /* lets calculate the scale: */
-
- if (part->draw_size == 0.0)
- pixsize_scale = 2.0f;
- else
- pixsize_scale = part->draw_size;
-
- if (draw_as == PART_DRAW_AXIS)
- create_cdata = 1;
- break;
- case PART_DRAW_OB:
- if (part->dup_ob == NULL)
- draw_as = PART_DRAW_DOT;
- else
- draw_as = 0;
- break;
- case PART_DRAW_GR:
- if (part->dup_group == NULL)
- draw_as = PART_DRAW_DOT;
- else
- draw_as = 0;
- break;
- case PART_DRAW_BB:
- if (v3d->camera == NULL && part->bb_ob == NULL) {
- printf("Billboards need an active camera or a target object!\n");
-
- draw_as = part->draw_as = PART_DRAW_DOT;
-
- if (part->draw_size)
- glPointSize(part->draw_size);
- else
- glPointSize(2.0); /* default dot size */
- }
- else if (part->bb_ob)
- bb.ob = part->bb_ob;
- else
- bb.ob = v3d->camera;
-
- bb.align = part->bb_align;
- bb.anim = part->bb_anim;
- bb.lock = part->draw & PART_DRAW_BB_LOCK;
- break;
- case PART_DRAW_PATH:
- break;
- case PART_DRAW_LINE:
- need_v = 1;
- break;
- }
- if (part->draw & PART_DRAW_SIZE && part->draw_as != PART_DRAW_CIRC) {
- copy_m4_m4(imat, rv3d->viewinv);
- normalize_v3(imat[0]);
- normalize_v3(imat[1]);
- }
-
- if (ELEM(draw_as, PART_DRAW_DOT, PART_DRAW_CROSS, PART_DRAW_LINE) &&
- (part->draw_col > PART_DRAW_COL_MAT))
- {
- create_cdata = 1;
- }
-
- if (!create_cdata && pdd && pdd->cdata) {
- MEM_freeN(pdd->cdata);
- pdd->cdata = pdd->cd = NULL;
- }
-
-/* 4. */
- if (draw_as && ELEM(draw_as, PART_DRAW_PATH, PART_DRAW_CIRC) == 0) {
- int tot_vec_size = (totpart + totchild) * 3 * sizeof(float);
- int create_ndata = 0;
-
- if (!pdd)
- pdd = psys->pdd = MEM_callocN(sizeof(ParticleDrawData), "ParticleDrawData");
-
- if (part->draw_as == PART_DRAW_REND && part->trail_count > 1) {
- tot_vec_size *= part->trail_count;
- psys_make_temp_pointcache(ob, psys);
- }
-
- switch (draw_as) {
- case PART_DRAW_AXIS:
- case PART_DRAW_CROSS:
- tot_vec_size *= 6;
- if (draw_as != PART_DRAW_CROSS)
- create_cdata = 1;
- break;
- case PART_DRAW_LINE:
- tot_vec_size *= 2;
- break;
- case PART_DRAW_BB:
- tot_vec_size *= 4;
- create_ndata = 1;
- break;
- }
-
- if (pdd->tot_vec_size != tot_vec_size)
- psys_free_pdd(psys);
-
- if (!pdd->vdata)
- pdd->vdata = MEM_callocN(tot_vec_size, "particle_vdata");
- if (create_cdata && !pdd->cdata)
- pdd->cdata = MEM_callocN(tot_vec_size, "particle_cdata");
- if (create_ndata && !pdd->ndata)
- pdd->ndata = MEM_callocN(tot_vec_size, "particle_ndata");
-
- if (part->draw & PART_DRAW_VEL && draw_as != PART_DRAW_LINE) {
- if (!pdd->vedata)
- pdd->vedata = MEM_callocN(2 * (totpart + totchild) * 3 * sizeof(float), "particle_vedata");
-
- need_v = 1;
- }
- else if (pdd->vedata) {
- /* velocity data not needed, so free it */
- MEM_freeN(pdd->vedata);
- pdd->vedata = NULL;
- }
-
- pdd->vd = pdd->vdata;
- pdd->ved = pdd->vedata;
- pdd->cd = pdd->cdata;
- pdd->nd = pdd->ndata;
- pdd->tot_vec_size = tot_vec_size;
- }
- else if (psys->pdd) {
- psys_free_pdd(psys);
- MEM_freeN(psys->pdd);
- pdd = psys->pdd = NULL;
- }
-
- if (pdd) {
- pdd->ma_col = ma_col;
- }
-
- psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
-
- /* circles don't use drawdata, so have to add a special case here */
- if ((pdd || draw_as == PART_DRAW_CIRC) && draw_as != PART_DRAW_PATH) {
- /* 5. */
- if (pdd && (pdd->flag & PARTICLE_DRAW_DATA_UPDATED) &&
- (pdd->vedata || part->draw & (PART_DRAW_SIZE | PART_DRAW_NUM | PART_DRAW_HEALTH)) == 0)
- {
- totpoint = pdd->totpoint; /* draw data is up to date */
- }
- else {
- for (a = 0, pa = pars; a < totpart + totchild; a++, pa++) {
- /* setup per particle individual stuff */
- if (a < totpart) {
- if (totchild && (part->draw & PART_DRAW_PARENT) == 0) continue;
- if (pa->flag & PARS_NO_DISP || pa->flag & PARS_UNEXIST) continue;
-
- pa_time = (cfra - pa->time) / pa->lifetime;
- pa_birthtime = pa->time;
- pa_dietime = pa->dietime;
- pa_size = pa->size;
- if (part->phystype == PART_PHYS_BOIDS)
- pa_health = pa->boid->data.health;
- else
- pa_health = -1.0;
-
- r_tilt = 2.0f * (psys_frand(psys, a + 21) - 0.5f);
- r_length = psys_frand(psys, a + 22);
-
- if (part->draw_col > PART_DRAW_COL_MAT) {
- switch (part->draw_col) {
- case PART_DRAW_COL_VEL:
- intensity = len_v3(pa->state.vel) / part->color_vec_max;
- break;
- case PART_DRAW_COL_ACC:
- intensity = len_v3v3(pa->state.vel, pa->prev_state.vel) / ((pa->state.time - pa->prev_state.time) * part->color_vec_max);
- break;
- default:
- intensity = 1.0f; /* should never happen */
- BLI_assert(0);
- break;
- }
- CLAMP(intensity, 0.0f, 1.0f);
- weight_to_rgb(ma_col, intensity);
- }
- }
- else {
- ChildParticle *cpa = &psys->child[a - totpart];
-
- pa_time = psys_get_child_time(psys, cpa, cfra, &pa_birthtime, &pa_dietime);
- pa_size = psys_get_child_size(psys, cpa, cfra, NULL);
-
- pa_health = -1.0;
-
- r_tilt = 2.0f * (psys_frand(psys, a + 21) - 0.5f);
- r_length = psys_frand(psys, a + 22);
- }
-
- drawn = 0;
- if (part->draw_as == PART_DRAW_REND && part->trail_count > 1) {
- float length = part->path_end * (1.0f - part->randlength * r_length);
- int trail_count = part->trail_count * (1.0f - part->randlength * r_length);
- float ct = ((part->draw & PART_ABS_PATH_TIME) ? cfra : pa_time) - length;
- float dt = length / (trail_count ? (float)trail_count : 1.0f);
- int i = 0;
-
- ct += dt;
- for (i = 0; i < trail_count; i++, ct += dt) {
-
- if (part->draw & PART_ABS_PATH_TIME) {
- if (ct < pa_birthtime || ct > pa_dietime)
- continue;
- }
- else if (ct < 0.0f || ct > 1.0f)
- continue;
-
- state.time = (part->draw & PART_ABS_PATH_TIME) ? -ct : -(pa_birthtime + ct * (pa_dietime - pa_birthtime));
- psys_get_particle_on_path(&sim, a, &state, need_v);
-
- draw_particle_data(psys, rv3d,
- &state, draw_as, imat, &bb, psys->pdd,
- ct, pa_size, r_tilt, pixsize_scale);
-
- totpoint++;
- drawn = 1;
- }
- }
- else {
- state.time = cfra;
- if (psys_get_particle_state(&sim, a, &state, 0)) {
-
- draw_particle_data(psys, rv3d,
- &state, draw_as, imat, &bb, psys->pdd,
- pa_time, pa_size, r_tilt, pixsize_scale);
-
- totpoint++;
- drawn = 1;
- }
- }
-
- if (drawn) {
- /* additional things to draw for each particle
- * (velocity, size and number) */
- if ((part->draw & PART_DRAW_VEL) && pdd && pdd->vedata) {
- copy_v3_v3(pdd->ved, state.co);
- pdd->ved += 3;
- mul_v3_v3fl(vel, state.vel, timestep);
- add_v3_v3v3(pdd->ved, state.co, vel);
- pdd->ved += 3;
-
- totve++;
- }
-
- if (part->draw & PART_DRAW_SIZE) {
- setlinestyle(3);
- drawcircball(GL_LINE_LOOP, state.co, pa_size, imat);
- setlinestyle(0);
- }
-
-
- if ((part->draw & PART_DRAW_NUM || part->draw & PART_DRAW_HEALTH) &&
- (v3d->flag2 & V3D_RENDER_OVERRIDE) == 0)
- {
- size_t numstr_len;
- float vec_txt[3];
- char *val_pos = numstr;
- numstr[0] = '\0';
-
- if (part->draw & PART_DRAW_NUM) {
- if (a < totpart && (part->draw & PART_DRAW_HEALTH) && (part->phystype == PART_PHYS_BOIDS)) {
- numstr_len = BLI_snprintf_rlen(val_pos, sizeof(numstr), "%d:%.2f", a, pa_health);
- }
- else {
- numstr_len = BLI_snprintf_rlen(val_pos, sizeof(numstr), "%d", a);
- }
- }
- else {
- if (a < totpart && (part->draw & PART_DRAW_HEALTH) && (part->phystype == PART_PHYS_BOIDS)) {
- numstr_len = BLI_snprintf_rlen(val_pos, sizeof(numstr), "%.2f", pa_health);
- }
- }
-
- if (numstr[0]) {
- /* in path drawing state.co is the end point
- * use worldspace because object matrix is already applied */
- mul_v3_m4v3(vec_txt, ob->imat, state.co);
- view3d_cached_text_draw_add(vec_txt, numstr, numstr_len,
- 10, V3D_CACHE_TEXT_WORLDSPACE | V3D_CACHE_TEXT_ASCII, tcol);
- }
- }
- }
- }
- }
- }
-/* 6. */
-
- glGetIntegerv(GL_POLYGON_MODE, polygonmode);
- glEnableClientState(GL_VERTEX_ARRAY);
-
- if (draw_as == PART_DRAW_PATH) {
- ParticleCacheKey **cache, *path;
- float *cdata2 = NULL;
-
- /* setup gl flags */
- if (1) { //ob_dt > OB_WIRE) {
- glEnableClientState(GL_NORMAL_ARRAY);
-
- if ((dflag & DRAW_CONSTCOLOR) == 0) {
- if (part->draw_col == PART_DRAW_COL_MAT)
- glEnableClientState(GL_COLOR_ARRAY);
- }
-
- // XXX test
- GPU_basic_shader_colors(NULL, NULL, 0.0f, 1.0f);
- GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_USE_COLOR);
- }
-
- if (totchild && (part->draw & PART_DRAW_PARENT) == 0)
- totpart = 0;
- else if (psys->pathcache == NULL)
- totpart = 0;
-
- /* draw actual/parent particles */
- cache = psys->pathcache;
- for (a = 0, pa = psys->particles; a < totpart; a++, pa++) {
- path = cache[a];
- if (path->segments > 0) {
- glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->co);
-
- if (1) { //ob_dt > OB_WIRE) {
- glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), path->vel);
- if ((dflag & DRAW_CONSTCOLOR) == 0) {
- if (part->draw_col == PART_DRAW_COL_MAT) {
- glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->col);
- }
- }
- }
-
- glDrawArrays(GL_LINE_STRIP, 0, path->segments + 1);
- }
- }
-
- if (part->type == PART_HAIR) {
- if (part->draw & PART_DRAW_GUIDE_HAIRS) {
- DerivedMesh *hair_dm = psys->hair_out_dm;
-
- glDisableClientState(GL_NORMAL_ARRAY);
- glDisableClientState(GL_COLOR_ARRAY);
-
- for (a = 0, pa = psys->particles; a < totpart; a++, pa++) {
- if (pa->totkey > 1) {
- HairKey *hkey = pa->hair;
-
- glVertexPointer(3, GL_FLOAT, sizeof(HairKey), hkey->world_co);
-
-#if 0 /* XXX use proper theme color here */
- UI_ThemeColor(TH_NORMAL);
-#else
- glColor3f(0.58f, 0.67f, 1.0f);
-#endif
-
- glDrawArrays(GL_LINE_STRIP, 0, pa->totkey);
- }
- }
-
- if (hair_dm) {
- MVert *mvert = hair_dm->getVertArray(hair_dm);
- int i;
-
- glColor3f(0.9f, 0.4f, 0.4f);
-
- glBegin(GL_LINES);
- for (a = 0, pa = psys->particles; a < totpart; a++, pa++) {
- for (i = 1; i < pa->totkey; ++i) {
- float v1[3], v2[3];
-
- copy_v3_v3(v1, mvert[pa->hair_index + i - 1].co);
- copy_v3_v3(v2, mvert[pa->hair_index + i].co);
-
- mul_m4_v3(ob->obmat, v1);
- mul_m4_v3(ob->obmat, v2);
-
- glVertex3fv(v1);
- glVertex3fv(v2);
- }
- }
- glEnd();
- }
-
- glEnableClientState(GL_NORMAL_ARRAY);
- if ((dflag & DRAW_CONSTCOLOR) == 0)
- if (part->draw_col == PART_DRAW_COL_MAT)
- glEnableClientState(GL_COLOR_ARRAY);
- }
-
- if (part->draw & PART_DRAW_HAIR_GRID) {
- ClothModifierData *clmd = psys->clmd;
- if (clmd) {
- float *gmin = clmd->hair_grid_min;
- float *gmax = clmd->hair_grid_max;
- int *res = clmd->hair_grid_res;
- int i;
-
- glDisableClientState(GL_NORMAL_ARRAY);
- glDisableClientState(GL_COLOR_ARRAY);
-
- if (select)
- UI_ThemeColor(TH_ACTIVE);
- else
- UI_ThemeColor(TH_WIRE);
- glBegin(GL_LINES);
- glVertex3f(gmin[0], gmin[1], gmin[2]); glVertex3f(gmax[0], gmin[1], gmin[2]);
- glVertex3f(gmax[0], gmin[1], gmin[2]); glVertex3f(gmax[0], gmax[1], gmin[2]);
- glVertex3f(gmax[0], gmax[1], gmin[2]); glVertex3f(gmin[0], gmax[1], gmin[2]);
- glVertex3f(gmin[0], gmax[1], gmin[2]); glVertex3f(gmin[0], gmin[1], gmin[2]);
-
- glVertex3f(gmin[0], gmin[1], gmax[2]); glVertex3f(gmax[0], gmin[1], gmax[2]);
- glVertex3f(gmax[0], gmin[1], gmax[2]); glVertex3f(gmax[0], gmax[1], gmax[2]);
- glVertex3f(gmax[0], gmax[1], gmax[2]); glVertex3f(gmin[0], gmax[1], gmax[2]);
- glVertex3f(gmin[0], gmax[1], gmax[2]); glVertex3f(gmin[0], gmin[1], gmax[2]);
-
- glVertex3f(gmin[0], gmin[1], gmin[2]); glVertex3f(gmin[0], gmin[1], gmax[2]);
- glVertex3f(gmax[0], gmin[1], gmin[2]); glVertex3f(gmax[0], gmin[1], gmax[2]);
- glVertex3f(gmin[0], gmax[1], gmin[2]); glVertex3f(gmin[0], gmax[1], gmax[2]);
- glVertex3f(gmax[0], gmax[1], gmin[2]); glVertex3f(gmax[0], gmax[1], gmax[2]);
- glEnd();
-
- if (select)
- UI_ThemeColorShadeAlpha(TH_ACTIVE, 0, -100);
- else
- UI_ThemeColorShadeAlpha(TH_WIRE, 0, -100);
- glEnable(GL_BLEND);
- glBegin(GL_LINES);
- for (i = 1; i < res[0] - 1; ++i) {
- float f = interpf(gmax[0], gmin[0], (float)i / (float)(res[0] - 1));
- glVertex3f(f, gmin[1], gmin[2]); glVertex3f(f, gmax[1], gmin[2]);
- glVertex3f(f, gmax[1], gmin[2]); glVertex3f(f, gmax[1], gmax[2]);
- glVertex3f(f, gmax[1], gmax[2]); glVertex3f(f, gmin[1], gmax[2]);
- glVertex3f(f, gmin[1], gmax[2]); glVertex3f(f, gmin[1], gmin[2]);
- }
- for (i = 1; i < res[1] - 1; ++i) {
- float f = interpf(gmax[1], gmin[1], (float)i / (float)(res[1] - 1));
- glVertex3f(gmin[0], f, gmin[2]); glVertex3f(gmax[0], f, gmin[2]);
- glVertex3f(gmax[0], f, gmin[2]); glVertex3f(gmax[0], f, gmax[2]);
- glVertex3f(gmax[0], f, gmax[2]); glVertex3f(gmin[0], f, gmax[2]);
- glVertex3f(gmin[0], f, gmax[2]); glVertex3f(gmin[0], f, gmin[2]);
- }
- for (i = 1; i < res[2] - 1; ++i) {
- float f = interpf(gmax[2], gmin[2], (float)i / (float)(res[2] - 1));
- glVertex3f(gmin[0], gmin[1], f); glVertex3f(gmax[0], gmin[1], f);
- glVertex3f(gmax[0], gmin[1], f); glVertex3f(gmax[0], gmax[1], f);
- glVertex3f(gmax[0], gmax[1], f); glVertex3f(gmin[0], gmax[1], f);
- glVertex3f(gmin[0], gmax[1], f); glVertex3f(gmin[0], gmin[1], f);
- }
- glEnd();
- glDisable(GL_BLEND);
-
- glEnableClientState(GL_NORMAL_ARRAY);
- if ((dflag & DRAW_CONSTCOLOR) == 0)
- if (part->draw_col == PART_DRAW_COL_MAT)
- glEnableClientState(GL_COLOR_ARRAY);
- }
- }
- }
-
- /* draw child particles */
- cache = psys->childcache;
- for (a = 0; a < totchild; a++) {
- path = cache[a];
- glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->co);
-
- if (1) { //ob_dt > OB_WIRE) {
- glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), path->vel);
- if ((dflag & DRAW_CONSTCOLOR) == 0) {
- if (part->draw_col == PART_DRAW_COL_MAT) {
- glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->col);
- }
- }
- }
-
- glDrawArrays(GL_LINE_STRIP, 0, path->segments + 1);
- }
-
- /* restore & clean up */
- if (1) { //ob_dt > OB_WIRE) {
- if (part->draw_col == PART_DRAW_COL_MAT)
- glDisableClientState(GL_COLOR_ARRAY);
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
- }
-
- if (cdata2) {
- MEM_freeN(cdata2);
- cdata2 = NULL;
- }
-
- if ((part->draw & PART_DRAW_NUM) && (v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) {
- cache = psys->pathcache;
-
- for (a = 0, pa = psys->particles; a < totpart; a++, pa++) {
- float vec_txt[3];
- size_t numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%i", a);
- /* use worldspace because object matrix is already applied */
- mul_v3_m4v3(vec_txt, ob->imat, cache[a]->co);
- view3d_cached_text_draw_add(vec_txt, numstr, numstr_len,
- 10, V3D_CACHE_TEXT_WORLDSPACE | V3D_CACHE_TEXT_ASCII, tcol);
- }
- }
- }
- else if (pdd && ELEM(draw_as, 0, PART_DRAW_CIRC) == 0) {
- glDisableClientState(GL_COLOR_ARRAY);
-
- /* enable point data array */
- if (pdd->vdata) {
- glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(3, GL_FLOAT, 0, pdd->vdata);
- }
- else
- glDisableClientState(GL_VERTEX_ARRAY);
-
- if ((dflag & DRAW_CONSTCOLOR) == 0) {
- if (select) {
- UI_ThemeColor(TH_ACTIVE);
-
- if (part->draw_size)
- glPointSize(part->draw_size + 2);
- else
- glPointSize(4.0);
-
- glLineWidth(3.0);
-
- draw_particle_arrays(draw_as, totpoint, ob_dt, 1);
- }
-
- /* restore from select */
- glColor3fv(ma_col);
- }
-
- glPointSize(part->draw_size ? part->draw_size : 2.0);
- glLineWidth(1.0);
-
- /* enable other data arrays */
-
- /* billboards are drawn this way */
- if (pdd->ndata && ob_dt > OB_WIRE) {
- glEnableClientState(GL_NORMAL_ARRAY);
- glNormalPointer(GL_FLOAT, 0, pdd->ndata);
- GPU_basic_shader_colors(NULL, NULL, 0.0f, 1.0f);
- GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_USE_COLOR);
- }
-
- if ((dflag & DRAW_CONSTCOLOR) == 0) {
- if (pdd->cdata) {
- glEnableClientState(GL_COLOR_ARRAY);
- glColorPointer(3, GL_FLOAT, 0, pdd->cdata);
- }
- }
-
- draw_particle_arrays(draw_as, totpoint, ob_dt, 0);
-
- pdd->flag |= PARTICLE_DRAW_DATA_UPDATED;
- pdd->totpoint = totpoint;
- }
-
- if (pdd && pdd->vedata) {
- if ((dflag & DRAW_CONSTCOLOR) == 0) {
- glDisableClientState(GL_COLOR_ARRAY);
- cpack(0xC0C0C0);
- }
-
- glVertexPointer(3, GL_FLOAT, 0, pdd->vedata);
-
- glDrawArrays(GL_LINES, 0, 2 * totve);
- }
-
- glPolygonMode(GL_FRONT, polygonmode[0]);
- glPolygonMode(GL_BACK, polygonmode[1]);
-
-/* 7. */
-
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
- glDisableClientState(GL_COLOR_ARRAY);
- glDisableClientState(GL_VERTEX_ARRAY);
- glDisableClientState(GL_NORMAL_ARRAY);
-
- if (states)
- MEM_freeN(states);
-
- psys->flag &= ~PSYS_DRAWING;
-
- /* draw data can't be saved for billboards as they must update to target changes */
- if (draw_as == PART_DRAW_BB) {
- psys_free_pdd(psys);
- pdd->flag &= ~PARTICLE_DRAW_DATA_UPDATED;
- }
-
- if (psys->lattice_deform_data) {
- end_latt_deform(psys->lattice_deform_data);
- psys->lattice_deform_data = NULL;
- }
-
- if (pdd) {
- /* drop references to stack memory */
- pdd->ma_col = NULL;
- }
-
- if ((base->flag & OB_FROMDUPLI) && (ob->flag & OB_FROMGROUP)) {
- glLoadMatrixf(rv3d->viewmat);
- }
-}
-
-static void draw_update_ptcache_edit(Scene *scene, Object *ob, PTCacheEdit *edit)
-{
- if (edit->psys && edit->psys->flag & PSYS_HAIR_UPDATED)
- PE_update_object(scene, ob, 0);
-
- /* create path and child path cache if it doesn't exist already */
- if (edit->pathcache == NULL)
- psys_cache_edit_paths(scene, ob, edit, CFRA, G.is_rendering);
-}
-
-static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit)
-{
- ParticleCacheKey **cache, *path, *pkey;
- PTCacheEditPoint *point;
- PTCacheEditKey *key;
- ParticleEditSettings *pset = PE_settings(scene);
- int i, k, totpoint = edit->totpoint, timed = (pset->flag & PE_FADE_TIME) ? pset->fade_frames : 0;
- int totkeys = 1;
- float sel_col[3];
- float nosel_col[3];
- float *pathcol = NULL, *pcol;
-
- if (edit->pathcache == NULL)
- return;
-
- PE_hide_keys_time(scene, edit, CFRA);
-
- /* opengl setup */
- if ((v3d->flag & V3D_ZBUF_SELECT) == 0)
- glDisable(GL_DEPTH_TEST);
-
- /* get selection theme colors */
- UI_GetThemeColor3fv(TH_VERTEX_SELECT, sel_col);
- UI_GetThemeColor3fv(TH_VERTEX, nosel_col);
-
- /* draw paths */
- totkeys = (*edit->pathcache)->segments + 1;
-
- glEnable(GL_BLEND);
- pathcol = MEM_callocN(totkeys * 4 * sizeof(float), "particle path color data");
-
- glEnableClientState(GL_VERTEX_ARRAY);
- glEnableClientState(GL_COLOR_ARRAY);
-
- if (pset->brushtype == PE_BRUSH_WEIGHT)
- glLineWidth(2.0f);
-
- cache = edit->pathcache;
- for (i = 0, point = edit->points; i < totpoint; i++, point++) {
- path = cache[i];
- glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->co);
-
- if (point->flag & PEP_HIDE) {
- for (k = 0, pcol = pathcol; k < totkeys; k++, pcol += 4) {
- copy_v3_v3(pcol, path->col);
- pcol[3] = 0.25f;
- }
-
- glColorPointer(4, GL_FLOAT, 4 * sizeof(float), pathcol);
- }
- else if (timed) {
- for (k = 0, pcol = pathcol, pkey = path; k < totkeys; k++, pkey++, pcol += 4) {
- copy_v3_v3(pcol, pkey->col);
- pcol[3] = 1.0f - fabsf((float)(CFRA) -pkey->time) / (float)pset->fade_frames;
- }
-
- glColorPointer(4, GL_FLOAT, 4 * sizeof(float), pathcol);
- }
- else
- glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->col);
-
- glDrawArrays(GL_LINE_STRIP, 0, path->segments + 1);
- }
-
- if (pathcol) { MEM_freeN(pathcol); pathcol = pcol = NULL; }
-
-
- /* draw edit vertices */
- if (pset->selectmode != SCE_SELECT_PATH) {
- glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
-
- if (pset->selectmode == SCE_SELECT_POINT) {
- float *pd = NULL, *pdata = NULL;
- float *cd = NULL, *cdata = NULL;
- int totkeys_visible = 0;
-
- for (i = 0, point = edit->points; i < totpoint; i++, point++)
- if (!(point->flag & PEP_HIDE))
- totkeys_visible += point->totkey;
-
- if (totkeys_visible) {
- if (edit->points && !(edit->points->keys->flag & PEK_USE_WCO))
- pd = pdata = MEM_callocN(totkeys_visible * 3 * sizeof(float), "particle edit point data");
- cd = cdata = MEM_callocN(totkeys_visible * (timed ? 4 : 3) * sizeof(float), "particle edit color data");
- }
-
- for (i = 0, point = edit->points; i < totpoint; i++, point++) {
- if (point->flag & PEP_HIDE)
- continue;
-
- for (k = 0, key = point->keys; k < point->totkey; k++, key++) {
- if (pd) {
- copy_v3_v3(pd, key->co);
- pd += 3;
- }
-
- if (key->flag & PEK_SELECT) {
- copy_v3_v3(cd, sel_col);
- }
- else {
- copy_v3_v3(cd, nosel_col);
- }
-
- if (timed)
- *(cd + 3) = 1.0f - fabsf((float)CFRA - *key->time) / (float)pset->fade_frames;
-
- cd += (timed ? 4 : 3);
- }
- }
- cd = cdata;
- pd = pdata;
- for (i = 0, point = edit->points; i < totpoint; i++, point++) {
- if (point->flag & PEP_HIDE || point->totkey == 0)
- continue;
-
- if (point->keys->flag & PEK_USE_WCO)
- glVertexPointer(3, GL_FLOAT, sizeof(PTCacheEditKey), point->keys->world_co);
- else
- glVertexPointer(3, GL_FLOAT, 3 * sizeof(float), pd);
-
- glColorPointer((timed ? 4 : 3), GL_FLOAT, (timed ? 4 : 3) * sizeof(float), cd);
-
- glDrawArrays(GL_POINTS, 0, point->totkey);
-
- pd += pd ? 3 * point->totkey : 0;
- cd += (timed ? 4 : 3) * point->totkey;
- }
- if (pdata) { MEM_freeN(pdata); pd = pdata = NULL; }
- if (cdata) { MEM_freeN(cdata); cd = cdata = NULL; }
- }
- else if (pset->selectmode == SCE_SELECT_END) {
- glBegin(GL_POINTS);
- for (i = 0, point = edit->points; i < totpoint; i++, point++) {
- if ((point->flag & PEP_HIDE) == 0 && point->totkey) {
- key = point->keys + point->totkey - 1;
- glColor3fv((key->flag & PEK_SELECT) ? sel_col : nosel_col);
- /* has to be like this.. otherwise selection won't work, have try glArrayElement later..*/
- glVertex3fv((key->flag & PEK_USE_WCO) ? key->world_co : key->co);
- }
- }
- glEnd();
- }
- }
-
- glDisable(GL_BLEND);
- glDisableClientState(GL_COLOR_ARRAY);
- glDisableClientState(GL_NORMAL_ARRAY);
- glDisableClientState(GL_VERTEX_ARRAY);
- if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
-}
static void ob_draw_RE_motion(float com[3], float rotscale[3][3], float itw, float ith, float drw_size)
{
@@ -6116,66 +5082,94 @@ static void drawhandlesN_active(Nurb *nu)
glColor3ub(0, 0, 0);
}
-static void drawvertsN(Nurb *nu, const char sel, const bool hide_handles, const void *vert)
+static void drawvertsN(const Nurb *nurb, const bool hide_handles, const void *vert)
{
- if (nu->hide) return;
+ const Nurb *nu;
- const int color = sel ? TH_VERTEX_SELECT : TH_VERTEX;
+ // just quick guesstimate of how many verts to draw
+ int count = 0;
+ for (nu = nurb; nu; nu = nu->next) {
+ if (!nu->hide) {
+ if (nu->type == CU_BEZIER) {
+ count += nu->pntsu * 3;
+ }
+ else {
+ count += nu->pntsu * nu->pntsv;
+ }
+ }
+ }
+ if (count == 0) return;
- UI_ThemeColor(color);
+ VertexFormat *format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ unsigned color = add_attrib(format, "color", GL_UNSIGNED_BYTE, 3, NORMALIZE_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR);
+
+ unsigned char vert_color[3];
+ unsigned char vert_color_select[3];
+ unsigned char vert_color_active[3];
+ UI_GetThemeColor3ubv(TH_VERTEX, vert_color);
+ UI_GetThemeColor3ubv(TH_VERTEX_SELECT, vert_color_select);
+ UI_GetThemeColor3ubv(TH_ACTIVE_VERT, vert_color_active);
glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
+
+ immBeginAtMost(GL_POINTS, count);
- glBegin(GL_POINTS);
-
- if (nu->type == CU_BEZIER) {
+ for (nu = nurb; nu; nu = nu->next) {
- BezTriple *bezt = nu->bezt;
- int a = nu->pntsu;
- while (a--) {
- if (bezt->hide == 0) {
- if (sel == 1 && bezt == vert) {
- UI_ThemeColor(TH_ACTIVE_VERT);
+ if (nu->hide) continue;
- if (bezt->f2 & SELECT) glVertex3fv(bezt->vec[1]);
- if (!hide_handles) {
- if (bezt->f1 & SELECT) glVertex3fv(bezt->vec[0]);
- if (bezt->f3 & SELECT) glVertex3fv(bezt->vec[2]);
- }
+ if (nu->type == CU_BEZIER) {
- UI_ThemeColor(color);
- }
- else if (hide_handles) {
- if ((bezt->f2 & SELECT) == sel) glVertex3fv(bezt->vec[1]);
- }
- else {
- if ((bezt->f1 & SELECT) == sel) glVertex3fv(bezt->vec[0]);
- if ((bezt->f2 & SELECT) == sel) glVertex3fv(bezt->vec[1]);
- if ((bezt->f3 & SELECT) == sel) glVertex3fv(bezt->vec[2]);
+ const BezTriple *bezt = nu->bezt;
+ int a = nu->pntsu;
+ while (a--) {
+ if (bezt->hide == 0) {
+ if (bezt == vert) {
+ immAttrib3ubv(color, bezt->f2 & SELECT ? vert_color_active : vert_color);
+ immVertex3fv(pos, bezt->vec[1]);
+ if (!hide_handles) {
+ immAttrib3ubv(color, bezt->f1 & SELECT ? vert_color_active : vert_color);
+ immVertex3fv(pos, bezt->vec[0]);
+ immAttrib3ubv(color, bezt->f3 & SELECT ? vert_color_active : vert_color);
+ immVertex3fv(pos, bezt->vec[2]);
+ }
+ }
+ else {
+ immAttrib3ubv(color, bezt->f2 & SELECT ? vert_color_select : vert_color);
+ immVertex3fv(pos, bezt->vec[1]);
+ if (!hide_handles) {
+ immAttrib3ubv(color, bezt->f1 & SELECT ? vert_color_select : vert_color);
+ immVertex3fv(pos, bezt->vec[0]);
+ immAttrib3ubv(color, bezt->f3 & SELECT ? vert_color_select : vert_color);
+ immVertex3fv(pos, bezt->vec[2]);
+ }
+ }
}
+ bezt++;
}
- bezt++;
}
- }
- else {
- BPoint *bp = nu->bp;
- int a = nu->pntsu * nu->pntsv;
- while (a--) {
- if (bp->hide == 0) {
- if (bp == vert) {
- UI_ThemeColor(TH_ACTIVE_VERT);
- glVertex3fv(bp->vec);
- UI_ThemeColor(color);
- }
- else {
- if ((bp->f1 & SELECT) == sel) glVertex3fv(bp->vec);
+ else {
+ const BPoint *bp = nu->bp;
+ int a = nu->pntsu * nu->pntsv;
+ while (a--) {
+ if (bp->hide == 0) {
+ if (bp == vert) {
+ immAttrib3ubv(color, vert_color_active);
+ }
+ else {
+ immAttrib3ubv(color, bp->f1 & SELECT ? vert_color_select : vert_color);
+ }
+ immVertex3fv(pos, bp->vec);
}
+ bp++;
}
- bp++;
}
}
-
- glEnd();
+
+ immEnd();
+ immUnbindProgram();
}
static void editnurb_draw_active_poly(Nurb *nu)
@@ -6393,7 +5387,6 @@ static void draw_editnurb(
for (nu = nurb; nu; nu = nu->next) {
if (nu->type == CU_BEZIER && (cu->drawflag & CU_HIDE_HANDLES) == 0)
drawhandlesN(nu, 1, hide_handles);
- drawvertsN(nu, 0, hide_handles, NULL);
}
if (v3d->zbuf) glDepthFunc(GL_LEQUAL);
@@ -6444,11 +5437,9 @@ static void draw_editnurb(
}
if (v3d->zbuf) glDepthFunc(GL_ALWAYS);
-
- for (nu = nurb; nu; nu = nu->next) {
- drawvertsN(nu, 1, hide_handles, vert);
- }
-
+
+ drawvertsN(nu, hide_handles, vert);
+
if (v3d->zbuf) glDepthFunc(GL_LEQUAL);
}
@@ -6596,56 +5587,58 @@ static void draw_editfont(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *b
}
/* draw a sphere for use as an empty drawtype */
-static void draw_empty_sphere(float size)
-{
- static GLuint displist = 0;
-
- if (displist == 0) {
- GLUquadricObj *qobj;
-
- displist = glGenLists(1);
- glNewList(displist, GL_COMPILE);
-
- glPushMatrix();
-
- qobj = gluNewQuadric();
- gluQuadricDrawStyle(qobj, GLU_SILHOUETTE);
- gluDisk(qobj, 0.0, 1, 16, 1);
-
- glRotatef(90, 0, 1, 0);
- gluDisk(qobj, 0.0, 1, 16, 1);
-
- glRotatef(90, 1, 0, 0);
- gluDisk(qobj, 0.0, 1, 16, 1);
-
- gluDeleteQuadric(qobj);
-
- glPopMatrix();
- glEndList();
- }
-
- glScalef(size, size, size);
- glCallList(displist);
- glScalef(1.0f / size, 1.0f / size, 1.0f / size);
+static void draw_empty_sphere(float size, unsigned pos)
+{
+#define NSEGMENTS 16
+ /* a single ring of vertices */
+ float p[NSEGMENTS][2];
+ for (int i = 0; i < NSEGMENTS; ++i) {
+ float angle = 2 * M_PI * ((float)i / (float)NSEGMENTS);
+ p[i][0] = size * cosf(angle);
+ p[i][1] = size * sinf(angle);
+ }
+
+ immBegin(GL_LINE_LOOP, NSEGMENTS);
+ for (int i = 0; i < NSEGMENTS; ++i)
+ immVertex3f(pos, p[i][0], p[i][1], 0.0f);
+ immEnd();
+ immBegin(GL_LINE_LOOP, NSEGMENTS);
+ for (int i = 0; i < NSEGMENTS; ++i)
+ immVertex3f(pos, p[i][0], 0.0f, p[i][1]);
+ immEnd();
+ immBegin(GL_LINE_LOOP, NSEGMENTS);
+ for (int i = 0; i < NSEGMENTS; ++i)
+ immVertex3f(pos, 0.0f, p[i][0], p[i][1]);
+ immEnd();
+#undef NSEGMENTS
}
/* draw a cone for use as an empty drawtype */
-static void draw_empty_cone(float size)
+static void draw_empty_cone(float size, unsigned pos)
{
- const float radius = size;
+#define NSEGMENTS 8
+ /* a single ring of vertices */
+ float p[NSEGMENTS][2];
+ for (int i = 0; i < NSEGMENTS; ++i) {
+ float angle = 2 * M_PI * ((float)i / (float)NSEGMENTS);
+ p[i][0] = size * cosf(angle);
+ p[i][1] = size * sinf(angle);
+ }
- GLUquadricObj *qobj = gluNewQuadric();
- gluQuadricDrawStyle(qobj, GLU_SILHOUETTE);
-
- glPushMatrix();
-
- glScalef(radius, size * 2.0f, radius);
- glRotatef(-90.0, 1.0, 0.0, 0.0);
- gluCylinder(qobj, 1.0, 0.0, 1.0, 8, 1);
+ /* cone sides */
+ immBegin(GL_LINES, NSEGMENTS * 2);
+ for (int i = 0; i < NSEGMENTS; ++i) {
+ immVertex3f(pos, 0.0f, 2.0f * size, 0.0f);
+ immVertex3f(pos, p[i][0], 0.0f, p[i][1]);
+ }
+ immEnd();
- glPopMatrix();
-
- gluDeleteQuadric(qobj);
+ /* end ring */
+ immBegin(GL_LINE_LOOP, NSEGMENTS);
+ for (int i = 0; i < NSEGMENTS; ++i)
+ immVertex3f(pos, p[i][0], 0.0f, p[i][1]);
+ immEnd();
+#undef NSEGMENTS
}
static void drawspiral(const float cent[3], float rad, float tmat[4][4], int start)
@@ -6716,20 +5709,19 @@ static void drawspiral(const float cent[3], float rad, float tmat[4][4], int sta
/* draws a circle on x-z plane given the scaling of the circle, assuming that
* all required matrices have been set (used for drawing empties) */
-static void drawcircle_size(float size)
+static void drawcircle_size(float size, unsigned pos)
{
- glBegin(GL_LINE_LOOP);
+ immBegin(GL_LINE_LOOP, CIRCLE_RESOL);
/* coordinates are: cos(degrees * 11.25) = x, sin(degrees * 11.25) = y, 0.0f = z */
for (short degrees = 0; degrees < CIRCLE_RESOL; degrees++) {
float x = cosval[degrees];
float y = sinval[degrees];
-
- glVertex3f(x * size, 0.0f, y * size);
+
+ immVertex3f(pos, x * size, 0.0f, y * size);
}
-
- glEnd();
+ immEnd();
}
/* needs fixing if non-identity matrix used */
@@ -6756,6 +5748,29 @@ static void drawtube(const float vec[3], float radius, float height, float tmat[
}
/* needs fixing if non-identity matrix used */
+static void imm_drawtube(const float vec[3], float radius, float height, float tmat[4][4], unsigned pos)
+{
+ float cur[3];
+ imm_drawcircball(vec, radius, tmat, pos);
+
+ copy_v3_v3(cur, vec);
+ cur[2] += height;
+
+ imm_drawcircball(cur, radius, tmat, pos);
+
+ immBegin(GL_LINES, 8);
+ immVertex3f(pos, vec[0] + radius, vec[1], vec[2]);
+ immVertex3f(pos, cur[0] + radius, cur[1], cur[2]);
+ immVertex3f(pos, vec[0] - radius, vec[1], vec[2]);
+ immVertex3f(pos, cur[0] - radius, cur[1], cur[2]);
+ immVertex3f(pos, vec[0], vec[1] + radius, vec[2]);
+ immVertex3f(pos, cur[0], cur[1] + radius, cur[2]);
+ immVertex3f(pos, vec[0], vec[1] - radius, vec[2]);
+ immVertex3f(pos, cur[0], cur[1] - radius, cur[2]);
+ immEnd();
+}
+
+/* needs fixing if non-identity matrix used */
static void drawcone(const float vec[3], float radius, float height, float tmat[4][4])
{
float cur[3];
@@ -6771,12 +5786,35 @@ static void drawcone(const float vec[3], float radius, float height, float tmat[
glVertex3f(vec[0], vec[1], vec[2]);
glVertex3f(cur[0] - radius, cur[1], cur[2]);
glVertex3f(vec[0], vec[1], vec[2]);
+
glVertex3f(cur[0], cur[1] + radius, cur[2]);
glVertex3f(vec[0], vec[1], vec[2]);
glVertex3f(cur[0], cur[1] - radius, cur[2]);
glEnd();
}
+/* needs fixing if non-identity matrix used */
+static void imm_drawcone(const float vec[3], float radius, float height, float tmat[4][4], unsigned pos)
+{
+ float cur[3];
+
+ copy_v3_v3(cur, vec);
+ cur[2] += height;
+
+ imm_drawcircball(cur, radius, tmat, pos);
+
+ immBegin(GL_LINES, 8);
+ immVertex3f(pos, vec[0], vec[1], vec[2]);
+ immVertex3f(pos, cur[0] + radius, cur[1], cur[2]);
+ immVertex3f(pos, vec[0], vec[1], vec[2]);
+ immVertex3f(pos, cur[0] - radius, cur[1], cur[2]);
+ immVertex3f(pos, vec[0], vec[1], vec[2]);
+ immVertex3f(pos, cur[0], cur[1] + radius, cur[2]);
+ immVertex3f(pos, vec[0], vec[1], vec[2]);
+ immVertex3f(pos, cur[0], cur[1] - radius, cur[2]);
+ immEnd();
+}
+
/* return true if nothing was drawn */
static bool drawmball(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
const char dt, const short dflag, const unsigned char ob_wire_col[4])
@@ -7466,15 +6504,12 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
Object *ob = base->object;
Curve *cu;
RegionView3D *rv3d = ar->regiondata;
- unsigned int col = 0;
unsigned char _ob_wire_col[4]; /* dont initialize this */
const unsigned char *ob_wire_col = NULL; /* dont initialize this, use NULL crashes as a way to find invalid use */
bool zbufoff = false, is_paint = false, empty_object = false;
const bool is_obact = (ob == OBACT);
const bool render_override = (v3d->flag2 & V3D_RENDER_OVERRIDE) != 0;
const bool is_picking = (G.f & G_PICKSEL) != 0;
- const bool has_particles = (ob->particlesystem.first != NULL);
- bool skip_object = false; /* Draw particles but not their emitter object. */
SmokeModifierData *smd = NULL;
if (ob != scene->obedit) {
@@ -7485,31 +6520,11 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
if (ob->restrictflag & OB_RESTRICT_RENDER)
return;
- if (!has_particles && (ob->transflag & (OB_DUPLI & ~OB_DUPLIFRAMES)))
+ if (ob->transflag & (OB_DUPLI & ~OB_DUPLIFRAMES))
return;
}
}
- if (has_particles) {
- /* XXX particles are not safe for simultaneous threaded render */
- if (G.is_rendering) {
- return;
- }
-
- if (ob->mode == OB_MODE_OBJECT) {
- ParticleSystem *psys;
-
- skip_object = render_override;
- for (psys = ob->particlesystem.first; psys; psys = psys->next) {
- /* Once we have found a psys which renders its emitter object, we are done. */
- if (psys->part->draw & PART_DRAW_EMITTER) {
- skip_object = false;
- break;
- }
- }
- }
- }
-
if (((base->flag & OB_FROMDUPLI) == 0) &&
(md = modifiers_findByType(ob, eModifierType_Smoke)) &&
(modifier_isEnabled(scene, md, eModifierMode_Realtime)))
@@ -7535,8 +6550,8 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
/* xray delay? */
if ((dflag & DRAW_PICKING) == 0 && (base->flag & OB_FROMDUPLI) == 0 && (v3d->flag2 & V3D_RENDER_SHADOW) == 0) {
- /* don't do xray in particle mode, need the z-buffer */
- if (!(ob->mode & OB_MODE_PARTICLE_EDIT)) {
+ /* sync with master */
+ {
/* xray and transp are set when it is drawing the 2nd/3rd pass */
if (!v3d->xray && !v3d->transp && (ob->dtx & OB_DRAWXRAY) && !(ob->dtx & OB_DRAWTRANSP)) {
ED_view3d_after_add(&v3d->afterdraw_xray, base, dflag);
@@ -7638,7 +6653,8 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
}
}
- if (!skip_object) {
+ /* sync with master */
+ {
/* draw outline for selected objects, mesh does itself */
if ((v3d->flag & V3D_SELECT_OUTLINE) && !render_override && ob->type != OB_MESH) {
if (dt > OB_WIRE && (ob->mode & OB_MODE_EDIT) == 0 && (dflag & DRAW_SCENESET) == 0) {
@@ -7648,6 +6664,13 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
}
}
+ /* TODO Viewport: draw only depth here, for selection */
+ if (!IS_VIEWPORT_LEGACY(v3d)) {
+ if (ELEM(ob->type, OB_EMPTY, OB_LAMP)) {
+ glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+ }
+ }
+
switch (ob->type) {
case OB_MESH:
empty_object = draw_mesh_object(scene, ar, v3d, rv3d, base, dt, ob_wire_col, dflag);
@@ -7719,7 +6742,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
draw_empty_image(ob, dflag, ob_wire_col);
}
else {
- drawaxes(rv3d->viewmatob, ob->empty_drawsize, ob->empty_drawtype);
+ drawaxes(rv3d->viewmatob, ob->empty_drawsize, ob->empty_drawtype, ob_wire_col);
}
}
break;
@@ -7737,7 +6760,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
break;
case OB_SPEAKER:
if (!render_override)
- drawspeaker(scene, v3d, rv3d, ob, dflag);
+ drawspeaker(ob_wire_col);
break;
case OB_LATTICE:
if (!render_override) {
@@ -7771,9 +6794,13 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
break;
default:
if (!render_override) {
- drawaxes(rv3d->viewmatob, 1.0, OB_ARROWS);
+ drawaxes(rv3d->viewmatob, 1.0, OB_ARROWS, ob_wire_col);
}
- break;
+ }
+
+ /* TODO Viewport: some eleemnts are being drawn for depth only */
+ if (!IS_VIEWPORT_LEGACY(v3d)) {
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
}
if (!render_override) {
@@ -7800,62 +6827,10 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
}
}
- /* code for new particle system */
- if ((ob->particlesystem.first) &&
- (ob != scene->obedit))
- {
- ParticleSystem *psys;
-
- if ((dflag & DRAW_CONSTCOLOR) == 0) {
- /* for visibility, also while wpaint */
- if (col || (ob->flag & SELECT)) {
- cpack(0xFFFFFF);
- }
- }
- //glDepthMask(GL_FALSE);
-
- glLoadMatrixf(rv3d->viewmat);
-
- view3d_cached_text_draw_begin();
-
- for (psys = ob->particlesystem.first; psys; psys = psys->next) {
- /* run this so that possible child particles get cached */
- if (ob->mode & OB_MODE_PARTICLE_EDIT && is_obact) {
- PTCacheEdit *edit = PE_create_current(scene, ob);
- if (edit && edit->psys == psys)
- draw_update_ptcache_edit(scene, ob, edit);
- }
-
- draw_new_particle_system(scene, v3d, rv3d, base, psys, dt, dflag);
- }
- invert_m4_m4(ob->imat, ob->obmat);
- view3d_cached_text_draw_end(v3d, ar, 0, NULL);
-
- glMultMatrixf(ob->obmat);
-
- //glDepthMask(GL_TRUE);
- if (col) cpack(col);
- }
-
- /* draw edit particles last so that they can draw over child particles */
- if ((dflag & DRAW_PICKING) == 0 &&
- (!scene->obedit))
- {
-
- if (ob->mode & OB_MODE_PARTICLE_EDIT && is_obact) {
- PTCacheEdit *edit = PE_create_current(scene, ob);
- if (edit) {
- glLoadMatrixf(rv3d->viewmat);
- draw_update_ptcache_edit(scene, ob, edit);
- draw_ptcache_edit(scene, v3d, edit);
- glMultMatrixf(ob->obmat);
- }
- }
- }
-
/* draw code for smoke, only draw domains */
if (smd && smd->domain) {
SmokeDomainSettings *sds = smd->domain;
+ const bool show_smoke = true; /* XXX was checking cached frame range before */
float viewnormal[3];
glLoadMatrixf(rv3d->viewmat);
@@ -7888,7 +6863,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
}
/* don't show smoke before simulation starts, this could be made an option in the future */
- if (sds->fluid && CFRA >= sds->point_cache[0]->startframe) {
+ if (sds->fluid && show_smoke) {
float p0[3], p1[3];
/* get view vector */
@@ -7956,7 +6931,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
if (dtx && (G.f & G_RENDER_OGL) == 0) {
if (dtx & OB_AXIS) {
- drawaxes(rv3d->viewmatob, 1.0f, OB_ARROWS);
+ drawaxes(rv3d->viewmatob, 1.0f, OB_ARROWS, NULL);
}
if (dtx & OB_DRAWBOUNDOX) {
draw_bounding_volume(ob, ob->boundtype);
@@ -8043,10 +7018,15 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
if ((base->sx != IS_CLIPPED) &&
(U.obcenter_dia != 0.0))
{
+ unsigned pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_POINT_FIXED_SIZE_UNIFORM_COLOR);
+ /* TODO: short term, use DEPTH_ONLY shader or set appropriate color */
+ /* TODO: long term, solve picking & selection problem better */
glPointSize(U.obcenter_dia);
- glBegin(GL_POINTS);
- glVertex3fv(ob->obmat[3]);
- glEnd();
+ immBegin(GL_POINTS, 1);
+ immVertex3fv(pos, ob->obmat[3]);
+ immEnd();
+ immUnbindProgram();
}
}
else if ((dflag & DRAW_CONSTCOLOR) == 0) {
@@ -8503,7 +7483,7 @@ void draw_object_instance(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object
draw_empty_image(ob, DRAW_CONSTCOLOR, NULL);
}
else {
- drawaxes(rv3d->viewmatob, ob->empty_drawsize, ob->empty_drawtype);
+ drawaxes(rv3d->viewmatob, ob->empty_drawsize, ob->empty_drawtype, NULL); /* TODO: use proper color */
}
break;
}
diff --git a/source/blender/editors/space_view3d/drawvolume.c b/source/blender/editors/space_view3d/drawvolume.c
index b0e21601b9c..9cfcd6cef05 100644
--- a/source/blender/editors/space_view3d/drawvolume.c
+++ b/source/blender/editors/space_view3d/drawvolume.c
@@ -32,6 +32,7 @@
#include "MEM_guardedalloc.h"
+#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_smoke_types.h"
@@ -41,7 +42,6 @@
#include "BLI_math.h"
#include "BKE_DerivedMesh.h"
-#include "BKE_particle.h"
#include "smoke_API.h"
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index 8139a407a43..b4cd8afc833 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -60,6 +60,7 @@
#include "GPU_material.h"
#include "GPU_probe.h"
#include "GPU_pbr.h"
+#include "GPU_viewport.h"
#include "BIF_gl.h"
@@ -603,6 +604,11 @@ static void view3d_main_region_exit(wmWindowManager *wm, ARegion *ar)
GPU_fx_compositor_destroy(rv3d->compositor);
rv3d->compositor = NULL;
}
+
+ if (rv3d->viewport) {
+ GPU_viewport_free(rv3d->viewport);
+ rv3d->viewport = NULL;
+ }
}
static int view3d_ob_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
@@ -760,6 +766,9 @@ static void view3d_main_region_free(ARegion *ar)
if (rv3d->compositor) {
GPU_fx_compositor_destroy(rv3d->compositor);
}
+ if (rv3d->viewport) {
+ GPU_viewport_free(rv3d->viewport);
+ }
MEM_freeN(rv3d);
ar->regiondata = NULL;
@@ -784,6 +793,7 @@ static void *view3d_main_region_duplicate(void *poin)
new->sms = NULL;
new->smooth_timer = NULL;
new->compositor = NULL;
+ new->viewport = NULL;
return new;
}
@@ -936,7 +946,6 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w
case ND_MODIFIER:
case ND_CONSTRAINT:
case ND_KEYS:
- case ND_PARTICLE:
case ND_LOD:
view3d_tag_probes_update(ar, wmn, scene);
ED_region_tag_redraw(ar);
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index 5924cf36fa1..9eed7b0a03e 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -28,947 +28,245 @@
* \ingroup spview3d
*/
-#include <string.h>
-#include <stdio.h>
#include <math.h>
-#include "DNA_armature_types.h"
-#include "DNA_camera_types.h"
-#include "DNA_customdata_types.h"
-#include "DNA_object_types.h"
-#include "DNA_group_types.h"
-#include "DNA_mesh_types.h"
-#include "DNA_key_types.h"
-#include "DNA_lamp_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_world_types.h"
-#include "DNA_brush_types.h"
-
-#include "MEM_guardedalloc.h"
-
-#include "BLI_blenlib.h"
-#include "BLI_math.h"
-#include "BLI_jitter.h"
-#include "BLI_utildefines.h"
-#include "BLI_endian_switch.h"
-#include "BLI_threads.h"
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
-#include "BKE_anim.h"
#include "BKE_camera.h"
#include "BKE_context.h"
-#include "BKE_customdata.h"
-#include "BKE_DerivedMesh.h"
-#include "BKE_image.h"
-#include "BKE_key.h"
-#include "BKE_main.h"
-#include "BKE_object.h"
-#include "BKE_global.h"
-#include "BKE_paint.h"
#include "BKE_scene.h"
-#include "BKE_screen.h"
#include "BKE_unit.h"
-#include "BKE_movieclip.h"
-
-#include "RE_engine.h"
-
-#include "IMB_imbuf_types.h"
-#include "IMB_imbuf.h"
-#include "IMB_colormanagement.h"
-#include "BIF_gl.h"
-#include "BIF_glutil.h"
+#include "BLF_api.h"
-#include "WM_api.h"
+#include "BLI_math.h"
+#include "BLI_rect.h"
+#include "BLI_threads.h"
-#include "BLF_api.h"
-#include "BLT_translation.h"
+#include "DNA_camera_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_windowmanager_types.h"
-#include "ED_armature.h"
-#include "ED_keyframing.h"
-#include "ED_gpencil.h"
#include "ED_screen.h"
-#include "ED_space_api.h"
-#include "ED_screen_types.h"
#include "ED_transform.h"
+#include "GPU_immediate.h"
+#include "GPU_viewport.h"
+
#include "UI_interface.h"
-#include "UI_interface_icons.h"
#include "UI_resources.h"
-#include "GPU_draw.h"
-#include "GPU_framebuffer.h"
-#include "GPU_material.h"
-#include "GPU_compositing.h"
-#include "GPU_extensions.h"
-#include "GPU_probe.h"
-#include "GPU_pbr.h"
+#include "RE_engine.h"
+
+#include "WM_api.h"
#include "view3d_intern.h" /* own include */
/* prototypes */
-static void view3d_stereo3d_setup(Scene *scene, View3D *v3d, ARegion *ar);
-static void view3d_stereo3d_setup_offscreen(Scene *scene, View3D *v3d, ARegion *ar,
- float winmat[4][4], const char *viewname);
-
-/* handy utility for drawing shapes in the viewport for arbitrary code.
- * could add lines and points too */
-// #define DEBUG_DRAW
-#ifdef DEBUG_DRAW
-static void bl_debug_draw(void);
-/* add these locally when using these functions for testing */
-extern void bl_debug_draw_quad_clear(void);
-extern void bl_debug_draw_quad_add(const float v0[3], const float v1[3], const float v2[3], const float v3[3]);
-extern void bl_debug_draw_edge_add(const float v0[3], const float v1[3]);
-extern void bl_debug_color_set(const unsigned int col);
-#endif
+static void draw_all_objects(const bContext *C, ARegion *ar, const bool only_depth, const bool use_depth);
-void circf(float x, float y, float rad)
-{
- GLUquadricObj *qobj = gluNewQuadric();
-
- gluQuadricDrawStyle(qobj, GLU_FILL);
-
- glPushMatrix();
-
- glTranslatef(x, y, 0.0);
-
- gluDisk(qobj, 0.0, rad, 32, 1);
-
- glPopMatrix();
-
- gluDeleteQuadric(qobj);
-}
+typedef struct DrawData {
+ rcti border_rect;
+ bool render_border;
+ bool clip_border;
+ bool is_render;
+} DrawData;
-void circ(float x, float y, float rad)
+static void view3d_draw_data_init(const bContext *C, ARegion *ar, DrawData *draw_data)
{
- GLUquadricObj *qobj = gluNewQuadric();
-
- gluQuadricDrawStyle(qobj, GLU_SILHOUETTE);
-
- glPushMatrix();
-
- glTranslatef(x, y, 0.0);
-
- gluDisk(qobj, 0.0, rad, 32, 1);
-
- glPopMatrix();
-
- gluDeleteQuadric(qobj);
-}
-
-
-/* ********* custom clipping *********** */
+ Scene *scene = CTX_data_scene(C);
+ View3D *v3d = CTX_wm_view3d(C);
-static void view3d_draw_clipping(RegionView3D *rv3d)
-{
- BoundBox *bb = rv3d->clipbb;
-
- if (bb) {
- const unsigned int clipping_index[6][4] = {
- {0, 1, 2, 3},
- {0, 4, 5, 1},
- {4, 7, 6, 5},
- {7, 3, 2, 6},
- {1, 5, 6, 2},
- {7, 4, 0, 3}
- };
-
- /* fill in zero alpha for rendering & re-projection [#31530] */
- unsigned char col[4];
- UI_GetThemeColor4ubv(TH_V3D_CLIPPING_BORDER, col);
- glColor4ubv(col);
-
- glEnable(GL_BLEND);
- glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(3, GL_FLOAT, 0, bb->vec);
- glDrawElements(GL_QUADS, sizeof(clipping_index) / sizeof(unsigned int), GL_UNSIGNED_INT, clipping_index);
- glDisableClientState(GL_VERTEX_ARRAY);
- glDisable(GL_BLEND);
- }
-}
+ draw_data->is_render = (v3d->drawtype == OB_RENDER);
-void ED_view3d_clipping_set(RegionView3D *rv3d)
-{
- double plane[4];
- const unsigned int tot = (rv3d->viewlock & RV3D_BOXCLIP) ? 4 : 6;
- unsigned int a;
-
- for (a = 0; a < tot; a++) {
- copy_v4db_v4fl(plane, rv3d->clip[a]);
- glClipPlane(GL_CLIP_PLANE0 + a, plane);
- glEnable(GL_CLIP_PLANE0 + a);
- }
+ draw_data->render_border = ED_view3d_calc_render_border(scene, v3d, ar, &draw_data->border_rect);
+ draw_data->clip_border = (draw_data->render_border && !BLI_rcti_compare(&ar->drawrct, &draw_data->border_rect));
}
-/* use these to temp disable/enable clipping when 'rv3d->rflag & RV3D_CLIPPING' is set */
-void ED_view3d_clipping_disable(void)
-{
- unsigned int a;
+/* ******************** general functions ***************** */
- for (a = 0; a < 6; a++) {
- glDisable(GL_CLIP_PLANE0 + a);
- }
-}
-void ED_view3d_clipping_enable(void)
+static bool use_depth_doit(Scene *scene, View3D *v3d)
{
- unsigned int a;
+ if (v3d->drawtype > OB_WIRE)
+ return true;
- for (a = 0; a < 6; a++) {
- glEnable(GL_CLIP_PLANE0 + a);
+ /* special case (depth for wire color) */
+ if (v3d->drawtype <= OB_WIRE) {
+ if (scene->obedit && scene->obedit->type == OB_MESH) {
+ Mesh *me = scene->obedit->data;
+ if (me->drawflag & ME_DRAWEIGHT) {
+ return true;
+ }
+ }
}
+ return false;
}
-static bool view3d_clipping_test(const float co[3], const float clip[6][4])
-{
- if (plane_point_side_v3(clip[0], co) > 0.0f)
- if (plane_point_side_v3(clip[1], co) > 0.0f)
- if (plane_point_side_v3(clip[2], co) > 0.0f)
- if (plane_point_side_v3(clip[3], co) > 0.0f)
- return false;
-
- return true;
-}
-
-/* for 'local' ED_view3d_clipping_local must run first
- * then all comparisons can be done in localspace */
-bool ED_view3d_clipping_test(const RegionView3D *rv3d, const float co[3], const bool is_local)
+static bool use_depth(const bContext *C)
{
- return view3d_clipping_test(co, is_local ? rv3d->clip_local : rv3d->clip);
-}
-
-/* ********* end custom clipping *********** */
-
-
-static void drawgrid_draw(ARegion *ar, double wx, double wy, double x, double y, double dx)
-{
- double verts[2][2];
-
- x += (wx);
- y += (wy);
-
- /* set fixed 'Y' */
- verts[0][1] = 0.0f;
- verts[1][1] = (double)ar->winy;
-
- /* iter over 'X' */
- verts[0][0] = verts[1][0] = x - dx * floor(x / dx);
- glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(2, GL_DOUBLE, 0, verts);
-
- while (verts[0][0] < ar->winx) {
- glDrawArrays(GL_LINES, 0, 2);
- verts[0][0] = verts[1][0] = verts[0][0] + dx;
- }
-
- /* set fixed 'X' */
- verts[0][0] = 0.0f;
- verts[1][0] = (double)ar->winx;
-
- /* iter over 'Y' */
- verts[0][1] = verts[1][1] = y - dx * floor(y / dx);
- while (verts[0][1] < ar->winy) {
- glDrawArrays(GL_LINES, 0, 2);
- verts[0][1] = verts[1][1] = verts[0][1] + dx;
- }
-
- glDisableClientState(GL_VERTEX_ARRAY);
+ View3D *v3d = CTX_wm_view3d(C);
+ Scene *scene = CTX_data_scene(C);
+ return use_depth_doit(scene, v3d);
}
-#define GRID_MIN_PX_D 6.0
-#define GRID_MIN_PX_F 6.0f
-
-static void drawgrid(UnitSettings *unit, ARegion *ar, View3D *v3d, const char **grid_unit)
+/**
+ * \note keep this synced with #ED_view3d_mats_rv3d_backup/#ED_view3d_mats_rv3d_restore
+ */
+void ED_view3d_update_viewmat(Scene *scene, View3D *v3d, ARegion *ar, float viewmat[4][4], float winmat[4][4])
{
- /* extern short bgpicmode; */
RegionView3D *rv3d = ar->regiondata;
- double wx, wy, x, y, fw, fx, fy, dx;
- double vec4[4];
- unsigned char col[3], col2[3];
-
- fx = rv3d->persmat[3][0];
- fy = rv3d->persmat[3][1];
- fw = rv3d->persmat[3][3];
-
- wx = (ar->winx / 2.0); /* because of rounding errors, grid at wrong location */
- wy = (ar->winy / 2.0);
-
- x = (wx) * fx / fw;
- y = (wy) * fy / fw;
-
- vec4[0] = vec4[1] = v3d->grid;
-
- vec4[2] = 0.0;
- vec4[3] = 1.0;
- mul_m4_v4d(rv3d->persmat, vec4);
- fx = vec4[0];
- fy = vec4[1];
- fw = vec4[3];
-
- dx = fabs(x - (wx) * fx / fw);
- if (dx == 0) dx = fabs(y - (wy) * fy / fw);
-
- glLineWidth(1.0f);
-
- glDepthMask(GL_FALSE); /* disable write in zbuffer */
-
- /* check zoom out */
- UI_ThemeColor(TH_GRID);
-
- if (unit->system) {
- /* Use GRID_MIN_PX * 2 for units because very very small grid
- * items are less useful when dealing with units */
- const void *usys;
- int len, i;
- double dx_scalar;
- float blend_fac;
-
- bUnit_GetSystem(unit->system, B_UNIT_LENGTH, &usys, &len);
-
- if (usys) {
- i = len;
- while (i--) {
- double scalar = bUnit_GetScaler(usys, i);
+ rctf cameraborder;
- dx_scalar = dx * scalar / (double)unit->scale_length;
- if (dx_scalar < (GRID_MIN_PX_D * 2.0))
- continue;
+ /* setup window matrices */
+ if (winmat)
+ copy_m4_m4(rv3d->winmat, winmat);
+ else
+ view3d_winmatrix_set(ar, v3d, NULL);
- /* Store the smallest drawn grid size units name so users know how big each grid cell is */
- if (*grid_unit == NULL) {
- *grid_unit = bUnit_GetNameDisplay(usys, i);
- rv3d->gridview = (float)((scalar * (double)v3d->grid) / (double)unit->scale_length);
- }
- blend_fac = 1.0f - ((GRID_MIN_PX_F * 2.0f) / (float)dx_scalar);
+ /* setup view matrix */
+ if (viewmat)
+ copy_m4_m4(rv3d->viewmat, viewmat);
+ else
+ view3d_viewmatrix_set(scene, v3d, rv3d); /* note: calls BKE_object_where_is_calc for camera... */
- /* tweak to have the fade a bit nicer */
- blend_fac = (blend_fac * blend_fac) * 2.0f;
- CLAMP(blend_fac, 0.3f, 1.0f);
+ /* update utilitity matrices */
+ mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat);
+ invert_m4_m4(rv3d->persinv, rv3d->persmat);
+ invert_m4_m4(rv3d->viewinv, rv3d->viewmat);
+ /* calculate GLSL view dependent values */
- UI_ThemeColorBlend(TH_HIGH_GRAD, TH_GRID, blend_fac);
+ /* store window coordinates scaling/offset */
+ if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
+ ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &cameraborder, false);
+ rv3d->viewcamtexcofac[0] = (float)ar->winx / BLI_rctf_size_x(&cameraborder);
+ rv3d->viewcamtexcofac[1] = (float)ar->winy / BLI_rctf_size_y(&cameraborder);
- drawgrid_draw(ar, wx, wy, x, y, dx_scalar);
- }
- }
+ rv3d->viewcamtexcofac[2] = -rv3d->viewcamtexcofac[0] * cameraborder.xmin / (float)ar->winx;
+ rv3d->viewcamtexcofac[3] = -rv3d->viewcamtexcofac[1] * cameraborder.ymin / (float)ar->winy;
}
else {
- const double sublines = v3d->gridsubdiv;
- const float sublines_fl = v3d->gridsubdiv;
-
- if (dx < GRID_MIN_PX_D) {
- rv3d->gridview *= sublines_fl;
- dx *= sublines;
-
- if (dx < GRID_MIN_PX_D) {
- rv3d->gridview *= sublines_fl;
- dx *= sublines;
-
- if (dx < GRID_MIN_PX_D) {
- rv3d->gridview *= sublines_fl;
- dx *= sublines;
- if (dx < GRID_MIN_PX_D) {
- /* pass */
- }
- else {
- UI_ThemeColor(TH_GRID);
- drawgrid_draw(ar, wx, wy, x, y, dx);
- }
- }
- else { /* start blending out */
- UI_ThemeColorBlend(TH_HIGH_GRAD, TH_GRID, dx / (GRID_MIN_PX_D * 6.0));
- drawgrid_draw(ar, wx, wy, x, y, dx);
-
- UI_ThemeColor(TH_GRID);
- drawgrid_draw(ar, wx, wy, x, y, sublines * dx);
- }
- }
- else { /* start blending out (GRID_MIN_PX < dx < (GRID_MIN_PX * 10)) */
- UI_ThemeColorBlend(TH_HIGH_GRAD, TH_GRID, dx / (GRID_MIN_PX_D * 6.0));
- drawgrid_draw(ar, wx, wy, x, y, dx);
-
- UI_ThemeColor(TH_GRID);
- drawgrid_draw(ar, wx, wy, x, y, sublines * dx);
- }
- }
- else {
- if (dx > (GRID_MIN_PX_D * 10.0)) { /* start blending in */
- rv3d->gridview /= sublines_fl;
- dx /= sublines;
- if (dx > (GRID_MIN_PX_D * 10.0)) { /* start blending in */
- rv3d->gridview /= sublines_fl;
- dx /= sublines;
- if (dx > (GRID_MIN_PX_D * 10.0)) {
- UI_ThemeColor(TH_GRID);
- drawgrid_draw(ar, wx, wy, x, y, dx);
- }
- else {
- UI_ThemeColorBlend(TH_HIGH_GRAD, TH_GRID, dx / (GRID_MIN_PX_D * 6.0));
- drawgrid_draw(ar, wx, wy, x, y, dx);
- UI_ThemeColor(TH_GRID);
- drawgrid_draw(ar, wx, wy, x, y, dx * sublines);
- }
- }
- else {
- UI_ThemeColorBlend(TH_HIGH_GRAD, TH_GRID, dx / (GRID_MIN_PX_D * 6.0));
- drawgrid_draw(ar, wx, wy, x, y, dx);
- UI_ThemeColor(TH_GRID);
- drawgrid_draw(ar, wx, wy, x, y, dx * sublines);
- }
- }
- else {
- UI_ThemeColorBlend(TH_HIGH_GRAD, TH_GRID, dx / (GRID_MIN_PX_D * 6.0));
- drawgrid_draw(ar, wx, wy, x, y, dx);
- UI_ThemeColor(TH_GRID);
- drawgrid_draw(ar, wx, wy, x, y, dx * sublines);
- }
- }
+ rv3d->viewcamtexcofac[0] = rv3d->viewcamtexcofac[1] = 1.0f;
+ rv3d->viewcamtexcofac[2] = rv3d->viewcamtexcofac[3] = 0.0f;
}
+ /* calculate pixelsize factor once, is used for lamps and obcenters */
+ {
+ /* note: '1.0f / len_v3(v1)' replaced 'len_v3(rv3d->viewmat[0])'
+ * because of float point precision problems at large values [#23908] */
+ float v1[3], v2[3];
+ float len_px, len_sc;
- x += (wx);
- y += (wy);
- UI_GetThemeColor3ubv(TH_GRID, col);
-
- setlinestyle(0);
-
- /* center cross */
- /* horizontal line */
- if (ELEM(rv3d->view, RV3D_VIEW_RIGHT, RV3D_VIEW_LEFT))
- UI_make_axis_color(col, col2, 'Y');
- else UI_make_axis_color(col, col2, 'X');
- glColor3ubv(col2);
-
- fdrawline(0.0, y, (float)ar->winx, y);
-
- /* vertical line */
- if (ELEM(rv3d->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM))
- UI_make_axis_color(col, col2, 'Y');
- else UI_make_axis_color(col, col2, 'Z');
- glColor3ubv(col2);
-
- fdrawline(x, 0.0, x, (float)ar->winy);
-
- glDepthMask(GL_TRUE); /* enable write in zbuffer */
-}
-#undef GRID_MIN_PX
+ v1[0] = rv3d->persmat[0][0];
+ v1[1] = rv3d->persmat[1][0];
+ v1[2] = rv3d->persmat[2][0];
-/** could move this elsewhere, but tied into #ED_view3d_grid_scale */
-float ED_scene_grid_scale(Scene *scene, const char **grid_unit)
-{
- /* apply units */
- if (scene->unit.system) {
- const void *usys;
- int len;
+ v2[0] = rv3d->persmat[0][1];
+ v2[1] = rv3d->persmat[1][1];
+ v2[2] = rv3d->persmat[2][1];
- bUnit_GetSystem(scene->unit.system, B_UNIT_LENGTH, &usys, &len);
+ len_px = 2.0f / sqrtf(min_ff(len_squared_v3(v1), len_squared_v3(v2)));
+ len_sc = (float)MAX2(ar->winx, ar->winy);
- if (usys) {
- int i = bUnit_GetBaseUnit(usys);
- if (grid_unit)
- *grid_unit = bUnit_GetNameDisplay(usys, i);
- return (float)bUnit_GetScaler(usys, i) / scene->unit.scale_length;
- }
+ rv3d->pixsize = len_px / len_sc;
}
-
- return 1.0f;
-}
-
-float ED_view3d_grid_scale(Scene *scene, View3D *v3d, const char **grid_unit)
-{
- return v3d->grid * ED_scene_grid_scale(scene, grid_unit);
}
-static void drawfloor(Scene *scene, View3D *v3d, const char **grid_unit, bool write_depth)
+static void view3d_main_region_setup_view(Scene *scene, View3D *v3d, ARegion *ar, float viewmat[4][4], float winmat[4][4])
{
- float grid, grid_scale;
- unsigned char col_grid[3];
- const int gridlines = v3d->gridlines / 2;
-
- if (v3d->gridlines < 3) return;
-
- /* use 'grid_scale' instead of 'v3d->grid' from now on */
- grid_scale = ED_view3d_grid_scale(scene, v3d, grid_unit);
- grid = gridlines * grid_scale;
-
- if (!write_depth)
- glDepthMask(GL_FALSE);
-
- UI_GetThemeColor3ubv(TH_GRID, col_grid);
-
- glLineWidth(1);
-
- /* draw the Y axis and/or grid lines */
- if (v3d->gridflag & V3D_SHOW_FLOOR) {
- const int sublines = v3d->gridsubdiv;
- float vert[4][3] = {{0.0f}};
- unsigned char col_bg[3];
- unsigned char col_grid_emphasise[3], col_grid_light[3];
- int a;
- int prev_emphasise = -1;
-
- UI_GetThemeColor3ubv(TH_BACK, col_bg);
-
- /* emphasise division lines lighter instead of darker, if background is darker than grid */
- UI_GetColorPtrShade3ubv(col_grid, col_grid_light, 10);
- UI_GetColorPtrShade3ubv(col_grid, col_grid_emphasise,
- (((col_grid[0] + col_grid[1] + col_grid[2]) + 30) >
- (col_bg[0] + col_bg[1] + col_bg[2])) ? 20 : -10);
-
- /* set fixed axis */
- vert[0][0] = vert[2][1] = grid;
- vert[1][0] = vert[3][1] = -grid;
-
- glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(3, GL_FLOAT, 0, vert);
-
- for (a = -gridlines; a <= gridlines; a++) {
- const float line = a * grid_scale;
- const int is_emphasise = (a % sublines) == 0;
-
- if (is_emphasise != prev_emphasise) {
- glColor3ubv(is_emphasise ? col_grid_emphasise : col_grid_light);
- prev_emphasise = is_emphasise;
- }
-
- /* set variable axis */
- vert[0][1] = vert[1][1] = vert[2][0] = vert[3][0] = line;
-
- glDrawArrays(GL_LINES, 0, 4);
- }
-
- glDisableClientState(GL_VERTEX_ARRAY);
- }
-
- /* draw the Z axis line */
- /* check for the 'show Z axis' preference */
- if (v3d->gridflag & (V3D_SHOW_X | V3D_SHOW_Y | V3D_SHOW_Z)) {
- glBegin(GL_LINES);
- int axis;
- for (axis = 0; axis < 3; axis++) {
- if (v3d->gridflag & (V3D_SHOW_X << axis)) {
- float vert[3];
- unsigned char tcol[3];
-
- UI_make_axis_color(col_grid, tcol, 'X' + axis);
- glColor3ubv(tcol);
-
- zero_v3(vert);
- vert[axis] = grid;
- glVertex3fv(vert);
- vert[axis] = -grid;
- glVertex3fv(vert);
- }
- }
- glEnd();
- }
-
- glDepthMask(GL_TRUE);
-}
+ RegionView3D *rv3d = ar->regiondata;
+ ED_view3d_update_viewmat(scene, v3d, ar, viewmat, winmat);
-static void drawcursor(Scene *scene, ARegion *ar, View3D *v3d)
-{
- int co[2];
-
- /* we don't want the clipping for cursor */
- if (ED_view3d_project_int_global(ar, ED_view3d_cursor3d_get(scene, v3d), co, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
- const float f5 = 0.25f * U.widget_unit;
- const float f10 = 0.5f * U.widget_unit;
- const float f20 = U.widget_unit;
-
- glLineWidth(1);
- setlinestyle(0);
- cpack(0xFF);
- circ((float)co[0], (float)co[1], f10);
- setlinestyle(4);
- cpack(0xFFFFFF);
- circ((float)co[0], (float)co[1], f10);
- setlinestyle(0);
-
- UI_ThemeColor(TH_VIEW_OVERLAY);
- sdrawline(co[0] - f20, co[1], co[0] - f5, co[1]);
- sdrawline(co[0] + f5, co[1], co[0] + f20, co[1]);
- sdrawline(co[0], co[1] - f20, co[0], co[1] - f5);
- sdrawline(co[0], co[1] + f5, co[0], co[1] + f20);
- }
+ /* set for opengl */
+ glMatrixMode(GL_PROJECTION);
+ glLoadMatrixf(rv3d->winmat);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadMatrixf(rv3d->viewmat);
}
-/* Draw a live substitute of the view icon, which is always shown
- * colors copied from transform_manipulator.c, we should keep these matching. */
-static void draw_view_axis(RegionView3D *rv3d, rcti *rect)
+static bool view3d_stereo3d_active(const bContext *C, Scene *scene, View3D *v3d, RegionView3D *rv3d)
{
- const float k = U.rvisize * U.pixelsize; /* axis size */
- const float toll = 0.5; /* used to see when view is quasi-orthogonal */
- float startx = k + 1.0f; /* axis center in screen coordinates, x=y */
- float starty = k + 1.0f;
- float ydisp = 0.0; /* vertical displacement to allow obj info text */
- int bright = - 20 * (10 - U.rvibright); /* axis alpha offset (rvibright has range 0-10) */
- float vec[3];
- float dx, dy;
-
- int axis_order[3] = {0, 1, 2};
- int axis_i;
-
- startx += rect->xmin;
- starty += rect->ymin;
-
- axis_sort_v3(rv3d->viewinv[2], axis_order);
-
- /* thickness of lines is proportional to k */
- glLineWidth(2);
-
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ wmWindow *win = CTX_wm_window(C);
- for (axis_i = 0; axis_i < 3; axis_i++) {
- int i = axis_order[axis_i];
- const char axis_text[2] = {'x' + i, '\0'};
+ if ((scene->r.scemode & R_MULTIVIEW) == 0)
+ return false;
- zero_v3(vec);
- vec[i] = 1.0f;
- mul_qt_v3(rv3d->viewquat, vec);
- dx = vec[0] * k;
- dy = vec[1] * k;
+ if (WM_stereo3d_enabled(win, true) == false)
+ return false;
- UI_ThemeColorShadeAlpha(TH_AXIS_X + i, 0, bright);
- glBegin(GL_LINES);
- glVertex2f(startx, starty + ydisp);
- glVertex2f(startx + dx, starty + dy + ydisp);
- glEnd();
+ if ((v3d->camera == NULL) || (v3d->camera->type != OB_CAMERA) || rv3d->persp != RV3D_CAMOB)
+ return false;
- if (fabsf(dx) > toll || fabsf(dy) > toll) {
- BLF_draw_default_ascii(startx + dx + 2, starty + dy + ydisp + 2, 0.0f, axis_text, 1);
+ if (scene->r.views_format & SCE_VIEWS_FORMAT_MULTIVIEW) {
+ if (v3d->stereo3d_camera == STEREO_MONO_ID)
+ return false;
- /* BLF_draw_default disables blending */
- glEnable(GL_BLEND);
- }
+ return BKE_scene_multiview_is_stereo3d(&scene->r);
}
- glDisable(GL_BLEND);
+ return true;
}
-#ifdef WITH_INPUT_NDOF
-/* draw center and axis of rotation for ongoing 3D mouse navigation */
-static void draw_rotation_guide(RegionView3D *rv3d)
+/* setup the view and win matrices for the multiview cameras
+ *
+ * unlike view3d_stereo3d_setup_offscreen, when view3d_stereo3d_setup is called
+ * we have no winmatrix (i.e., projection matrix) defined at that time.
+ * Since the camera and the camera shift are needed for the winmat calculation
+ * we do a small hack to replace it temporarily so we don't need to change the
+ * view3d)main_region_setup_view() code to account for that.
+ */
+static void view3d_stereo3d_setup(Scene *scene, View3D *v3d, ARegion *ar)
{
- float o[3]; /* center of rotation */
- float end[3]; /* endpoints for drawing */
-
- float color[4] = {0.0f, 0.4235f, 1.0f, 1.0f}; /* bright blue so it matches device LEDs */
-
- negate_v3_v3(o, rv3d->ofs);
-
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glPointSize(5);
- glEnable(GL_POINT_SMOOTH);
- glDepthMask(0); /* don't overwrite zbuf */
-
- if (rv3d->rot_angle != 0.0f) {
- /* -- draw rotation axis -- */
- float scaled_axis[3];
- const float scale = rv3d->dist;
- mul_v3_v3fl(scaled_axis, rv3d->rot_axis, scale);
-
-
- glBegin(GL_LINE_STRIP);
- color[3] = 0.0f; /* more transparent toward the ends */
- glColor4fv(color);
- add_v3_v3v3(end, o, scaled_axis);
- glVertex3fv(end);
+ bool is_left;
+ const char *names[2] = { STEREO_LEFT_NAME, STEREO_RIGHT_NAME };
+ const char *viewname;
-#if 0
- color[3] = 0.2f + fabsf(rv3d->rot_angle); /* modulate opacity with angle */
- /* ^^ neat idea, but angle is frame-rate dependent, so it's usually close to 0.2 */
-#endif
+ /* show only left or right camera */
+ if (v3d->stereo3d_camera != STEREO_3D_ID)
+ v3d->multiview_eye = v3d->stereo3d_camera;
- color[3] = 0.5f; /* more opaque toward the center */
- glColor4fv(color);
- glVertex3fv(o);
-
- color[3] = 0.0f;
- glColor4fv(color);
- sub_v3_v3v3(end, o, scaled_axis);
- glVertex3fv(end);
- glEnd();
-
- /* -- draw ring around rotation center -- */
- {
-#define ROT_AXIS_DETAIL 13
-
- const float s = 0.05f * scale;
- const float step = 2.0f * (float)(M_PI / ROT_AXIS_DETAIL);
- float angle;
- int i;
-
- float q[4]; /* rotate ring so it's perpendicular to axis */
- const int upright = fabsf(rv3d->rot_axis[2]) >= 0.95f;
- if (!upright) {
- const float up[3] = {0.0f, 0.0f, 1.0f};
- float vis_angle, vis_axis[3];
-
- cross_v3_v3v3(vis_axis, up, rv3d->rot_axis);
- vis_angle = acosf(dot_v3v3(up, rv3d->rot_axis));
- axis_angle_to_quat(q, vis_axis, vis_angle);
- }
+ is_left = v3d->multiview_eye == STEREO_LEFT_ID;
+ viewname = names[is_left ? STEREO_LEFT_ID : STEREO_RIGHT_ID];
- color[3] = 0.25f; /* somewhat faint */
- glColor4fv(color);
- glBegin(GL_LINE_LOOP);
- for (i = 0, angle = 0.0f; i < ROT_AXIS_DETAIL; ++i, angle += step) {
- float p[3] = {s * cosf(angle), s * sinf(angle), 0.0f};
+ /* update the viewport matrices with the new camera */
+ if (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D) {
+ Camera *data;
+ float viewmat[4][4];
+ float shiftx;
- if (!upright) {
- mul_qt_v3(q, p);
- }
+ data = (Camera *)v3d->camera->data;
+ shiftx = data->shiftx;
- add_v3_v3(p, o);
- glVertex3fv(p);
- }
- glEnd();
+ BLI_lock_thread(LOCK_VIEW3D);
+ data->shiftx = BKE_camera_multiview_shift_x(&scene->r, v3d->camera, viewname);
-#undef ROT_AXIS_DETAIL
- }
+ BKE_camera_multiview_view_matrix(&scene->r, v3d->camera, is_left, viewmat);
+ view3d_main_region_setup_view(scene, v3d, ar, viewmat, NULL);
- color[3] = 1.0f; /* solid dot */
+ data->shiftx = shiftx;
+ BLI_unlock_thread(LOCK_VIEW3D);
}
- else
- color[3] = 0.5f; /* see-through dot */
-
- /* -- draw rotation center -- */
- glColor4fv(color);
- glBegin(GL_POINTS);
- glVertex3fv(o);
- glEnd();
-
-#if 0
- /* find screen coordinates for rotation center, then draw pretty icon */
- mul_m4_v3(rv3d->persinv, rot_center);
- UI_icon_draw(rot_center[0], rot_center[1], ICON_NDOF_TURN);
- /* ^^ just playing around, does not work */
-#endif
-
- glDisable(GL_BLEND);
- glDisable(GL_POINT_SMOOTH);
- glDepthMask(1);
-}
-#endif /* WITH_INPUT_NDOF */
-
-static void draw_view_icon(RegionView3D *rv3d, rcti *rect)
-{
- BIFIconID icon;
-
- if (ELEM(rv3d->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM))
- icon = ICON_AXIS_TOP;
- else if (ELEM(rv3d->view, RV3D_VIEW_FRONT, RV3D_VIEW_BACK))
- icon = ICON_AXIS_FRONT;
- else if (ELEM(rv3d->view, RV3D_VIEW_RIGHT, RV3D_VIEW_LEFT))
- icon = ICON_AXIS_SIDE;
- else return;
-
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
- UI_icon_draw(5.0 + rect->xmin, 5.0 + rect->ymin, icon);
-
- glDisable(GL_BLEND);
-}
+ else { /* SCE_VIEWS_FORMAT_MULTIVIEW */
+ float viewmat[4][4];
+ Object *view_ob = v3d->camera;
+ Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname);
-static const char *view3d_get_name(View3D *v3d, RegionView3D *rv3d)
-{
- const char *name = NULL;
-
- switch (rv3d->view) {
- case RV3D_VIEW_FRONT:
- if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Front Ortho");
- else name = IFACE_("Front Persp");
- break;
- case RV3D_VIEW_BACK:
- if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Back Ortho");
- else name = IFACE_("Back Persp");
- break;
- case RV3D_VIEW_TOP:
- if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Top Ortho");
- else name = IFACE_("Top Persp");
- break;
- case RV3D_VIEW_BOTTOM:
- if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Bottom Ortho");
- else name = IFACE_("Bottom Persp");
- break;
- case RV3D_VIEW_RIGHT:
- if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Right Ortho");
- else name = IFACE_("Right Persp");
- break;
- case RV3D_VIEW_LEFT:
- if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Left Ortho");
- else name = IFACE_("Left Persp");
- break;
-
- default:
- if (rv3d->persp == RV3D_CAMOB) {
- if ((v3d->camera) && (v3d->camera->type == OB_CAMERA)) {
- Camera *cam;
- cam = v3d->camera->data;
- if (cam->type == CAM_PERSP) {
- name = IFACE_("Camera Persp");
- }
- else if (cam->type == CAM_ORTHO) {
- name = IFACE_("Camera Ortho");
- }
- else {
- BLI_assert(cam->type == CAM_PANO);
- name = IFACE_("Camera Pano");
- }
- }
- else {
- name = IFACE_("Object as Camera");
- }
- }
- else {
- name = (rv3d->persp == RV3D_ORTHO) ? IFACE_("User Ortho") : IFACE_("User Persp");
- }
- break;
- }
-
- return name;
-}
+ BLI_lock_thread(LOCK_VIEW3D);
+ v3d->camera = camera;
-static void draw_viewport_name(ARegion *ar, View3D *v3d, rcti *rect)
-{
- RegionView3D *rv3d = ar->regiondata;
- const char *name = view3d_get_name(v3d, rv3d);
- /* increase size for unicode languages (Chinese in utf-8...) */
-#ifdef WITH_INTERNATIONAL
- char tmpstr[96];
-#else
- char tmpstr[32];
-#endif
+ BKE_camera_multiview_view_matrix(&scene->r, camera, false, viewmat);
+ view3d_main_region_setup_view(scene, v3d, ar, viewmat, NULL);
- if (v3d->localvd) {
- BLI_snprintf(tmpstr, sizeof(tmpstr), IFACE_("%s (Local)"), name);
- name = tmpstr;
+ v3d->camera = view_ob;
+ BLI_unlock_thread(LOCK_VIEW3D);
}
-
- UI_ThemeColor(TH_TEXT_HI);
-#ifdef WITH_INTERNATIONAL
- BLF_draw_default(U.widget_unit + rect->xmin, rect->ymax - U.widget_unit, 0.0f, name, sizeof(tmpstr));
-#else
- BLF_draw_default_ascii(U.widget_unit + rect->xmin, rect->ymax - U.widget_unit, 0.0f, name, sizeof(tmpstr));
-#endif
}
-/* draw info beside axes in bottom left-corner:
- * framenum, object name, bone name (if available), marker name (if available)
- */
-
-static void draw_selected_name(Scene *scene, Object *ob, rcti *rect)
-{
- const int cfra = CFRA;
- const char *msg_pin = " (Pinned)";
- const char *msg_sep = " : ";
-
- char info[300];
- const char *markern;
- char *s = info;
- short offset = 1.5f * UI_UNIT_X + rect->xmin;
-
- s += sprintf(s, "(%d)", cfra);
-
- /*
- * info can contain:
- * - a frame (7 + 2)
- * - 3 object names (MAX_NAME)
- * - 2 BREAD_CRUMB_SEPARATORs (6)
- * - a SHAPE_KEY_PINNED marker and a trailing '\0' (9+1) - translated, so give some room!
- * - a marker name (MAX_NAME + 3)
- */
-
- /* get name of marker on current frame (if available) */
- markern = BKE_scene_find_marker_name(scene, cfra);
-
- /* check if there is an object */
- if (ob) {
- *s++ = ' ';
- s += BLI_strcpy_rlen(s, ob->id.name + 2);
-
- /* name(s) to display depends on type of object */
- if (ob->type == OB_ARMATURE) {
- bArmature *arm = ob->data;
-
- /* show name of active bone too (if possible) */
- if (arm->edbo) {
- if (arm->act_edbone) {
- s += BLI_strcpy_rlen(s, msg_sep);
- s += BLI_strcpy_rlen(s, arm->act_edbone->name);
- }
- }
- else if (ob->mode & OB_MODE_POSE) {
- if (arm->act_bone) {
-
- if (arm->act_bone->layer & arm->layer) {
- s += BLI_strcpy_rlen(s, msg_sep);
- s += BLI_strcpy_rlen(s, arm->act_bone->name);
- }
- }
- }
- }
- else if (ELEM(ob->type, OB_MESH, OB_LATTICE, OB_CURVE)) {
- Key *key = NULL;
- KeyBlock *kb = NULL;
-
- /* try to display active bone and active shapekey too (if they exist) */
-
- if (ob->type == OB_MESH && ob->mode & OB_MODE_WEIGHT_PAINT) {
- Object *armobj = BKE_object_pose_armature_get(ob);
- if (armobj && armobj->mode & OB_MODE_POSE) {
- bArmature *arm = armobj->data;
- if (arm->act_bone) {
- if (arm->act_bone->layer & arm->layer) {
- s += BLI_strcpy_rlen(s, msg_sep);
- s += BLI_strcpy_rlen(s, arm->act_bone->name);
- }
- }
- }
- }
-
- key = BKE_key_from_object(ob);
- if (key) {
- kb = BLI_findlink(&key->block, ob->shapenr - 1);
- if (kb) {
- s += BLI_strcpy_rlen(s, msg_sep);
- s += BLI_strcpy_rlen(s, kb->name);
- if (ob->shapeflag & OB_SHAPE_LOCK) {
- s += BLI_strcpy_rlen(s, IFACE_(msg_pin));
- }
- }
- }
- }
-
- /* color depends on whether there is a keyframe */
- if (id_frame_has_keyframe((ID *)ob, /* BKE_scene_frame_get(scene) */ (float)cfra, ANIMFILTER_KEYS_LOCAL))
- UI_ThemeColor(TH_TIME_KEYFRAME);
- else if (ED_gpencil_has_keyframe_v3d(scene, ob, cfra))
- UI_ThemeColor(TH_TIME_GP_KEYFRAME);
- else
- UI_ThemeColor(TH_TEXT_HI);
- }
- else {
- /* no object */
- if (ED_gpencil_has_keyframe_v3d(scene, NULL, cfra))
- UI_ThemeColor(TH_TIME_GP_KEYFRAME);
- else
- UI_ThemeColor(TH_TEXT_HI);
- }
-
- if (markern) {
- s += sprintf(s, " <%s>", markern);
- }
-
- if (U.uiflag & USER_SHOW_ROTVIEWICON)
- offset = U.widget_unit + (U.rvisize * 2) + rect->xmin;
-
- BLF_draw_default(offset, 0.5f * U.widget_unit, 0.0f, info, sizeof(info));
-}
+/* ******************** view border ***************** */
static void view3d_camera_border(
const Scene *scene, const ARegion *ar, const View3D *v3d, const RegionView3D *rv3d,
@@ -1023,7 +321,7 @@ void ED_view3d_calc_camera_border(
view3d_camera_border(scene, ar, v3d, rv3d, r_viewborder, no_shift, false);
}
-static void drawviewborder_grid3(float x1, float x2, float y1, float y2, float fac)
+static void drawviewborder_grid3(unsigned pos, float x1, float x2, float y1, float y2, float fac)
{
float x3, y3, x4, y4;
@@ -1032,29 +330,29 @@ static void drawviewborder_grid3(float x1, float x2, float y1, float y2, float f
x4 = x1 + (1.0f - fac) * (x2 - x1);
y4 = y1 + (1.0f - fac) * (y2 - y1);
- glBegin(GL_LINES);
- glVertex2f(x1, y3);
- glVertex2f(x2, y3);
+ immBegin(GL_LINES, 8);
+ immVertex2f(pos, x1, y3);
+ immVertex2f(pos, x2, y3);
- glVertex2f(x1, y4);
- glVertex2f(x2, y4);
+ immVertex2f(pos, x1, y4);
+ immVertex2f(pos, x2, y4);
- glVertex2f(x3, y1);
- glVertex2f(x3, y2);
+ immVertex2f(pos, x3, y1);
+ immVertex2f(pos, x3, y2);
- glVertex2f(x4, y1);
- glVertex2f(x4, y2);
- glEnd();
+ immVertex2f(pos, x4, y1);
+ immVertex2f(pos, x4, y2);
+ immEnd();
}
/* harmonious triangle */
-static void drawviewborder_triangle(float x1, float x2, float y1, float y2, const char golden, const char dir)
+static void drawviewborder_triangle(unsigned pos, float x1, float x2, float y1, float y2, const char golden, const char dir)
{
float ofs;
float w = x2 - x1;
float h = y2 - y1;
- glBegin(GL_LINES);
+ immBegin(GL_LINES, 6);
if (w > h) {
if (golden) {
ofs = w * (1.0f - (1.0f / 1.61803399f));
@@ -1064,14 +362,14 @@ static void drawviewborder_triangle(float x1, float x2, float y1, float y2, cons
}
if (dir == 'B') SWAP(float, y1, y2);
- glVertex2f(x1, y1);
- glVertex2f(x2, y2);
+ immVertex2f(pos, x1, y1);
+ immVertex2f(pos, x2, y2);
- glVertex2f(x2, y1);
- glVertex2f(x1 + (w - ofs), y2);
+ immVertex2f(pos, x2, y1);
+ immVertex2f(pos, x1 + (w - ofs), y2);
- glVertex2f(x1, y2);
- glVertex2f(x1 + ofs, y1);
+ immVertex2f(pos, x1, y2);
+ immVertex2f(pos, x1 + ofs, y1);
}
else {
if (golden) {
@@ -1082,16 +380,16 @@ static void drawviewborder_triangle(float x1, float x2, float y1, float y2, cons
}
if (dir == 'B') SWAP(float, x1, x2);
- glVertex2f(x1, y1);
- glVertex2f(x2, y2);
+ immVertex2f(pos, x1, y1);
+ immVertex2f(pos, x2, y2);
- glVertex2f(x2, y1);
- glVertex2f(x1, y1 + ofs);
+ immVertex2f(pos, x2, y1);
+ immVertex2f(pos, x1, y1 + ofs);
- glVertex2f(x1, y2);
- glVertex2f(x2, y1 + (h - ofs));
+ immVertex2f(pos, x1, y2);
+ immVertex2f(pos, x2, y1 + (h - ofs));
}
- glEnd();
+ immEnd();
}
static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d)
@@ -1107,14 +405,14 @@ static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d)
return;
if (v3d->camera->type == OB_CAMERA)
ca = v3d->camera->data;
-
+
ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &viewborder, false);
/* the offsets */
x1 = viewborder.xmin;
y1 = viewborder.ymin;
x2 = viewborder.xmax;
y2 = viewborder.ymax;
-
+
glLineWidth(1.0f);
/* apply offsets so the real 3D camera shows through */
@@ -1128,43 +426,49 @@ static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d)
y1i = (int)(y1 - 1.0001f);
x2i = (int)(x2 + (1.0f - 0.0001f));
y2i = (int)(y2 + (1.0f - 0.0001f));
-
+
+ /* use the same program for everything */
+ VertexFormat *format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
/* passepartout, specified in camera edit buttons */
if (ca && (ca->flag & CAM_SHOWPASSEPARTOUT) && ca->passepartalpha > 0.000001f) {
const float winx = (ar->winx + 1);
const float winy = (ar->winy + 1);
- if (ca->passepartalpha == 1.0f) {
- glColor3f(0, 0, 0);
- }
- else {
+ float alpha = 1.0f;
+
+ if (ca->passepartalpha != 1.0f) {
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
- glColor4f(0, 0, 0, ca->passepartalpha);
+ alpha = ca->passepartalpha;
}
+ immUniformColor4f(0.0f, 0.0f, 0.0f, alpha);
+
if (x1i > 0.0f)
- glRectf(0.0, winy, x1i, 0.0);
+ immRectf(pos, 0.0f, winy, x1i, 0.0f);
if (x2i < winx)
- glRectf(x2i, winy, winx, 0.0);
+ immRectf(pos, x2i, winy, winx, 0.0f);
if (y2i < winy)
- glRectf(x1i, winy, x2i, y2i);
+ immRectf(pos, x1i, winy, x2i, y2i);
if (y2i > 0.0f)
- glRectf(x1i, y1i, x2i, 0.0);
-
+ immRectf(pos, x1i, y1i, x2i, 0.0f);
+
glDisable(GL_BLEND);
}
setlinestyle(0);
- UI_ThemeColor(TH_BACK);
-
- fdrawbox(x1i, y1i, x2i, y2i);
+ immUniformThemeColor(TH_BACK);
+ imm_draw_line_box(pos, x1i, y1i, x2i, y2i);
#ifdef VIEW3D_CAMERA_BORDER_HACK
if (view3d_camera_border_hack_test == true) {
- glColor3ubv(view3d_camera_border_hack_col);
- fdrawbox(x1i + 1, y1i + 1, x2i - 1, y2i - 1);
+ immUniformColor3ubv(view3d_camera_border_hack_col);
+ imm_draw_line_box(pos, x1i + 1, y1i + 1, x2i - 1, y2i - 1);
view3d_camera_border_hack_test = false;
}
#endif
@@ -1173,12 +477,12 @@ static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d)
/* outer line not to confuse with object selecton */
if (v3d->flag2 & V3D_LOCK_CAMERA) {
- UI_ThemeColor(TH_REDALERT);
- fdrawbox(x1i - 1, y1i - 1, x2i + 1, y2i + 1);
+ immUniformThemeColor(TH_REDALERT);
+ imm_draw_line_box(pos, x1i - 1, y1i - 1, x2i + 1, y2i + 1);
}
- UI_ThemeColor(TH_VIEW_OVERLAY);
- fdrawbox(x1i, y1i, x2i, y2i);
+ immUniformThemeColor(TH_VIEW_OVERLAY);
+ imm_draw_line_box(pos, x1i, y1i, x2i, y2i);
/* border */
if (scene->r.mode & R_BORDER) {
@@ -1189,8 +493,8 @@ static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d)
x4 = floorf(x1 + (scene->r.border.xmax * (x2 - x1))) + (U.pixelsize - 1);
y4 = floorf(y1 + (scene->r.border.ymax * (y2 - y1))) + (U.pixelsize - 1);
- cpack(0x4040FF);
- sdrawbox(x3, y3, x4, y4);
+ imm_cpack(0x4040FF);
+ imm_draw_line_box(pos, x3, y3, x4, y4);
}
/* safety border */
@@ -1198,71 +502,74 @@ static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d)
if (ca->dtx & CAM_DTX_CENTER) {
float x3, y3;
- UI_ThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25, 0);
-
x3 = x1 + 0.5f * (x2 - x1);
y3 = y1 + 0.5f * (y2 - y1);
- glBegin(GL_LINES);
- glVertex2f(x1, y3);
- glVertex2f(x2, y3);
+ immUniformThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25f, 0);
+ immBegin(GL_LINES, 4);
+
+ immVertex2f(pos, x1, y3);
+ immVertex2f(pos, x2, y3);
+
+ immVertex2f(pos, x3, y1);
+ immVertex2f(pos, x3, y2);
- glVertex2f(x3, y1);
- glVertex2f(x3, y2);
- glEnd();
+ immEnd();
}
if (ca->dtx & CAM_DTX_CENTER_DIAG) {
- UI_ThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25, 0);
- glBegin(GL_LINES);
- glVertex2f(x1, y1);
- glVertex2f(x2, y2);
+ immUniformThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25f, 0);
+ immBegin(GL_LINES, 4);
+
+ immVertex2f(pos, x1, y1);
+ immVertex2f(pos, x2, y2);
+
+ immVertex2f(pos, x1, y2);
+ immVertex2f(pos, x2, y1);
- glVertex2f(x1, y2);
- glVertex2f(x2, y1);
- glEnd();
+ immEnd();
}
if (ca->dtx & CAM_DTX_THIRDS) {
- UI_ThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25, 0);
- drawviewborder_grid3(x1, x2, y1, y2, 1.0f / 3.0f);
+ immUniformThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25f, 0);
+ drawviewborder_grid3(pos, x1, x2, y1, y2, 1.0f / 3.0f);
}
if (ca->dtx & CAM_DTX_GOLDEN) {
- UI_ThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25, 0);
- drawviewborder_grid3(x1, x2, y1, y2, 1.0f - (1.0f / 1.61803399f));
+ immUniformThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25f, 0);
+ drawviewborder_grid3(pos, x1, x2, y1, y2, 1.0f - (1.0f / 1.61803399f));
}
if (ca->dtx & CAM_DTX_GOLDEN_TRI_A) {
- UI_ThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25, 0);
- drawviewborder_triangle(x1, x2, y1, y2, 0, 'A');
+ immUniformThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25f, 0);
+ drawviewborder_triangle(pos, x1, x2, y1, y2, 0, 'A');
}
if (ca->dtx & CAM_DTX_GOLDEN_TRI_B) {
- UI_ThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25, 0);
- drawviewborder_triangle(x1, x2, y1, y2, 0, 'B');
+ immUniformThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25f, 0);
+ drawviewborder_triangle(pos, x1, x2, y1, y2, 0, 'B');
}
if (ca->dtx & CAM_DTX_HARMONY_TRI_A) {
- UI_ThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25, 0);
- drawviewborder_triangle(x1, x2, y1, y2, 1, 'A');
+ immUniformThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25f, 0);
+ drawviewborder_triangle(pos, x1, x2, y1, y2, 1, 'A');
}
if (ca->dtx & CAM_DTX_HARMONY_TRI_B) {
- UI_ThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25, 0);
- drawviewborder_triangle(x1, x2, y1, y2, 1, 'B');
+ immUniformThemeColorBlendShade(TH_VIEW_OVERLAY, TH_BACK, 0.25f, 0);
+ drawviewborder_triangle(pos, x1, x2, y1, y2, 1, 'B');
}
if (ca->flag & CAM_SHOW_SAFE_MARGINS) {
UI_draw_safe_areas(
- x1, x2, y1, y2,
+ pos, x1, x2, y1, y2,
scene->safe_areas.title,
scene->safe_areas.action);
if (ca->flag & CAM_SHOW_SAFE_CENTER) {
UI_draw_safe_areas(
- x1, x2, y1, y2,
+ pos, x1, x2, y1, y2,
scene->safe_areas.title_center,
scene->safe_areas.action_center);
}
@@ -1300,8 +607,9 @@ static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d)
}
/* draw */
- UI_ThemeColorShade(TH_VIEW_OVERLAY, 100);
- UI_draw_roundbox_gl_mode(GL_LINE_LOOP, rect.xmin, rect.ymin, rect.xmax, rect.ymax, 2.0f);
+ float color[4];
+ UI_GetThemeColorShade4fv(TH_VIEW_OVERLAY, 100, color);
+ UI_draw_roundbox_gl_mode(GL_LINE_LOOP, rect.xmin, rect.ymin, rect.xmax, rect.ymax, 2.0f, color);
}
}
@@ -1314,3161 +622,1045 @@ static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d)
x1i, y1i - (0.7f * U.widget_unit), 0.0f,
v3d->camera->id.name + 2, sizeof(v3d->camera->id.name) - 2);
}
+
+ immUnbindProgram();
+}
+
+static void drawrenderborder(ARegion *ar, View3D *v3d)
+{
+ /* use the same program for everything */
+ VertexFormat *format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ glLineWidth(1.0f);
+ setlinestyle(3);
+ imm_cpack(0x4040FF);
+
+ imm_draw_line_box(
+ pos, v3d->render_border.xmin * ar->winx, v3d->render_border.ymin * ar->winy,
+ v3d->render_border.xmax * ar->winx, v3d->render_border.ymax * ar->winy);
+
+ setlinestyle(0);
+
+ immUnbindProgram();
}
-/* *********************** backdraw for selection *************** */
+/* ******************** offline engine ***************** */
-static void backdrawview3d(Scene *scene, wmWindow *win, ARegion *ar, View3D *v3d)
+static bool view3d_draw_render_draw(const bContext *C, Scene *scene,
+ ARegion *ar, View3D *v3d,
+ bool clip_border, const rcti *border_rect)
{
RegionView3D *rv3d = ar->regiondata;
- struct Base *base = scene->basact;
- int multisample_enabled;
+ RenderEngineType *type;
+ GLint scissor[4];
- BLI_assert(ar->regiontype == RGN_TYPE_WINDOW);
+ /* create render engine */
+ if (!rv3d->render_engine) {
+ RenderEngine *engine;
- if (base && (base->object->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT) ||
- BKE_paint_select_face_test(base->object)))
- {
- /* do nothing */
- }
- /* texture paint mode sampling */
- else if (base && (base->object->mode & OB_MODE_TEXTURE_PAINT) &&
- (v3d->drawtype > OB_WIRE))
- {
- /* do nothing */
- }
- else if ((base && (base->object->mode & OB_MODE_PARTICLE_EDIT)) &&
- V3D_IS_ZBUF(v3d))
- {
- /* do nothing */
- }
- else if (scene->obedit &&
- V3D_IS_ZBUF(v3d))
- {
- /* do nothing */
- }
- else {
- v3d->flag &= ~V3D_INVALID_BACKBUF;
- return;
- }
+ type = RE_engines_find(scene->r.engine);
- if (!(v3d->flag & V3D_INVALID_BACKBUF))
- return;
+ if (!(type->view_update && type->view_draw))
+ return false;
-#if 0
- if (test) {
- if (qtest()) {
- addafterqueue(ar->win, BACKBUFDRAW, 1);
- return;
- }
- }
-#endif
+ engine = RE_engine_create_ex(type, true);
- if (v3d->drawtype > OB_WIRE) v3d->zbuf = true;
-
- /* dithering and AA break color coding, so disable */
- glDisable(GL_DITHER);
-
- multisample_enabled = glIsEnabled(GL_MULTISAMPLE);
- if (multisample_enabled)
- glDisable(GL_MULTISAMPLE);
-
- if (win->multisamples != USER_MULTISAMPLE_NONE) {
- /* for multisample we use an offscreen FBO. multisample drawing can fail
- * with color coded selection drawing, and reading back depths from such
- * a buffer can also cause a few seconds freeze on OS X / NVidia. */
- int w = BLI_rcti_size_x(&ar->winrct);
- int h = BLI_rcti_size_y(&ar->winrct);
- char error[256];
-
- if (rv3d->gpuoffscreen) {
- if (GPU_offscreen_width(rv3d->gpuoffscreen) != w ||
- GPU_offscreen_height(rv3d->gpuoffscreen) != h)
- {
- GPU_offscreen_free(rv3d->gpuoffscreen);
- rv3d->gpuoffscreen = NULL;
- }
- }
+ engine->tile_x = scene->r.tilex;
+ engine->tile_y = scene->r.tiley;
- if (!rv3d->gpuoffscreen) {
- rv3d->gpuoffscreen = GPU_offscreen_create(w, h, 0, error);
+ type->view_update(engine, C);
- if (!rv3d->gpuoffscreen)
- fprintf(stderr, "Failed to create offscreen selection buffer for multisample: %s\n", error);
- }
+ rv3d->render_engine = engine;
}
- if (rv3d->gpuoffscreen)
- GPU_offscreen_bind(rv3d->gpuoffscreen, true);
- else
- glScissor(ar->winrct.xmin, ar->winrct.ymin, BLI_rcti_size_x(&ar->winrct), BLI_rcti_size_y(&ar->winrct));
+ /* background draw */
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ ED_region_pixelspace(ar);
- glClearColor(0.0, 0.0, 0.0, 0.0);
- if (v3d->zbuf) {
- glEnable(GL_DEPTH_TEST);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- }
- else {
- glClear(GL_COLOR_BUFFER_BIT);
- glDisable(GL_DEPTH_TEST);
+ if (clip_border) {
+ /* for border draw, we only need to clear a subset of the 3d view */
+ if (border_rect->xmax > border_rect->xmin && border_rect->ymax > border_rect->ymin) {
+ glGetIntegerv(GL_SCISSOR_BOX, scissor);
+ glScissor(border_rect->xmin, border_rect->ymin,
+ BLI_rcti_size_x(border_rect), BLI_rcti_size_y(border_rect));
+ }
+ else {
+ return false;
+ }
}
-
- if (rv3d->rflag & RV3D_CLIPPING)
- ED_view3d_clipping_set(rv3d);
-
- G.f |= G_BACKBUFSEL;
-
- if (base && (base->lay & v3d->lay))
- draw_object_backbufsel(scene, v3d, rv3d, base->object);
-
- if (rv3d->gpuoffscreen)
- GPU_offscreen_unbind(rv3d->gpuoffscreen, true);
- else
- ar->swap = 0; /* mark invalid backbuf for wm draw */
-
- v3d->flag &= ~V3D_INVALID_BACKBUF;
-
- G.f &= ~G_BACKBUFSEL;
- v3d->zbuf = false;
- glDisable(GL_DEPTH_TEST);
- glEnable(GL_DITHER);
- if (multisample_enabled)
- glEnable(GL_MULTISAMPLE);
- if (rv3d->rflag & RV3D_CLIPPING)
- ED_view3d_clipping_disable();
-}
+ glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ /* don't change depth buffer */
+ glClear(GL_COLOR_BUFFER_BIT);
-void view3d_opengl_read_pixels(ARegion *ar, int x, int y, int w, int h, int format, int type, void *data)
-{
- RegionView3D *rv3d = ar->regiondata;
+ /* render result draw */
+ type = rv3d->render_engine->type;
+ type->view_draw(rv3d->render_engine, C);
- if (rv3d->gpuoffscreen) {
- GPU_offscreen_bind(rv3d->gpuoffscreen, true);
- glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
- glReadPixels(x, y, w, h, format, type, data);
- GPU_offscreen_unbind(rv3d->gpuoffscreen, true);
- }
- else {
- glReadPixels(ar->winrct.xmin + x, ar->winrct.ymin + y, w, h, format, type, data);
+ if (clip_border) {
+ /* restore scissor as it was before */
+ glScissor(scissor[0], scissor[1], scissor[2], scissor[3]);
}
-}
-/* XXX depth reading exception, for code not using gpu offscreen */
-static void view3d_opengl_read_Z_pixels(ARegion *ar, int x, int y, int w, int h, int format, int type, void *data)
-{
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
- glReadPixels(ar->winrct.xmin + x, ar->winrct.ymin + y, w, h, format, type, data);
+ return true;
}
-void ED_view3d_backbuf_validate(ViewContext *vc)
+/* ******************** solid plates ***************** */
+
+/**
+ *
+ */
+static void view3d_draw_background(const bContext *C)
{
- if (vc->v3d->flag & V3D_INVALID_BACKBUF)
- backdrawview3d(vc->scene, vc->win, vc->ar, vc->v3d);
+ /* TODO viewport */
+ UI_ThemeClearColor(TH_HIGH_GRAD);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
/**
- * allow for small values [0.5 - 2.5],
- * and large values, FLT_MAX by clamping by the area size
+ *
*/
-int ED_view3d_backbuf_sample_size_clamp(ARegion *ar, const float dist)
+static void view3d_draw_render_solid_surfaces(const bContext *C, ARegion *ar, const bool run_screen_shaders)
{
- return (int)min_ff(ceilf(dist), (float)max_ii(ar->winx, ar->winx));
+ /* TODO viewport */
+ draw_all_objects(C, ar, false, use_depth(C));
}
-/* samples a single pixel (copied from vpaint) */
-unsigned int ED_view3d_backbuf_sample(ViewContext *vc, int x, int y)
+/**
+ *
+ */
+static void view3d_draw_render_transparent_surfaces(const bContext *C)
{
- unsigned int col;
-
- if (x >= vc->ar->winx || y >= vc->ar->winy) {
- return 0;
- }
-
- ED_view3d_backbuf_validate(vc);
-
- view3d_opengl_read_pixels(vc->ar, x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col);
- glReadBuffer(GL_BACK);
-
- if (ENDIAN_ORDER == B_ENDIAN) {
- BLI_endian_switch_uint32(&col);
- }
-
- return GPU_select_to_index(col);
+ /* TODO viewport */
}
-/* reads full rect, converts indices */
-ImBuf *ED_view3d_backbuf_read(ViewContext *vc, int xmin, int ymin, int xmax, int ymax)
+/**
+ *
+ */
+static void view3d_draw_post_draw(const bContext *C)
{
- struct ImBuf *ibuf_clip;
- /* clip */
- const rcti clip = {
- max_ii(xmin, 0), min_ii(xmax, vc->ar->winx - 1),
- max_ii(ymin, 0), min_ii(ymax, vc->ar->winy - 1)};
- const int size_clip[2] = {
- BLI_rcti_size_x(&clip) + 1,
- BLI_rcti_size_y(&clip) + 1};
-
- if (UNLIKELY((clip.xmin > clip.xmax) ||
- (clip.ymin > clip.ymax)))
- {
- return NULL;
- }
-
- ibuf_clip = IMB_allocImBuf(size_clip[0], size_clip[1], 32, IB_rect);
-
- ED_view3d_backbuf_validate(vc);
-
- view3d_opengl_read_pixels(vc->ar, clip.xmin, clip.ymin, size_clip[0], size_clip[1], GL_RGBA, GL_UNSIGNED_BYTE, ibuf_clip->rect);
-
- glReadBuffer(GL_BACK);
+ /* TODO viewport */
+}
- if (ENDIAN_ORDER == B_ENDIAN) {
- IMB_convert_rgba_to_abgr(ibuf_clip);
- }
+/* ******************** geometry overlay ***************** */
- GPU_select_to_index_array(ibuf_clip->rect, size_clip[0] * size_clip[1]);
-
- if ((clip.xmin == xmin) &&
- (clip.xmax == xmax) &&
- (clip.ymin == ymin) &&
- (clip.ymax == ymax))
- {
- return ibuf_clip;
- }
- else {
- /* put clipped result into a non-clipped buffer */
- struct ImBuf *ibuf_full;
- const int size[2] = {
- (xmax - xmin + 1),
- (ymax - ymin + 1)};
-
- ibuf_full = IMB_allocImBuf(size[0], size[1], 32, IB_rect);
-
- IMB_rectcpy(
- ibuf_full, ibuf_clip,
- clip.xmin - xmin, clip.ymin - ymin,
- 0, 0,
- size_clip[0], size_clip[1]);
- IMB_freeImBuf(ibuf_clip);
- return ibuf_full;
- }
+/**
+ * Front/back wire frames
+ */
+static void view3d_draw_wire_plates(const bContext *C)
+{
+ /* TODO viewport */
}
-/* smart function to sample a rect spiralling outside, nice for backbuf selection */
-unsigned int ED_view3d_backbuf_sample_rect(
- ViewContext *vc, const int mval[2], int size,
- unsigned int min, unsigned int max, float *r_dist)
+/**
+ * Special treatment for selected objects
+ */
+static void view3d_draw_outline_plates(const bContext *C)
{
- struct ImBuf *buf;
- const unsigned int *bufmin, *bufmax, *tbuf;
- int minx, miny;
- int a, b, rc, nr, amount, dirvec[4][2];
- unsigned int index = 0;
-
- amount = (size - 1) / 2;
-
- minx = mval[0] - (amount + 1);
- miny = mval[1] - (amount + 1);
- buf = ED_view3d_backbuf_read(vc, minx, miny, minx + size - 1, miny + size - 1);
- if (!buf) return 0;
-
- rc = 0;
-
- dirvec[0][0] = 1; dirvec[0][1] = 0;
- dirvec[1][0] = 0; dirvec[1][1] = -size;
- dirvec[2][0] = -1; dirvec[2][1] = 0;
- dirvec[3][0] = 0; dirvec[3][1] = size;
-
- bufmin = buf->rect;
- tbuf = buf->rect;
- bufmax = buf->rect + size * size;
- tbuf += amount * size + amount;
-
- for (nr = 1; nr <= size; nr++) {
-
- for (a = 0; a < 2; a++) {
- for (b = 0; b < nr; b++) {
- if (*tbuf && *tbuf >= min && *tbuf < max) {
- /* we got a hit */
-
- /* get x,y pixel coords from the offset
- * (manhatten distance in keeping with other screen-based selection) */
- *r_dist = (float)(
- abs(((int)(tbuf - buf->rect) % size) - (size / 2)) +
- abs(((int)(tbuf - buf->rect) / size) - (size / 2)));
-
- /* indices start at 1 here */
- index = (*tbuf - min) + 1;
- goto exit;
- }
-
- tbuf += (dirvec[rc][0] + dirvec[rc][1]);
-
- if (tbuf < bufmin || tbuf >= bufmax) {
- goto exit;
- }
- }
- rc++;
- rc &= 3;
- }
- }
-
-exit:
- IMB_freeImBuf(buf);
- return index;
+ /* TODO viewport */
}
+/* ******************** other elements ***************** */
+
-/* ************************************************************* */
+#define DEBUG_GRID 0
-static void view3d_stereo_bgpic_setup(Scene *scene, View3D *v3d, Image *ima, ImageUser *iuser)
+static void gridline_range(double x0, double dx, double max, int* first_out, int* count_out)
{
- if (BKE_image_is_stereo(ima)) {
- iuser->flag |= IMA_SHOW_STEREO;
+ /* determine range of gridlines that appear in this Area -- similar calc but separate ranges for x & y
+ * x0 is gridline 0, the axis in screen space
+ * Area covers [0 .. max) pixels */
- if ((scene->r.scemode & R_MULTIVIEW) == 0) {
- iuser->multiview_eye = STEREO_LEFT_ID;
- }
- else if (v3d->stereo3d_camera != STEREO_3D_ID) {
- /* show only left or right camera */
- iuser->multiview_eye = v3d->stereo3d_camera;
- }
+ int first = (int)ceil(-x0 / dx);
+ int last = (int)floor((max - x0) / dx);
- BKE_image_multiview_index(ima, iuser);
+ if (first <= last) {
+ *first_out = first;
+ *count_out = last - first + 1;
}
else {
- iuser->flag &= ~IMA_SHOW_STEREO;
+ *first_out = 0;
+ *count_out = 0;
}
-}
-
-static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d,
- const bool do_foreground, const bool do_camera_frame)
-{
- RegionView3D *rv3d = ar->regiondata;
- BGpic *bgpic;
- int fg_flag = do_foreground ? V3D_BGPIC_FOREGROUND : 0;
-
- for (bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next) {
- bgpic->iuser.scene = scene; /* Needed for render results. */
-
- if ((bgpic->flag & V3D_BGPIC_FOREGROUND) != fg_flag)
- continue;
-
- if ((bgpic->view == 0) || /* zero for any */
- (bgpic->view & (1 << rv3d->view)) || /* check agaist flags */
- (rv3d->persp == RV3D_CAMOB && bgpic->view == (1 << RV3D_VIEW_CAMERA)))
- {
- float image_aspect[2];
- float fac, asp, zoomx, zoomy;
- float x1, y1, x2, y2, centx, centy;
-
- ImBuf *ibuf = NULL, *freeibuf, *releaseibuf;
- void *lock;
- rctf clip_rect;
-
- Image *ima = NULL;
- MovieClip *clip = NULL;
-
- /* disable individual images */
- if ((bgpic->flag & V3D_BGPIC_DISABLED))
- continue;
-
- freeibuf = NULL;
- releaseibuf = NULL;
- if (bgpic->source == V3D_BGPIC_IMAGE) {
- ima = bgpic->ima;
- if (ima == NULL)
- continue;
- BKE_image_user_frame_calc(&bgpic->iuser, CFRA, 0);
- if (ima->source == IMA_SRC_SEQUENCE && !(bgpic->iuser.flag & IMA_USER_FRAME_IN_RANGE)) {
- ibuf = NULL; /* frame is out of range, dont show */
- }
- else {
- view3d_stereo_bgpic_setup(scene, v3d, ima, &bgpic->iuser);
- ibuf = BKE_image_acquire_ibuf(ima, &bgpic->iuser, &lock);
- releaseibuf = ibuf;
- }
-
- image_aspect[0] = ima->aspx;
- image_aspect[1] = ima->aspy;
- }
- else if (bgpic->source == V3D_BGPIC_MOVIE) {
- /* TODO: skip drawing when out of frame range (as image sequences do above) */
-
- if (bgpic->flag & V3D_BGPIC_CAMERACLIP) {
- if (scene->camera)
- clip = BKE_object_movieclip_get(scene, scene->camera, true);
- }
- else {
- clip = bgpic->clip;
- }
-
- if (clip == NULL)
- continue;
-
- BKE_movieclip_user_set_frame(&bgpic->cuser, CFRA);
- ibuf = BKE_movieclip_get_ibuf(clip, &bgpic->cuser);
-
- image_aspect[0] = clip->aspx;
- image_aspect[1] = clip->aspy;
-
- /* working with ibuf from image and clip has got different workflow now.
- * ibuf acquired from clip is referenced by cache system and should
- * be dereferenced after usage. */
- freeibuf = ibuf;
- }
- else {
- /* perhaps when loading future files... */
- BLI_assert(0);
- copy_v2_fl(image_aspect, 1.0f);
- }
-
- if (ibuf == NULL)
- continue;
-
- if ((ibuf->rect == NULL && ibuf->rect_float == NULL) || ibuf->channels != 4) { /* invalid image format */
- if (freeibuf)
- IMB_freeImBuf(freeibuf);
- if (releaseibuf)
- BKE_image_release_ibuf(ima, releaseibuf, lock);
-
- continue;
- }
- if (ibuf->rect == NULL)
- IMB_rect_from_float(ibuf);
-
- if (rv3d->persp == RV3D_CAMOB) {
-
- if (do_camera_frame) {
- rctf vb;
- ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &vb, false);
- x1 = vb.xmin;
- y1 = vb.ymin;
- x2 = vb.xmax;
- y2 = vb.ymax;
- }
- else {
- x1 = ar->winrct.xmin;
- y1 = ar->winrct.ymin;
- x2 = ar->winrct.xmax;
- y2 = ar->winrct.ymax;
- }
-
- /* apply offset last - camera offset is different to offset in blender units */
- /* so this has some sane way of working - this matches camera's shift _exactly_ */
- {
- const float max_dim = max_ff(x2 - x1, y2 - y1);
- const float xof_scale = bgpic->xof * max_dim;
- const float yof_scale = bgpic->yof * max_dim;
-
- x1 += xof_scale;
- y1 += yof_scale;
- x2 += xof_scale;
- y2 += yof_scale;
- }
-
- centx = (x1 + x2) / 2.0f;
- centy = (y1 + y2) / 2.0f;
-
- /* aspect correction */
- if (bgpic->flag & V3D_BGPIC_CAMERA_ASPECT) {
- /* apply aspect from clip */
- const float w_src = ibuf->x * image_aspect[0];
- const float h_src = ibuf->y * image_aspect[1];
-
- /* destination aspect is already applied from the camera frame */
- const float w_dst = x1 - x2;
- const float h_dst = y1 - y2;
-
- const float asp_src = w_src / h_src;
- const float asp_dst = w_dst / h_dst;
-
- if (fabsf(asp_src - asp_dst) >= FLT_EPSILON) {
- if ((asp_src > asp_dst) == ((bgpic->flag & V3D_BGPIC_CAMERA_CROP) != 0)) {
- /* fit X */
- const float div = asp_src / asp_dst;
- x1 = ((x1 - centx) * div) + centx;
- x2 = ((x2 - centx) * div) + centx;
- }
- else {
- /* fit Y */
- const float div = asp_dst / asp_src;
- y1 = ((y1 - centy) * div) + centy;
- y2 = ((y2 - centy) * div) + centy;
- }
- }
- }
- }
- else {
- float tvec[3];
- float sco[2];
- const float mval_f[2] = {1.0f, 0.0f};
- const float co_zero[3] = {0};
- float zfac;
-
- /* calc window coord */
- zfac = ED_view3d_calc_zfac(rv3d, co_zero, NULL);
- ED_view3d_win_to_delta(ar, mval_f, tvec, zfac);
- fac = max_ff(fabsf(tvec[0]), max_ff(fabsf(tvec[1]), fabsf(tvec[2]))); /* largest abs axis */
- fac = 1.0f / fac;
-
- asp = (float)ibuf->y / (float)ibuf->x;
-
- zero_v3(tvec);
- ED_view3d_project_float_v2_m4(ar, tvec, sco, rv3d->persmat);
-
- x1 = sco[0] + fac * (bgpic->xof - bgpic->size);
- y1 = sco[1] + asp * fac * (bgpic->yof - bgpic->size);
- x2 = sco[0] + fac * (bgpic->xof + bgpic->size);
- y2 = sco[1] + asp * fac * (bgpic->yof + bgpic->size);
-
- centx = (x1 + x2) / 2.0f;
- centy = (y1 + y2) / 2.0f;
- }
-
- /* complete clip? */
- BLI_rctf_init(&clip_rect, x1, x2, y1, y2);
- if (bgpic->rotation) {
- BLI_rctf_rotate_expand(&clip_rect, &clip_rect, bgpic->rotation);
- }
-
- if (clip_rect.xmax < 0 || clip_rect.ymax < 0 || clip_rect.xmin > ar->winx || clip_rect.ymin > ar->winy) {
- if (freeibuf)
- IMB_freeImBuf(freeibuf);
- if (releaseibuf)
- BKE_image_release_ibuf(ima, releaseibuf, lock);
-
- continue;
- }
-
- zoomx = (x2 - x1) / ibuf->x;
- zoomy = (y2 - y1) / ibuf->y;
-
- /* for some reason; zoomlevels down refuses to use GL_ALPHA_SCALE */
- if (zoomx < 1.0f || zoomy < 1.0f) {
- float tzoom = min_ff(zoomx, zoomy);
- int mip = 0;
-
- if ((ibuf->userflags & IB_MIPMAP_INVALID) != 0) {
- IMB_remakemipmap(ibuf, 0);
- ibuf->userflags &= ~IB_MIPMAP_INVALID;
- }
- else if (ibuf->mipmap[0] == NULL)
- IMB_makemipmap(ibuf, 0);
-
- while (tzoom < 1.0f && mip < 8 && ibuf->mipmap[mip]) {
- tzoom *= 2.0f;
- zoomx *= 2.0f;
- zoomy *= 2.0f;
- mip++;
- }
- if (mip > 0)
- ibuf = ibuf->mipmap[mip - 1];
- }
-
- if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
- glDepthMask(0);
-
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
- ED_region_pixelspace(ar);
-
- glTranslatef(centx, centy, 0.0);
- glRotatef(RAD2DEGF(-bgpic->rotation), 0.0f, 0.0f, 1.0f);
-
- if (bgpic->flag & V3D_BGPIC_FLIP_X) {
- zoomx *= -1.0f;
- x1 = x2;
- }
- if (bgpic->flag & V3D_BGPIC_FLIP_Y) {
- zoomy *= -1.0f;
- y1 = y2;
- }
- glPixelZoom(zoomx, zoomy);
- glColor4f(1.0f, 1.0f, 1.0f, 1.0f - bgpic->blend);
-
- /* could not use glaDrawPixelsAuto because it could fallback to
- * glaDrawPixelsSafe in some cases, which will end up in missing
- * alpha transparency for the background image (sergey)
- */
- glaDrawPixelsTex(x1 - centx, y1 - centy, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_LINEAR, ibuf->rect);
-
- glPixelZoom(1.0, 1.0);
- glPixelTransferf(GL_ALPHA_SCALE, 1.0f);
-
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
-
- glDisable(GL_BLEND);
-
- glDepthMask(1);
- if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
-
- if (freeibuf)
- IMB_freeImBuf(freeibuf);
- if (releaseibuf)
- BKE_image_release_ibuf(ima, releaseibuf, lock);
- }
- }
+#if DEBUG_GRID
+ printf(" first %d * dx = %f\n", first, x0 + first * dx);
+ printf(" last %d * dx = %f\n", last, x0 + last * dx);
+ printf(" count = %d\n", *count_out);
+#endif
}
-static void view3d_draw_bgpic_test(Scene *scene, ARegion *ar, View3D *v3d,
- const bool do_foreground, const bool do_camera_frame)
+static int gridline_count(ARegion *ar, double x0, double y0, double dx)
{
- RegionView3D *rv3d = ar->regiondata;
-
- if ((v3d->flag & V3D_DISPBGPICS) == 0)
- return;
+ /* x0 & y0 establish the "phase" of the grid within this 2D region
+ * dx is the frequency, shared by x & y directions
+ * pass in dx of smallest (highest precision) grid we want to draw */
- /* disabled - mango request, since footage /w only render is quite useful
- * and this option is easy to disable all background images at once */
-#if 0
- if (v3d->flag2 & V3D_RENDER_OVERRIDE)
- return;
+#if DEBUG_GRID
+ printf(" %s(%f, %f, dx:%f)\n", __FUNCTION__, x0, y0, dx);
#endif
- if ((rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO)) {
- if (rv3d->persp == RV3D_CAMOB) {
- view3d_draw_bgpic(scene, ar, v3d, do_foreground, do_camera_frame);
- }
- }
- else {
- view3d_draw_bgpic(scene, ar, v3d, do_foreground, do_camera_frame);
- }
-}
+ int first, x_ct, y_ct;
-/* ****************** View3d afterdraw *************** */
+ gridline_range(x0, dx, ar->winx, &first, &x_ct);
+ gridline_range(y0, dx, ar->winy, &first, &y_ct);
-typedef struct View3DAfter {
- struct View3DAfter *next, *prev;
- struct Base *base;
- short dflag;
-} View3DAfter;
+ int total_ct = x_ct + y_ct;
-/* temp storage of Objects that need to be drawn as last */
-void ED_view3d_after_add(ListBase *lb, Base *base, const short dflag)
-{
- View3DAfter *v3da = MEM_callocN(sizeof(View3DAfter), "View 3d after");
- BLI_assert((base->flag & OB_FROMDUPLI) == 0);
- BLI_addtail(lb, v3da);
- v3da->base = base;
- v3da->dflag = dflag;
-}
+#if DEBUG_GRID
+ printf(" %d + %d = %d gridlines\n", x_ct, y_ct, total_ct);
+#endif
-/* disables write in zbuffer and draws it over */
-static void view3d_draw_transp(Scene *scene, ARegion *ar, View3D *v3d)
-{
- View3DAfter *v3da;
-
- glDepthMask(GL_FALSE);
- v3d->transp = true;
-
- while ((v3da = BLI_pophead(&v3d->afterdraw_transp))) {
- draw_object(scene, ar, v3d, v3da->base, v3da->dflag);
- MEM_freeN(v3da);
- }
- v3d->transp = false;
-
- glDepthMask(GL_TRUE);
-
+ return total_ct;
}
-/* clears zbuffer and draws it over */
-static void view3d_draw_xray(Scene *scene, ARegion *ar, View3D *v3d, bool *clear)
+static bool drawgrid_draw(ARegion *ar, double x0, double y0, double dx, int skip_mod, unsigned pos, unsigned col, GLubyte col_value[3])
{
- View3DAfter *v3da;
+ /* skip every skip_mod lines relative to each axis; they will be overlaid by another drawgrid_draw
+ * always skip exact x0 & y0 axes; they will be drawn later in color
+ *
+ * set grid color once, just before the first line is drawn
+ * it's harmless to set same color for every line, or every vertex
+ * but if no lines are drawn, color must not be set! */
- if (*clear && v3d->zbuf) {
- glClear(GL_DEPTH_BUFFER_BIT);
- *clear = false;
- }
+#if DEBUG_GRID
+ printf(" %s(%f, %f, dx:%f, skip_mod:%d)\n", __FUNCTION__, x0, y0, dx, skip_mod);
+#endif
- v3d->xray = true;
- while ((v3da = BLI_pophead(&v3d->afterdraw_xray))) {
- draw_object(scene, ar, v3d, v3da->base, v3da->dflag);
- MEM_freeN(v3da);
- }
- v3d->xray = false;
-}
+ const float x_max = (float)ar->winx;
+ const float y_max = (float)ar->winy;
+ int first, ct;
+ int x_ct = 0, y_ct = 0; /* count of lines actually drawn */
+ int lines_skipped_for_next_unit = 0;
-/* clears zbuffer and draws it over */
-static void view3d_draw_xraytransp(Scene *scene, ARegion *ar, View3D *v3d, const bool clear)
-{
- View3DAfter *v3da;
+ /* draw vertical lines */
+ gridline_range(x0, dx, x_max, &first, &ct);
- if (clear && v3d->zbuf)
- glClear(GL_DEPTH_BUFFER_BIT);
+ for (int i = first; i < first + ct; ++i) {
+ if (i == 0)
+ continue;
+ else if (skip_mod && (i % skip_mod) == 0) {
+ ++lines_skipped_for_next_unit;
+ continue;
+ }
- v3d->xray = true;
- v3d->transp = true;
-
- glDepthMask(GL_FALSE);
+ if (x_ct == 0)
+ immAttrib3ub(col, col_value[0], col_value[1], col_value[2]);
- while ((v3da = BLI_pophead(&v3d->afterdraw_xraytransp))) {
- draw_object(scene, ar, v3d, v3da->base, v3da->dflag);
- MEM_freeN(v3da);
+ float x = (float)(x0 + i * dx);
+ immVertex2f(pos, x, 0.0f);
+ immVertex2f(pos, x, y_max);
+ ++x_ct;
}
- v3d->transp = false;
- v3d->xray = false;
+ /* draw horizontal lines */
+ gridline_range(y0, dx, y_max, &first, &ct);
- glDepthMask(GL_TRUE);
-}
+ for (int i = first; i < first + ct; ++i) {
+ if (i == 0)
+ continue;
+ else if (skip_mod && (i % skip_mod) == 0) {
+ ++lines_skipped_for_next_unit;
+ continue;
+ }
-/* *********************** */
+ if (x_ct + y_ct == 0)
+ immAttrib3ub(col, col_value[0], col_value[1], col_value[2]);
-/*
- * In most cases call draw_dupli_objects,
- * draw_dupli_objects_color was added because when drawing set dupli's
- * we need to force the color
- */
+ float y = (float)(y0 + i * dx);
+ immVertex2f(pos, 0.0f, y);
+ immVertex2f(pos, x_max, y);
+ ++y_ct;
+ }
-#if 0
-int dupli_ob_sort(void *arg1, void *arg2)
-{
- void *p1 = ((DupliObject *)arg1)->ob;
- void *p2 = ((DupliObject *)arg2)->ob;
- int val = 0;
- if (p1 < p2) val = -1;
- else if (p1 > p2) val = 1;
- return val;
-}
+#if DEBUG_GRID
+ int total_ct = x_ct + y_ct;
+ printf(" %d + %d = %d gridlines drawn, %d skipped for next unit\n", x_ct, y_ct, total_ct, lines_skipped_for_next_unit);
#endif
-
-static DupliObject *dupli_step(DupliObject *dob)
-{
- while (dob && dob->no_draw)
- dob = dob->next;
- return dob;
+ return lines_skipped_for_next_unit > 0;
}
-static void draw_dupli_objects_color(
- Scene *scene, ARegion *ar, View3D *v3d, Base *base,
- const short dflag, const int color)
+#define GRID_MIN_PX_D 6.0
+#define GRID_MIN_PX_F 6.0f
+
+static void drawgrid(UnitSettings *unit, ARegion *ar, View3D *v3d, const char **grid_unit)
{
RegionView3D *rv3d = ar->regiondata;
- ListBase *lb;
- LodLevel *savedlod;
- DupliObject *dob_prev = NULL, *dob, *dob_next = NULL;
- Base tbase = {NULL};
- BoundBox bb, *bb_tmp; /* use a copy because draw_object, calls clear_mesh_caches */
- GLuint displist = 0;
- unsigned char color_rgb[3];
- const short dflag_dupli = dflag | DRAW_CONSTCOLOR;
- short transflag;
- bool use_displist = false; /* -1 is initialize */
- char dt;
- short dtx;
- DupliApplyData *apply_data;
-
- if (base->object->restrictflag & OB_RESTRICT_VIEW) return;
- if ((base->object->restrictflag & OB_RESTRICT_RENDER) && (v3d->flag2 & V3D_RENDER_OVERRIDE)) return;
-
- if (dflag & DRAW_CONSTCOLOR) {
- BLI_assert(color == TH_UNDEFINED);
- }
- else {
- UI_GetThemeColorBlend3ubv(color, TH_BACK, 0.5f, color_rgb);
- }
-
- tbase.flag = OB_FROMDUPLI | base->flag;
- lb = object_duplilist(G.main->eval_ctx, scene, base->object);
- // BLI_listbase_sort(lb, dupli_ob_sort); /* might be nice to have if we have a dupli list with mixed objects. */
-
- apply_data = duplilist_apply(base->object, scene, lb);
-
- dob = dupli_step(lb->first);
- if (dob) dob_next = dupli_step(dob->next);
-
- for (; dob; dob_prev = dob, dob = dob_next, dob_next = dob_next ? dupli_step(dob_next->next) : NULL) {
- bool testbb = false;
- tbase.object = dob->ob;
-
- /* Make sure lod is updated from dupli's position */
- savedlod = dob->ob->currentlod;
-
-#ifdef WITH_GAMEENGINE
- if (rv3d->rflag & RV3D_IS_GAME_ENGINE) {
- BKE_object_lod_update(dob->ob, rv3d->viewinv[3]);
- }
+#if DEBUG_GRID
+ printf("%s width %d, height %d\n", __FUNCTION__, ar->winx, ar->winy);
#endif
- /* extra service: draw the duplicator in drawtype of parent, minimum taken
- * to allow e.g. boundbox box objects in groups for LOD */
- dt = tbase.object->dt;
- tbase.object->dt = MIN2(tbase.object->dt, base->object->dt);
-
- /* inherit draw extra, but not if a boundbox under the assumption that this
- * is intended to speed up drawing, and drawing extra (especially wire) can
- * slow it down too much */
- dtx = tbase.object->dtx;
- if (tbase.object->dt != OB_BOUNDBOX)
- tbase.object->dtx = base->object->dtx;
-
- /* negative scale flag has to propagate */
- transflag = tbase.object->transflag;
-
- if (is_negative_m4(dob->mat))
- tbase.object->transflag |= OB_NEG_SCALE;
- else
- tbase.object->transflag &= ~OB_NEG_SCALE;
-
- /* should move outside the loop but possible color is set in draw_object still */
- if ((dflag & DRAW_CONSTCOLOR) == 0) {
- glColor3ubv(color_rgb);
- }
-
- /* generate displist, test for new object */
- if (dob_prev && dob_prev->ob != dob->ob) {
- if (use_displist == true)
- glDeleteLists(displist, 1);
-
- use_displist = false;
- }
-
- if ((bb_tmp = BKE_object_boundbox_get(dob->ob))) {
- bb = *bb_tmp; /* must make a copy */
- testbb = true;
- }
+ double fx = rv3d->persmat[3][0];
+ double fy = rv3d->persmat[3][1];
+ double fw = rv3d->persmat[3][3];
- if (!testbb || ED_view3d_boundbox_clip_ex(rv3d, &bb, dob->mat)) {
- /* generate displist */
- if (use_displist == false) {
-
- /* note, since this was added, its checked (dob->type == OB_DUPLIGROUP)
- * however this is very slow, it was probably needed for the NLA
- * offset feature (used in group-duplicate.blend but no longer works in 2.5)
- * so for now it should be ok to - campbell */
-
- if ( /* if this is the last no need to make a displist */
- (dob_next == NULL || dob_next->ob != dob->ob) ||
- /* lamp drawing messes with matrices, could be handled smarter... but this works */
- (dob->ob->type == OB_LAMP) ||
- (dob->type == OB_DUPLIGROUP && dob->animated) ||
- !bb_tmp ||
- draw_glsl_material(scene, dob->ob, v3d, dt) ||
- check_object_draw_texture(scene, v3d, dt) ||
- (v3d->flag2 & V3D_SOLID_MATCAP) != 0)
- {
- // printf("draw_dupli_objects_color: skipping displist for %s\n", dob->ob->id.name + 2);
- use_displist = false;
- }
- else {
- // printf("draw_dupli_objects_color: using displist for %s\n", dob->ob->id.name + 2);
-
- /* disable boundbox check for list creation */
- BKE_object_boundbox_flag(dob->ob, BOUNDBOX_DISABLED, 1);
- /* need this for next part of code */
- unit_m4(dob->ob->obmat); /* obmat gets restored */
-
- displist = glGenLists(1);
- glNewList(displist, GL_COMPILE);
- draw_object(scene, ar, v3d, &tbase, dflag_dupli);
- glEndList();
-
- use_displist = true;
- BKE_object_boundbox_flag(dob->ob, BOUNDBOX_DISABLED, 0);
- }
- }
-
- if (use_displist) {
- glPushMatrix();
- glMultMatrixf(dob->mat);
- glCallList(displist);
- glPopMatrix();
- }
- else {
- copy_m4_m4(dob->ob->obmat, dob->mat);
- GPU_begin_dupli_object(dob);
- draw_object(scene, ar, v3d, &tbase, dflag_dupli);
- GPU_end_dupli_object();
- }
- }
-
- tbase.object->dt = dt;
- tbase.object->dtx = dtx;
- tbase.object->transflag = transflag;
- tbase.object->currentlod = savedlod;
- }
+ const double wx = 0.5 * ar->winx; /* use double precision to avoid rounding errors */
+ const double wy = 0.5 * ar->winy;
- if (apply_data) {
- duplilist_restore(lb, apply_data);
- duplilist_free_apply_data(apply_data);
- }
+ double x = wx * fx / fw;
+ double y = wy * fy / fw;
- free_object_duplilist(lb);
-
- if (use_displist)
- glDeleteLists(displist, 1);
-}
+ double vec4[4] = { v3d->grid, v3d->grid, 0.0, 1.0 };
+ mul_m4_v4d(rv3d->persmat, vec4);
+ fx = vec4[0];
+ fy = vec4[1];
+ fw = vec4[3];
-static void draw_dupli_objects(Scene *scene, ARegion *ar, View3D *v3d, Base *base)
-{
- /* define the color here so draw_dupli_objects_color can be called
- * from the set loop */
-
- int color = (base->flag & SELECT) ? TH_SELECT : TH_WIRE;
- /* debug */
- if (base->object->dup_group && base->object->dup_group->id.us < 1)
- color = TH_REDALERT;
-
- draw_dupli_objects_color(scene, ar, v3d, base, 0, color);
-}
+ double dx = fabs(x - wx * fx / fw);
+ if (dx == 0) dx = fabs(y - wy * fy / fw);
-/* XXX warning, not using gpu offscreen here */
-void view3d_update_depths_rect(ARegion *ar, ViewDepths *d, rcti *rect)
-{
- int x, y, w, h;
- rcti r;
- /* clamp rect by region */
+ x += wx;
+ y += wy;
- r.xmin = 0;
- r.xmax = ar->winx - 1;
- r.ymin = 0;
- r.ymax = ar->winy - 1;
+ /* now x, y, and dx have their final values
+ * (x,y) is the world origin (0,0,0) mapped to Area-relative screen space
+ * dx is the distance in pixels between grid lines -- same for horiz or vert grid lines */
- /* Constrain rect to depth bounds */
- BLI_rcti_isect(&r, rect, rect);
+ glLineWidth(1.0f);
- /* assign values to compare with the ViewDepths */
- x = rect->xmin;
- y = rect->ymin;
+ glDepthMask(GL_FALSE); /* disable write in zbuffer */
- w = BLI_rcti_size_x(rect);
- h = BLI_rcti_size_y(rect);
+ VertexFormat* format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ unsigned color = add_attrib(format, "color", GL_UNSIGNED_BYTE, 3, NORMALIZE_INT_TO_FLOAT);
- if (w <= 0 || h <= 0) {
- if (d->depths)
- MEM_freeN(d->depths);
- d->depths = NULL;
+ immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
- d->damaged = false;
- }
- else if (d->w != w ||
- d->h != h ||
- d->x != x ||
- d->y != y ||
- d->depths == NULL
- )
- {
- d->x = x;
- d->y = y;
- d->w = w;
- d->h = h;
+ unsigned char col[3], col2[3];
+ UI_GetThemeColor3ubv(TH_GRID, col);
- if (d->depths)
- MEM_freeN(d->depths);
+ if (unit->system) {
+ const void *usys;
+ int len;
- d->depths = MEM_mallocN(sizeof(float) * d->w * d->h, "View depths Subset");
-
- d->damaged = true;
- }
+ bUnit_GetSystem(unit->system, B_UNIT_LENGTH, &usys, &len);
- if (d->damaged) {
- /* XXX using special function here, it doesn't use the gpu offscreen system */
- view3d_opengl_read_Z_pixels(ar, d->x, d->y, d->w, d->h, GL_DEPTH_COMPONENT, GL_FLOAT, d->depths);
- glGetDoublev(GL_DEPTH_RANGE, d->depth_range);
- d->damaged = false;
- }
-}
+ bool first = true;
-/* note, with nouveau drivers the glReadPixels() is very slow. [#24339] */
-void ED_view3d_depth_update(ARegion *ar)
-{
- RegionView3D *rv3d = ar->regiondata;
-
- /* Create storage for, and, if necessary, copy depth buffer */
- if (!rv3d->depths) rv3d->depths = MEM_callocN(sizeof(ViewDepths), "ViewDepths");
- if (rv3d->depths) {
- ViewDepths *d = rv3d->depths;
- if (d->w != ar->winx ||
- d->h != ar->winy ||
- !d->depths)
- {
- d->w = ar->winx;
- d->h = ar->winy;
- if (d->depths)
- MEM_freeN(d->depths);
- d->depths = MEM_mallocN(sizeof(float) * d->w * d->h, "View depths");
- d->damaged = true;
- }
-
- if (d->damaged) {
- view3d_opengl_read_pixels(ar, 0, 0, d->w, d->h, GL_DEPTH_COMPONENT, GL_FLOAT, d->depths);
- glGetDoublev(GL_DEPTH_RANGE, d->depth_range);
-
- d->damaged = false;
- }
- }
-}
+ if (usys) {
+ int i = len;
+ while (i--) {
+ double scalar = bUnit_GetScaler(usys, i);
-/* utility function to find the closest Z value, use for autodepth */
-float view3d_depth_near(ViewDepths *d)
-{
- /* convert to float for comparisons */
- const float near = (float)d->depth_range[0];
- const float far_real = (float)d->depth_range[1];
- float far = far_real;
-
- const float *depths = d->depths;
- float depth = FLT_MAX;
- int i = (int)d->w * (int)d->h; /* cast to avoid short overflow */
-
- /* far is both the starting 'far' value
- * and the closest value found. */
- while (i--) {
- depth = *depths++;
- if ((depth < far) && (depth > near)) {
- far = depth;
- }
- }
+ double dx_scalar = dx * scalar / (double)unit->scale_length;
+ if (dx_scalar < (GRID_MIN_PX_D * 2.0)) {
+ /* very very small grid items are less useful when dealing with units */
+ continue;
+ }
- return far == far_real ? FLT_MAX : far;
-}
+ if (first) {
+ first = false;
-void ED_view3d_draw_depth_gpencil(Scene *scene, ARegion *ar, View3D *v3d)
-{
- short zbuf = v3d->zbuf;
- RegionView3D *rv3d = ar->regiondata;
-
- view3d_winmatrix_set(ar, v3d, NULL);
- view3d_viewmatrix_set(scene, v3d, rv3d); /* note: calls BKE_object_where_is_calc for camera... */
+ /* Store the smallest drawn grid size units name so users know how big each grid cell is */
+ *grid_unit = bUnit_GetNameDisplay(usys, i);
+ rv3d->gridview = (float)((scalar * (double)v3d->grid) / (double)unit->scale_length);
- mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat);
- invert_m4_m4(rv3d->persinv, rv3d->persmat);
- invert_m4_m4(rv3d->viewinv, rv3d->viewmat);
+ int gridline_ct = gridline_count(ar, x, y, dx_scalar);
+ if (gridline_ct == 0)
+ goto drawgrid_cleanup; /* nothing to draw */
- glClear(GL_DEPTH_BUFFER_BIT);
+ immBegin(GL_LINES, gridline_ct * 2);
+ }
- glLoadMatrixf(rv3d->viewmat);
+ float blend_fac = 1.0f - ((GRID_MIN_PX_F * 2.0f) / (float)dx_scalar);
+ /* tweak to have the fade a bit nicer */
+ blend_fac = (blend_fac * blend_fac) * 2.0f;
+ CLAMP(blend_fac, 0.3f, 1.0f);
- v3d->zbuf = true;
- glEnable(GL_DEPTH_TEST);
+ UI_GetThemeColorBlend3ubv(TH_HIGH_GRAD, TH_GRID, blend_fac, col2);
- if (v3d->flag2 & V3D_SHOW_GPENCIL) {
- ED_gpencil_draw_view3d(NULL, scene, v3d, ar, true);
+ const int skip_mod = (i == 0) ? 0 : (int)round(bUnit_GetScaler(usys, i - 1) / scalar);
+#if DEBUG_GRID
+ printf("%s %f, ", bUnit_GetNameDisplay(usys, i), scalar);
+ if (i > 0)
+ printf("next unit is %d times larger\n", skip_mod);
+ else
+ printf("largest unit\n");
+#endif
+ if (!drawgrid_draw(ar, x, y, dx_scalar, skip_mod, pos, color, col2))
+ break;
+ }
+ }
}
-
- v3d->zbuf = zbuf;
-
-}
+ else {
+ const double sublines = v3d->gridsubdiv;
+ const float sublines_fl = v3d->gridsubdiv;
-void ED_view3d_draw_depth(Scene *scene, ARegion *ar, View3D *v3d, bool alphaoverride)
-{
- RegionView3D *rv3d = ar->regiondata;
- Base *base;
- short zbuf = v3d->zbuf;
- short flag = v3d->flag;
- float glalphaclip = U.glalphaclip;
- int obcenter_dia = U.obcenter_dia;
- /* no need for color when drawing depth buffer */
- const short dflag_depth = DRAW_CONSTCOLOR;
- /* temp set drawtype to solid */
-
- /* Setting these temporarily is not nice */
- v3d->flag &= ~V3D_SELECT_OUTLINE;
- U.glalphaclip = alphaoverride ? 0.5f : glalphaclip; /* not that nice but means we wont zoom into billboards */
- U.obcenter_dia = 0;
-
- view3d_winmatrix_set(ar, v3d, NULL);
- view3d_viewmatrix_set(scene, v3d, rv3d); /* note: calls BKE_object_where_is_calc for camera... */
-
- mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat);
- invert_m4_m4(rv3d->persinv, rv3d->persmat);
- invert_m4_m4(rv3d->viewinv, rv3d->viewmat);
-
- glClear(GL_DEPTH_BUFFER_BIT);
-
- glLoadMatrixf(rv3d->viewmat);
-
- if (rv3d->rflag & RV3D_CLIPPING) {
- ED_view3d_clipping_set(rv3d);
- }
- /* get surface depth without bias */
- rv3d->rflag |= RV3D_ZOFFSET_DISABLED;
+ int grids_to_draw = 2; /* first the faint fine grid, then the bold coarse grid */
- v3d->zbuf = true;
- glEnable(GL_DEPTH_TEST);
-
- /* draw set first */
- if (scene->set) {
- Scene *sce_iter;
- for (SETLOOPER(scene->set, sce_iter, base)) {
- if (v3d->lay & base->lay) {
- draw_object(scene, ar, v3d, base, 0);
- if (base->object->transflag & OB_DUPLI) {
- draw_dupli_objects_color(scene, ar, v3d, base, dflag_depth, TH_UNDEFINED);
+ if (dx < GRID_MIN_PX_D) {
+ rv3d->gridview *= sublines_fl;
+ dx *= sublines;
+ if (dx < GRID_MIN_PX_D) {
+ rv3d->gridview *= sublines_fl;
+ dx *= sublines;
+ if (dx < GRID_MIN_PX_D) {
+ rv3d->gridview *= sublines_fl;
+ dx *= sublines;
+ grids_to_draw = (dx < GRID_MIN_PX_D) ? 0 : 1;
}
}
}
- }
-
- for (base = scene->base.first; base; base = base->next) {
- if (v3d->lay & base->lay) {
- /* dupli drawing */
- if (base->object->transflag & OB_DUPLI) {
- draw_dupli_objects_color(scene, ar, v3d, base, dflag_depth, TH_UNDEFINED);
+ else {
+ if (dx >(GRID_MIN_PX_D * 10.0)) { /* start blending in */
+ rv3d->gridview /= sublines_fl;
+ dx /= sublines;
+ if (dx > (GRID_MIN_PX_D * 10.0)) { /* start blending in */
+ rv3d->gridview /= sublines_fl;
+ dx /= sublines;
+ if (dx > (GRID_MIN_PX_D * 10.0)) {
+ grids_to_draw = 1;
+ }
+ }
}
- draw_object(scene, ar, v3d, base, dflag_depth);
}
- }
-
- /* this isn't that nice, draw xray objects as if they are normal */
- if (v3d->afterdraw_transp.first ||
- v3d->afterdraw_xray.first ||
- v3d->afterdraw_xraytransp.first)
- {
- View3DAfter *v3da;
- int mask_orig;
-
- v3d->xray = true;
-
- /* transp materials can change the depth mask, see #21388 */
- glGetIntegerv(GL_DEPTH_WRITEMASK, &mask_orig);
+ int gridline_ct = gridline_count(ar, x, y, dx);
+ if (gridline_ct == 0)
+ goto drawgrid_cleanup; /* nothing to draw */
- if (v3d->afterdraw_xray.first || v3d->afterdraw_xraytransp.first) {
- glDepthFunc(GL_ALWAYS); /* always write into the depth bufer, overwriting front z values */
- for (v3da = v3d->afterdraw_xray.first; v3da; v3da = v3da->next) {
- draw_object(scene, ar, v3d, v3da->base, dflag_depth);
- }
- glDepthFunc(GL_LEQUAL); /* Now write the depth buffer normally */
- }
+ immBegin(GL_LINES, gridline_ct * 2);
- /* draw 3 passes, transp/xray/xraytransp */
- v3d->xray = false;
- v3d->transp = true;
- while ((v3da = BLI_pophead(&v3d->afterdraw_transp))) {
- draw_object(scene, ar, v3d, v3da->base, dflag_depth);
- MEM_freeN(v3da);
+ if (grids_to_draw == 2) {
+ UI_GetThemeColorBlend3ubv(TH_HIGH_GRAD, TH_GRID, dx / (GRID_MIN_PX_D * 6.0), col2);
+ if (drawgrid_draw(ar, x, y, dx, v3d->gridsubdiv, pos, color, col2))
+ drawgrid_draw(ar, x, y, dx * sublines, 0, pos, color, col);
}
-
- v3d->xray = true;
- v3d->transp = false;
- while ((v3da = BLI_pophead(&v3d->afterdraw_xray))) {
- draw_object(scene, ar, v3d, v3da->base, dflag_depth);
- MEM_freeN(v3da);
+ else if (grids_to_draw == 1) {
+ drawgrid_draw(ar, x, y, dx, 0, pos, color, col);
}
-
- v3d->xray = true;
- v3d->transp = true;
- while ((v3da = BLI_pophead(&v3d->afterdraw_xraytransp))) {
- draw_object(scene, ar, v3d, v3da->base, dflag_depth);
- MEM_freeN(v3da);
- }
-
-
- v3d->xray = false;
- v3d->transp = false;
-
- glDepthMask(mask_orig);
- }
-
- if (rv3d->rflag & RV3D_CLIPPING) {
- ED_view3d_clipping_disable();
}
- rv3d->rflag &= ~RV3D_ZOFFSET_DISABLED;
-
- v3d->zbuf = zbuf;
- if (!v3d->zbuf) glDisable(GL_DEPTH_TEST);
-
- U.glalphaclip = glalphaclip;
- v3d->flag = flag;
- U.obcenter_dia = obcenter_dia;
-}
-typedef struct View3DShadow {
- struct View3DShadow *next, *prev;
- GPULamp *lamp;
-} View3DShadow;
-
-static void gpu_render_lamp_update(Scene *scene, View3D *v3d,
- Object *ob, Object *par,
- float obmat[4][4], unsigned int lay,
- ListBase *shadows, SceneRenderLayer *srl)
-{
- GPULamp *lamp;
- Lamp *la = (Lamp *)ob->data;
- View3DShadow *shadow;
- unsigned int layers;
-
- lamp = GPU_lamp_from_blender(scene, ob, par, BKE_scene_use_new_shading_nodes(scene));
-
- if (lamp) {
- bool hide = (ob->restrictflag & OB_RESTRICT_VIEW);
- GPU_lamp_update(lamp, lay, hide, obmat);
- GPU_lamp_update_colors(lamp, la->r, la->g, la->b, la->energy);
-
- if (la->area_shape == LA_AREA_SQUARE)
- GPU_lamp_update_size(lamp, la->area_size, la->area_size);
- else
- GPU_lamp_update_size(lamp, la->area_size, la->area_sizey);
-
- layers = lay & v3d->lay;
- if (srl)
- layers &= srl->lay;
-
- if (layers &&
- GPU_lamp_has_shadow_buffer(lamp) &&
- /* keep last, may do string lookup */
- GPU_lamp_override_visible(lamp, srl, NULL))
- {
- shadow = MEM_callocN(sizeof(View3DShadow), "View3DShadow");
- shadow->lamp = lamp;
- BLI_addtail(shadows, shadow);
- }
+ /* draw visible axes */
+ /* horizontal line */
+ if (0 <= y && y < ar->winy) {
+ UI_make_axis_color(col, col2, ELEM(rv3d->view, RV3D_VIEW_RIGHT, RV3D_VIEW_LEFT) ? 'Y' : 'X');
+ immAttrib3ub(color, col2[0], col2[1], col2[2]);
+ immVertex2f(pos, 0.0f, y);
+ immVertex2f(pos, (float)ar->winx, y);
}
-}
-static void gpu_update_lamps_shadows_world(Scene *scene, View3D *v3d)
-{
- ListBase shadows;
- View3DShadow *shadow;
- Scene *sce_iter;
- Base *base;
- Object *ob;
- World *world = scene->world;
- SceneRenderLayer *srl = v3d->scenelock ? BLI_findlink(&scene->r.layers, scene->r.actlay) : NULL;
-
- BLI_listbase_clear(&shadows);
-
- /* update lamp transform and gather shadow lamps */
- for (SETLOOPER(scene, sce_iter, base)) {
- ob = base->object;
-
- if (ob->type == OB_LAMP)
- gpu_render_lamp_update(scene, v3d, ob, NULL, ob->obmat, ob->lay, &shadows, srl);
-
- if (ob->transflag & OB_DUPLI) {
- DupliObject *dob;
- ListBase *lb = object_duplilist(G.main->eval_ctx, scene, ob);
-
- for (dob = lb->first; dob; dob = dob->next)
- if (dob->ob->type == OB_LAMP)
- gpu_render_lamp_update(scene, v3d, dob->ob, ob, dob->mat, ob->lay, &shadows, srl);
-
- free_object_duplilist(lb);
- }
- }
-
- /* render shadows after updating all lamps, nested object_duplilist
- * don't work correct since it's replacing object matrices */
- for (shadow = shadows.first; shadow; shadow = shadow->next) {
- /* this needs to be done better .. */
- float viewmat[4][4], winmat[4][4];
- int drawtype, lay, winsize, flag2 = v3d->flag2;
- ARegion ar = {NULL};
- RegionView3D rv3d = {{{0}}};
-
- drawtype = v3d->drawtype;
- lay = v3d->lay;
-
- v3d->drawtype = OB_SOLID;
- v3d->lay &= GPU_lamp_shadow_layer(shadow->lamp);
- v3d->flag2 &= ~(V3D_SOLID_TEX | V3D_SHOW_SOLID_MATCAP);
- v3d->flag2 |= V3D_RENDER_OVERRIDE | V3D_RENDER_SHADOW;
-
- GPU_lamp_shadow_buffer_bind(shadow->lamp, viewmat, &winsize, winmat);
-
- ar.regiondata = &rv3d;
- ar.regiontype = RGN_TYPE_WINDOW;
- rv3d.persp = RV3D_CAMOB;
- copy_m4_m4(rv3d.winmat, winmat);
- copy_m4_m4(rv3d.viewmat, viewmat);
- invert_m4_m4(rv3d.viewinv, rv3d.viewmat);
- mul_m4_m4m4(rv3d.persmat, rv3d.winmat, rv3d.viewmat);
- invert_m4_m4(rv3d.persinv, rv3d.viewinv);
-
- /* no need to call ED_view3d_draw_offscreen_init since shadow buffers were already updated */
- ED_view3d_draw_offscreen(
- scene, v3d, &ar, winsize, winsize, viewmat, winmat,
- false, false, true, true,
- NULL, NULL, NULL, NULL);
- GPU_lamp_shadow_buffer_unbind(shadow->lamp);
-
- v3d->drawtype = drawtype;
- v3d->lay = lay;
- v3d->flag2 = flag2;
- }
-
- BLI_freelistN(&shadows);
-
- /* update world values */
- if (world) {
- GPU_mist_update_enable(world->mode & WO_MIST);
- GPU_mist_update_values(world->mistype, world->miststa, world->mistdist, world->misi, &world->horr);
- GPU_horizon_update_color(&world->horr);
- GPU_ambient_update_color(&world->ambr);
- GPU_zenith_update_color(&world->zenr);
+ /* vertical line */
+ if (0 <= x && x < ar->winx) {
+ UI_make_axis_color(col, col2, ELEM(rv3d->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM) ? 'Y' : 'Z');
+ immAttrib3ub(color, col2[0], col2[1], col2[2]);
+ immVertex2f(pos, x, 0.0f);
+ immVertex2f(pos, x, (float)ar->winy);
}
-}
-/* ***************** Probes rendering *************** */
+ immEnd();
-typedef struct View3DProbe {
- struct View3DProbe *next, *prev;
- GPUProbe *probe;
-} View3DProbe;
+drawgrid_cleanup:
+ immUnbindProgram();
+ glDepthMask(GL_TRUE); /* enable write in zbuffer */
+}
-static void gpu_update_probes(Scene *scene, View3D *v3d, ARegion *basear)
+#undef DEBUG_GRID
+#undef GRID_MIN_PX_D
+#undef GRID_MIN_PX_F
+
+static void drawfloor(Scene *scene, View3D *v3d, const char **grid_unit, bool write_depth)
{
- ListBase probelist;
- ListBase afterlist;
- int i = 0;
- bool do_sky = false;
- View3DProbe *vprobe;
- GPUProbe *probe;
- Scene *sce_iter;
- Object *ob;
- Base *base;
- RegionView3D *baserv3d = basear->regiondata;
-
- /* gathering probes */
- BLI_listbase_clear(&probelist);
- BLI_listbase_clear(&afterlist);
-
- /* Order matters : watch BLI_addhead and BLI_addtail
- * rendering the world first
- * then the cubemaps
- * finally the planar reflections. */
-
- /* Objects Probe (don't do dupliobjects) */
- for (SETLOOPER(scene, sce_iter, base)) {
- ob = base->object;
-
- if (ob->probetype == OB_PROBE_CUBEMAP || ob->probetype == OB_PROBE_PLANAR) {
- probe = GPU_probe_object(scene, ob);
-
- /* XXX free probes if size or type changes */
- if (probe && ((GPU_probe_get_size(probe) != ob->probesize) ||
- (GPU_probe_get_type(probe) != ob->probetype))) {
- if (ob->gpuprobe.first)
- GPU_probe_free(&ob->gpuprobe);
- probe = GPU_probe_object(scene, ob);
- }
+ /* draw only if there is something to draw */
+ if (v3d->gridflag & (V3D_SHOW_FLOOR | V3D_SHOW_X | V3D_SHOW_Y | V3D_SHOW_Z)) {
+ /* draw how many lines?
+ * trunc(v3d->gridlines / 2) * 4
+ * + 2 for xy axes (possibly with special colors)
+ * + 1 for z axis (the only line not in xy plane)
+ * even v3d->gridlines are honored, odd rounded down */
+ const int gridlines = v3d->gridlines / 2;
+ const float grid_scale = ED_view3d_grid_scale(scene, v3d, grid_unit);
+ const float grid = gridlines * grid_scale;
- if (probe) {
- if (ob->probetype == OB_PROBE_CUBEMAP) {
- GPU_probe_update_layers(probe, ob->lay);
+ const bool show_floor = (v3d->gridflag & V3D_SHOW_FLOOR) && gridlines >= 1;
- if (ob->parallaxcorrect)
- GPU_probe_update_parallax(probe, ob->parallaxcorrect->obmat, ob->obmat);
- else
- GPU_probe_update_parallax(probe, ob->obmat, ob->obmat);
+ bool show_axis_x = v3d->gridflag & V3D_SHOW_X;
+ bool show_axis_y = v3d->gridflag & V3D_SHOW_Y;
+ bool show_axis_z = v3d->gridflag & V3D_SHOW_Z;
- if (GPU_probe_get_update(probe)) {
- GPU_probe_update_clip(probe, ob->probeclipsta, ob->probeclipend);
- GPU_probe_update_sh_res(probe, ob->probeshres);
+ unsigned char col_grid[3], col_axis[3];
- vprobe = MEM_callocN(sizeof(View3DProbe), "View3DProbe");
- vprobe->probe = probe;
- BLI_addhead(&probelist, vprobe);
+ glLineWidth(1.0f);
- if (ob->probeflags & OB_PROBE_DOUBLE_UPDATE) {
- vprobe = MEM_callocN(sizeof(View3DProbe), "View3DProbe");
- vprobe->probe = probe;
- BLI_addhead(&afterlist, vprobe);
- }
- }
- }
- else if (ob->probetype == OB_PROBE_PLANAR) {
+ UI_GetThemeColor3ubv(TH_GRID, col_grid);
- GPU_probe_update_layers(probe, ob->lay);
- GPU_probe_update_clip(probe, ob->probeclipbias, ob->probeclipend);
+ if (!write_depth)
+ glDepthMask(GL_FALSE);
- if (ob->probe) {
- if (ob->probe->parallaxcorrect)
- GPU_probe_update_parallax(probe, ob->probe->parallaxcorrect->obmat, ob->probe->obmat);
- else
- GPU_probe_update_parallax(probe, ob->probe->obmat, ob->probe->obmat);
- }
+ if (show_floor) {
+ const unsigned vertex_ct = 2 * (gridlines * 4 + 2);
+ const int sublines = v3d->gridsubdiv;
- if (ob->reflectionplane)
- GPU_probe_update_ref_plane(probe, ob->reflectionplane->obmat);
- else
- GPU_probe_update_ref_plane(probe, ob->obmat);
+ unsigned char col_bg[3], col_grid_emphasise[3], col_grid_light[3];
- vprobe = MEM_callocN(sizeof(View3DProbe), "View3DProbe");
- vprobe->probe = probe;
- BLI_addtail(&probelist, vprobe);
+ VertexFormat* format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ unsigned color = add_attrib(format, "color", GL_UNSIGNED_BYTE, 3, NORMALIZE_INT_TO_FLOAT);
- if (ob->probeflags & OB_PROBE_DOUBLE_UPDATE) {
- vprobe = MEM_callocN(sizeof(View3DProbe), "View3DProbe");
- vprobe->probe = probe;
- BLI_addtail(&afterlist, vprobe);
- }
- }
- }
- }
- else {
- if (ob->gpuprobe.first)
- GPU_probe_free(&ob->gpuprobe);
- }
- }
+ immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR);
- /* World Probe */
- if (scene->world) {
- do_sky = true;
- probe = GPU_probe_world(scene, scene->world);
+ immBegin(GL_LINES, vertex_ct);
- /* XXX free probes if size change */
- if (probe && (GPU_probe_get_size(probe) != scene->world->probesize)) {
- if (scene->world->gpuprobe.first)
- GPU_probe_free(&scene->world->gpuprobe);
- probe = GPU_probe_world(scene, scene->world);
- }
+ /* draw normal grid lines */
+ UI_GetColorPtrShade3ubv(col_grid, col_grid_light, 10);
- if (probe && GPU_probe_get_update(probe)) {
- GPU_probe_update_sh_res(probe, scene->world->probeshres);
+ for (int a = 1; a <= gridlines; a++) {
+ /* skip emphasised divider lines */
+ if (a % sublines != 0) {
+ const float line = a * grid_scale;
- vprobe = MEM_callocN(sizeof(View3DProbe), "View3DProbe");
- vprobe->probe = probe;
- BLI_addhead(&probelist, vprobe);
- }
- }
+ immAttrib3ubv(color, col_grid_light);
- BLI_movelisttolist(&probelist, &afterlist);
-
- /* Updating probes */
- for (vprobe = probelist.first, i = 0; vprobe; vprobe = vprobe->next, i++) {
-
- float viewmat[4][4], winmat[4][4];
- int drawtype, lay, winsize, flag2 = v3d->flag2, flag3 = v3d->flag3, restrictflag;
- int pbr_flag = v3d->pbr_settings.pbr_flag;
- ARegion ar = {NULL};
- RegionView3D rv3d = {{{0}}};
- Object *ob = GPU_probe_get_object(vprobe->probe);
- bool is_cubemap = (GPU_probe_get_type(vprobe->probe) == OB_PROBE_CUBEMAP);
-
- drawtype = v3d->drawtype;
- lay = v3d->lay;
-
- v3d->drawtype = OB_MATERIAL;
- v3d->lay = GPU_probe_get_layers(vprobe->probe);
- v3d->flag2 &= ~(V3D_SOLID_TEX | V3D_SHOW_SOLID_MATCAP);
- v3d->flag2 |= V3D_RENDER_OVERRIDE;
- v3d->flag3 |= V3D_SHOW_WORLD;
- v3d->flag3 &= ~V3D_SHOW_WORLD_DIFFUSE;
- v3d->flag3 |= V3D_PROBE_CAPTURE;
- v3d->pbr_settings.pbr_flag &= ~GPU_PBR_FLAG_SSR;
- v3d->pbr_settings.pbr_flag &= ~GPU_PBR_FLAG_SSAO;
-
- if (ob) {
- restrictflag = ob->restrictflag;
- ob->restrictflag |= OB_RESTRICT_VIEW;
- v3d->probe_source = ob;
- }
- else {
- v3d->probe_source = NULL;
- }
+ immVertex2f(pos, -grid, -line);
+ immVertex2f(pos, +grid, -line);
+ immVertex2f(pos, -grid, +line);
+ immVertex2f(pos, +grid, +line);
- GPU_probe_buffer_bind(vprobe->probe);
-
- /* cubemap */
- if (is_cubemap) {
- for (int face = 0; face < 6; face++) {
- GPU_probe_switch_fb_cubeface(vprobe->probe, face, viewmat, &winsize, winmat);
-
- ar.regiondata = &rv3d;
- ar.regiontype = RGN_TYPE_WINDOW;
- rv3d.persp = RV3D_CAMOB;
- copy_m4_m4(rv3d.winmat, winmat);
- copy_m4_m4(rv3d.viewmat, viewmat);
- invert_m4_m4(rv3d.viewinv, rv3d.viewmat);
- mul_m4_m4m4(rv3d.persmat, rv3d.winmat, rv3d.viewmat);
- invert_m4_m4(rv3d.persinv, rv3d.viewinv);
-
- ED_view3d_draw_offscreen(
- scene, v3d, &ar, winsize, winsize, viewmat, winmat,
- false, do_sky, true, (bool)ob,
- NULL, NULL, NULL, NULL);
+ immVertex2f(pos, -line, -grid);
+ immVertex2f(pos, -line, +grid);
+ immVertex2f(pos, +line, -grid);
+ immVertex2f(pos, +line, +grid);
+ }
}
- }
- /* planar */
- else {
- ar.regiondata = &rv3d;
- ar.regiontype = RGN_TYPE_WINDOW;
- rv3d.persp = RV3D_CAMOB;
-
- /* Getting normal camera */
- view3d_winmatrix_set(basear, v3d, NULL);
- view3d_viewmatrix_set(scene, v3d, baserv3d); /* note: calls BKE_object_where_is_calc for camera... */
- /* Flip it along the plane */
- GPU_probe_attach_planar_fb(vprobe->probe, baserv3d->viewmat, baserv3d->winmat, viewmat, &winsize, false);
+ /* draw emphasised grid lines */
+ UI_GetThemeColor3ubv(TH_BACK, col_bg);
+ /* emphasise division lines lighter instead of darker, if background is darker than grid */
+ UI_GetColorPtrShade3ubv(col_grid, col_grid_emphasise,
+ (col_grid[0] + col_grid[1] + col_grid[2] + 30 >
+ col_bg[0] + col_bg[1] + col_bg[2]) ? 20 : -10);
- copy_m4_m4(rv3d.viewmat, viewmat);
- invert_m4_m4(rv3d.viewinv, rv3d.viewmat);
- mul_m4_m4m4(rv3d.persmat, baserv3d->winmat, rv3d.viewmat);
- invert_m4_m4(rv3d.persinv, rv3d.viewinv);
+ if (sublines <= gridlines) {
+ immAttrib3ubv(color, col_grid_emphasise);
- v3d->flag3 |= V3D_FLIP_NORMALS;
+ for (int a = sublines; a <= gridlines; a += sublines) {
+ const float line = a * grid_scale;
- ED_view3d_draw_offscreen(
- scene, v3d, &ar, winsize, winsize, viewmat, baserv3d->winmat,
- false, do_sky, true, true,
- NULL, NULL, NULL, NULL);
+ immVertex2f(pos, -grid, -line);
+ immVertex2f(pos, +grid, -line);
+ immVertex2f(pos, -grid, +line);
+ immVertex2f(pos, +grid, +line);
- /* Non-fliped Camera for refraction */
- GPU_probe_attach_planar_fb(vprobe->probe, baserv3d->viewmat, baserv3d->winmat, viewmat, &winsize, true);
-
- copy_m4_m4(rv3d.viewmat, viewmat);
- invert_m4_m4(rv3d.viewinv, rv3d.viewmat);
- mul_m4_m4m4(rv3d.persmat, baserv3d->winmat, rv3d.viewmat);
- invert_m4_m4(rv3d.persinv, rv3d.viewinv);
-
- v3d->flag3 &= ~V3D_FLIP_NORMALS;
-
- ED_view3d_draw_offscreen(
- scene, v3d, &ar, winsize, winsize, viewmat, baserv3d->winmat,
- false, do_sky, true, true,
- NULL, NULL, NULL, NULL);
-
- }
-
- GPU_probe_buffer_unbind(vprobe->probe);
+ immVertex2f(pos, -line, -grid);
+ immVertex2f(pos, -line, +grid);
+ immVertex2f(pos, +line, -grid);
+ immVertex2f(pos, +line, +grid);
+ }
+ }
- v3d->drawtype = drawtype;
- v3d->lay = lay;
- v3d->flag2 = flag2;
- v3d->flag3 = flag3;
- v3d->probe_source = NULL;
- v3d->pbr_settings.pbr_flag = pbr_flag;
+ /* draw X axis */
+ if (show_axis_x) {
+ show_axis_x = false; /* drawing now, won't need to draw later */
+ UI_make_axis_color(col_grid, col_axis, 'X');
+ immAttrib3ubv(color, col_axis);
+ }
+ else
+ immAttrib3ubv(color, col_grid_emphasise);
- if (ob)
- ob->restrictflag = restrictflag;
+ immVertex2f(pos, -grid, 0.0f);
+ immVertex2f(pos, +grid, 0.0f);
- GPU_probe_rebuild_mipmaps(vprobe->probe);
+ /* draw Y axis */
+ if (show_axis_y) {
+ show_axis_y = false; /* drawing now, won't need to draw later */
+ UI_make_axis_color(col_grid, col_axis, 'Y');
+ immAttrib3ubv(color, col_axis);
+ }
+ else
+ immAttrib3ubv(color, col_grid_emphasise);
- GPU_probe_sh_compute(vprobe->probe);
+ immVertex2f(pos, 0.0f, -grid);
+ immVertex2f(pos, 0.0f, +grid);
- GPU_probe_set_update(vprobe->probe, false);
- }
+ immEnd();
+ immUnbindProgram();
- BLI_freelistN(&probelist);
-}
+ /* done with XY plane */
+ }
-/* ***************** Scene buffer update *************** */
+ if (show_axis_x || show_axis_y || show_axis_z) {
+ /* draw axis lines -- sometimes grid floor is off, other times we still need to draw the Z axis */
-static void gpu_update_scene_buffer(Scene *scene, View3D *v3d, ARegion *basear)
-{
- int drawtype = v3d->drawtype, winsize[2], flag2 = v3d->flag2, flag3 = v3d->flag3;
- float clipsta, clipend;
- ARegion ar = {NULL};
- RegionView3D *baserv3d = basear->regiondata;
- RegionView3D rv3d = {{{0}}};
- GPUScreenBuffer *scene_buffer;
- int res[2] = {basear->winx, basear->winy};
- int pbr_flag = v3d->pbr_settings.pbr_flag;
-
- scene_buffer = GPU_pbr_scene_buffer(v3d->pbr, res[0], res[1]);
-
- v3d->drawtype = OB_MATERIAL;
- v3d->flag2 &= ~(V3D_SOLID_TEX | V3D_SHOW_SOLID_MATCAP);
- v3d->flag2 |= V3D_RENDER_OVERRIDE;
- v3d->flag3 |= V3D_SHOW_WORLD;
- v3d->flag3 &= ~V3D_SHOW_WORLD_DIFFUSE;
- v3d->flag3 |= V3D_PROBE_CAPTURE;
- v3d->pbr_settings.pbr_flag &= ~GPU_PBR_FLAG_SSR;
- v3d->pbr_settings.pbr_flag &= ~GPU_PBR_FLAG_SSAO;
-
- ar.regiondata = &rv3d;
- ar.regiontype = RGN_TYPE_WINDOW;
- rv3d.persp = RV3D_CAMOB;
-
- /* Getting camera coords */
- ED_view3d_viewplane_get(v3d, baserv3d, basear->winx, basear->winy, NULL, &clipsta, &clipend, NULL);
- view3d_winmatrix_set(basear, v3d, NULL);
- view3d_viewmatrix_set(scene, v3d, baserv3d); /* note: calls BKE_object_where_is_calc for camera... */
-
- GPU_scenebuf_bind(scene_buffer, baserv3d->winmat, winsize, clipsta, clipend);
-
- copy_m4_m4(rv3d.viewmat, baserv3d->viewmat);
- invert_m4_m4(rv3d.viewinv, rv3d.viewmat);
- mul_m4_m4m4(rv3d.persmat, baserv3d->winmat, rv3d.viewmat);
- invert_m4_m4(rv3d.persinv, rv3d.viewinv);
-
- ED_view3d_draw_offscreen(
- scene, v3d, &ar, winsize[0], winsize[1], baserv3d->viewmat, baserv3d->winmat,
- false, (bool)scene->world, true, true,
- NULL, NULL, NULL, NULL);
-
- v3d->drawtype = drawtype;
- v3d->flag2 = flag2;
- v3d->flag3 = flag3;
- v3d->pbr_settings.pbr_flag = pbr_flag;
-
- GPU_scenebuf_unbind(scene_buffer);
- GPU_scenebuf_filter_texture(scene_buffer);
-}
+ VertexFormat* format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ unsigned color = add_attrib(format, "color", GL_UNSIGNED_BYTE, 3, NORMALIZE_INT_TO_FLOAT);
-static void gpu_update_backface_buffer(Scene *scene, View3D *v3d, ARegion *basear)
-{
- int drawtype = v3d->drawtype, winsize[2], flag2 = v3d->flag2, flag3 = v3d->flag3;
- float clipsta, clipend;
- ARegion ar = {NULL};
- RegionView3D *baserv3d = basear->regiondata;
- RegionView3D rv3d = {{{0}}};
- GPUScreenBuffer *backface_buffer;
- int res[2] = {basear->winx, basear->winy};
-
- backface_buffer = GPU_pbr_backface_buffer(v3d->pbr, res[0], res[1]);
-
- v3d->drawtype = OB_SOLID;
- v3d->flag2 &= ~(V3D_SOLID_TEX | V3D_SHOW_SOLID_MATCAP);
- v3d->flag2 |= V3D_BACKFACE_CULLING | V3D_RENDER_OVERRIDE | V3D_RENDER_SHADOW;
- v3d->flag3 |= V3D_FLIP_NORMALS;
-
- ar.regiondata = &rv3d;
- ar.regiontype = RGN_TYPE_WINDOW;
- rv3d.persp = RV3D_CAMOB;
-
- /* Getting camera coords */
- ED_view3d_viewplane_get(v3d, baserv3d, basear->winx, basear->winy, NULL, &clipsta, &clipend, NULL);
- view3d_winmatrix_set(basear, v3d, NULL);
- view3d_viewmatrix_set(scene, v3d, baserv3d); /* note: calls BKE_object_where_is_calc for camera... */
-
- GPU_scenebuf_bind(backface_buffer, baserv3d->winmat, winsize, clipsta, clipend);
-
- copy_m4_m4(rv3d.viewmat, baserv3d->viewmat);
- invert_m4_m4(rv3d.viewinv, rv3d.viewmat);
- mul_m4_m4m4(rv3d.persmat, baserv3d->winmat, rv3d.viewmat);
- invert_m4_m4(rv3d.persinv, rv3d.viewinv);
-
- ED_view3d_draw_offscreen(
- scene, v3d, &ar, winsize[0], winsize[1], baserv3d->viewmat, baserv3d->winmat,
- false, (bool)scene->world, true, true,
- NULL, NULL, NULL, NULL);
-
- v3d->drawtype = drawtype;
- v3d->flag2 = flag2;
- v3d->flag3 = flag3;
-
- GPU_scenebuf_unbind(backface_buffer);
- GPU_scenebuf_filter_texture(backface_buffer);
-}
+ immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR);
+ immBegin(GL_LINES, (show_axis_x + show_axis_y + show_axis_z) * 2);
+ if (show_axis_x) {
+ UI_make_axis_color(col_grid, col_axis, 'X');
+ immAttrib3ubv(color, col_axis);
+ immVertex3f(pos, -grid, 0.0f, 0.0f);
+ immVertex3f(pos, +grid, 0.0f, 0.0f);
+ }
-static void gpu_pbr_update(Scene *scene, View3D *v3d, ARegion *ar)
-{
- GPUPBR *pbr = v3d->pbr;
+ if (show_axis_y) {
+ UI_make_axis_color(col_grid, col_axis, 'Y');
+ immAttrib3ubv(color, col_axis);
+ immVertex3f(pos, 0.0f, -grid, 0.0f);
+ immVertex3f(pos, 0.0f, +grid, 0.0f);
+ }
- gpu_update_probes(scene, v3d, ar);
+ if (show_axis_z) {
+ UI_make_axis_color(col_grid, col_axis, 'Z');
+ immAttrib3ubv(color, col_axis);
+ immVertex3f(pos, 0.0f, 0.0f, -grid);
+ immVertex3f(pos, 0.0f, 0.0f, +grid);
+ }
- if (v3d->pbr_settings.pbr_flag & (GPU_PBR_FLAG_SSR | GPU_PBR_FLAG_SSAO))
- gpu_update_scene_buffer(scene, v3d, ar);
- else if (pbr->scene) {
- GPU_scenebuf_free(pbr->scene);
- pbr->scene = NULL;
- }
+ immEnd();
+ immUnbindProgram();
+ }
- if ((v3d->pbr_settings.pbr_flag & GPU_PBR_FLAG_BACKFACE) && (v3d->pbr_settings.pbr_flag & (GPU_PBR_FLAG_SSR | GPU_PBR_FLAG_SSAO)))
- gpu_update_backface_buffer(scene, v3d, ar);
- else if (pbr->backface) {
- GPU_scenebuf_free(pbr->backface);
- pbr->backface = NULL;
+ if (!write_depth)
+ glDepthMask(GL_TRUE);
}
}
-/* *********************** customdata **************** */
-
-CustomDataMask ED_view3d_datamask(const Scene *scene, const View3D *v3d)
+/** could move this elsewhere, but tied into #ED_view3d_grid_scale */
+float ED_scene_grid_scale(Scene *scene, const char **grid_unit)
{
- CustomDataMask mask = 0;
- const int drawtype = view3d_effective_drawtype(v3d);
-
- if (ELEM(drawtype, OB_TEXTURE, OB_MATERIAL) ||
- ((drawtype == OB_SOLID) && (v3d->flag2 & V3D_SOLID_TEX)))
- {
- mask |= CD_MASK_MTEXPOLY | CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL;
-
- if (BKE_scene_use_new_shading_nodes(scene)) {
- if (drawtype == OB_MATERIAL)
- mask |= CD_MASK_ORCO;
- }
- else {
- if ((scene->gm.matmode == GAME_MAT_GLSL && drawtype == OB_TEXTURE) ||
- (drawtype == OB_MATERIAL))
- {
- mask |= CD_MASK_ORCO;
- }
- }
- }
+ /* apply units */
+ if (scene->unit.system) {
+ const void *usys;
+ int len;
- return mask;
-}
+ bUnit_GetSystem(scene->unit.system, B_UNIT_LENGTH, &usys, &len);
-/* goes over all modes and view3d settings */
-CustomDataMask ED_view3d_screen_datamask(const bScreen *screen)
-{
- const Scene *scene = screen->scene;
- CustomDataMask mask = CD_MASK_BAREMESH;
- const ScrArea *sa;
-
- /* check if we need tfaces & mcols due to view mode */
- for (sa = screen->areabase.first; sa; sa = sa->next) {
- if (sa->spacetype == SPACE_VIEW3D) {
- mask |= ED_view3d_datamask(scene, sa->spacedata.first);
+ if (usys) {
+ int i = bUnit_GetBaseUnit(usys);
+ if (grid_unit)
+ *grid_unit = bUnit_GetNameDisplay(usys, i);
+ return (float)bUnit_GetScaler(usys, i) / scene->unit.scale_length;
}
}
- return mask;
+ return 1.0f;
}
-/**
- * \note keep this synced with #ED_view3d_mats_rv3d_backup/#ED_view3d_mats_rv3d_restore
- */
-void ED_view3d_update_viewmat(Scene *scene, View3D *v3d, ARegion *ar, float viewmat[4][4], float winmat[4][4])
+float ED_view3d_grid_scale(Scene *scene, View3D *v3d, const char **grid_unit)
{
- RegionView3D *rv3d = ar->regiondata;
- rctf cameraborder;
-
- /* setup window matrices */
- if (winmat)
- copy_m4_m4(rv3d->winmat, winmat);
- else
- view3d_winmatrix_set(ar, v3d, NULL);
-
- /* setup view matrix */
- if (viewmat)
- copy_m4_m4(rv3d->viewmat, viewmat);
- else
- view3d_viewmatrix_set(scene, v3d, rv3d); /* note: calls BKE_object_where_is_calc for camera... */
-
- /* update utilitity matrices */
- mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat);
- invert_m4_m4(rv3d->persinv, rv3d->persmat);
- invert_m4_m4(rv3d->viewinv, rv3d->viewmat);
-
- /* calculate GLSL view dependent values */
-
- /* store window coordinates scaling/offset */
- if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
- ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &cameraborder, false);
- rv3d->viewcamtexcofac[0] = (float)ar->winx / BLI_rctf_size_x(&cameraborder);
- rv3d->viewcamtexcofac[1] = (float)ar->winy / BLI_rctf_size_y(&cameraborder);
-
- rv3d->viewcamtexcofac[2] = -rv3d->viewcamtexcofac[0] * cameraborder.xmin / (float)ar->winx;
- rv3d->viewcamtexcofac[3] = -rv3d->viewcamtexcofac[1] * cameraborder.ymin / (float)ar->winy;
- }
- else {
- rv3d->viewcamtexcofac[0] = rv3d->viewcamtexcofac[1] = 1.0f;
- rv3d->viewcamtexcofac[2] = rv3d->viewcamtexcofac[3] = 0.0f;
- }
-
- /* calculate pixelsize factor once, is used for lamps and obcenters */
- {
- /* note: '1.0f / len_v3(v1)' replaced 'len_v3(rv3d->viewmat[0])'
- * because of float point precision problems at large values [#23908] */
- float v1[3], v2[3];
- float len_px, len_sc;
-
- v1[0] = rv3d->persmat[0][0];
- v1[1] = rv3d->persmat[1][0];
- v1[2] = rv3d->persmat[2][0];
-
- v2[0] = rv3d->persmat[0][1];
- v2[1] = rv3d->persmat[1][1];
- v2[2] = rv3d->persmat[2][1];
-
- len_px = 2.0f / sqrtf(min_ff(len_squared_v3(v1), len_squared_v3(v2)));
- len_sc = (float)MAX2(ar->winx, ar->winy);
-
- rv3d->pixsize = len_px / len_sc;
- }
+ return v3d->grid * ED_scene_grid_scale(scene, grid_unit);
}
/**
- * Shared by #ED_view3d_draw_offscreen and #view3d_main_region_draw_objects
*
- * \note \a C and \a grid_unit will be NULL when \a draw_offscreen is set.
- * \note Drawing lamps and opengl render uses this, so dont do grease pencil or view widgets here.
*/
-static void view3d_draw_objects(
- const bContext *C,
- Scene *scene, View3D *v3d, ARegion *ar,
- const char **grid_unit,
- const bool do_bgpic, const bool draw_offscreen, GPUFX *fx)
-{
+static void view3d_draw_grid(const bContext *C, ARegion *ar)
+{
+ /* TODO viewport
+ * Missing is the flags to check whether to draw it
+ * for now now we are using the flags in v3d itself.
+ *
+ * Also for now always assume depth is there, so we
+ * draw on top of it.
+ */
+ Scene *scene = CTX_data_scene(C);
+ View3D *v3d = CTX_wm_view3d(C);
RegionView3D *rv3d = ar->regiondata;
- Base *base;
- const bool do_camera_frame = !draw_offscreen;
- const bool draw_grids = !draw_offscreen && (v3d->flag2 & V3D_RENDER_OVERRIDE) == 0;
- const bool draw_floor = (rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO);
- /* only draw grids after in solid modes, else it hovers over mesh wires */
- const bool draw_grids_after = draw_grids && draw_floor && (v3d->drawtype > OB_WIRE) && fx;
- bool do_composite_xray = false;
- bool xrayclear = true;
-
- if (!draw_offscreen) {
- ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW);
- }
-
- if (rv3d->rflag & RV3D_CLIPPING)
- view3d_draw_clipping(rv3d);
-
- /* set zbuffer after we draw clipping region */
- if (v3d->drawtype > OB_WIRE) {
- v3d->zbuf = true;
- }
- else {
- v3d->zbuf = false;
- }
-
- /* special case (depth for wire color) */
- if (v3d->drawtype <= OB_WIRE) {
- if (scene->obedit && scene->obedit->type == OB_MESH) {
- Mesh *me = scene->obedit->data;
- if (me->drawflag & ME_DRAWEIGHT) {
- v3d->zbuf = true;
- }
- }
- }
- if (v3d->zbuf) {
- glEnable(GL_DEPTH_TEST);
- }
+ const bool draw_floor = (rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO);
+ const char *grid_unit = NULL;
/* ortho grid goes first, does not write to depth buffer and doesn't need depth test so it will override
- * objects if done last */
- if (draw_grids) {
- /* needs to be done always, gridview is adjusted in drawgrid() now, but only for ortho views. */
- rv3d->gridview = ED_view3d_grid_scale(scene, v3d, grid_unit);
-
- if (!draw_floor) {
- ED_region_pixelspace(ar);
- *grid_unit = NULL; /* drawgrid need this to detect/affect smallest valid unit... */
- drawgrid(&scene->unit, ar, v3d, grid_unit);
- /* XXX make function? replaces persp(1) */
- glMatrixMode(GL_PROJECTION);
- glLoadMatrixf(rv3d->winmat);
- glMatrixMode(GL_MODELVIEW);
- glLoadMatrixf(rv3d->viewmat);
- }
- else if (!draw_grids_after) {
- drawfloor(scene, v3d, grid_unit, true);
- }
- }
-
- /* important to do before clipping */
- if (do_bgpic) {
- view3d_draw_bgpic_test(scene, ar, v3d, false, do_camera_frame);
- }
-
- if (rv3d->rflag & RV3D_CLIPPING) {
- ED_view3d_clipping_set(rv3d);
- }
-
- /* draw set first */
- if (scene->set) {
- const short dflag = DRAW_CONSTCOLOR | DRAW_SCENESET;
- Scene *sce_iter;
- for (SETLOOPER(scene->set, sce_iter, base)) {
- if (v3d->lay & base->lay) {
- UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.6f);
- draw_object(scene, ar, v3d, base, dflag);
-
- if (base->object->transflag & OB_DUPLI) {
- draw_dupli_objects_color(scene, ar, v3d, base, dflag, TH_UNDEFINED);
- }
- }
- }
-
- /* Transp and X-ray afterdraw stuff for sets is done later */
- }
+ * objects if done last
+ * needs to be done always, gridview is adjusted in drawgrid() now, but only for ortho views.
+ */
+ rv3d->gridview = ED_view3d_grid_scale(scene, v3d, &grid_unit);
+ glEnable(GL_DEPTH_TEST);
- if (draw_offscreen) {
- for (base = scene->base.first; base; base = base->next) {
- if (v3d->lay & base->lay) {
- /* dupli drawing */
- if (base->object->transflag & OB_DUPLI)
- draw_dupli_objects(scene, ar, v3d, base);
+ if (!draw_floor) {
+ ED_region_pixelspace(ar);
+ *(&grid_unit) = NULL; /* drawgrid need this to detect/affect smallest valid unit... */
+ drawgrid(&scene->unit, ar, v3d, &grid_unit);
- draw_object(scene, ar, v3d, base, 0);
- }
- }
+ glMatrixMode(GL_PROJECTION);
+ glLoadMatrixf(rv3d->winmat);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadMatrixf(rv3d->viewmat);
}
else {
- unsigned int lay_used = 0;
-
- /* then draw not selected and the duplis, but skip editmode object */
- for (base = scene->base.first; base; base = base->next) {
- lay_used |= base->lay;
-
- if (v3d->lay & base->lay) {
-
- /* dupli drawing */
- if (base->object->transflag & OB_DUPLI) {
- draw_dupli_objects(scene, ar, v3d, base);
- }
- if ((base->flag & SELECT) == 0) {
- if (base->object != scene->obedit)
- draw_object(scene, ar, v3d, base, 0);
- }
- }
- }
-
- /* mask out localview */
- v3d->lay_used = lay_used & ((1 << 20) - 1);
-
- /* draw selected and editmode */
- for (base = scene->base.first; base; base = base->next) {
- if (v3d->lay & base->lay) {
- if (base->object == scene->obedit || (base->flag & SELECT)) {
- draw_object(scene, ar, v3d, base, 0);
- }
- }
- }
- }
-
- /* perspective floor goes last to use scene depth and avoid writing to depth buffer */
- if (draw_grids_after) {
- drawfloor(scene, v3d, grid_unit, false);
- }
-
- /* must be before xray draw which clears the depth buffer */
- if (v3d->flag2 & V3D_SHOW_GPENCIL) {
- wmWindowManager *wm = (C != NULL) ? CTX_wm_manager(C) : NULL;
-
- /* must be before xray draw which clears the depth buffer */
- if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
- ED_gpencil_draw_view3d(wm, scene, v3d, ar, true);
- if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
- }
-
- /* transp and X-ray afterdraw stuff */
- if (v3d->afterdraw_transp.first) view3d_draw_transp(scene, ar, v3d);
-
- /* always do that here to cleanup depth buffers if none needed */
- if (fx) {
- do_composite_xray = v3d->zbuf && (v3d->afterdraw_xray.first || v3d->afterdraw_xraytransp.first);
- GPU_fx_compositor_setup_XRay_pass(fx, do_composite_xray);
- }
-
- if (v3d->afterdraw_xray.first) view3d_draw_xray(scene, ar, v3d, &xrayclear);
- if (v3d->afterdraw_xraytransp.first) view3d_draw_xraytransp(scene, ar, v3d, xrayclear);
-
- if (fx && do_composite_xray) {
- GPU_fx_compositor_XRay_resolve(fx);
- }
-
- if (!draw_offscreen) {
- ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
+ drawfloor(scene, v3d, &grid_unit, false);
}
- if (rv3d->rflag & RV3D_CLIPPING)
- ED_view3d_clipping_disable();
+ glDisable(GL_DEPTH_TEST);
+}
- /* important to do after clipping */
- if (do_bgpic) {
- view3d_draw_bgpic_test(scene, ar, v3d, true, do_camera_frame);
- }
+/* ******************** non-meshes ***************** */
- if (!draw_offscreen) {
- BIF_draw_manipulator(C);
- }
+static void view3d_draw_non_mesh(
+Scene *scene, Object *ob, Base *base, View3D *v3d,
+RegionView3D *rv3d, const unsigned char color[4])
+{
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
- /* cleanup */
- if (v3d->zbuf) {
- v3d->zbuf = false;
- glDisable(GL_DEPTH_TEST);
- }
+ /* multiply view with object matrix.
+ * local viewmat and persmat, to calculate projections */
+ ED_view3d_init_mats_rv3d_gl(ob, rv3d);
- if ((v3d->flag2 & V3D_RENDER_SHADOW) == 0) {
- GPU_free_images_old();
+ switch (ob->type) {
+ case OB_EMPTY:
+ drawaxes(rv3d->viewmatob, ob->empty_drawsize, ob->empty_drawtype, color);
+ break;
+ case OB_LAMP:
+ drawlamp(scene, v3d, rv3d, base, OB_SOLID, DRAW_CONSTCOLOR, color, false);
+ break;
+ default:
+ /* TODO Viewport: handle the other cases*/
+ break;
}
-}
-static void view3d_main_region_setup_view(Scene *scene, View3D *v3d, ARegion *ar, float viewmat[4][4], float winmat[4][4])
-{
- RegionView3D *rv3d = ar->regiondata;
+ ED_view3d_clear_mats_rv3d(rv3d);
- ED_view3d_update_viewmat(scene, v3d, ar, viewmat, winmat);
-
- /* set for opengl */
glMatrixMode(GL_PROJECTION);
- glLoadMatrixf(rv3d->winmat);
+ glPopMatrix();
glMatrixMode(GL_MODELVIEW);
- glLoadMatrixf(rv3d->viewmat);
-}
-
-/**
- * Store values from #RegionView3D, set when drawing.
- * This is needed when we draw with to a viewport using a different matrix (offscreen drawing for example).
- *
- * Values set by #ED_view3d_update_viewmat should be handled here.
- */
-struct RV3DMatrixStore {
- float winmat[4][4];
- float viewmat[4][4];
- float viewinv[4][4];
- float persmat[4][4];
- float persinv[4][4];
- float viewcamtexcofac[4];
- float pixsize;
-};
-
-void *ED_view3d_mats_rv3d_backup(struct RegionView3D *rv3d)
-{
- struct RV3DMatrixStore *rv3dmat = MEM_mallocN(sizeof(*rv3dmat), __func__);
- copy_m4_m4(rv3dmat->winmat, rv3d->winmat);
- copy_m4_m4(rv3dmat->viewmat, rv3d->viewmat);
- copy_m4_m4(rv3dmat->persmat, rv3d->persmat);
- copy_m4_m4(rv3dmat->persinv, rv3d->persinv);
- copy_m4_m4(rv3dmat->viewinv, rv3d->viewinv);
- copy_v4_v4(rv3dmat->viewcamtexcofac, rv3d->viewcamtexcofac);
- rv3dmat->pixsize = rv3d->pixsize;
- return (void *)rv3dmat;
+ glPopMatrix();
}
-void ED_view3d_mats_rv3d_restore(struct RegionView3D *rv3d, void *rv3dmat_pt)
-{
- struct RV3DMatrixStore *rv3dmat = rv3dmat_pt;
- copy_m4_m4(rv3d->winmat, rv3dmat->winmat);
- copy_m4_m4(rv3d->viewmat, rv3dmat->viewmat);
- copy_m4_m4(rv3d->persmat, rv3dmat->persmat);
- copy_m4_m4(rv3d->persinv, rv3dmat->persinv);
- copy_m4_m4(rv3d->viewinv, rv3dmat->viewinv);
- copy_v4_v4(rv3d->viewcamtexcofac, rv3dmat->viewcamtexcofac);
- rv3d->pixsize = rv3dmat->pixsize;
-}
+/* ******************** info ***************** */
-void ED_view3d_draw_offscreen_init(Scene *scene, View3D *v3d, ARegion *ar)
+/**
+* Render and camera border
+*/
+static void view3d_draw_border(const bContext *C, ARegion *ar)
{
- /* shadow buffers, before we setup matrices */
- if (draw_glsl_material(scene, NULL, v3d, v3d->drawtype)){
- gpu_update_lamps_shadows_world(scene, v3d);
-
- /* Cycles Material Mode only */
- if (BKE_scene_use_new_shading_nodes(scene) && (v3d->pbr_settings.pbr_flag & GPU_PBR_FLAG_ENABLE)) {
- GPU_pbr_settings_validate(&v3d->pbr_settings);
-
- if (!v3d->pbr)
- v3d->pbr = GPU_pbr_create();
+ Scene *scene = CTX_data_scene(C);
+ RegionView3D *rv3d = ar->regiondata;
+ View3D *v3d = CTX_wm_view3d(C);
- gpu_pbr_update(scene, v3d, ar);
- }
+ if (rv3d->persp == RV3D_CAMOB) {
+ drawviewborder(scene, ar, v3d);
+ }
+ else if (v3d->flag2 & V3D_RENDER_BORDER) {
+ drawrenderborder(ar, v3d);
}
}
-/*
- * Function to clear the view
- */
-static void view3d_main_region_clear(Scene *scene, View3D *v3d, ARegion *ar)
+/**
+* Grease Pencil
+*/
+static void view3d_draw_grease_pencil(const bContext *C)
{
- GPUFXSettings *fx_settings = &v3d->fx_settings;
- bool use_color_correction = (fx_settings->fx_flag2 && (fx_settings->fx_flag2 & GPU_FX_FLAG_COLORMANAGEMENT)) ? false : true;
-
- if (scene->world && (v3d->flag3 & V3D_SHOW_WORLD)) {
- RegionView3D *rv3d = ar->regiondata;
- GPUMaterial *gpumat;
- GPUProbe *gpuprobe;
- bool material_not_bound;
-
- if (v3d->flag3 & V3D_SHOW_WORLD_DIFFUSE) {
- gpuprobe = GPU_probe_world(scene, scene->world);
- GPU_probe_sh_shader_bind(gpuprobe);
- }
- else {
- gpumat = GPU_material_world(scene, scene->world);
-
- /* calculate full shader for background */
- GPU_material_bind(gpumat, 1, 1, 1.0, false, rv3d->viewmat, rv3d->viewinv, rv3d->viewcamtexcofac, (v3d->scenelock != 0));
-
- material_not_bound = !GPU_material_bound(gpumat);
-
- if (material_not_bound) {
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glLoadIdentity();
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
- glLoadIdentity();
- glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
- }
- }
-
- /* Draw world */
- glEnable(GL_DEPTH_TEST);
- glDepthFunc(GL_ALWAYS);
- glBegin(GL_TRIANGLE_STRIP);
- glVertex3f(-1.0, -1.0, 1.0);
- glVertex3f(1.0, -1.0, 1.0);
- glVertex3f(-1.0, 1.0, 1.0);
- glVertex3f(1.0, 1.0, 1.0);
- glEnd();
-
- if (v3d->flag3 & V3D_SHOW_WORLD_DIFFUSE) {
- GPU_probe_sh_shader_unbind();
- }
- else {
- if (material_not_bound) {
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
- }
-
- GPU_material_unbind(gpumat);
- }
-
- glDepthFunc(GL_LEQUAL);
- glDisable(GL_DEPTH_TEST);
- }
- else {
- if (UI_GetThemeValue(TH_SHOW_BACK_GRAD)) {
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glLoadIdentity();
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
- glLoadIdentity();
-
- glEnable(GL_DEPTH_TEST);
- glDepthFunc(GL_ALWAYS);
- glBegin(GL_QUADS);
- UI_ThemeColor(TH_LOW_GRAD);
- glVertex3f(-1.0, -1.0, 1.0);
- glVertex3f(1.0, -1.0, 1.0);
- UI_ThemeColor(TH_HIGH_GRAD);
- glVertex3f(1.0, 1.0, 1.0);
- glVertex3f(-1.0, 1.0, 1.0);
- glEnd();
- glDepthFunc(GL_LEQUAL);
- glDisable(GL_DEPTH_TEST);
-
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
-
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
- }
- else {
- UI_ThemeClearColorAlpha(TH_HIGH_GRAD, 1.0f);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- }
- }
+ /* TODO viewport */
}
-/* ED_view3d_draw_offscreen_init should be called before this to initialize
- * stuff like shadow buffers
+/* ******************** view loop ***************** */
+
+/**
+ * Set the correct matrices
*/
-void ED_view3d_draw_offscreen(
- Scene *scene, View3D *v3d, ARegion *ar, int winx, int winy,
- float viewmat[4][4], float winmat[4][4],
- bool do_bgpic, bool do_sky, bool is_persp, bool do_meshes, const char *viewname,
- GPUFX *fx, GPUFXSettings *fx_settings,
- GPUOffScreen *ofs)
+static void view3d_draw_setup_view(const bContext *C, ARegion *ar)
{
- struct bThemeState theme_state;
- int bwinx, bwiny;
- rcti brect;
- bool do_compositing = false;
+ Scene *scene = CTX_data_scene(C);
+ View3D *v3d = CTX_wm_view3d(C);
RegionView3D *rv3d = ar->regiondata;
- glPushMatrix();
-
- /* set temporary new size */
- bwinx = ar->winx;
- bwiny = ar->winy;
- brect = ar->winrct;
-
- ar->winx = winx;
- ar->winy = winy;
- ar->winrct.xmin = 0;
- ar->winrct.ymin = 0;
- ar->winrct.xmax = winx;
- ar->winrct.ymax = winy;
-
- UI_Theme_Store(&theme_state);
- UI_SetTheme(SPACE_VIEW3D, RGN_TYPE_WINDOW);
-
- /* set flags */
- G.f |= G_RENDER_OGL;
-
- if ((v3d->flag2 & V3D_RENDER_SHADOW) == 0) {
- /* free images which can have changed on frame-change
- * warning! can be slow so only free animated images - campbell */
- GPU_free_images_anim();
- }
-
- /* setup view matrices before fx or unbinding the offscreen buffers will cause issues */
- if ((viewname != NULL && viewname[0] != '\0') && (viewmat == NULL) && rv3d->persp == RV3D_CAMOB && v3d->camera)
- view3d_stereo3d_setup_offscreen(scene, v3d, ar, winmat, viewname);
+ /* setup the view matrix */
+ if (view3d_stereo3d_active(C, scene, v3d, rv3d))
+ view3d_stereo3d_setup(scene, v3d, ar);
else
- view3d_main_region_setup_view(scene, v3d, ar, viewmat, winmat);
-
- /* framebuffer fx needed, we need to draw offscreen first */
- if ((v3d->fx_settings.fx_flag || v3d->fx_settings.fx_flag2) && fx) {
- GPUSSAOSettings *ssao = NULL;
- char fx_flag2 = v3d->fx_settings.fx_flag2;
-
- /* Don't do color management fx for offscreen */
- v3d->fx_settings.fx_flag2 &= ~GPU_FX_FLAG_COLORMANAGEMENT;
-
- if (v3d->drawtype < OB_SOLID) {
- ssao = v3d->fx_settings.ssao;
- v3d->fx_settings.ssao = NULL;
- }
-
- do_compositing = GPU_fx_compositor_initialize_passes(fx, &ar->winrct, NULL, fx_settings, scene);
-
- v3d->fx_settings.fx_flag2 = fx_flag2;
-
- if (ssao)
- v3d->fx_settings.ssao = ssao;
- }
+ view3d_main_region_setup_view(scene, v3d, ar, NULL, NULL);
+}
- /* clear opengl buffers */
- if (do_sky) {
- view3d_main_region_clear(scene, v3d, ar);
- }
- else {
- glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- }
+static void draw_all_objects(const bContext *C, ARegion *ar, const bool only_depth, const bool use_depth)
+{
+ Scene *scene = CTX_data_scene(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ Base *base;
- /* main drawing call */
- if (do_meshes)
- view3d_draw_objects(NULL, scene, v3d, ar, NULL, do_bgpic, true, do_compositing ? fx : NULL);
+ if (only_depth)
+ glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
- /* post process */
- if (do_compositing) {
- if (!winmat)
- is_persp = rv3d->is_persp;
- GPU_fx_do_composite_pass(fx, winmat, is_persp, scene, ofs);
+ if (only_depth || use_depth) {
+ glEnable(GL_DEPTH_TEST);
+ v3d->zbuf = true;
}
- if ((v3d->flag2 & V3D_RENDER_SHADOW) == 0) {
- /* draw grease-pencil stuff */
- ED_region_pixelspace(ar);
-
+ for (base = scene->base.first; base; base = base->next) {
+ if (v3d->lay & base->lay) {
+ /* dupli drawing */
+ if (base->object->transflag & OB_DUPLI)
+ draw_dupli_objects(scene, ar, v3d, base);
- if (v3d->flag2 & V3D_SHOW_GPENCIL) {
- /* draw grease-pencil stuff - needed to get paint-buffer shown too (since it's 2D) */
- ED_gpencil_draw_view3d(NULL, scene, v3d, ar, false);
+ draw_object(scene, ar, v3d, base, 0);
}
-
- /* freeing the images again here could be done after the operator runs, leaving for now */
- GPU_free_images_anim();
}
- /* restore size */
- ar->winx = bwinx;
- ar->winy = bwiny;
- ar->winrct = brect;
-
- glPopMatrix();
-
- UI_Theme_Restore(&theme_state);
+ if (only_depth)
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- G.f &= ~G_RENDER_OGL;
+ if (only_depth || use_depth) {
+ glDisable(GL_DEPTH_TEST);
+ v3d->zbuf = false;
+ }
}
/**
- * Utility func for ED_view3d_draw_offscreen
- *
- * \param ofs: Optional off-screen buffer, can be NULL.
- * (avoids re-creating when doing multiple GL renders).
+ * Draw only the scene depth buffer
*/
-ImBuf *ED_view3d_draw_offscreen_imbuf(
- Scene *scene, View3D *v3d, ARegion *ar, int sizex, int sizey,
- unsigned int flag, bool draw_background,
- int alpha_mode, int samples, bool full_samples, const char *viewname,
- /* output vars */
- GPUFX *fx, GPUOffScreen *ofs, char err_out[256])
+static void draw_depth_buffer(const bContext *C, ARegion *ar)
{
- RegionView3D *rv3d = ar->regiondata;
- ImBuf *ibuf;
- const bool draw_sky = (alpha_mode == R_ADDSKY);
-
- /* view state */
- GPUFXSettings fx_settings = v3d->fx_settings;
- bool is_ortho = false;
- float winmat[4][4];
-
- if (ofs && ((GPU_offscreen_width(ofs) != sizex) || (GPU_offscreen_height(ofs) != sizey))) {
- /* sizes differ, can't reuse */
- ofs = NULL;
- }
-
- const bool own_ofs = (ofs == NULL);
-
- if (own_ofs) {
- /* bind */
- ofs = GPU_offscreen_create(sizex, sizey, full_samples ? 0 : samples, err_out);
- if (ofs == NULL) {
- return NULL;
- }
- }
-
- ED_view3d_draw_offscreen_init(scene, v3d, ar);
-
- GPU_offscreen_bind(ofs, true);
-
- /* read in pixels & stamp */
- ibuf = IMB_allocImBuf(sizex, sizey, 32, flag);
-
- /* render 3d view */
- if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
- CameraParams params;
- Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname);
-
- BKE_camera_params_init(&params);
- /* fallback for non camera objects */
- params.clipsta = v3d->near;
- params.clipend = v3d->far;
- BKE_camera_params_from_object(&params, camera);
- BKE_camera_multiview_params(&scene->r, &params, camera, viewname);
- BKE_camera_params_compute_viewplane(&params, sizex, sizey, scene->r.xasp, scene->r.yasp);
- BKE_camera_params_compute_matrix(&params);
-
- BKE_camera_to_gpu_dof(camera, &fx_settings);
-
- is_ortho = params.is_ortho;
- copy_m4_m4(winmat, params.winmat);
- }
- else {
- rctf viewplane;
- float clipsta, clipend;
-
- is_ortho = ED_view3d_viewplane_get(v3d, rv3d, sizex, sizey, &viewplane, &clipsta, &clipend, NULL);
- if (is_ortho) {
- orthographic_m4(winmat, viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, -clipend, clipend);
- }
- else {
- perspective_m4(winmat, viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clipsta, clipend);
- }
- }
-
- if ((samples && full_samples) == 0) {
- /* Single-pass render, common case */
- ED_view3d_draw_offscreen(
- scene, v3d, ar, sizex, sizey, NULL, winmat,
- draw_background, draw_sky, !is_ortho, true, viewname,
- fx, &fx_settings, ofs);
-
- if (ibuf->rect_float) {
- GPU_offscreen_read_pixels(ofs, GL_FLOAT, ibuf->rect_float);
- }
- else if (ibuf->rect) {
- GPU_offscreen_read_pixels(ofs, GL_UNSIGNED_BYTE, ibuf->rect);
- }
- }
- else {
- /* Multi-pass render, use accumulation buffer & jitter for 'full' oversampling.
- * Use because OpenGL may use a lower quality MSAA, and only over-sample edges. */
- static float jit_ofs[32][2];
- float winmat_jitter[4][4];
- /* use imbuf as temp storage, before writing into it from accumulation buffer */
- unsigned char *rect_temp = ibuf->rect ? (void *)ibuf->rect : (void *)ibuf->rect_float;
- unsigned int *accum_buffer = MEM_mallocN(sizex * sizey * sizeof(int[4]), "accum1");
- unsigned int i;
- int j;
-
- BLI_jitter_init(jit_ofs, samples);
-
- /* first sample buffer, also initializes 'rv3d->persmat' */
- ED_view3d_draw_offscreen(
- scene, v3d, ar, sizex, sizey, NULL, winmat,
- draw_background, draw_sky, !is_ortho, true, viewname,
- fx, &fx_settings, ofs);
- GPU_offscreen_read_pixels(ofs, GL_UNSIGNED_BYTE, rect_temp);
-
- i = sizex * sizey * 4;
- while (i--) {
- accum_buffer[i] = rect_temp[i];
- }
-
- /* skip the first sample */
- for (j = 1; j < samples; j++) {
- copy_m4_m4(winmat_jitter, winmat);
- window_translate_m4(
- winmat_jitter, rv3d->persmat,
- (jit_ofs[j][0] * 2.0f) / sizex,
- (jit_ofs[j][1] * 2.0f) / sizey);
-
- ED_view3d_draw_offscreen(
- scene, v3d, ar, sizex, sizey, NULL, winmat_jitter,
- draw_background, draw_sky, !is_ortho, true, viewname,
- fx, &fx_settings, ofs);
- GPU_offscreen_read_pixels(ofs, GL_UNSIGNED_BYTE, rect_temp);
-
- i = sizex * sizey * 4;
- while (i--) {
- accum_buffer[i] += rect_temp[i];
- }
- }
-
- if (ibuf->rect_float) {
- float *rect_float = ibuf->rect_float;
- i = sizex * sizey * 4;
- while (i--) {
- rect_float[i] = (float)(accum_buffer[i] / samples) * (1.0f / 255.0f);
- }
- }
- else {
- unsigned char *rect_ub = (unsigned char *)ibuf->rect;
- i = sizex * sizey * 4;
- while (i--) {
- rect_ub[i] = accum_buffer[i] / samples;
- }
- }
-
- MEM_freeN(accum_buffer);
- }
-
- /* unbind */
- GPU_offscreen_unbind(ofs, true);
-
- if (own_ofs) {
- GPU_offscreen_free(ofs);
- }
-
- if (ibuf->rect_float && ibuf->rect)
- IMB_rect_from_float(ibuf);
-
- return ibuf;
+ draw_all_objects(C, ar, true, true);
}
/**
- * Creates own fake 3d views (wrapping #ED_view3d_draw_offscreen_imbuf)
- *
- * \param ofs: Optional off-screen buffer can be NULL.
- * (avoids re-creating when doing multiple GL renders).
- *
- * \note used by the sequencer
+ * Required if the shaders need it or external engines
+ * (e.g., Cycles requires depth buffer handled separately).
*/
-ImBuf *ED_view3d_draw_offscreen_imbuf_simple(
- Scene *scene, Object *camera, int width, int height,
- unsigned int flag, int drawtype, bool use_solid_tex, bool use_gpencil, bool draw_background,
- int alpha_mode, int samples, bool full_samples, const char *viewname,
- GPUFX *fx, GPUOffScreen *ofs, char err_out[256])
+static void view3d_draw_prerender_buffers(const bContext *C, ARegion *ar, DrawData *draw_data)
{
- View3D v3d = {NULL};
- ARegion ar = {NULL};
- RegionView3D rv3d = {{{0}}};
-
- /* connect data */
- v3d.regionbase.first = v3d.regionbase.last = &ar;
- ar.regiondata = &rv3d;
- ar.regiontype = RGN_TYPE_WINDOW;
-
- v3d.camera = camera;
- v3d.lay = scene->lay;
- v3d.drawtype = drawtype;
- v3d.flag2 = V3D_RENDER_OVERRIDE;
-
- if (use_gpencil)
- v3d.flag2 |= V3D_SHOW_GPENCIL;
-
- if (use_solid_tex)
- v3d.flag2 |= V3D_SOLID_TEX;
-
- if (draw_background)
- v3d.flag3 |= V3D_SHOW_WORLD;
-
- rv3d.persp = RV3D_CAMOB;
-
- copy_m4_m4(rv3d.viewinv, v3d.camera->obmat);
- normalize_m4(rv3d.viewinv);
- invert_m4_m4(rv3d.viewmat, rv3d.viewinv);
+ View3D *v3d = CTX_wm_view3d(C);
- {
- CameraParams params;
- Object *view_camera = BKE_camera_multiview_render(scene, v3d.camera, viewname);
-
- BKE_camera_params_init(&params);
- BKE_camera_params_from_object(&params, view_camera);
- BKE_camera_multiview_params(&scene->r, &params, view_camera, viewname);
- BKE_camera_params_compute_viewplane(&params, width, height, scene->r.xasp, scene->r.yasp);
- BKE_camera_params_compute_matrix(&params);
-
- copy_m4_m4(rv3d.winmat, params.winmat);
- v3d.near = params.clipsta;
- v3d.far = params.clipend;
- v3d.lens = params.lens;
+ /* TODO viewport */
+ if (draw_data->is_render && ((!draw_data->clip_border) || (v3d->drawtype <= OB_WIRE))) {
+ draw_depth_buffer(C, ar);
}
-
- mul_m4_m4m4(rv3d.persmat, rv3d.winmat, rv3d.viewmat);
- invert_m4_m4(rv3d.persinv, rv3d.viewinv);
-
- return ED_view3d_draw_offscreen_imbuf(
- scene, &v3d, &ar, width, height, flag,
- draw_background, alpha_mode, samples, full_samples, viewname,
- fx, ofs, err_out);
}
-
/**
- * \note The info that this uses is updated in #ED_refresh_viewport_fps,
- * which currently gets called during #SCREEN_OT_animation_step.
+ * Draw all the plates that will fill the RGBD buffer
*/
-void ED_scene_draw_fps(Scene *scene, const rcti *rect)
+static void view3d_draw_solid_plates(const bContext *C, ARegion *ar, DrawData *draw_data)
{
- ScreenFrameRateInfo *fpsi = scene->fps_info;
- float fps;
- char printable[16];
- int i, tot;
-
- if (!fpsi || !fpsi->lredrawtime || !fpsi->redrawtime)
- return;
-
- printable[0] = '\0';
-
-#if 0
- /* this is too simple, better do an average */
- fps = (float)(1.0 / (fpsi->lredrawtime - fpsi->redrawtime))
-#else
- fpsi->redrawtimes_fps[fpsi->redrawtime_index] = (float)(1.0 / (fpsi->lredrawtime - fpsi->redrawtime));
-
- for (i = 0, tot = 0, fps = 0.0f; i < REDRAW_FRAME_AVERAGE; i++) {
- if (fpsi->redrawtimes_fps[i]) {
- fps += fpsi->redrawtimes_fps[i];
- tot++;
- }
- }
- if (tot) {
- fpsi->redrawtime_index = (fpsi->redrawtime_index + 1) % REDRAW_FRAME_AVERAGE;
-
- //fpsi->redrawtime_index++;
- //if (fpsi->redrawtime >= REDRAW_FRAME_AVERAGE)
- // fpsi->redrawtime = 0;
-
- fps = fps / tot;
- }
-#endif
+ Scene *scene = CTX_data_scene(C);
+ View3D *v3d = CTX_wm_view3d(C);
- /* is this more than half a frame behind? */
- if (fps + 0.5f < (float)(FPS)) {
- UI_ThemeColor(TH_REDALERT);
- BLI_snprintf(printable, sizeof(printable), IFACE_("fps: %.2f"), fps);
- }
- else {
- UI_ThemeColor(TH_TEXT_HI);
- BLI_snprintf(printable, sizeof(printable), IFACE_("fps: %i"), (int)(fps + 0.5f));
+ /* realtime plates */
+ if ((!draw_data->is_render) || draw_data->clip_border) {
+ view3d_draw_background(C);
+ view3d_draw_render_solid_surfaces(C, ar, true);
+ view3d_draw_render_transparent_surfaces(C);
+ view3d_draw_post_draw(C);
}
-#ifdef WITH_INTERNATIONAL
- BLF_draw_default(rect->xmin + U.widget_unit, rect->ymax - U.widget_unit, 0.0f, printable, sizeof(printable));
-#else
- BLF_draw_default_ascii(rect->xmin + U.widget_unit, rect->ymax - U.widget_unit, 0.0f, printable, sizeof(printable));
-#endif
+ /* offline plates*/
+ if (draw_data->is_render) {
+ view3d_draw_render_draw(C, scene, ar, v3d, draw_data->clip_border, &draw_data->border_rect);
+ }
}
-static bool view3d_main_region_do_render_draw(Scene *scene)
+/**
+ * Wires, outline, ...
+ */
+static void view3d_draw_geometry_overlay(const bContext *C)
{
- RenderEngineType *type = RE_engines_find(scene->r.engine);
-
- return (type && type->view_update && type->view_draw);
+ view3d_draw_wire_plates(C);
+ view3d_draw_outline_plates(C);
}
-bool ED_view3d_calc_render_border(Scene *scene, View3D *v3d, ARegion *ar, rcti *rect)
-{
- RegionView3D *rv3d = ar->regiondata;
- rctf viewborder;
- bool use_border;
-
- /* test if there is a 3d view rendering */
- if (v3d->drawtype != OB_RENDER || !view3d_main_region_do_render_draw(scene))
- return false;
-
- /* test if there is a border render */
- if (rv3d->persp == RV3D_CAMOB)
- use_border = (scene->r.mode & R_BORDER) != 0;
- else
- use_border = (v3d->flag2 & V3D_RENDER_BORDER) != 0;
-
- if (!use_border)
- return false;
-
- /* compute border */
- if (rv3d->persp == RV3D_CAMOB) {
- ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &viewborder, false);
-
- rect->xmin = viewborder.xmin + scene->r.border.xmin * BLI_rctf_size_x(&viewborder);
- rect->ymin = viewborder.ymin + scene->r.border.ymin * BLI_rctf_size_y(&viewborder);
- rect->xmax = viewborder.xmin + scene->r.border.xmax * BLI_rctf_size_x(&viewborder);
- rect->ymax = viewborder.ymin + scene->r.border.ymax * BLI_rctf_size_y(&viewborder);
- }
- else {
- rect->xmin = v3d->render_border.xmin * ar->winx;
- rect->xmax = v3d->render_border.xmax * ar->winx;
- rect->ymin = v3d->render_border.ymin * ar->winy;
- rect->ymax = v3d->render_border.ymax * ar->winy;
- }
-
- BLI_rcti_translate(rect, ar->winrct.xmin, ar->winrct.ymin);
- BLI_rcti_isect(&ar->winrct, rect, rect);
-
- return true;
-}
-
-static bool view3d_main_region_draw_engine(const bContext *C, Scene *scene,
- ARegion *ar, View3D *v3d,
- bool clip_border, const rcti *border_rect)
+/* drawing cameras, lamps, ... */
+static void view3d_draw_non_meshes(const bContext *C, ARegion *ar)
{
+ /* TODO viewport
+ * for now we draw them all, in the near future
+ * we filter them based on the plates/layers
+ */
+ Scene *scene = CTX_data_scene(C);
+ View3D *v3d = CTX_wm_view3d(C);
RegionView3D *rv3d = ar->regiondata;
- RenderEngineType *type;
- GLint scissor[4];
-
- /* create render engine */
- if (!rv3d->render_engine) {
- RenderEngine *engine;
-
- type = RE_engines_find(scene->r.engine);
-
- if (!(type->view_update && type->view_draw))
- return false;
-
- engine = RE_engine_create_ex(type, true);
-
- engine->tile_x = scene->r.tilex;
- engine->tile_y = scene->r.tiley;
-
- type->view_update(engine, C);
-
- rv3d->render_engine = engine;
- }
-
- /* setup view matrices */
- view3d_main_region_setup_view(scene, v3d, ar, NULL, NULL);
-
- /* background draw */
- ED_region_pixelspace(ar);
-
- if (clip_border) {
- /* for border draw, we only need to clear a subset of the 3d view */
- if (border_rect->xmax > border_rect->xmin && border_rect->ymax > border_rect->ymin) {
- glGetIntegerv(GL_SCISSOR_BOX, scissor);
- glScissor(border_rect->xmin, border_rect->ymin,
- BLI_rcti_size_x(border_rect), BLI_rcti_size_y(border_rect));
- }
- else {
- return false;
- }
- }
-
- glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
- if (v3d->flag & V3D_DISPBGPICS)
- view3d_draw_bgpic_test(scene, ar, v3d, false, true);
- else
- fdrawcheckerboard(0, 0, ar->winx, ar->winy);
-
- /* render result draw */
- type = rv3d->render_engine->type;
- type->view_draw(rv3d->render_engine, C);
+ Object *ob_act = CTX_data_active_object(C);
+ Base *base;
- if (v3d->flag & V3D_DISPBGPICS)
- view3d_draw_bgpic_test(scene, ar, v3d, true, true);
+ unsigned char *color, *color_prev = NULL;
+ unsigned char color_active[4], color_select[4], color_normal[4];
- if (clip_border) {
- /* restore scissor as it was before */
- glScissor(scissor[0], scissor[1], scissor[2], scissor[3]);
- }
-
- return true;
-}
+ UI_GetThemeColor4ubv(TH_ACTIVE, color_active);
+ UI_GetThemeColor4ubv(TH_SELECT, color_select);
+ UI_GetThemeColor4ubv(TH_WIRE, color_normal);
-static void view3d_main_region_draw_engine_info(View3D *v3d, RegionView3D *rv3d, ARegion *ar, bool render_border)
-{
- float fill_color[4] = {0.0f, 0.0f, 0.0f, 0.25f};
+ glEnable(GL_DEPTH_TEST);
+ glDepthMask(GL_FALSE); /* disable write in zbuffer */
+ /* TODO Viewport
+ * we are already temporarily writing to zbuffer in draw_object()
+ * for now let's avoid writing again to zbuffer to prevent glitches
+ */
- if (!rv3d->render_engine || !rv3d->render_engine->text[0])
- return;
-
- if (render_border) {
- /* draw darkened background color. no alpha because border render does
- * partial redraw and will not redraw the region behind this info bar */
- float alpha = 1.0f - fill_color[3];
- Camera *camera = ED_view3d_camera_data_get(v3d, rv3d);
-
- if (camera) {
- if (camera->flag & CAM_SHOWPASSEPARTOUT) {
- alpha *= (1.0f - camera->passepartalpha);
+ for (base = scene->base.first; base; base = base->next) {
+ if (v3d->lay & base->lay) {
+ Object *ob = base->object;
+
+ if (ob == ob_act)
+ color = color_active;
+ else if (ob->flag & SELECT)
+ color = color_select;
+ else
+ color = color_normal;
+
+ if (color != color_prev) {
+ glColor4ubv(color);
+ color_prev = color;
}
- }
- UI_GetThemeColor3fv(TH_HIGH_GRAD, fill_color);
- mul_v3_fl(fill_color, alpha);
- fill_color[3] = 1.0f;
+ view3d_draw_non_mesh(scene, ob, base, v3d, rv3d, color);
+ }
}
- ED_region_info_draw(ar, rv3d->render_engine->text, fill_color, true);
+ glDepthMask(GL_TRUE);
+ glDisable(GL_DEPTH_TEST);
}
-static bool view3d_stereo3d_active(const bContext *C, Scene *scene, View3D *v3d, RegionView3D *rv3d)
+/**
+* Parent lines, grid, ...
+*/
+static void view3d_draw_other_elements(const bContext *C, ARegion *ar)
{
- wmWindow *win = CTX_wm_window(C);
-
- if ((scene->r.scemode & R_MULTIVIEW) == 0)
- return false;
-
- if (WM_stereo3d_enabled(win, true) == false)
- return false;
-
- if ((v3d->camera == NULL) || (v3d->camera->type != OB_CAMERA) || rv3d->persp != RV3D_CAMOB)
- return false;
-
- if (scene->r.views_format & SCE_VIEWS_FORMAT_MULTIVIEW) {
- if (v3d->stereo3d_camera == STEREO_MONO_ID)
- return false;
-
- return BKE_scene_multiview_is_stereo3d(&scene->r);
- }
-
- return true;
+ /* TODO viewport */
+ view3d_draw_grid(C, ar);
}
-/* setup the view and win matrices for the multiview cameras
- *
- * unlike view3d_stereo3d_setup_offscreen, when view3d_stereo3d_setup is called
- * we have no winmatrix (i.e., projection matrix) defined at that time.
- * Since the camera and the camera shift are needed for the winmat calculation
- * we do a small hack to replace it temporarily so we don't need to change the
- * view3d)main_region_setup_view() code to account for that.
+/**
+ * Paint brushes, armatures, ...
*/
-static void view3d_stereo3d_setup(Scene *scene, View3D *v3d, ARegion *ar)
+static void view3d_draw_tool_ui(const bContext *C)
{
- bool is_left;
- const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME};
- const char *viewname;
-
- /* show only left or right camera */
- if (v3d->stereo3d_camera != STEREO_3D_ID)
- v3d->multiview_eye = v3d->stereo3d_camera;
-
- is_left = v3d->multiview_eye == STEREO_LEFT_ID;
- viewname = names[is_left ? STEREO_LEFT_ID : STEREO_RIGHT_ID];
-
- /* update the viewport matrices with the new camera */
- if (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D) {
- Camera *data;
- float viewmat[4][4];
- float shiftx;
-
- data = (Camera *)v3d->camera->data;
- shiftx = data->shiftx;
-
- BLI_lock_thread(LOCK_VIEW3D);
- data->shiftx = BKE_camera_multiview_shift_x(&scene->r, v3d->camera, viewname);
-
- BKE_camera_multiview_view_matrix(&scene->r, v3d->camera, is_left, viewmat);
- view3d_main_region_setup_view(scene, v3d, ar, viewmat, NULL);
-
- data->shiftx = shiftx;
- BLI_unlock_thread(LOCK_VIEW3D);
- }
- else { /* SCE_VIEWS_FORMAT_MULTIVIEW */
- float viewmat[4][4];
- Object *view_ob = v3d->camera;
- Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname);
-
- BLI_lock_thread(LOCK_VIEW3D);
- v3d->camera = camera;
-
- BKE_camera_multiview_view_matrix(&scene->r, camera, false, viewmat);
- view3d_main_region_setup_view(scene, v3d, ar, viewmat, NULL);
-
- v3d->camera = view_ob;
- BLI_unlock_thread(LOCK_VIEW3D);
- }
+ /* TODO viewport */
}
-static void view3d_stereo3d_setup_offscreen(Scene *scene, View3D *v3d, ARegion *ar,
- float winmat[4][4], const char *viewname)
+/**
+ * Blueprint images
+ */
+static void view3d_draw_reference_images(const bContext *C)
{
- /* update the viewport matrices with the new camera */
- if (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D) {
- float viewmat[4][4];
- const bool is_left = STREQ(viewname, STEREO_LEFT_NAME);
-
- BKE_camera_multiview_view_matrix(&scene->r, v3d->camera, is_left, viewmat);
- view3d_main_region_setup_view(scene, v3d, ar, viewmat, winmat);
- }
- else { /* SCE_VIEWS_FORMAT_MULTIVIEW */
- float viewmat[4][4];
- Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname);
-
- BKE_camera_multiview_view_matrix(&scene->r, camera, false, viewmat);
- view3d_main_region_setup_view(scene, v3d, ar, viewmat, winmat);
- }
+ /* TODO viewport */
}
-#ifdef WITH_GAMEENGINE
-static void update_lods(Scene *scene, float camera_pos[3])
+/**
+* 3D manipulators
+*/
+static void view3d_draw_manipulator(const bContext *C)
{
- Scene *sce_iter;
- Base *base;
- Object *ob;
-
- for (SETLOOPER(scene, sce_iter, base)) {
- ob = base->object;
- BKE_object_lod_update(ob, camera_pos);
- }
+ View3D *v3d = CTX_wm_view3d(C);
+ v3d->zbuf = false;
+ BIF_draw_manipulator(C);
}
-#endif
-static void view3d_main_region_draw_objects(const bContext *C, Scene *scene, View3D *v3d,
- ARegion *ar, const char **grid_unit)
+/**
+* Information drawn on top of the solid plates and composed data
+*/
+static void view3d_draw_region_info(const bContext *C, ARegion *ar)
{
- wmWindow *win = CTX_wm_window(C);
- RegionView3D *rv3d = ar->regiondata;
- unsigned int lay_used = v3d->lay_used;
-
-
- /* post processing */
- bool do_compositing = false;
-
- /* shadow buffers, before we setup matrices */
- if (draw_glsl_material(scene, NULL, v3d, v3d->drawtype)) {
- gpu_update_lamps_shadows_world(scene, v3d);
-
- if (BKE_scene_use_new_shading_nodes(scene) && (v3d->pbr_settings.pbr_flag & GPU_PBR_FLAG_ENABLE)) {
- GPU_pbr_settings_validate(&v3d->pbr_settings);
-
- if (!v3d->pbr)
- v3d->pbr = GPU_pbr_create();
-
- gpu_pbr_update(scene, v3d, ar);
- }
- }
-
- /* reset default OpenGL lights if needed (i.e. after preferences have been altered) */
- if (rv3d->rflag & RV3D_GPULIGHT_UPDATE) {
- rv3d->rflag &= ~RV3D_GPULIGHT_UPDATE;
- GPU_default_lights();
- }
-
- /* setup the view matrix */
- if (view3d_stereo3d_active(C, scene, v3d, rv3d))
- view3d_stereo3d_setup(scene, v3d, ar);
- else
- view3d_main_region_setup_view(scene, v3d, ar, NULL, NULL);
-
- rv3d->rflag &= ~RV3D_IS_GAME_ENGINE;
-#ifdef WITH_GAMEENGINE
- if (STREQ(scene->r.engine, RE_engine_id_BLENDER_GAME)) {
- rv3d->rflag |= RV3D_IS_GAME_ENGINE;
-
- /* Make sure LoDs are up to date */
- update_lods(scene, rv3d->viewinv[3]);
- }
-#endif
-
- /* framebuffer fx needed, we need to draw offscreen first */
- if ((v3d->fx_settings.fx_flag || v3d->fx_settings.fx_flag2) && v3d->drawtype >= OB_SOLID) {
- GPUFXSettings fx_settings;
- BKE_screen_gpu_fx_validate(&v3d->fx_settings);
- fx_settings = v3d->fx_settings;
- if (!rv3d->compositor)
- rv3d->compositor = GPU_fx_compositor_create();
-
- if (rv3d->persp == RV3D_CAMOB && v3d->camera)
- BKE_camera_to_gpu_dof(v3d->camera, &fx_settings);
- else {
- fx_settings.dof = NULL;
- }
-
- do_compositing = GPU_fx_compositor_initialize_passes(rv3d->compositor, &ar->winrct, &ar->drawrct, &fx_settings, scene);
- }
-
- /* clear the background */
- view3d_main_region_clear(scene, v3d, ar);
-
- /* enables anti-aliasing for 3D view drawing */
- if (win->multisamples != USER_MULTISAMPLE_NONE) {
- glEnable(GL_MULTISAMPLE);
- }
-
- /* main drawing call */
- view3d_draw_objects(C, scene, v3d, ar, grid_unit, true, false, do_compositing ? rv3d->compositor : NULL);
-
- /* post process */
- if (do_compositing) {
- GPU_fx_do_composite_pass(rv3d->compositor, rv3d->winmat, rv3d->is_persp, scene, NULL);
- }
+ rcti rect;
- /* Disable back anti-aliasing */
- if (win->multisamples != USER_MULTISAMPLE_NONE) {
- glDisable(GL_MULTISAMPLE);
- }
+ /* correct projection matrix */
+ ED_region_pixelspace(ar);
- if (v3d->lay_used != lay_used) { /* happens when loading old files or loading with UI load */
- /* find header and force tag redraw */
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar_header = BKE_area_find_region_type(sa, RGN_TYPE_HEADER);
- ED_region_tag_redraw(ar_header); /* can be NULL */
- }
+ /* local coordinate visible rect inside region, to accomodate overlapping ui */
+ ED_region_visible_rect(ar, &rect);
- if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) {
- BDR_drawSketch(C);
- }
+ view3d_draw_border(C, ar);
+ view3d_draw_grease_pencil(C);
-#ifdef WITH_INPUT_NDOF
- if ((U.ndof_flag & NDOF_SHOW_GUIDE) && ((rv3d->viewlock & RV3D_LOCKED) == 0) && (rv3d->persp != RV3D_CAMOB))
- /* TODO: draw something else (but not this) during fly mode */
- draw_rotation_guide(rv3d);
-#endif
+ /* TODO viewport */
}
-static bool is_cursor_visible(Scene *scene)
+/**
+ * This could run once per view, or even in parallel
+ * for each of them. What is a "view"?
+ * - a viewport with the camera elsewhere
+ * - left/right stereo
+ * - panorama / fisheye individual cubemap faces
+ */
+static void view3d_draw_view(const bContext *C, ARegion *ar, DrawData *draw_data)
{
- Object *ob = OBACT;
-
- /* don't draw cursor in paint modes, but with a few exceptions */
- if (ob && ob->mode & OB_MODE_ALL_PAINT) {
- /* exception: object is in weight paint and has deforming armature in pose mode */
- if (ob->mode & OB_MODE_WEIGHT_PAINT) {
- if (BKE_object_pose_armature_get(ob) != NULL) {
- return true;
- }
- }
- /* exception: object in texture paint mode, clone brush, use_clone_layer disabled */
- else if (ob->mode & OB_MODE_TEXTURE_PAINT) {
- const Paint *p = BKE_paint_get_active(scene);
-
- if (p && p->brush && p->brush->imagepaint_tool == PAINT_TOOL_CLONE) {
- if ((scene->toolsettings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_CLONE) == 0) {
- return true;
- }
- }
- }
-
- /* no exception met? then don't draw cursor! */
- return false;
- }
+ /* TODO - Technically this should be drawn to a few FBO, so we can handle
+ * compositing better, but for now this will get the ball rolling (dfelinto) */
- return true;
+ view3d_draw_setup_view(C, ar);
+ view3d_draw_prerender_buffers(C, ar, draw_data);
+ view3d_draw_solid_plates(C, ar, draw_data);
+ view3d_draw_geometry_overlay(C);
+ view3d_draw_non_meshes(C, ar);
+ view3d_draw_other_elements(C, ar);
+ view3d_draw_tool_ui(C);
+ view3d_draw_reference_images(C);
+ view3d_draw_manipulator(C);
+ view3d_draw_region_info(C, ar);
}
-static void view3d_main_region_draw_info(const bContext *C, Scene *scene,
- ARegion *ar, View3D *v3d,
- const char *grid_unit, bool render_border)
+void view3d_main_region_draw(const bContext *C, ARegion *ar)
{
- wmWindowManager *wm = CTX_wm_manager(C);
+ View3D *v3d = CTX_wm_view3d(C);
RegionView3D *rv3d = ar->regiondata;
- rcti rect;
-
- /* local coordinate visible rect inside region, to accomodate overlapping ui */
- ED_region_visible_rect(ar, &rect);
-
- if (rv3d->persp == RV3D_CAMOB) {
- drawviewborder(scene, ar, v3d);
- }
- else if (v3d->flag2 & V3D_RENDER_BORDER) {
- glLineWidth(1.0f);
- setlinestyle(3);
- cpack(0x4040FF);
-
- sdrawbox(v3d->render_border.xmin * ar->winx, v3d->render_border.ymin * ar->winy,
- v3d->render_border.xmax * ar->winx, v3d->render_border.ymax * ar->winy);
-
- setlinestyle(0);
- }
-
- if (v3d->flag2 & V3D_SHOW_GPENCIL) {
- /* draw grease-pencil stuff - needed to get paint-buffer shown too (since it's 2D) */
- ED_gpencil_draw_view3d(wm, scene, v3d, ar, false);
- }
- if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) {
- Object *ob;
-
- /* 3d cursor */
- if (is_cursor_visible(scene)) {
- drawcursor(scene, ar, v3d);
- }
-
- if (U.uiflag & USER_SHOW_ROTVIEWICON)
- draw_view_axis(rv3d, &rect);
- else
- draw_view_icon(rv3d, &rect);
-
- ob = OBACT;
- if (U.uiflag & USER_DRAWVIEWINFO)
- draw_selected_name(scene, ob, &rect);
- }
-
- if (rv3d->render_engine) {
- view3d_main_region_draw_engine_info(v3d, rv3d, ar, render_border);
+ if (IS_VIEWPORT_LEGACY(v3d)) {
+ view3d_main_region_draw_legacy(C, ar);
return;
}
- if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) {
- if ((U.uiflag & USER_SHOW_FPS) && ED_screen_animation_no_scrub(wm)) {
- ED_scene_draw_fps(scene, &rect);
- }
- else if (U.uiflag & USER_SHOW_VIEWPORTNAME) {
- draw_viewport_name(ar, v3d, &rect);
- }
-
- if (grid_unit) { /* draw below the viewport name */
- char numstr[32] = "";
+ if (!rv3d->viewport)
+ rv3d->viewport = GPU_viewport_create();
- UI_ThemeColor(TH_TEXT_HI);
- if (v3d->grid != 1.0f) {
- BLI_snprintf(numstr, sizeof(numstr), "%s x %.4g", grid_unit, v3d->grid);
- }
+ /* TODO viewport - there is so much to be done, in fact a lot will need to happen in the space_view3d.c
+ * before we even call the drawing routine, but let's move on for now (dfelinto)
+ * but this is a provisory way to start seeing things in the viewport */
+ DrawData draw_data;
+ view3d_draw_data_init(C, ar, &draw_data);
+ view3d_draw_view(C, ar, &draw_data);
- BLF_draw_default_ascii(rect.xmin + U.widget_unit,
- rect.ymax - (USER_SHOW_VIEWPORTNAME ? 2 * U.widget_unit : U.widget_unit), 0.0f,
- numstr[0] ? numstr : grid_unit, sizeof(numstr));
- }
- }
+ v3d->flag |= V3D_INVALID_BACKBUF;
}
-void view3d_main_region_draw(const bContext *C, ARegion *ar)
-{
- Scene *scene = CTX_data_scene(C);
- View3D *v3d = CTX_wm_view3d(C);
- const char *grid_unit = NULL;
- rcti border_rect;
- bool render_border, clip_border;
-
- /* if we only redraw render border area, skip opengl draw and also
- * don't do scissor because it's already set */
- render_border = ED_view3d_calc_render_border(scene, v3d, ar, &border_rect);
- clip_border = (render_border && !BLI_rcti_compare(&ar->drawrct, &border_rect));
-
- /* draw viewport using opengl */
- if (v3d->drawtype != OB_RENDER || !view3d_main_region_do_render_draw(scene) || clip_border) {
- view3d_main_region_draw_objects(C, scene, v3d, ar, &grid_unit);
-
-#ifdef DEBUG_DRAW
- bl_debug_draw();
-#endif
- if (G.debug & G_DEBUG_SIMDATA)
- draw_sim_debug_data(scene, v3d, ar);
-
- ED_region_pixelspace(ar);
- }
+/* ******************** legacy interface ***************** */
+/**
+ * This will be removed once the viewport gets replaced
+ * meanwhile it should keep the old viewport working.
+ */
- /* draw viewport using external renderer */
- if (v3d->drawtype == OB_RENDER)
- view3d_main_region_draw_engine(C, scene, ar, v3d, clip_border, &border_rect);
-
- view3d_main_region_draw_info(C, scene, ar, v3d, grid_unit, render_border);
+void VP_legacy_drawgrid(UnitSettings *unit, ARegion *ar, View3D *v3d, const char **grid_unit)
+{
+ drawgrid(unit, ar, v3d, grid_unit);
+}
- v3d->flag |= V3D_INVALID_BACKBUF;
+void VP_legacy_drawfloor(Scene *scene, View3D *v3d, const char **grid_unit, bool write_depth)
+{
+ drawfloor(scene, v3d, grid_unit, write_depth);
+}
- BLI_assert(BLI_listbase_is_empty(&v3d->afterdraw_transp));
- BLI_assert(BLI_listbase_is_empty(&v3d->afterdraw_xray));
- BLI_assert(BLI_listbase_is_empty(&v3d->afterdraw_xraytransp));
+void VP_legacy_view3d_main_region_setup_view(Scene *scene, View3D *v3d, ARegion *ar, float viewmat[4][4], float winmat[4][4])
+{
+ view3d_main_region_setup_view(scene, v3d, ar, viewmat, winmat);
}
-#ifdef DEBUG_DRAW
-/* debug drawing */
-#define _DEBUG_DRAW_QUAD_TOT 1024
-#define _DEBUG_DRAW_EDGE_TOT 1024
-static float _bl_debug_draw_quads[_DEBUG_DRAW_QUAD_TOT][4][3];
-static int _bl_debug_draw_quads_tot = 0;
-static float _bl_debug_draw_edges[_DEBUG_DRAW_QUAD_TOT][2][3];
-static int _bl_debug_draw_edges_tot = 0;
-static unsigned int _bl_debug_draw_quads_color[_DEBUG_DRAW_QUAD_TOT];
-static unsigned int _bl_debug_draw_edges_color[_DEBUG_DRAW_EDGE_TOT];
-static unsigned int _bl_debug_draw_color;
-
-void bl_debug_draw_quad_clear(void)
+bool VP_legacy_view3d_stereo3d_active(const bContext *C, Scene *scene, View3D *v3d, RegionView3D *rv3d)
{
- _bl_debug_draw_quads_tot = 0;
- _bl_debug_draw_edges_tot = 0;
- _bl_debug_draw_color = 0x00FF0000;
+ return view3d_stereo3d_active(C, scene, v3d, rv3d);
}
-void bl_debug_color_set(const unsigned int color)
+
+void VP_legacy_view3d_stereo3d_setup(Scene *scene, View3D *v3d, ARegion *ar)
{
- _bl_debug_draw_color = color;
+ view3d_stereo3d_setup(scene, v3d, ar);
}
-void bl_debug_draw_quad_add(const float v0[3], const float v1[3], const float v2[3], const float v3[3])
+
+bool VP_legacy_use_depth(Scene *scene, View3D *v3d)
{
- if (_bl_debug_draw_quads_tot >= _DEBUG_DRAW_QUAD_TOT) {
- printf("%s: max quad count hit %d!", __func__, _bl_debug_draw_quads_tot);
- }
- else {
- float *pt = &_bl_debug_draw_quads[_bl_debug_draw_quads_tot][0][0];
- copy_v3_v3(pt, v0); pt += 3;
- copy_v3_v3(pt, v1); pt += 3;
- copy_v3_v3(pt, v2); pt += 3;
- copy_v3_v3(pt, v3); pt += 3;
- _bl_debug_draw_quads_color[_bl_debug_draw_quads_tot] = _bl_debug_draw_color;
- _bl_debug_draw_quads_tot++;
- }
+ return use_depth_doit(scene, v3d);
}
-void bl_debug_draw_edge_add(const float v0[3], const float v1[3])
+
+void VP_drawviewborder(Scene *scene, ARegion *ar, View3D *v3d)
{
- if (_bl_debug_draw_quads_tot >= _DEBUG_DRAW_EDGE_TOT) {
- printf("%s: max edge count hit %d!", __func__, _bl_debug_draw_edges_tot);
- }
- else {
- float *pt = &_bl_debug_draw_edges[_bl_debug_draw_edges_tot][0][0];
- copy_v3_v3(pt, v0); pt += 3;
- copy_v3_v3(pt, v1); pt += 3;
- _bl_debug_draw_edges_color[_bl_debug_draw_edges_tot] = _bl_debug_draw_color;
- _bl_debug_draw_edges_tot++;
- }
+ drawviewborder(scene, ar, v3d);
}
-static void bl_debug_draw(void)
+
+void VP_drawrenderborder(ARegion *ar, View3D *v3d)
{
- unsigned int color;
- if (_bl_debug_draw_quads_tot) {
- int i;
- color = _bl_debug_draw_quads_color[0];
- cpack(color);
- for (i = 0; i < _bl_debug_draw_quads_tot; i ++) {
- if (_bl_debug_draw_quads_color[i] != color) {
- color = _bl_debug_draw_quads_color[i];
- cpack(color);
- }
- glBegin(GL_LINE_LOOP);
- glVertex3fv(_bl_debug_draw_quads[i][0]);
- glVertex3fv(_bl_debug_draw_quads[i][1]);
- glVertex3fv(_bl_debug_draw_quads[i][2]);
- glVertex3fv(_bl_debug_draw_quads[i][3]);
- glEnd();
- }
- }
- if (_bl_debug_draw_edges_tot) {
- int i;
- color = _bl_debug_draw_edges_color[0];
- cpack(color);
- glBegin(GL_LINES);
- for (i = 0; i < _bl_debug_draw_edges_tot; i ++) {
- if (_bl_debug_draw_edges_color[i] != color) {
- color = _bl_debug_draw_edges_color[i];
- cpack(color);
- }
- glVertex3fv(_bl_debug_draw_edges[i][0]);
- glVertex3fv(_bl_debug_draw_edges[i][1]);
- }
- glEnd();
- color = _bl_debug_draw_edges_color[0];
- cpack(color);
- glPointSize(4.0);
- glBegin(GL_POINTS);
- for (i = 0; i < _bl_debug_draw_edges_tot; i ++) {
- if (_bl_debug_draw_edges_color[i] != color) {
- color = _bl_debug_draw_edges_color[i];
- cpack(color);
- }
- glVertex3fv(_bl_debug_draw_edges[i][0]);
- glVertex3fv(_bl_debug_draw_edges[i][1]);
- }
- glEnd();
- }
+ drawrenderborder(ar, v3d);
}
-#endif
diff --git a/source/blender/editors/space_view3d/view3d_draw_legacy.c b/source/blender/editors/space_view3d/view3d_draw_legacy.c
new file mode 100644
index 00000000000..276ea95b955
--- /dev/null
+++ b/source/blender/editors/space_view3d/view3d_draw_legacy.c
@@ -0,0 +1,3647 @@
+/*
+ * ***** 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) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/space_view3d/view3d_draw.c
+ * \ingroup spview3d
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_customdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_group_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_key_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_world_types.h"
+#include "DNA_brush_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+#include "BLI_jitter.h"
+#include "BLI_utildefines.h"
+#include "BLI_endian_switch.h"
+#include "BLI_threads.h"
+
+#include "BKE_anim.h"
+#include "BKE_camera.h"
+#include "BKE_context.h"
+#include "BKE_customdata.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_image.h"
+#include "BKE_key.h"
+#include "BKE_main.h"
+#include "BKE_object.h"
+#include "BKE_global.h"
+#include "BKE_paint.h"
+#include "BKE_scene.h"
+#include "BKE_screen.h"
+#include "BKE_unit.h"
+#include "BKE_movieclip.h"
+
+#include "RE_engine.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+#include "IMB_colormanagement.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "WM_api.h"
+
+#include "BLF_api.h"
+#include "BLT_translation.h"
+
+#include "ED_armature.h"
+#include "ED_keyframing.h"
+#include "ED_gpencil.h"
+#include "ED_screen.h"
+#include "ED_space_api.h"
+#include "ED_screen_types.h"
+#include "ED_transform.h"
+
+#include "UI_interface.h"
+#include "UI_interface_icons.h"
+#include "UI_resources.h"
+
+#include "GPU_draw.h"
+#include "GPU_framebuffer.h"
+#include "GPU_material.h"
+#include "GPU_compositing.h"
+#include "GPU_extensions.h"
+#include "GPU_immediate.h"
+#include "GPU_probe.h"
+#include "GPU_pbr.h"
+
+#include "view3d_intern.h" /* own include */
+
+/* prototypes */
+static void view3d_stereo3d_setup_offscreen(Scene *scene, View3D *v3d, ARegion *ar,
+ float winmat[4][4], const char *viewname);
+
+/* handy utility for drawing shapes in the viewport for arbitrary code.
+ * could add lines and points too */
+// #define DEBUG_DRAW
+#ifdef DEBUG_DRAW
+static void bl_debug_draw(void);
+/* add these locally when using these functions for testing */
+extern void bl_debug_draw_quad_clear(void);
+extern void bl_debug_draw_quad_add(const float v0[3], const float v1[3], const float v2[3], const float v3[3]);
+extern void bl_debug_draw_edge_add(const float v0[3], const float v1[3]);
+extern void bl_debug_color_set(const unsigned int col);
+#endif
+
+void circ(float x, float y, float rad)
+{
+ glBegin(GL_LINE_LOOP);
+ const int segments = 32;
+ for (int i = 0; i < segments; ++i) {
+ float angle = 2 * M_PI * ((float)i / (float)segments);
+ glVertex2f(x + rad * cosf(angle),
+ y + rad * sinf(angle));
+ }
+ glEnd();
+}
+
+
+/* ********* custom clipping *********** */
+
+static void view3d_draw_clipping(RegionView3D *rv3d)
+{
+ BoundBox *bb = rv3d->clipbb;
+
+ if (bb) {
+ const unsigned int clipping_index[6][4] = {
+ {0, 1, 2, 3},
+ {0, 4, 5, 1},
+ {4, 7, 6, 5},
+ {7, 3, 2, 6},
+ {1, 5, 6, 2},
+ {7, 4, 0, 3}
+ };
+
+ /* fill in zero alpha for rendering & re-projection [#31530] */
+ unsigned char col[4];
+ UI_GetThemeColor4ubv(TH_V3D_CLIPPING_BORDER, col);
+ glColor4ubv(col);
+
+ glEnable(GL_BLEND);
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glVertexPointer(3, GL_FLOAT, 0, bb->vec);
+ glDrawElements(GL_QUADS, sizeof(clipping_index) / sizeof(unsigned int), GL_UNSIGNED_INT, clipping_index);
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisable(GL_BLEND);
+ }
+}
+
+void ED_view3d_clipping_set(RegionView3D *rv3d)
+{
+ double plane[4];
+ const unsigned int tot = (rv3d->viewlock & RV3D_BOXCLIP) ? 4 : 6;
+ unsigned int a;
+
+ for (a = 0; a < tot; a++) {
+ copy_v4db_v4fl(plane, rv3d->clip[a]);
+ glClipPlane(GL_CLIP_PLANE0 + a, plane);
+ glEnable(GL_CLIP_PLANE0 + a);
+ }
+}
+
+/* use these to temp disable/enable clipping when 'rv3d->rflag & RV3D_CLIPPING' is set */
+void ED_view3d_clipping_disable(void)
+{
+ unsigned int a;
+
+ for (a = 0; a < 6; a++) {
+ glDisable(GL_CLIP_PLANE0 + a);
+ }
+}
+void ED_view3d_clipping_enable(void)
+{
+ unsigned int a;
+
+ for (a = 0; a < 6; a++) {
+ glEnable(GL_CLIP_PLANE0 + a);
+ }
+}
+
+static bool view3d_clipping_test(const float co[3], const float clip[6][4])
+{
+ if (plane_point_side_v3(clip[0], co) > 0.0f)
+ if (plane_point_side_v3(clip[1], co) > 0.0f)
+ if (plane_point_side_v3(clip[2], co) > 0.0f)
+ if (plane_point_side_v3(clip[3], co) > 0.0f)
+ return false;
+
+ return true;
+}
+
+/* for 'local' ED_view3d_clipping_local must run first
+ * then all comparisons can be done in localspace */
+bool ED_view3d_clipping_test(const RegionView3D *rv3d, const float co[3], const bool is_local)
+{
+ return view3d_clipping_test(co, is_local ? rv3d->clip_local : rv3d->clip);
+}
+
+/* ********* end custom clipping *********** */
+
+static void drawcursor(Scene *scene, ARegion *ar, View3D *v3d)
+{
+ int co[2];
+
+ /* we don't want the clipping for cursor */
+ if (ED_view3d_project_int_global(ar, ED_view3d_cursor3d_get(scene, v3d), co, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
+ const float f5 = 0.25f * U.widget_unit;
+ const float f10 = 0.5f * U.widget_unit;
+ const float f20 = U.widget_unit;
+
+ glLineWidth(1);
+
+ VertexFormat* format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ unsigned color = add_attrib(format, "color", GL_UNSIGNED_BYTE, 3, NORMALIZE_INT_TO_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
+
+ const int segments = 16;
+
+ immBegin(GL_LINE_LOOP, segments);
+
+ for (int i = 0; i < segments; ++i) {
+ float angle = 2 * M_PI * ((float)i / (float)segments);
+ float x = co[0] + f10 * cosf(angle);
+ float y = co[1] + f10 * sinf(angle);
+
+ if (i % 2 == 0)
+ immAttrib3ub(color, 255, 0, 0);
+ else
+ immAttrib3ub(color, 255, 255, 255);
+
+ immVertex2f(pos, x, y);
+ }
+ immEnd();
+
+ immUnbindProgram();
+
+ VertexFormat_clear(format);
+ pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ unsigned char crosshair_color[3];
+ UI_GetThemeColor3ubv(TH_VIEW_OVERLAY, crosshair_color);
+ immUniformColor3ubv(crosshair_color);
+
+ immBegin(GL_LINES, 8);
+ immVertex2f(pos, co[0] - f20, co[1]);
+ immVertex2f(pos, co[0] - f5, co[1]);
+ immVertex2f(pos, co[0] + f5, co[1]);
+ immVertex2f(pos, co[0] + f20, co[1]);
+ immVertex2f(pos, co[0], co[1] - f20);
+ immVertex2f(pos, co[0], co[1] - f5);
+ immVertex2f(pos, co[0], co[1] + f5);
+ immVertex2f(pos, co[0], co[1] + f20);
+ immEnd();
+
+ immUnbindProgram();
+ }
+}
+
+static void draw_view_axis(RegionView3D *rv3d, rcti *rect)
+{
+ const float k = U.rvisize * U.pixelsize; /* axis size */
+ const int bright = - 20 * (10 - U.rvibright); /* axis alpha offset (rvibright has range 0-10) */
+
+ const float startx = rect->xmin + k + 1.0f; /* axis center in screen coordinates, x=y */
+ const float starty = rect->ymin + k + 1.0f;
+
+ float axis_pos[3][2];
+ unsigned char axis_col[3][4];
+
+ int axis_order[3] = {0, 1, 2};
+ axis_sort_v3(rv3d->viewinv[2], axis_order);
+
+ for (int axis_i = 0; axis_i < 3; axis_i++) {
+ int i = axis_order[axis_i];
+
+ /* get position of each axis tip on screen */
+ float vec[3] = { 0.0f };
+ vec[i] = 1.0f;
+ mul_qt_v3(rv3d->viewquat, vec);
+ axis_pos[i][0] = startx + vec[0] * k;
+ axis_pos[i][1] = starty + vec[1] * k;
+
+ /* get color of each axis */
+ UI_GetThemeColorShade3ubv(TH_AXIS_X + i, bright, axis_col[i]); /* rgb */
+ axis_col[i][3] = 255 * hypotf(vec[0], vec[1]); /* alpha */
+ }
+
+ /* draw axis lines */
+ glLineWidth(2);
+ glEnable(GL_LINE_SMOOTH);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ VertexFormat *format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ unsigned col = add_attrib(format, "color", GL_UNSIGNED_BYTE, 4, NORMALIZE_INT_TO_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
+ immBegin(GL_LINES, 6);
+
+ for (int axis_i = 0; axis_i < 3; axis_i++) {
+ int i = axis_order[axis_i];
+
+ immAttrib4ubv(col, axis_col[i]);
+ immVertex2f(pos, startx, starty);
+ immVertex2fv(pos, axis_pos[i]);
+ }
+
+ immEnd();
+ immUnbindProgram();
+ glDisable(GL_LINE_SMOOTH);
+
+ /* draw axis names */
+ for (int axis_i = 0; axis_i < 3; axis_i++) {
+ int i = axis_order[axis_i];
+
+ const char axis_text[2] = {'x' + i, '\0'};
+ glColor4ubv(axis_col[i]); /* text shader still uses gl_Color */
+ BLF_draw_default_ascii(axis_pos[i][0] + 2, axis_pos[i][1] + 2, 0.0f, axis_text, 1);
+ }
+
+ /* BLF_draw_default disabled blending for us */
+}
+
+#ifdef WITH_INPUT_NDOF
+/* draw center and axis of rotation for ongoing 3D mouse navigation */
+static void draw_rotation_guide(RegionView3D *rv3d)
+{
+ float o[3]; /* center of rotation */
+ float end[3]; /* endpoints for drawing */
+
+ GLubyte color[4] = {0, 108, 255, 255}; /* bright blue so it matches device LEDs */
+
+ negate_v3_v3(o, rv3d->ofs);
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glPointSize(5);
+ glEnable(GL_POINT_SMOOTH);
+ glDepthMask(0); /* don't overwrite zbuf */
+
+ VertexFormat *format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ unsigned col = add_attrib(format, "color", GL_UNSIGNED_BYTE, 4, NORMALIZE_INT_TO_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_SMOOTH_COLOR);
+
+ if (rv3d->rot_angle != 0.0f) {
+ /* -- draw rotation axis -- */
+ float scaled_axis[3];
+ const float scale = rv3d->dist;
+ mul_v3_v3fl(scaled_axis, rv3d->rot_axis, scale);
+
+
+ immBegin(GL_LINE_STRIP, 3);
+ color[3] = 0; /* more transparent toward the ends */
+ immAttrib4ubv(col, color);
+ add_v3_v3v3(end, o, scaled_axis);
+ immVertex3fv(pos, end);
+
+#if 0
+ color[3] = 0.2f + fabsf(rv3d->rot_angle); /* modulate opacity with angle */
+ /* ^^ neat idea, but angle is frame-rate dependent, so it's usually close to 0.2 */
+#endif
+
+ color[3] = 127; /* more opaque toward the center */
+ immAttrib4ubv(col, color);
+ immVertex3fv(pos, o);
+
+ color[3] = 0;
+ immAttrib4ubv(col, color);
+ sub_v3_v3v3(end, o, scaled_axis);
+ immVertex3fv(pos, end);
+ immEnd();
+
+ /* -- draw ring around rotation center -- */
+ {
+#define ROT_AXIS_DETAIL 13
+
+ const float s = 0.05f * scale;
+ const float step = 2.0f * (float)(M_PI / ROT_AXIS_DETAIL);
+ float angle;
+ int i;
+
+ float q[4]; /* rotate ring so it's perpendicular to axis */
+ const int upright = fabsf(rv3d->rot_axis[2]) >= 0.95f;
+ if (!upright) {
+ const float up[3] = {0.0f, 0.0f, 1.0f};
+ float vis_angle, vis_axis[3];
+
+ cross_v3_v3v3(vis_axis, up, rv3d->rot_axis);
+ vis_angle = acosf(dot_v3v3(up, rv3d->rot_axis));
+ axis_angle_to_quat(q, vis_axis, vis_angle);
+ }
+
+ immBegin(GL_LINE_LOOP, ROT_AXIS_DETAIL);
+ color[3] = 63; /* somewhat faint */
+ immAttrib4ubv(col, color);
+ for (i = 0, angle = 0.0f; i < ROT_AXIS_DETAIL; ++i, angle += step) {
+ float p[3] = {s * cosf(angle), s * sinf(angle), 0.0f};
+
+ if (!upright) {
+ mul_qt_v3(q, p);
+ }
+
+ add_v3_v3(p, o);
+ immVertex3fv(pos, p);
+ }
+ immEnd();
+
+#undef ROT_AXIS_DETAIL
+ }
+
+ color[3] = 255; /* solid dot */
+ }
+ else
+ color[3] = 127; /* see-through dot */
+
+ /* -- draw rotation center -- */
+ immBegin(GL_POINTS, 1);
+ immAttrib4ubv(col, color);
+ immVertex3fv(pos, o);
+ immEnd();
+ immUnbindProgram();
+
+#if 0
+ /* find screen coordinates for rotation center, then draw pretty icon */
+ mul_m4_v3(rv3d->persinv, rot_center);
+ UI_icon_draw(rot_center[0], rot_center[1], ICON_NDOF_TURN);
+ /* ^^ just playing around, does not work */
+#endif
+
+ glDisable(GL_BLEND);
+ glDisable(GL_POINT_SMOOTH);
+ glDepthMask(1);
+}
+#endif /* WITH_INPUT_NDOF */
+
+static void draw_view_icon(RegionView3D *rv3d, rcti *rect)
+{
+ BIFIconID icon;
+
+ if (ELEM(rv3d->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM))
+ icon = ICON_AXIS_TOP;
+ else if (ELEM(rv3d->view, RV3D_VIEW_FRONT, RV3D_VIEW_BACK))
+ icon = ICON_AXIS_FRONT;
+ else if (ELEM(rv3d->view, RV3D_VIEW_RIGHT, RV3D_VIEW_LEFT))
+ icon = ICON_AXIS_SIDE;
+ else return;
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ UI_icon_draw(5.0 + rect->xmin, 5.0 + rect->ymin, icon);
+
+ glDisable(GL_BLEND);
+}
+
+static const char *view3d_get_name(View3D *v3d, RegionView3D *rv3d)
+{
+ const char *name = NULL;
+
+ switch (rv3d->view) {
+ case RV3D_VIEW_FRONT:
+ if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Front Ortho");
+ else name = IFACE_("Front Persp");
+ break;
+ case RV3D_VIEW_BACK:
+ if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Back Ortho");
+ else name = IFACE_("Back Persp");
+ break;
+ case RV3D_VIEW_TOP:
+ if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Top Ortho");
+ else name = IFACE_("Top Persp");
+ break;
+ case RV3D_VIEW_BOTTOM:
+ if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Bottom Ortho");
+ else name = IFACE_("Bottom Persp");
+ break;
+ case RV3D_VIEW_RIGHT:
+ if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Right Ortho");
+ else name = IFACE_("Right Persp");
+ break;
+ case RV3D_VIEW_LEFT:
+ if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Left Ortho");
+ else name = IFACE_("Left Persp");
+ break;
+
+ default:
+ if (rv3d->persp == RV3D_CAMOB) {
+ if ((v3d->camera) && (v3d->camera->type == OB_CAMERA)) {
+ Camera *cam;
+ cam = v3d->camera->data;
+ if (cam->type == CAM_PERSP) {
+ name = IFACE_("Camera Persp");
+ }
+ else if (cam->type == CAM_ORTHO) {
+ name = IFACE_("Camera Ortho");
+ }
+ else {
+ BLI_assert(cam->type == CAM_PANO);
+ name = IFACE_("Camera Pano");
+ }
+ }
+ else {
+ name = IFACE_("Object as Camera");
+ }
+ }
+ else {
+ name = (rv3d->persp == RV3D_ORTHO) ? IFACE_("User Ortho") : IFACE_("User Persp");
+ }
+ break;
+ }
+
+ return name;
+}
+
+static void draw_viewport_name(ARegion *ar, View3D *v3d, rcti *rect)
+{
+ RegionView3D *rv3d = ar->regiondata;
+ const char *name = view3d_get_name(v3d, rv3d);
+ /* increase size for unicode languages (Chinese in utf-8...) */
+#ifdef WITH_INTERNATIONAL
+ char tmpstr[96];
+#else
+ char tmpstr[32];
+#endif
+
+ if (v3d->localvd) {
+ BLI_snprintf(tmpstr, sizeof(tmpstr), IFACE_("%s (Local)"), name);
+ name = tmpstr;
+ }
+
+ UI_ThemeColor(TH_TEXT_HI);
+#ifdef WITH_INTERNATIONAL
+ BLF_draw_default(U.widget_unit + rect->xmin, rect->ymax - U.widget_unit, 0.0f, name, sizeof(tmpstr));
+#else
+ BLF_draw_default_ascii(U.widget_unit + rect->xmin, rect->ymax - U.widget_unit, 0.0f, name, sizeof(tmpstr));
+#endif
+}
+
+/* draw info beside axes in bottom left-corner:
+ * framenum, object name, bone name (if available), marker name (if available)
+ */
+
+static void draw_selected_name(Scene *scene, Object *ob, rcti *rect)
+{
+ const int cfra = CFRA;
+ const char *msg_pin = " (Pinned)";
+ const char *msg_sep = " : ";
+
+ char info[300];
+ const char *markern;
+ char *s = info;
+ short offset = 1.5f * UI_UNIT_X + rect->xmin;
+
+ s += sprintf(s, "(%d)", cfra);
+
+ /*
+ * info can contain:
+ * - a frame (7 + 2)
+ * - 3 object names (MAX_NAME)
+ * - 2 BREAD_CRUMB_SEPARATORs (6)
+ * - a SHAPE_KEY_PINNED marker and a trailing '\0' (9+1) - translated, so give some room!
+ * - a marker name (MAX_NAME + 3)
+ */
+
+ /* get name of marker on current frame (if available) */
+ markern = BKE_scene_find_marker_name(scene, cfra);
+
+ /* check if there is an object */
+ if (ob) {
+ *s++ = ' ';
+ s += BLI_strcpy_rlen(s, ob->id.name + 2);
+
+ /* name(s) to display depends on type of object */
+ if (ob->type == OB_ARMATURE) {
+ bArmature *arm = ob->data;
+
+ /* show name of active bone too (if possible) */
+ if (arm->edbo) {
+ if (arm->act_edbone) {
+ s += BLI_strcpy_rlen(s, msg_sep);
+ s += BLI_strcpy_rlen(s, arm->act_edbone->name);
+ }
+ }
+ else if (ob->mode & OB_MODE_POSE) {
+ if (arm->act_bone) {
+
+ if (arm->act_bone->layer & arm->layer) {
+ s += BLI_strcpy_rlen(s, msg_sep);
+ s += BLI_strcpy_rlen(s, arm->act_bone->name);
+ }
+ }
+ }
+ }
+ else if (ELEM(ob->type, OB_MESH, OB_LATTICE, OB_CURVE)) {
+ Key *key = NULL;
+ KeyBlock *kb = NULL;
+
+ /* try to display active bone and active shapekey too (if they exist) */
+
+ if (ob->type == OB_MESH && ob->mode & OB_MODE_WEIGHT_PAINT) {
+ Object *armobj = BKE_object_pose_armature_get(ob);
+ if (armobj && armobj->mode & OB_MODE_POSE) {
+ bArmature *arm = armobj->data;
+ if (arm->act_bone) {
+ if (arm->act_bone->layer & arm->layer) {
+ s += BLI_strcpy_rlen(s, msg_sep);
+ s += BLI_strcpy_rlen(s, arm->act_bone->name);
+ }
+ }
+ }
+ }
+
+ key = BKE_key_from_object(ob);
+ if (key) {
+ kb = BLI_findlink(&key->block, ob->shapenr - 1);
+ if (kb) {
+ s += BLI_strcpy_rlen(s, msg_sep);
+ s += BLI_strcpy_rlen(s, kb->name);
+ if (ob->shapeflag & OB_SHAPE_LOCK) {
+ s += BLI_strcpy_rlen(s, IFACE_(msg_pin));
+ }
+ }
+ }
+ }
+
+ /* color depends on whether there is a keyframe */
+ if (id_frame_has_keyframe((ID *)ob, /* BKE_scene_frame_get(scene) */ (float)cfra, ANIMFILTER_KEYS_LOCAL))
+ UI_ThemeColor(TH_TIME_KEYFRAME);
+ else if (ED_gpencil_has_keyframe_v3d(scene, ob, cfra))
+ UI_ThemeColor(TH_TIME_GP_KEYFRAME);
+ else
+ UI_ThemeColor(TH_TEXT_HI);
+ }
+ else {
+ /* no object */
+ if (ED_gpencil_has_keyframe_v3d(scene, NULL, cfra))
+ UI_ThemeColor(TH_TIME_GP_KEYFRAME);
+ else
+ UI_ThemeColor(TH_TEXT_HI);
+ }
+
+ if (markern) {
+ s += sprintf(s, " <%s>", markern);
+ }
+
+ if (U.uiflag & USER_SHOW_ROTVIEWICON)
+ offset = U.widget_unit + (U.rvisize * 2) + rect->xmin;
+
+ BLF_draw_default(offset, 0.5f * U.widget_unit, 0.0f, info, sizeof(info));
+}
+
+/* *********************** backdraw for selection *************** */
+
+static void backdrawview3d(Scene *scene, wmWindow *win, ARegion *ar, View3D *v3d)
+{
+ RegionView3D *rv3d = ar->regiondata;
+ struct Base *base = scene->basact;
+ int multisample_enabled;
+
+ BLI_assert(ar->regiontype == RGN_TYPE_WINDOW);
+
+ if (base && (base->object->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT) ||
+ BKE_paint_select_face_test(base->object)))
+ {
+ /* do nothing */
+ }
+ /* texture paint mode sampling */
+ else if (base && (base->object->mode & OB_MODE_TEXTURE_PAINT) &&
+ (v3d->drawtype > OB_WIRE))
+ {
+ /* do nothing */
+ }
+ else if (scene->obedit &&
+ V3D_IS_ZBUF(v3d))
+ {
+ /* do nothing */
+ }
+ else {
+ v3d->flag &= ~V3D_INVALID_BACKBUF;
+ return;
+ }
+
+ if (!(v3d->flag & V3D_INVALID_BACKBUF))
+ return;
+
+#if 0
+ if (test) {
+ if (qtest()) {
+ addafterqueue(ar->win, BACKBUFDRAW, 1);
+ return;
+ }
+ }
+#endif
+
+ if (v3d->drawtype > OB_WIRE) v3d->zbuf = true;
+
+ /* dithering and AA break color coding, so disable */
+ glDisable(GL_DITHER);
+
+ multisample_enabled = glIsEnabled(GL_MULTISAMPLE);
+ if (multisample_enabled)
+ glDisable(GL_MULTISAMPLE);
+
+ if (win->multisamples != USER_MULTISAMPLE_NONE) {
+ /* for multisample we use an offscreen FBO. multisample drawing can fail
+ * with color coded selection drawing, and reading back depths from such
+ * a buffer can also cause a few seconds freeze on OS X / NVidia. */
+ int w = BLI_rcti_size_x(&ar->winrct);
+ int h = BLI_rcti_size_y(&ar->winrct);
+ char error[256];
+
+ if (rv3d->gpuoffscreen) {
+ if (GPU_offscreen_width(rv3d->gpuoffscreen) != w ||
+ GPU_offscreen_height(rv3d->gpuoffscreen) != h)
+ {
+ GPU_offscreen_free(rv3d->gpuoffscreen);
+ rv3d->gpuoffscreen = NULL;
+ }
+ }
+
+ if (!rv3d->gpuoffscreen) {
+ rv3d->gpuoffscreen = GPU_offscreen_create(w, h, 0, error);
+
+ if (!rv3d->gpuoffscreen)
+ fprintf(stderr, "Failed to create offscreen selection buffer for multisample: %s\n", error);
+ }
+ }
+
+ if (rv3d->gpuoffscreen)
+ GPU_offscreen_bind(rv3d->gpuoffscreen, true);
+ else
+ glScissor(ar->winrct.xmin, ar->winrct.ymin, BLI_rcti_size_x(&ar->winrct), BLI_rcti_size_y(&ar->winrct));
+
+ glClearColor(0.0, 0.0, 0.0, 0.0);
+ if (v3d->zbuf) {
+ glEnable(GL_DEPTH_TEST);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ }
+ else {
+ glClear(GL_COLOR_BUFFER_BIT);
+ glDisable(GL_DEPTH_TEST);
+ }
+
+ if (rv3d->rflag & RV3D_CLIPPING)
+ ED_view3d_clipping_set(rv3d);
+
+ G.f |= G_BACKBUFSEL;
+
+ if (base && (base->lay & v3d->lay))
+ draw_object_backbufsel(scene, v3d, rv3d, base->object);
+
+ if (rv3d->gpuoffscreen)
+ GPU_offscreen_unbind(rv3d->gpuoffscreen, true);
+ else
+ ar->swap = 0; /* mark invalid backbuf for wm draw */
+
+ v3d->flag &= ~V3D_INVALID_BACKBUF;
+
+ G.f &= ~G_BACKBUFSEL;
+ v3d->zbuf = false;
+ glDisable(GL_DEPTH_TEST);
+ glEnable(GL_DITHER);
+ if (multisample_enabled)
+ glEnable(GL_MULTISAMPLE);
+
+ if (rv3d->rflag & RV3D_CLIPPING)
+ ED_view3d_clipping_disable();
+}
+
+void view3d_opengl_read_pixels(ARegion *ar, int x, int y, int w, int h, int format, int type, void *data)
+{
+ RegionView3D *rv3d = ar->regiondata;
+
+ if (rv3d->gpuoffscreen) {
+ GPU_offscreen_bind(rv3d->gpuoffscreen, true);
+ glReadBuffer(GL_COLOR_ATTACHMENT0);
+ glReadPixels(x, y, w, h, format, type, data);
+ GPU_offscreen_unbind(rv3d->gpuoffscreen, true);
+ }
+ else {
+ glReadPixels(ar->winrct.xmin + x, ar->winrct.ymin + y, w, h, format, type, data);
+ }
+}
+
+/* XXX depth reading exception, for code not using gpu offscreen */
+static void view3d_opengl_read_Z_pixels(ARegion *ar, int x, int y, int w, int h, int format, int type, void *data)
+{
+
+ glReadPixels(ar->winrct.xmin + x, ar->winrct.ymin + y, w, h, format, type, data);
+}
+
+void ED_view3d_backbuf_validate(ViewContext *vc)
+{
+ if (vc->v3d->flag & V3D_INVALID_BACKBUF)
+ backdrawview3d(vc->scene, vc->win, vc->ar, vc->v3d);
+}
+
+/**
+ * allow for small values [0.5 - 2.5],
+ * and large values, FLT_MAX by clamping by the area size
+ */
+int ED_view3d_backbuf_sample_size_clamp(ARegion *ar, const float dist)
+{
+ return (int)min_ff(ceilf(dist), (float)max_ii(ar->winx, ar->winx));
+}
+
+/* samples a single pixel (copied from vpaint) */
+unsigned int ED_view3d_backbuf_sample(ViewContext *vc, int x, int y)
+{
+ unsigned int col;
+
+ if (x >= vc->ar->winx || y >= vc->ar->winy) {
+ return 0;
+ }
+
+ ED_view3d_backbuf_validate(vc);
+
+ view3d_opengl_read_pixels(vc->ar, x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col);
+ glReadBuffer(GL_BACK);
+
+ if (ENDIAN_ORDER == B_ENDIAN) {
+ BLI_endian_switch_uint32(&col);
+ }
+
+ return GPU_select_to_index(col);
+}
+
+/* reads full rect, converts indices */
+ImBuf *ED_view3d_backbuf_read(ViewContext *vc, int xmin, int ymin, int xmax, int ymax)
+{
+ struct ImBuf *ibuf_clip;
+ /* clip */
+ const rcti clip = {
+ max_ii(xmin, 0), min_ii(xmax, vc->ar->winx - 1),
+ max_ii(ymin, 0), min_ii(ymax, vc->ar->winy - 1)};
+ const int size_clip[2] = {
+ BLI_rcti_size_x(&clip) + 1,
+ BLI_rcti_size_y(&clip) + 1};
+
+ if (UNLIKELY((clip.xmin > clip.xmax) ||
+ (clip.ymin > clip.ymax)))
+ {
+ return NULL;
+ }
+
+ ibuf_clip = IMB_allocImBuf(size_clip[0], size_clip[1], 32, IB_rect);
+
+ ED_view3d_backbuf_validate(vc);
+
+ view3d_opengl_read_pixels(vc->ar, clip.xmin, clip.ymin, size_clip[0], size_clip[1], GL_RGBA, GL_UNSIGNED_BYTE, ibuf_clip->rect);
+
+ glReadBuffer(GL_BACK);
+
+ if (ENDIAN_ORDER == B_ENDIAN) {
+ IMB_convert_rgba_to_abgr(ibuf_clip);
+ }
+
+ GPU_select_to_index_array(ibuf_clip->rect, size_clip[0] * size_clip[1]);
+
+ if ((clip.xmin == xmin) &&
+ (clip.xmax == xmax) &&
+ (clip.ymin == ymin) &&
+ (clip.ymax == ymax))
+ {
+ return ibuf_clip;
+ }
+ else {
+ /* put clipped result into a non-clipped buffer */
+ struct ImBuf *ibuf_full;
+ const int size[2] = {
+ (xmax - xmin + 1),
+ (ymax - ymin + 1)};
+
+ ibuf_full = IMB_allocImBuf(size[0], size[1], 32, IB_rect);
+
+ IMB_rectcpy(
+ ibuf_full, ibuf_clip,
+ clip.xmin - xmin, clip.ymin - ymin,
+ 0, 0,
+ size_clip[0], size_clip[1]);
+ IMB_freeImBuf(ibuf_clip);
+ return ibuf_full;
+ }
+}
+
+/* smart function to sample a rect spiralling outside, nice for backbuf selection */
+unsigned int ED_view3d_backbuf_sample_rect(
+ ViewContext *vc, const int mval[2], int size,
+ unsigned int min, unsigned int max, float *r_dist)
+{
+ struct ImBuf *buf;
+ const unsigned int *bufmin, *bufmax, *tbuf;
+ int minx, miny;
+ int a, b, rc, nr, amount, dirvec[4][2];
+ unsigned int index = 0;
+
+ amount = (size - 1) / 2;
+
+ minx = mval[0] - (amount + 1);
+ miny = mval[1] - (amount + 1);
+ buf = ED_view3d_backbuf_read(vc, minx, miny, minx + size - 1, miny + size - 1);
+ if (!buf) return 0;
+
+ rc = 0;
+
+ dirvec[0][0] = 1; dirvec[0][1] = 0;
+ dirvec[1][0] = 0; dirvec[1][1] = -size;
+ dirvec[2][0] = -1; dirvec[2][1] = 0;
+ dirvec[3][0] = 0; dirvec[3][1] = size;
+
+ bufmin = buf->rect;
+ tbuf = buf->rect;
+ bufmax = buf->rect + size * size;
+ tbuf += amount * size + amount;
+
+ for (nr = 1; nr <= size; nr++) {
+
+ for (a = 0; a < 2; a++) {
+ for (b = 0; b < nr; b++) {
+ if (*tbuf && *tbuf >= min && *tbuf < max) {
+ /* we got a hit */
+
+ /* get x,y pixel coords from the offset
+ * (manhatten distance in keeping with other screen-based selection) */
+ *r_dist = (float)(
+ abs(((int)(tbuf - buf->rect) % size) - (size / 2)) +
+ abs(((int)(tbuf - buf->rect) / size) - (size / 2)));
+
+ /* indices start at 1 here */
+ index = (*tbuf - min) + 1;
+ goto exit;
+ }
+
+ tbuf += (dirvec[rc][0] + dirvec[rc][1]);
+
+ if (tbuf < bufmin || tbuf >= bufmax) {
+ goto exit;
+ }
+ }
+ rc++;
+ rc &= 3;
+ }
+ }
+
+exit:
+ IMB_freeImBuf(buf);
+ return index;
+}
+
+
+/* ************************************************************* */
+
+static void view3d_stereo_bgpic_setup(Scene *scene, View3D *v3d, Image *ima, ImageUser *iuser)
+{
+ if (BKE_image_is_stereo(ima)) {
+ iuser->flag |= IMA_SHOW_STEREO;
+
+ if ((scene->r.scemode & R_MULTIVIEW) == 0) {
+ iuser->multiview_eye = STEREO_LEFT_ID;
+ }
+ else if (v3d->stereo3d_camera != STEREO_3D_ID) {
+ /* show only left or right camera */
+ iuser->multiview_eye = v3d->stereo3d_camera;
+ }
+
+ BKE_image_multiview_index(ima, iuser);
+ }
+ else {
+ iuser->flag &= ~IMA_SHOW_STEREO;
+ }
+}
+
+static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d,
+ const bool do_foreground, const bool do_camera_frame)
+{
+ RegionView3D *rv3d = ar->regiondata;
+ BGpic *bgpic;
+ int fg_flag = do_foreground ? V3D_BGPIC_FOREGROUND : 0;
+
+ for (bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next) {
+ bgpic->iuser.scene = scene; /* Needed for render results. */
+
+ if ((bgpic->flag & V3D_BGPIC_FOREGROUND) != fg_flag)
+ continue;
+
+ if ((bgpic->view == 0) || /* zero for any */
+ (bgpic->view & (1 << rv3d->view)) || /* check agaist flags */
+ (rv3d->persp == RV3D_CAMOB && bgpic->view == (1 << RV3D_VIEW_CAMERA)))
+ {
+ float image_aspect[2];
+ float fac, asp, zoomx, zoomy;
+ float x1, y1, x2, y2, centx, centy;
+
+ ImBuf *ibuf = NULL, *freeibuf, *releaseibuf;
+ void *lock;
+ rctf clip_rect;
+
+ Image *ima = NULL;
+ MovieClip *clip = NULL;
+
+ /* disable individual images */
+ if ((bgpic->flag & V3D_BGPIC_DISABLED))
+ continue;
+
+ freeibuf = NULL;
+ releaseibuf = NULL;
+ if (bgpic->source == V3D_BGPIC_IMAGE) {
+ ima = bgpic->ima;
+ if (ima == NULL)
+ continue;
+ BKE_image_user_frame_calc(&bgpic->iuser, CFRA, 0);
+ if (ima->source == IMA_SRC_SEQUENCE && !(bgpic->iuser.flag & IMA_USER_FRAME_IN_RANGE)) {
+ ibuf = NULL; /* frame is out of range, dont show */
+ }
+ else {
+ view3d_stereo_bgpic_setup(scene, v3d, ima, &bgpic->iuser);
+ ibuf = BKE_image_acquire_ibuf(ima, &bgpic->iuser, &lock);
+ releaseibuf = ibuf;
+ }
+
+ image_aspect[0] = ima->aspx;
+ image_aspect[1] = ima->aspy;
+ }
+ else if (bgpic->source == V3D_BGPIC_MOVIE) {
+ /* TODO: skip drawing when out of frame range (as image sequences do above) */
+
+ if (bgpic->flag & V3D_BGPIC_CAMERACLIP) {
+ if (scene->camera)
+ clip = BKE_object_movieclip_get(scene, scene->camera, true);
+ }
+ else {
+ clip = bgpic->clip;
+ }
+
+ if (clip == NULL)
+ continue;
+
+ BKE_movieclip_user_set_frame(&bgpic->cuser, CFRA);
+ ibuf = BKE_movieclip_get_ibuf(clip, &bgpic->cuser);
+
+ image_aspect[0] = clip->aspx;
+ image_aspect[1] = clip->aspy;
+
+ /* working with ibuf from image and clip has got different workflow now.
+ * ibuf acquired from clip is referenced by cache system and should
+ * be dereferenced after usage. */
+ freeibuf = ibuf;
+ }
+ else {
+ /* perhaps when loading future files... */
+ BLI_assert(0);
+ copy_v2_fl(image_aspect, 1.0f);
+ }
+
+ if (ibuf == NULL)
+ continue;
+
+ if ((ibuf->rect == NULL && ibuf->rect_float == NULL) || ibuf->channels != 4) { /* invalid image format */
+ if (freeibuf)
+ IMB_freeImBuf(freeibuf);
+ if (releaseibuf)
+ BKE_image_release_ibuf(ima, releaseibuf, lock);
+
+ continue;
+ }
+
+ if (ibuf->rect == NULL)
+ IMB_rect_from_float(ibuf);
+
+ if (rv3d->persp == RV3D_CAMOB) {
+
+ if (do_camera_frame) {
+ rctf vb;
+ ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &vb, false);
+ x1 = vb.xmin;
+ y1 = vb.ymin;
+ x2 = vb.xmax;
+ y2 = vb.ymax;
+ }
+ else {
+ x1 = ar->winrct.xmin;
+ y1 = ar->winrct.ymin;
+ x2 = ar->winrct.xmax;
+ y2 = ar->winrct.ymax;
+ }
+
+ /* apply offset last - camera offset is different to offset in blender units */
+ /* so this has some sane way of working - this matches camera's shift _exactly_ */
+ {
+ const float max_dim = max_ff(x2 - x1, y2 - y1);
+ const float xof_scale = bgpic->xof * max_dim;
+ const float yof_scale = bgpic->yof * max_dim;
+
+ x1 += xof_scale;
+ y1 += yof_scale;
+ x2 += xof_scale;
+ y2 += yof_scale;
+ }
+
+ centx = (x1 + x2) / 2.0f;
+ centy = (y1 + y2) / 2.0f;
+
+ /* aspect correction */
+ if (bgpic->flag & V3D_BGPIC_CAMERA_ASPECT) {
+ /* apply aspect from clip */
+ const float w_src = ibuf->x * image_aspect[0];
+ const float h_src = ibuf->y * image_aspect[1];
+
+ /* destination aspect is already applied from the camera frame */
+ const float w_dst = x1 - x2;
+ const float h_dst = y1 - y2;
+
+ const float asp_src = w_src / h_src;
+ const float asp_dst = w_dst / h_dst;
+
+ if (fabsf(asp_src - asp_dst) >= FLT_EPSILON) {
+ if ((asp_src > asp_dst) == ((bgpic->flag & V3D_BGPIC_CAMERA_CROP) != 0)) {
+ /* fit X */
+ const float div = asp_src / asp_dst;
+ x1 = ((x1 - centx) * div) + centx;
+ x2 = ((x2 - centx) * div) + centx;
+ }
+ else {
+ /* fit Y */
+ const float div = asp_dst / asp_src;
+ y1 = ((y1 - centy) * div) + centy;
+ y2 = ((y2 - centy) * div) + centy;
+ }
+ }
+ }
+ }
+ else {
+ float tvec[3];
+ float sco[2];
+ const float mval_f[2] = {1.0f, 0.0f};
+ const float co_zero[3] = {0};
+ float zfac;
+
+ /* calc window coord */
+ zfac = ED_view3d_calc_zfac(rv3d, co_zero, NULL);
+ ED_view3d_win_to_delta(ar, mval_f, tvec, zfac);
+ fac = max_ff(fabsf(tvec[0]), max_ff(fabsf(tvec[1]), fabsf(tvec[2]))); /* largest abs axis */
+ fac = 1.0f / fac;
+
+ asp = (float)ibuf->y / (float)ibuf->x;
+
+ zero_v3(tvec);
+ ED_view3d_project_float_v2_m4(ar, tvec, sco, rv3d->persmat);
+
+ x1 = sco[0] + fac * (bgpic->xof - bgpic->size);
+ y1 = sco[1] + asp * fac * (bgpic->yof - bgpic->size);
+ x2 = sco[0] + fac * (bgpic->xof + bgpic->size);
+ y2 = sco[1] + asp * fac * (bgpic->yof + bgpic->size);
+
+ centx = (x1 + x2) / 2.0f;
+ centy = (y1 + y2) / 2.0f;
+ }
+
+ /* complete clip? */
+ BLI_rctf_init(&clip_rect, x1, x2, y1, y2);
+ if (bgpic->rotation) {
+ BLI_rctf_rotate_expand(&clip_rect, &clip_rect, bgpic->rotation);
+ }
+
+ if (clip_rect.xmax < 0 || clip_rect.ymax < 0 || clip_rect.xmin > ar->winx || clip_rect.ymin > ar->winy) {
+ if (freeibuf)
+ IMB_freeImBuf(freeibuf);
+ if (releaseibuf)
+ BKE_image_release_ibuf(ima, releaseibuf, lock);
+
+ continue;
+ }
+
+ zoomx = (x2 - x1) / ibuf->x;
+ zoomy = (y2 - y1) / ibuf->y;
+
+ /* for some reason; zoomlevels down refuses to use GL_ALPHA_SCALE */
+ if (zoomx < 1.0f || zoomy < 1.0f) {
+ float tzoom = min_ff(zoomx, zoomy);
+ int mip = 0;
+
+ if ((ibuf->userflags & IB_MIPMAP_INVALID) != 0) {
+ IMB_remakemipmap(ibuf, 0);
+ ibuf->userflags &= ~IB_MIPMAP_INVALID;
+ }
+ else if (ibuf->mipmap[0] == NULL)
+ IMB_makemipmap(ibuf, 0);
+
+ while (tzoom < 1.0f && mip < 8 && ibuf->mipmap[mip]) {
+ tzoom *= 2.0f;
+ zoomx *= 2.0f;
+ zoomy *= 2.0f;
+ mip++;
+ }
+ if (mip > 0)
+ ibuf = ibuf->mipmap[mip - 1];
+ }
+
+ if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
+ glDepthMask(0);
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ ED_region_pixelspace(ar);
+
+ glTranslatef(centx, centy, 0.0);
+ glRotatef(RAD2DEGF(-bgpic->rotation), 0.0f, 0.0f, 1.0f);
+
+ if (bgpic->flag & V3D_BGPIC_FLIP_X) {
+ zoomx *= -1.0f;
+ x1 = x2;
+ }
+ if (bgpic->flag & V3D_BGPIC_FLIP_Y) {
+ zoomy *= -1.0f;
+ y1 = y2;
+ }
+ glPixelZoom(zoomx, zoomy);
+ glColor4f(1.0f, 1.0f, 1.0f, 1.0f - bgpic->blend);
+
+ /* could not use glaDrawPixelsAuto because it could fallback to
+ * glaDrawPixelsSafe in some cases, which will end up in missing
+ * alpha transparency for the background image (sergey)
+ */
+ glaDrawPixelsTex(x1 - centx, y1 - centy, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_LINEAR, ibuf->rect);
+
+ glPixelZoom(1.0, 1.0);
+ glPixelTransferf(GL_ALPHA_SCALE, 1.0f);
+
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+
+ glDisable(GL_BLEND);
+
+ glDepthMask(1);
+ if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
+
+ if (freeibuf)
+ IMB_freeImBuf(freeibuf);
+ if (releaseibuf)
+ BKE_image_release_ibuf(ima, releaseibuf, lock);
+ }
+ }
+}
+
+static void view3d_draw_bgpic_test(Scene *scene, ARegion *ar, View3D *v3d,
+ const bool do_foreground, const bool do_camera_frame)
+{
+ RegionView3D *rv3d = ar->regiondata;
+
+ if ((v3d->flag & V3D_DISPBGPICS) == 0)
+ return;
+
+ /* disabled - mango request, since footage /w only render is quite useful
+ * and this option is easy to disable all background images at once */
+#if 0
+ if (v3d->flag2 & V3D_RENDER_OVERRIDE)
+ return;
+#endif
+
+ if ((rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO)) {
+ if (rv3d->persp == RV3D_CAMOB) {
+ view3d_draw_bgpic(scene, ar, v3d, do_foreground, do_camera_frame);
+ }
+ }
+ else {
+ view3d_draw_bgpic(scene, ar, v3d, do_foreground, do_camera_frame);
+ }
+}
+
+/* ****************** View3d afterdraw *************** */
+
+typedef struct View3DAfter {
+ struct View3DAfter *next, *prev;
+ struct Base *base;
+ short dflag;
+} View3DAfter;
+
+/* temp storage of Objects that need to be drawn as last */
+void ED_view3d_after_add(ListBase *lb, Base *base, const short dflag)
+{
+ View3DAfter *v3da = MEM_callocN(sizeof(View3DAfter), "View 3d after");
+ BLI_assert((base->flag & OB_FROMDUPLI) == 0);
+ BLI_addtail(lb, v3da);
+ v3da->base = base;
+ v3da->dflag = dflag;
+}
+
+/* disables write in zbuffer and draws it over */
+static void view3d_draw_transp(Scene *scene, ARegion *ar, View3D *v3d)
+{
+ View3DAfter *v3da;
+
+ glDepthMask(GL_FALSE);
+ v3d->transp = true;
+
+ while ((v3da = BLI_pophead(&v3d->afterdraw_transp))) {
+ draw_object(scene, ar, v3d, v3da->base, v3da->dflag);
+ MEM_freeN(v3da);
+ }
+ v3d->transp = false;
+
+ glDepthMask(GL_TRUE);
+
+}
+
+/* clears zbuffer and draws it over */
+static void view3d_draw_xray(Scene *scene, ARegion *ar, View3D *v3d, bool *clear)
+{
+ View3DAfter *v3da;
+
+ if (*clear && v3d->zbuf) {
+ glClear(GL_DEPTH_BUFFER_BIT);
+ *clear = false;
+ }
+
+ v3d->xray = true;
+ while ((v3da = BLI_pophead(&v3d->afterdraw_xray))) {
+ draw_object(scene, ar, v3d, v3da->base, v3da->dflag);
+ MEM_freeN(v3da);
+ }
+ v3d->xray = false;
+}
+
+
+/* clears zbuffer and draws it over */
+static void view3d_draw_xraytransp(Scene *scene, ARegion *ar, View3D *v3d, const bool clear)
+{
+ View3DAfter *v3da;
+
+ if (clear && v3d->zbuf)
+ glClear(GL_DEPTH_BUFFER_BIT);
+
+ v3d->xray = true;
+ v3d->transp = true;
+
+ glDepthMask(GL_FALSE);
+
+ while ((v3da = BLI_pophead(&v3d->afterdraw_xraytransp))) {
+ draw_object(scene, ar, v3d, v3da->base, v3da->dflag);
+ MEM_freeN(v3da);
+ }
+
+ v3d->transp = false;
+ v3d->xray = false;
+
+ glDepthMask(GL_TRUE);
+}
+
+/* *********************** */
+
+/*
+ * In most cases call draw_dupli_objects,
+ * draw_dupli_objects_color was added because when drawing set dupli's
+ * we need to force the color
+ */
+
+#if 0
+int dupli_ob_sort(void *arg1, void *arg2)
+{
+ void *p1 = ((DupliObject *)arg1)->ob;
+ void *p2 = ((DupliObject *)arg2)->ob;
+ int val = 0;
+ if (p1 < p2) val = -1;
+ else if (p1 > p2) val = 1;
+ return val;
+}
+#endif
+
+
+static DupliObject *dupli_step(DupliObject *dob)
+{
+ while (dob && dob->no_draw)
+ dob = dob->next;
+ return dob;
+}
+
+static void draw_dupli_objects_color(
+ Scene *scene, ARegion *ar, View3D *v3d, Base *base,
+ const short dflag, const int color)
+{
+ RegionView3D *rv3d = ar->regiondata;
+ ListBase *lb;
+ LodLevel *savedlod;
+ DupliObject *dob_prev = NULL, *dob, *dob_next = NULL;
+ Base tbase = {NULL};
+ BoundBox bb, *bb_tmp; /* use a copy because draw_object, calls clear_mesh_caches */
+ GLuint displist = 0;
+ unsigned char color_rgb[3];
+ const short dflag_dupli = dflag | DRAW_CONSTCOLOR;
+ short transflag;
+ bool use_displist = false; /* -1 is initialize */
+ char dt;
+ short dtx;
+ DupliApplyData *apply_data;
+
+ if (base->object->restrictflag & OB_RESTRICT_VIEW) return;
+ if ((base->object->restrictflag & OB_RESTRICT_RENDER) && (v3d->flag2 & V3D_RENDER_OVERRIDE)) return;
+
+ if (dflag & DRAW_CONSTCOLOR) {
+ BLI_assert(color == TH_UNDEFINED);
+ }
+ else {
+ UI_GetThemeColorBlend3ubv(color, TH_BACK, 0.5f, color_rgb);
+ }
+
+ tbase.flag = OB_FROMDUPLI | base->flag;
+ lb = object_duplilist(G.main->eval_ctx, scene, base->object);
+ // BLI_listbase_sort(lb, dupli_ob_sort); /* might be nice to have if we have a dupli list with mixed objects. */
+
+ apply_data = duplilist_apply(base->object, scene, lb);
+
+ dob = dupli_step(lb->first);
+ if (dob) dob_next = dupli_step(dob->next);
+
+ for (; dob; dob_prev = dob, dob = dob_next, dob_next = dob_next ? dupli_step(dob_next->next) : NULL) {
+ bool testbb = false;
+
+ tbase.object = dob->ob;
+
+ /* Make sure lod is updated from dupli's position */
+ savedlod = dob->ob->currentlod;
+
+#ifdef WITH_GAMEENGINE
+ if (rv3d->rflag & RV3D_IS_GAME_ENGINE) {
+ BKE_object_lod_update(dob->ob, rv3d->viewinv[3]);
+ }
+#endif
+
+ /* extra service: draw the duplicator in drawtype of parent, minimum taken
+ * to allow e.g. boundbox box objects in groups for LOD */
+ dt = tbase.object->dt;
+ tbase.object->dt = MIN2(tbase.object->dt, base->object->dt);
+
+ /* inherit draw extra, but not if a boundbox under the assumption that this
+ * is intended to speed up drawing, and drawing extra (especially wire) can
+ * slow it down too much */
+ dtx = tbase.object->dtx;
+ if (tbase.object->dt != OB_BOUNDBOX)
+ tbase.object->dtx = base->object->dtx;
+
+ /* negative scale flag has to propagate */
+ transflag = tbase.object->transflag;
+
+ if (is_negative_m4(dob->mat))
+ tbase.object->transflag |= OB_NEG_SCALE;
+ else
+ tbase.object->transflag &= ~OB_NEG_SCALE;
+
+ /* should move outside the loop but possible color is set in draw_object still */
+ if ((dflag & DRAW_CONSTCOLOR) == 0) {
+ glColor3ubv(color_rgb);
+ }
+
+ /* generate displist, test for new object */
+ if (dob_prev && dob_prev->ob != dob->ob) {
+ if (use_displist == true)
+ glDeleteLists(displist, 1);
+
+ use_displist = false;
+ }
+
+ if ((bb_tmp = BKE_object_boundbox_get(dob->ob))) {
+ bb = *bb_tmp; /* must make a copy */
+ testbb = true;
+ }
+
+ if (!testbb || ED_view3d_boundbox_clip_ex(rv3d, &bb, dob->mat)) {
+ /* generate displist */
+ if (use_displist == false) {
+
+ /* note, since this was added, its checked (dob->type == OB_DUPLIGROUP)
+ * however this is very slow, it was probably needed for the NLA
+ * offset feature (used in group-duplicate.blend but no longer works in 2.5)
+ * so for now it should be ok to - campbell */
+
+ if ( /* if this is the last no need to make a displist */
+ (dob_next == NULL || dob_next->ob != dob->ob) ||
+ /* lamp drawing messes with matrices, could be handled smarter... but this works */
+ (dob->ob->type == OB_LAMP) ||
+ (dob->type == OB_DUPLIGROUP && dob->animated) ||
+ !bb_tmp ||
+ draw_glsl_material(scene, dob->ob, v3d, dt) ||
+ check_object_draw_texture(scene, v3d, dt) ||
+ (v3d->flag2 & V3D_SOLID_MATCAP) != 0)
+ {
+ // printf("draw_dupli_objects_color: skipping displist for %s\n", dob->ob->id.name + 2);
+ use_displist = false;
+ }
+ else {
+ // printf("draw_dupli_objects_color: using displist for %s\n", dob->ob->id.name + 2);
+
+ /* disable boundbox check for list creation */
+ BKE_object_boundbox_flag(dob->ob, BOUNDBOX_DISABLED, 1);
+ /* need this for next part of code */
+ unit_m4(dob->ob->obmat); /* obmat gets restored */
+
+ displist = glGenLists(1);
+ glNewList(displist, GL_COMPILE);
+ draw_object(scene, ar, v3d, &tbase, dflag_dupli);
+ glEndList();
+
+ use_displist = true;
+ BKE_object_boundbox_flag(dob->ob, BOUNDBOX_DISABLED, 0);
+ }
+ }
+
+ if (use_displist) {
+ glPushMatrix();
+ glMultMatrixf(dob->mat);
+ glCallList(displist);
+ glPopMatrix();
+ }
+ else {
+ copy_m4_m4(dob->ob->obmat, dob->mat);
+ GPU_begin_dupli_object(dob);
+ draw_object(scene, ar, v3d, &tbase, dflag_dupli);
+ GPU_end_dupli_object();
+ }
+ }
+
+ tbase.object->dt = dt;
+ tbase.object->dtx = dtx;
+ tbase.object->transflag = transflag;
+ tbase.object->currentlod = savedlod;
+ }
+
+ if (apply_data) {
+ duplilist_restore(lb, apply_data);
+ duplilist_free_apply_data(apply_data);
+ }
+
+ free_object_duplilist(lb);
+
+ if (use_displist)
+ glDeleteLists(displist, 1);
+}
+
+void draw_dupli_objects(Scene *scene, ARegion *ar, View3D *v3d, Base *base)
+{
+ /* define the color here so draw_dupli_objects_color can be called
+ * from the set loop */
+
+ int color = (base->flag & SELECT) ? TH_SELECT : TH_WIRE;
+ /* debug */
+ if (base->object->dup_group && base->object->dup_group->id.us < 1)
+ color = TH_REDALERT;
+
+ draw_dupli_objects_color(scene, ar, v3d, base, 0, color);
+}
+
+/* XXX warning, not using gpu offscreen here */
+void view3d_update_depths_rect(ARegion *ar, ViewDepths *d, rcti *rect)
+{
+ int x, y, w, h;
+ rcti r;
+ /* clamp rect by region */
+
+ r.xmin = 0;
+ r.xmax = ar->winx - 1;
+ r.ymin = 0;
+ r.ymax = ar->winy - 1;
+
+ /* Constrain rect to depth bounds */
+ BLI_rcti_isect(&r, rect, rect);
+
+ /* assign values to compare with the ViewDepths */
+ x = rect->xmin;
+ y = rect->ymin;
+
+ w = BLI_rcti_size_x(rect);
+ h = BLI_rcti_size_y(rect);
+
+ if (w <= 0 || h <= 0) {
+ if (d->depths)
+ MEM_freeN(d->depths);
+ d->depths = NULL;
+
+ d->damaged = false;
+ }
+ else if (d->w != w ||
+ d->h != h ||
+ d->x != x ||
+ d->y != y ||
+ d->depths == NULL
+ )
+ {
+ d->x = x;
+ d->y = y;
+ d->w = w;
+ d->h = h;
+
+ if (d->depths)
+ MEM_freeN(d->depths);
+
+ d->depths = MEM_mallocN(sizeof(float) * d->w * d->h, "View depths Subset");
+
+ d->damaged = true;
+ }
+
+ if (d->damaged) {
+ /* XXX using special function here, it doesn't use the gpu offscreen system */
+ view3d_opengl_read_Z_pixels(ar, d->x, d->y, d->w, d->h, GL_DEPTH_COMPONENT, GL_FLOAT, d->depths);
+ glGetDoublev(GL_DEPTH_RANGE, d->depth_range);
+ d->damaged = false;
+ }
+}
+
+/* note, with nouveau drivers the glReadPixels() is very slow. [#24339] */
+void ED_view3d_depth_update(ARegion *ar)
+{
+ RegionView3D *rv3d = ar->regiondata;
+
+ /* Create storage for, and, if necessary, copy depth buffer */
+ if (!rv3d->depths) rv3d->depths = MEM_callocN(sizeof(ViewDepths), "ViewDepths");
+ if (rv3d->depths) {
+ ViewDepths *d = rv3d->depths;
+ if (d->w != ar->winx ||
+ d->h != ar->winy ||
+ !d->depths)
+ {
+ d->w = ar->winx;
+ d->h = ar->winy;
+ if (d->depths)
+ MEM_freeN(d->depths);
+ d->depths = MEM_mallocN(sizeof(float) * d->w * d->h, "View depths");
+ d->damaged = true;
+ }
+
+ if (d->damaged) {
+ view3d_opengl_read_pixels(ar, 0, 0, d->w, d->h, GL_DEPTH_COMPONENT, GL_FLOAT, d->depths);
+ glGetDoublev(GL_DEPTH_RANGE, d->depth_range);
+
+ d->damaged = false;
+ }
+ }
+}
+
+/* utility function to find the closest Z value, use for autodepth */
+float view3d_depth_near(ViewDepths *d)
+{
+ /* convert to float for comparisons */
+ const float near = (float)d->depth_range[0];
+ const float far_real = (float)d->depth_range[1];
+ float far = far_real;
+
+ const float *depths = d->depths;
+ float depth = FLT_MAX;
+ int i = (int)d->w * (int)d->h; /* cast to avoid short overflow */
+
+ /* far is both the starting 'far' value
+ * and the closest value found. */
+ while (i--) {
+ depth = *depths++;
+ if ((depth < far) && (depth > near)) {
+ far = depth;
+ }
+ }
+
+ return far == far_real ? FLT_MAX : far;
+}
+
+void ED_view3d_draw_depth_gpencil(Scene *scene, ARegion *ar, View3D *v3d)
+{
+ short zbuf = v3d->zbuf;
+ RegionView3D *rv3d = ar->regiondata;
+
+ view3d_winmatrix_set(ar, v3d, NULL);
+ view3d_viewmatrix_set(scene, v3d, rv3d); /* note: calls BKE_object_where_is_calc for camera... */
+
+ mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat);
+ invert_m4_m4(rv3d->persinv, rv3d->persmat);
+ invert_m4_m4(rv3d->viewinv, rv3d->viewmat);
+
+ glClear(GL_DEPTH_BUFFER_BIT);
+
+ glLoadMatrixf(rv3d->viewmat);
+
+ v3d->zbuf = true;
+ glEnable(GL_DEPTH_TEST);
+
+ if (v3d->flag2 & V3D_SHOW_GPENCIL) {
+ ED_gpencil_draw_view3d(NULL, scene, v3d, ar, true);
+ }
+
+ v3d->zbuf = zbuf;
+
+}
+
+void ED_view3d_draw_depth(Scene *scene, ARegion *ar, View3D *v3d, bool alphaoverride)
+{
+ RegionView3D *rv3d = ar->regiondata;
+ Base *base;
+ short zbuf = v3d->zbuf;
+ short flag = v3d->flag;
+ float glalphaclip = U.glalphaclip;
+ int obcenter_dia = U.obcenter_dia;
+ /* no need for color when drawing depth buffer */
+ const short dflag_depth = DRAW_CONSTCOLOR;
+ /* temp set drawtype to solid */
+
+ /* Setting these temporarily is not nice */
+ v3d->flag &= ~V3D_SELECT_OUTLINE;
+ U.glalphaclip = alphaoverride ? 0.5f : glalphaclip; /* not that nice but means we wont zoom into billboards */
+ U.obcenter_dia = 0;
+
+ view3d_winmatrix_set(ar, v3d, NULL);
+ view3d_viewmatrix_set(scene, v3d, rv3d); /* note: calls BKE_object_where_is_calc for camera... */
+
+ mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat);
+ invert_m4_m4(rv3d->persinv, rv3d->persmat);
+ invert_m4_m4(rv3d->viewinv, rv3d->viewmat);
+
+ glClear(GL_DEPTH_BUFFER_BIT);
+
+ glLoadMatrixf(rv3d->viewmat);
+
+ if (rv3d->rflag & RV3D_CLIPPING) {
+ ED_view3d_clipping_set(rv3d);
+ }
+ /* get surface depth without bias */
+ rv3d->rflag |= RV3D_ZOFFSET_DISABLED;
+
+ v3d->zbuf = true;
+ glEnable(GL_DEPTH_TEST);
+
+ /* draw set first */
+ if (scene->set) {
+ Scene *sce_iter;
+ for (SETLOOPER(scene->set, sce_iter, base)) {
+ if (v3d->lay & base->lay) {
+ draw_object(scene, ar, v3d, base, 0);
+ if (base->object->transflag & OB_DUPLI) {
+ draw_dupli_objects_color(scene, ar, v3d, base, dflag_depth, TH_UNDEFINED);
+ }
+ }
+ }
+ }
+
+ for (base = scene->base.first; base; base = base->next) {
+ if (v3d->lay & base->lay) {
+ /* dupli drawing */
+ if (base->object->transflag & OB_DUPLI) {
+ draw_dupli_objects_color(scene, ar, v3d, base, dflag_depth, TH_UNDEFINED);
+ }
+ draw_object(scene, ar, v3d, base, dflag_depth);
+ }
+ }
+
+ /* this isn't that nice, draw xray objects as if they are normal */
+ if (v3d->afterdraw_transp.first ||
+ v3d->afterdraw_xray.first ||
+ v3d->afterdraw_xraytransp.first)
+ {
+ View3DAfter *v3da;
+ int mask_orig;
+
+ v3d->xray = true;
+
+ /* transp materials can change the depth mask, see #21388 */
+ glGetIntegerv(GL_DEPTH_WRITEMASK, &mask_orig);
+
+
+ if (v3d->afterdraw_xray.first || v3d->afterdraw_xraytransp.first) {
+ glDepthFunc(GL_ALWAYS); /* always write into the depth bufer, overwriting front z values */
+ for (v3da = v3d->afterdraw_xray.first; v3da; v3da = v3da->next) {
+ draw_object(scene, ar, v3d, v3da->base, dflag_depth);
+ }
+ glDepthFunc(GL_LEQUAL); /* Now write the depth buffer normally */
+ }
+
+ /* draw 3 passes, transp/xray/xraytransp */
+ v3d->xray = false;
+ v3d->transp = true;
+ while ((v3da = BLI_pophead(&v3d->afterdraw_transp))) {
+ draw_object(scene, ar, v3d, v3da->base, dflag_depth);
+ MEM_freeN(v3da);
+ }
+
+ v3d->xray = true;
+ v3d->transp = false;
+ while ((v3da = BLI_pophead(&v3d->afterdraw_xray))) {
+ draw_object(scene, ar, v3d, v3da->base, dflag_depth);
+ MEM_freeN(v3da);
+ }
+
+ v3d->xray = true;
+ v3d->transp = true;
+ while ((v3da = BLI_pophead(&v3d->afterdraw_xraytransp))) {
+ draw_object(scene, ar, v3d, v3da->base, dflag_depth);
+ MEM_freeN(v3da);
+ }
+
+
+ v3d->xray = false;
+ v3d->transp = false;
+
+ glDepthMask(mask_orig);
+ }
+
+ if (rv3d->rflag & RV3D_CLIPPING) {
+ ED_view3d_clipping_disable();
+ }
+ rv3d->rflag &= ~RV3D_ZOFFSET_DISABLED;
+
+ v3d->zbuf = zbuf;
+ if (!v3d->zbuf) glDisable(GL_DEPTH_TEST);
+
+ U.glalphaclip = glalphaclip;
+ v3d->flag = flag;
+ U.obcenter_dia = obcenter_dia;
+}
+
+typedef struct View3DShadow {
+ struct View3DShadow *next, *prev;
+ GPULamp *lamp;
+} View3DShadow;
+
+static void gpu_render_lamp_update(Scene *scene, View3D *v3d,
+ Object *ob, Object *par,
+ float obmat[4][4], unsigned int lay,
+ ListBase *shadows, SceneRenderLayer *srl)
+{
+ GPULamp *lamp;
+ Lamp *la = (Lamp *)ob->data;
+ View3DShadow *shadow;
+ unsigned int layers;
+
+ lamp = GPU_lamp_from_blender(scene, ob, par, BKE_scene_use_new_shading_nodes(scene));
+
+ if (lamp) {
+ GPU_lamp_update(lamp, lay, (ob->restrictflag & OB_RESTRICT_RENDER), obmat);
+ GPU_lamp_update_colors(lamp, la->r, la->g, la->b, la->energy);
+
+ layers = lay & v3d->lay;
+ if (srl)
+ layers &= srl->lay;
+
+ if (layers &&
+ GPU_lamp_has_shadow_buffer(lamp) &&
+ /* keep last, may do string lookup */
+ GPU_lamp_override_visible(lamp, srl, NULL))
+ {
+ shadow = MEM_callocN(sizeof(View3DShadow), "View3DShadow");
+ shadow->lamp = lamp;
+ BLI_addtail(shadows, shadow);
+ }
+ }
+}
+
+static void gpu_update_lamps_shadows_world(Scene *scene, View3D *v3d)
+{
+ ListBase shadows;
+ View3DShadow *shadow;
+ Scene *sce_iter;
+ Base *base;
+ Object *ob;
+ World *world = scene->world;
+ SceneRenderLayer *srl = v3d->scenelock ? BLI_findlink(&scene->r.layers, scene->r.actlay) : NULL;
+
+ BLI_listbase_clear(&shadows);
+
+ /* update lamp transform and gather shadow lamps */
+ for (SETLOOPER(scene, sce_iter, base)) {
+ ob = base->object;
+
+ if (ob->type == OB_LAMP)
+ gpu_render_lamp_update(scene, v3d, ob, NULL, ob->obmat, ob->lay, &shadows, srl);
+
+ if (ob->transflag & OB_DUPLI) {
+ DupliObject *dob;
+ ListBase *lb = object_duplilist(G.main->eval_ctx, scene, ob);
+
+ for (dob = lb->first; dob; dob = dob->next)
+ if (dob->ob->type == OB_LAMP)
+ gpu_render_lamp_update(scene, v3d, dob->ob, ob, dob->mat, ob->lay, &shadows, srl);
+
+ free_object_duplilist(lb);
+ }
+ }
+
+ /* render shadows after updating all lamps, nested object_duplilist
+ * don't work correct since it's replacing object matrices */
+ for (shadow = shadows.first; shadow; shadow = shadow->next) {
+ /* this needs to be done better .. */
+ float viewmat[4][4], winmat[4][4];
+ int drawtype, lay, winsize, flag2 = v3d->flag2;
+ ARegion ar = {NULL};
+ RegionView3D rv3d = {{{0}}};
+
+ drawtype = v3d->drawtype;
+ lay = v3d->lay;
+
+ v3d->drawtype = OB_SOLID;
+ v3d->lay &= GPU_lamp_shadow_layer(shadow->lamp);
+ v3d->flag2 &= ~(V3D_SOLID_TEX | V3D_SHOW_SOLID_MATCAP);
+ v3d->flag2 |= V3D_RENDER_OVERRIDE | V3D_RENDER_SHADOW;
+
+ GPU_lamp_shadow_buffer_bind(shadow->lamp, viewmat, &winsize, winmat);
+
+ ar.regiondata = &rv3d;
+ ar.regiontype = RGN_TYPE_WINDOW;
+ rv3d.persp = RV3D_CAMOB;
+ copy_m4_m4(rv3d.winmat, winmat);
+ copy_m4_m4(rv3d.viewmat, viewmat);
+ invert_m4_m4(rv3d.viewinv, rv3d.viewmat);
+ mul_m4_m4m4(rv3d.persmat, rv3d.winmat, rv3d.viewmat);
+ invert_m4_m4(rv3d.persinv, rv3d.viewinv);
+
+ /* no need to call ED_view3d_draw_offscreen_init since shadow buffers were already updated */
+ ED_view3d_draw_offscreen(
+ scene, v3d, &ar, winsize, winsize, viewmat, winmat,
+ false, false, true, true,
+ NULL, NULL, NULL, NULL);
+ GPU_lamp_shadow_buffer_unbind(shadow->lamp);
+
+ v3d->drawtype = drawtype;
+ v3d->lay = lay;
+ v3d->flag2 = flag2;
+ }
+
+ BLI_freelistN(&shadows);
+
+ /* update world values */
+ if (world) {
+ GPU_mist_update_enable(world->mode & WO_MIST);
+ GPU_mist_update_values(world->mistype, world->miststa, world->mistdist, world->misi, &world->horr);
+ GPU_horizon_update_color(&world->horr);
+ GPU_ambient_update_color(&world->ambr);
+ GPU_zenith_update_color(&world->zenr);
+ }
+}
+
+/* ***************** Probes rendering *************** */
+
+typedef struct View3DProbe {
+ struct View3DProbe *next, *prev;
+ GPUProbe *probe;
+} View3DProbe;
+
+static void gpu_update_probes(Scene *scene, View3D *v3d, ARegion *basear)
+{
+ ListBase probelist;
+ ListBase afterlist;
+ int i = 0;
+ bool do_sky = false;
+ View3DProbe *vprobe;
+ GPUProbe *probe;
+ Scene *sce_iter;
+ Object *ob;
+ Base *base;
+ RegionView3D *baserv3d = basear->regiondata;
+
+ /* gathering probes */
+ BLI_listbase_clear(&probelist);
+ BLI_listbase_clear(&afterlist);
+
+ /* Order matters : watch BLI_addhead and BLI_addtail
+ * rendering the world first
+ * then the cubemaps
+ * finally the planar reflections. */
+
+ /* Objects Probe (don't do dupliobjects) */
+ for (SETLOOPER(scene, sce_iter, base)) {
+ ob = base->object;
+
+ if (ob->probetype == OB_PROBE_CUBEMAP || ob->probetype == OB_PROBE_PLANAR) {
+ probe = GPU_probe_object(scene, ob);
+
+ /* XXX free probes if size or type changes */
+ if (probe && ((GPU_probe_get_size(probe) != ob->probesize) ||
+ (GPU_probe_get_type(probe) != ob->probetype))) {
+ if (ob->gpuprobe.first)
+ GPU_probe_free(&ob->gpuprobe);
+ probe = GPU_probe_object(scene, ob);
+ }
+
+ if (probe) {
+ if (ob->probetype == OB_PROBE_CUBEMAP) {
+ GPU_probe_update_layers(probe, ob->lay);
+
+ if (ob->parallaxcorrect)
+ GPU_probe_update_parallax(probe, ob->parallaxcorrect->obmat, ob->obmat);
+ else
+ GPU_probe_update_parallax(probe, ob->obmat, ob->obmat);
+
+ if (GPU_probe_get_update(probe)) {
+ GPU_probe_update_clip(probe, ob->probeclipsta, ob->probeclipend);
+ GPU_probe_update_sh_res(probe, ob->probeshres);
+
+ vprobe = MEM_callocN(sizeof(View3DProbe), "View3DProbe");
+ vprobe->probe = probe;
+ BLI_addhead(&probelist, vprobe);
+
+ if (ob->probeflags & OB_PROBE_DOUBLE_UPDATE) {
+ vprobe = MEM_callocN(sizeof(View3DProbe), "View3DProbe");
+ vprobe->probe = probe;
+ BLI_addhead(&afterlist, vprobe);
+ }
+ }
+ }
+ else if (ob->probetype == OB_PROBE_PLANAR) {
+
+ GPU_probe_update_layers(probe, ob->lay);
+ GPU_probe_update_clip(probe, ob->probeclipbias, ob->probeclipend);
+
+ if (ob->probe) {
+ if (ob->probe->parallaxcorrect)
+ GPU_probe_update_parallax(probe, ob->probe->parallaxcorrect->obmat, ob->probe->obmat);
+ else
+ GPU_probe_update_parallax(probe, ob->probe->obmat, ob->probe->obmat);
+ }
+
+ if (ob->reflectionplane)
+ GPU_probe_update_ref_plane(probe, ob->reflectionplane->obmat);
+ else
+ GPU_probe_update_ref_plane(probe, ob->obmat);
+
+ vprobe = MEM_callocN(sizeof(View3DProbe), "View3DProbe");
+ vprobe->probe = probe;
+ BLI_addtail(&probelist, vprobe);
+
+ if (ob->probeflags & OB_PROBE_DOUBLE_UPDATE) {
+ vprobe = MEM_callocN(sizeof(View3DProbe), "View3DProbe");
+ vprobe->probe = probe;
+ BLI_addtail(&afterlist, vprobe);
+ }
+ }
+ }
+ }
+ else {
+ if (ob->gpuprobe.first)
+ GPU_probe_free(&ob->gpuprobe);
+ }
+ }
+
+ /* World Probe */
+ if (scene->world) {
+ do_sky = true;
+ probe = GPU_probe_world(scene, scene->world);
+
+ /* XXX free probes if size change */
+ if (probe && (GPU_probe_get_size(probe) != scene->world->probesize)) {
+ if (scene->world->gpuprobe.first)
+ GPU_probe_free(&scene->world->gpuprobe);
+ probe = GPU_probe_world(scene, scene->world);
+ }
+
+ if (probe && GPU_probe_get_update(probe)) {
+ GPU_probe_update_sh_res(probe, scene->world->probeshres);
+
+ vprobe = MEM_callocN(sizeof(View3DProbe), "View3DProbe");
+ vprobe->probe = probe;
+ BLI_addhead(&probelist, vprobe);
+ }
+ }
+
+ BLI_movelisttolist(&probelist, &afterlist);
+
+ /* Updating probes */
+ for (vprobe = probelist.first, i = 0; vprobe; vprobe = vprobe->next, i++) {
+
+ float viewmat[4][4], winmat[4][4];
+ int drawtype, lay, winsize, flag2 = v3d->flag2, flag3 = v3d->flag3, restrictflag;
+ int pbr_flag = v3d->pbr_settings.pbr_flag;
+ ARegion ar = {NULL};
+ RegionView3D rv3d = {{{0}}};
+ Object *ob = GPU_probe_get_object(vprobe->probe);
+ bool is_cubemap = (GPU_probe_get_type(vprobe->probe) == OB_PROBE_CUBEMAP);
+
+ drawtype = v3d->drawtype;
+ lay = v3d->lay;
+
+ v3d->drawtype = OB_MATERIAL;
+ v3d->lay = GPU_probe_get_layers(vprobe->probe);
+ v3d->flag2 &= ~(V3D_SOLID_TEX | V3D_SHOW_SOLID_MATCAP);
+ v3d->flag2 |= V3D_RENDER_OVERRIDE;
+ v3d->flag3 |= V3D_SHOW_WORLD;
+ v3d->flag3 &= ~V3D_SHOW_WORLD_DIFFUSE;
+ v3d->flag3 |= V3D_PROBE_CAPTURE;
+ v3d->pbr_settings.pbr_flag &= ~GPU_PBR_FLAG_SSR;
+ v3d->pbr_settings.pbr_flag &= ~GPU_PBR_FLAG_SSAO;
+
+ if (ob) {
+ restrictflag = ob->restrictflag;
+ ob->restrictflag |= OB_RESTRICT_VIEW;
+ v3d->probe_source = ob;
+ }
+ else {
+ v3d->probe_source = NULL;
+ }
+
+ GPU_probe_buffer_bind(vprobe->probe);
+
+ /* cubemap */
+ if (is_cubemap) {
+ for (int face = 0; face < 6; face++) {
+ GPU_probe_switch_fb_cubeface(vprobe->probe, face, viewmat, &winsize, winmat);
+
+ ar.regiondata = &rv3d;
+ ar.regiontype = RGN_TYPE_WINDOW;
+ rv3d.persp = RV3D_CAMOB;
+ copy_m4_m4(rv3d.winmat, winmat);
+ copy_m4_m4(rv3d.viewmat, viewmat);
+ invert_m4_m4(rv3d.viewinv, rv3d.viewmat);
+ mul_m4_m4m4(rv3d.persmat, rv3d.winmat, rv3d.viewmat);
+ invert_m4_m4(rv3d.persinv, rv3d.viewinv);
+
+ ED_view3d_draw_offscreen(
+ scene, v3d, &ar, winsize, winsize, viewmat, winmat,
+ false, do_sky, true, (bool)ob,
+ NULL, NULL, NULL, NULL);
+ }
+ }
+ /* planar */
+ else {
+ ar.regiondata = &rv3d;
+ ar.regiontype = RGN_TYPE_WINDOW;
+ rv3d.persp = RV3D_CAMOB;
+
+ /* Getting normal camera */
+ view3d_winmatrix_set(basear, v3d, NULL);
+ view3d_viewmatrix_set(scene, v3d, baserv3d); /* note: calls BKE_object_where_is_calc for camera... */
+
+ /* Flip it along the plane */
+ GPU_probe_attach_planar_fb(vprobe->probe, baserv3d->viewmat, baserv3d->winmat, viewmat, &winsize, false);
+
+ copy_m4_m4(rv3d.viewmat, viewmat);
+ invert_m4_m4(rv3d.viewinv, rv3d.viewmat);
+ mul_m4_m4m4(rv3d.persmat, baserv3d->winmat, rv3d.viewmat);
+ invert_m4_m4(rv3d.persinv, rv3d.viewinv);
+
+ v3d->flag3 |= V3D_FLIP_NORMALS;
+
+ ED_view3d_draw_offscreen(
+ scene, v3d, &ar, winsize, winsize, viewmat, baserv3d->winmat,
+ false, do_sky, true, true,
+ NULL, NULL, NULL, NULL);
+
+ /* Non-fliped Camera for refraction */
+ GPU_probe_attach_planar_fb(vprobe->probe, baserv3d->viewmat, baserv3d->winmat, viewmat, &winsize, true);
+
+ copy_m4_m4(rv3d.viewmat, viewmat);
+ invert_m4_m4(rv3d.viewinv, rv3d.viewmat);
+ mul_m4_m4m4(rv3d.persmat, baserv3d->winmat, rv3d.viewmat);
+ invert_m4_m4(rv3d.persinv, rv3d.viewinv);
+
+ v3d->flag3 &= ~V3D_FLIP_NORMALS;
+
+ ED_view3d_draw_offscreen(
+ scene, v3d, &ar, winsize, winsize, viewmat, baserv3d->winmat,
+ false, do_sky, true, true,
+ NULL, NULL, NULL, NULL);
+
+ }
+
+ GPU_probe_buffer_unbind(vprobe->probe);
+
+ v3d->drawtype = drawtype;
+ v3d->lay = lay;
+ v3d->flag2 = flag2;
+ v3d->flag3 = flag3;
+ v3d->probe_source = NULL;
+ v3d->pbr_settings.pbr_flag = pbr_flag;
+
+ if (ob)
+ ob->restrictflag = restrictflag;
+
+ GPU_probe_rebuild_mipmaps(vprobe->probe);
+
+ GPU_probe_sh_compute(vprobe->probe);
+
+ GPU_probe_set_update(vprobe->probe, false);
+ }
+
+ BLI_freelistN(&probelist);
+}
+
+/* ***************** Scene buffer update *************** */
+
+static void gpu_update_scene_buffer(Scene *scene, View3D *v3d, ARegion *basear)
+{
+ int drawtype = v3d->drawtype, winsize[2], flag2 = v3d->flag2, flag3 = v3d->flag3;
+ float clipsta, clipend;
+ ARegion ar = {NULL};
+ RegionView3D *baserv3d = basear->regiondata;
+ RegionView3D rv3d = {{{0}}};
+ GPUScreenBuffer *scene_buffer;
+ int res[2] = {basear->winx, basear->winy};
+ int pbr_flag = v3d->pbr_settings.pbr_flag;
+
+ scene_buffer = GPU_pbr_scene_buffer(v3d->pbr, res[0], res[1]);
+
+ v3d->drawtype = OB_MATERIAL;
+ v3d->flag2 &= ~(V3D_SOLID_TEX | V3D_SHOW_SOLID_MATCAP);
+ v3d->flag2 |= V3D_RENDER_OVERRIDE;
+ v3d->flag3 |= V3D_SHOW_WORLD;
+ v3d->flag3 &= ~V3D_SHOW_WORLD_DIFFUSE;
+ v3d->flag3 |= V3D_PROBE_CAPTURE;
+ v3d->pbr_settings.pbr_flag &= ~GPU_PBR_FLAG_SSR;
+ v3d->pbr_settings.pbr_flag &= ~GPU_PBR_FLAG_SSAO;
+
+ ar.regiondata = &rv3d;
+ ar.regiontype = RGN_TYPE_WINDOW;
+ rv3d.persp = RV3D_CAMOB;
+
+ /* Getting camera coords */
+ ED_view3d_viewplane_get(v3d, baserv3d, basear->winx, basear->winy, NULL, &clipsta, &clipend, NULL);
+ view3d_winmatrix_set(basear, v3d, NULL);
+ view3d_viewmatrix_set(scene, v3d, baserv3d); /* note: calls BKE_object_where_is_calc for camera... */
+
+ GPU_scenebuf_bind(scene_buffer, baserv3d->winmat, winsize, clipsta, clipend);
+
+ copy_m4_m4(rv3d.viewmat, baserv3d->viewmat);
+ invert_m4_m4(rv3d.viewinv, rv3d.viewmat);
+ mul_m4_m4m4(rv3d.persmat, baserv3d->winmat, rv3d.viewmat);
+ invert_m4_m4(rv3d.persinv, rv3d.viewinv);
+
+ ED_view3d_draw_offscreen(
+ scene, v3d, &ar, winsize[0], winsize[1], baserv3d->viewmat, baserv3d->winmat,
+ false, (bool)scene->world, true, true,
+ NULL, NULL, NULL, NULL);
+
+ v3d->drawtype = drawtype;
+ v3d->flag2 = flag2;
+ v3d->flag3 = flag3;
+ v3d->pbr_settings.pbr_flag = pbr_flag;
+
+ GPU_scenebuf_unbind(scene_buffer);
+ GPU_scenebuf_filter_texture(scene_buffer);
+}
+
+static void gpu_update_backface_buffer(Scene *scene, View3D *v3d, ARegion *basear)
+{
+ int drawtype = v3d->drawtype, winsize[2], flag2 = v3d->flag2, flag3 = v3d->flag3;
+ float clipsta, clipend;
+ ARegion ar = {NULL};
+ RegionView3D *baserv3d = basear->regiondata;
+ RegionView3D rv3d = {{{0}}};
+ GPUScreenBuffer *backface_buffer;
+ int res[2] = {basear->winx, basear->winy};
+
+ backface_buffer = GPU_pbr_backface_buffer(v3d->pbr, res[0], res[1]);
+
+ v3d->drawtype = OB_SOLID;
+ v3d->flag2 &= ~(V3D_SOLID_TEX | V3D_SHOW_SOLID_MATCAP);
+ v3d->flag2 |= V3D_BACKFACE_CULLING | V3D_RENDER_OVERRIDE | V3D_RENDER_SHADOW;
+ v3d->flag3 |= V3D_FLIP_NORMALS;
+
+ ar.regiondata = &rv3d;
+ ar.regiontype = RGN_TYPE_WINDOW;
+ rv3d.persp = RV3D_CAMOB;
+
+ /* Getting camera coords */
+ ED_view3d_viewplane_get(v3d, baserv3d, basear->winx, basear->winy, NULL, &clipsta, &clipend, NULL);
+ view3d_winmatrix_set(basear, v3d, NULL);
+ view3d_viewmatrix_set(scene, v3d, baserv3d); /* note: calls BKE_object_where_is_calc for camera... */
+
+ GPU_scenebuf_bind(backface_buffer, baserv3d->winmat, winsize, clipsta, clipend);
+
+ copy_m4_m4(rv3d.viewmat, baserv3d->viewmat);
+ invert_m4_m4(rv3d.viewinv, rv3d.viewmat);
+ mul_m4_m4m4(rv3d.persmat, baserv3d->winmat, rv3d.viewmat);
+ invert_m4_m4(rv3d.persinv, rv3d.viewinv);
+
+ ED_view3d_draw_offscreen(
+ scene, v3d, &ar, winsize[0], winsize[1], baserv3d->viewmat, baserv3d->winmat,
+ false, (bool)scene->world, true, true,
+ NULL, NULL, NULL, NULL);
+
+ v3d->drawtype = drawtype;
+ v3d->flag2 = flag2;
+ v3d->flag3 = flag3;
+
+ GPU_scenebuf_unbind(backface_buffer);
+ GPU_scenebuf_filter_texture(backface_buffer);
+}
+
+
+static void gpu_pbr_update(Scene *scene, View3D *v3d, ARegion *ar)
+{
+ GPUPBR *pbr = v3d->pbr;
+
+ gpu_update_probes(scene, v3d, ar);
+
+ if (v3d->pbr_settings.pbr_flag & (GPU_PBR_FLAG_SSR | GPU_PBR_FLAG_SSAO))
+ gpu_update_scene_buffer(scene, v3d, ar);
+ else if (pbr->scene) {
+ GPU_scenebuf_free(pbr->scene);
+ pbr->scene = NULL;
+ }
+
+ if ((v3d->pbr_settings.pbr_flag & GPU_PBR_FLAG_BACKFACE) && (v3d->pbr_settings.pbr_flag & (GPU_PBR_FLAG_SSR | GPU_PBR_FLAG_SSAO)))
+ gpu_update_backface_buffer(scene, v3d, ar);
+ else if (pbr->backface) {
+ GPU_scenebuf_free(pbr->backface);
+ pbr->backface = NULL;
+ }
+}
+
+/* *********************** customdata **************** */
+
+CustomDataMask ED_view3d_datamask(const Scene *scene, const View3D *v3d)
+{
+ CustomDataMask mask = 0;
+ const int drawtype = view3d_effective_drawtype(v3d);
+
+ if (ELEM(drawtype, OB_TEXTURE, OB_MATERIAL) ||
+ ((drawtype == OB_SOLID) && (v3d->flag2 & V3D_SOLID_TEX)))
+ {
+ mask |= CD_MASK_MTEXPOLY | CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL;
+
+ if (BKE_scene_use_new_shading_nodes(scene)) {
+ if (drawtype == OB_MATERIAL)
+ mask |= CD_MASK_ORCO;
+ }
+ else {
+ if ((scene->gm.matmode == GAME_MAT_GLSL && drawtype == OB_TEXTURE) ||
+ (drawtype == OB_MATERIAL))
+ {
+ mask |= CD_MASK_ORCO;
+ }
+ }
+ }
+
+ return mask;
+}
+
+/* goes over all modes and view3d settings */
+CustomDataMask ED_view3d_screen_datamask(const bScreen *screen)
+{
+ const Scene *scene = screen->scene;
+ CustomDataMask mask = CD_MASK_BAREMESH;
+ const ScrArea *sa;
+
+ /* check if we need tfaces & mcols due to view mode */
+ for (sa = screen->areabase.first; sa; sa = sa->next) {
+ if (sa->spacetype == SPACE_VIEW3D) {
+ mask |= ED_view3d_datamask(scene, sa->spacedata.first);
+ }
+ }
+
+ return mask;
+}
+
+/**
+ * Shared by #ED_view3d_draw_offscreen and #view3d_main_region_draw_objects
+ *
+ * \note \a C and \a grid_unit will be NULL when \a draw_offscreen is set.
+ * \note Drawing lamps and opengl render uses this, so dont do grease pencil or view widgets here.
+ */
+static void view3d_draw_objects(
+ const bContext *C,
+ Scene *scene, View3D *v3d, ARegion *ar,
+ const char **grid_unit,
+ const bool do_bgpic, const bool draw_offscreen, GPUFX *fx)
+{
+ RegionView3D *rv3d = ar->regiondata;
+ Base *base;
+ const bool do_camera_frame = !draw_offscreen;
+ const bool draw_grids = !draw_offscreen && (v3d->flag2 & V3D_RENDER_OVERRIDE) == 0;
+ const bool draw_floor = (rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO);
+ /* only draw grids after in solid modes, else it hovers over mesh wires */
+ const bool draw_grids_after = draw_grids && draw_floor && (v3d->drawtype > OB_WIRE) && fx;
+ bool do_composite_xray = false;
+ bool xrayclear = true;
+
+ if (!draw_offscreen) {
+ ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW);
+ }
+
+ if (rv3d->rflag & RV3D_CLIPPING)
+ view3d_draw_clipping(rv3d);
+
+ /* set zbuffer after we draw clipping region */
+ v3d->zbuf = VP_legacy_use_depth(scene, v3d);
+
+ if (v3d->zbuf) {
+ glEnable(GL_DEPTH_TEST);
+ }
+
+ /* ortho grid goes first, does not write to depth buffer and doesn't need depth test so it will override
+ * objects if done last */
+ if (draw_grids) {
+ /* needs to be done always, gridview is adjusted in drawgrid() now, but only for ortho views. */
+ rv3d->gridview = ED_view3d_grid_scale(scene, v3d, grid_unit);
+
+ if (!draw_floor) {
+ ED_region_pixelspace(ar);
+ *grid_unit = NULL; /* drawgrid need this to detect/affect smallest valid unit... */
+ VP_legacy_drawgrid(&scene->unit, ar, v3d, grid_unit);
+ /* XXX make function? replaces persp(1) */
+ glMatrixMode(GL_PROJECTION);
+ glLoadMatrixf(rv3d->winmat);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadMatrixf(rv3d->viewmat);
+ }
+ else if (!draw_grids_after) {
+ VP_legacy_drawfloor(scene, v3d, grid_unit, true);
+ }
+ }
+
+ /* important to do before clipping */
+ if (do_bgpic) {
+ view3d_draw_bgpic_test(scene, ar, v3d, false, do_camera_frame);
+ }
+
+ if (rv3d->rflag & RV3D_CLIPPING) {
+ ED_view3d_clipping_set(rv3d);
+ }
+
+ /* draw set first */
+ if (scene->set) {
+ const short dflag = DRAW_CONSTCOLOR | DRAW_SCENESET;
+ Scene *sce_iter;
+ for (SETLOOPER(scene->set, sce_iter, base)) {
+ if (v3d->lay & base->lay) {
+ UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.6f);
+ draw_object(scene, ar, v3d, base, dflag);
+
+ if (base->object->transflag & OB_DUPLI) {
+ draw_dupli_objects_color(scene, ar, v3d, base, dflag, TH_UNDEFINED);
+ }
+ }
+ }
+
+ /* Transp and X-ray afterdraw stuff for sets is done later */
+ }
+
+
+ if (draw_offscreen) {
+ for (base = scene->base.first; base; base = base->next) {
+ if (v3d->lay & base->lay) {
+ /* dupli drawing */
+ if (base->object->transflag & OB_DUPLI)
+ draw_dupli_objects(scene, ar, v3d, base);
+
+ draw_object(scene, ar, v3d, base, 0);
+ }
+ }
+ }
+ else {
+ unsigned int lay_used = 0;
+
+ /* then draw not selected and the duplis, but skip editmode object */
+ for (base = scene->base.first; base; base = base->next) {
+ lay_used |= base->lay;
+
+ if (v3d->lay & base->lay) {
+
+ /* dupli drawing */
+ if (base->object->transflag & OB_DUPLI) {
+ draw_dupli_objects(scene, ar, v3d, base);
+ }
+ if ((base->flag & SELECT) == 0) {
+ if (base->object != scene->obedit)
+ draw_object(scene, ar, v3d, base, 0);
+ }
+ }
+ }
+
+ /* mask out localview */
+ v3d->lay_used = lay_used & ((1 << 20) - 1);
+
+ /* draw selected and editmode */
+ for (base = scene->base.first; base; base = base->next) {
+ if (v3d->lay & base->lay) {
+ if (base->object == scene->obedit || (base->flag & SELECT)) {
+ draw_object(scene, ar, v3d, base, 0);
+ }
+ }
+ }
+ }
+
+ /* perspective floor goes last to use scene depth and avoid writing to depth buffer */
+ if (draw_grids_after) {
+ VP_legacy_drawfloor(scene, v3d, grid_unit, false);
+ }
+
+ /* must be before xray draw which clears the depth buffer */
+ if (v3d->flag2 & V3D_SHOW_GPENCIL) {
+ wmWindowManager *wm = (C != NULL) ? CTX_wm_manager(C) : NULL;
+
+ /* must be before xray draw which clears the depth buffer */
+ if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
+ ED_gpencil_draw_view3d(wm, scene, v3d, ar, true);
+ if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
+ }
+
+ /* transp and X-ray afterdraw stuff */
+ if (v3d->afterdraw_transp.first) view3d_draw_transp(scene, ar, v3d);
+
+ /* always do that here to cleanup depth buffers if none needed */
+ if (fx) {
+ do_composite_xray = v3d->zbuf && (v3d->afterdraw_xray.first || v3d->afterdraw_xraytransp.first);
+ GPU_fx_compositor_setup_XRay_pass(fx, do_composite_xray);
+ }
+
+ if (v3d->afterdraw_xray.first) view3d_draw_xray(scene, ar, v3d, &xrayclear);
+ if (v3d->afterdraw_xraytransp.first) view3d_draw_xraytransp(scene, ar, v3d, xrayclear);
+
+ if (fx && do_composite_xray) {
+ GPU_fx_compositor_XRay_resolve(fx);
+ }
+
+ if (!draw_offscreen) {
+ ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
+ }
+
+ if (rv3d->rflag & RV3D_CLIPPING)
+ ED_view3d_clipping_disable();
+
+ /* important to do after clipping */
+ if (do_bgpic) {
+ view3d_draw_bgpic_test(scene, ar, v3d, true, do_camera_frame);
+ }
+
+ if (!draw_offscreen) {
+ BIF_draw_manipulator(C);
+ }
+
+ /* cleanup */
+ if (v3d->zbuf) {
+ v3d->zbuf = false;
+ glDisable(GL_DEPTH_TEST);
+ }
+
+ if ((v3d->flag2 & V3D_RENDER_SHADOW) == 0) {
+ GPU_free_images_old();
+ }
+}
+
+/**
+ * Store values from #RegionView3D, set when drawing.
+ * This is needed when we draw with to a viewport using a different matrix (offscreen drawing for example).
+ *
+ * Values set by #ED_view3d_update_viewmat should be handled here.
+ */
+struct RV3DMatrixStore {
+ float winmat[4][4];
+ float viewmat[4][4];
+ float viewinv[4][4];
+ float persmat[4][4];
+ float persinv[4][4];
+ float viewcamtexcofac[4];
+ float pixsize;
+};
+
+void *ED_view3d_mats_rv3d_backup(struct RegionView3D *rv3d)
+{
+ struct RV3DMatrixStore *rv3dmat = MEM_mallocN(sizeof(*rv3dmat), __func__);
+ copy_m4_m4(rv3dmat->winmat, rv3d->winmat);
+ copy_m4_m4(rv3dmat->viewmat, rv3d->viewmat);
+ copy_m4_m4(rv3dmat->persmat, rv3d->persmat);
+ copy_m4_m4(rv3dmat->persinv, rv3d->persinv);
+ copy_m4_m4(rv3dmat->viewinv, rv3d->viewinv);
+ copy_v4_v4(rv3dmat->viewcamtexcofac, rv3d->viewcamtexcofac);
+ rv3dmat->pixsize = rv3d->pixsize;
+ return (void *)rv3dmat;
+}
+
+void ED_view3d_mats_rv3d_restore(struct RegionView3D *rv3d, void *rv3dmat_pt)
+{
+ struct RV3DMatrixStore *rv3dmat = rv3dmat_pt;
+ copy_m4_m4(rv3d->winmat, rv3dmat->winmat);
+ copy_m4_m4(rv3d->viewmat, rv3dmat->viewmat);
+ copy_m4_m4(rv3d->persmat, rv3dmat->persmat);
+ copy_m4_m4(rv3d->persinv, rv3dmat->persinv);
+ copy_m4_m4(rv3d->viewinv, rv3dmat->viewinv);
+ copy_v4_v4(rv3d->viewcamtexcofac, rv3dmat->viewcamtexcofac);
+ rv3d->pixsize = rv3dmat->pixsize;
+}
+
+void ED_view3d_draw_offscreen_init(Scene *scene, View3D *v3d, ARegion *ar)
+{
+ /* shadow buffers, before we setup matrices */
+ if (draw_glsl_material(scene, NULL, v3d, v3d->drawtype)){
+ gpu_update_lamps_shadows_world(scene, v3d);
+
+ /* Cycles Material Mode only */
+ if (BKE_scene_use_new_shading_nodes(scene) && (v3d->pbr_settings.pbr_flag & GPU_PBR_FLAG_ENABLE)) {
+ GPU_pbr_settings_validate(&v3d->pbr_settings);
+
+ if (!v3d->pbr)
+ v3d->pbr = GPU_pbr_create();
+
+ gpu_pbr_update(scene, v3d, ar);
+ }
+ }
+}
+
+/*
+ * Function to clear the view
+ */
+static void view3d_main_region_clear(Scene *scene, View3D *v3d, ARegion *ar)
+{
+ GPUFXSettings *fx_settings = &v3d->fx_settings;
+ bool use_color_correction = (fx_settings->fx_flag2 && (fx_settings->fx_flag2 & GPU_FX_FLAG_COLORMANAGEMENT)) ? false : true;
+
+ if (scene->world && (v3d->flag3 & V3D_SHOW_WORLD)) {
+ RegionView3D *rv3d = ar->regiondata;
+ GPUMaterial *gpumat;
+ GPUProbe *gpuprobe;
+ bool material_not_bound;
+
+ if (v3d->flag3 & V3D_SHOW_WORLD_DIFFUSE) {
+ gpuprobe = GPU_probe_world(scene, scene->world);
+ GPU_probe_sh_shader_bind(gpuprobe);
+ }
+ else {
+ gpumat = GPU_material_world(scene, scene->world);
+
+ /* calculate full shader for background */
+ GPU_material_bind(gpumat, 1, 1, 1.0, false, rv3d->viewmat, rv3d->viewinv, rv3d->viewcamtexcofac, (v3d->scenelock != 0));
+
+ material_not_bound = !GPU_material_bound(gpumat);
+
+ if (material_not_bound) {
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glLoadIdentity();
+ glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
+ }
+ }
+
+ /* Draw world */
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_ALWAYS);
+ glBegin(GL_TRIANGLE_STRIP);
+ glVertex3f(-1.0, -1.0, 1.0);
+ glVertex3f(1.0, -1.0, 1.0);
+ glVertex3f(-1.0, 1.0, 1.0);
+ glVertex3f(1.0, 1.0, 1.0);
+ glEnd();
+
+ if (v3d->flag3 & V3D_SHOW_WORLD_DIFFUSE) {
+ GPU_probe_sh_shader_unbind();
+ }
+ else {
+ if (material_not_bound) {
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+ }
+
+ GPU_material_unbind(gpumat);
+ }
+
+ glDepthFunc(GL_LEQUAL);
+ glDisable(GL_DEPTH_TEST);
+ }
+ else {
+ if (UI_GetThemeValue(TH_SHOW_BACK_GRAD)) {
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glLoadIdentity();
+
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_ALWAYS);
+ glBegin(GL_QUADS);
+ UI_ThemeColor(TH_LOW_GRAD);
+ glVertex3f(-1.0, -1.0, 1.0);
+ glVertex3f(1.0, -1.0, 1.0);
+ UI_ThemeColor(TH_HIGH_GRAD);
+ glVertex3f(1.0, 1.0, 1.0);
+ glVertex3f(-1.0, 1.0, 1.0);
+ glEnd();
+ glDepthFunc(GL_LEQUAL);
+ glDisable(GL_DEPTH_TEST);
+
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+ }
+ else {
+ UI_ThemeClearColorAlpha(TH_HIGH_GRAD, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ }
+ }
+}
+
+/* ED_view3d_draw_offscreen_init should be called before this to initialize
+ * stuff like shadow buffers
+ */
+void ED_view3d_draw_offscreen(
+ Scene *scene, View3D *v3d, ARegion *ar, int winx, int winy,
+ float viewmat[4][4], float winmat[4][4],
+ bool do_bgpic, bool do_sky, bool is_persp, bool do_meshes, const char *viewname,
+ GPUFX *fx, GPUFXSettings *fx_settings,
+ GPUOffScreen *ofs)
+{
+ struct bThemeState theme_state;
+ int bwinx, bwiny;
+ rcti brect;
+ bool do_compositing = false;
+ RegionView3D *rv3d = ar->regiondata;
+
+ glPushMatrix();
+
+ /* set temporary new size */
+ bwinx = ar->winx;
+ bwiny = ar->winy;
+ brect = ar->winrct;
+
+ ar->winx = winx;
+ ar->winy = winy;
+ ar->winrct.xmin = 0;
+ ar->winrct.ymin = 0;
+ ar->winrct.xmax = winx;
+ ar->winrct.ymax = winy;
+
+ UI_Theme_Store(&theme_state);
+ UI_SetTheme(SPACE_VIEW3D, RGN_TYPE_WINDOW);
+
+ /* set flags */
+ G.f |= G_RENDER_OGL;
+
+ if ((v3d->flag2 & V3D_RENDER_SHADOW) == 0) {
+ /* free images which can have changed on frame-change
+ * warning! can be slow so only free animated images - campbell */
+ GPU_free_images_anim();
+ }
+
+ /* setup view matrices before fx or unbinding the offscreen buffers will cause issues */
+ if ((viewname != NULL && viewname[0] != '\0') && (viewmat == NULL) && rv3d->persp == RV3D_CAMOB && v3d->camera)
+ view3d_stereo3d_setup_offscreen(scene, v3d, ar, winmat, viewname);
+ else
+ VP_legacy_view3d_main_region_setup_view(scene, v3d, ar, viewmat, winmat);
+
+ /* framebuffer fx needed, we need to draw offscreen first */
+ if ((v3d->fx_settings.fx_flag || v3d->fx_settings.fx_flag2) && fx) {
+ GPUSSAOSettings *ssao = NULL;
+ char fx_flag2 = v3d->fx_settings.fx_flag2;
+
+ /* Don't do color management fx for offscreen */
+ v3d->fx_settings.fx_flag2 &= ~GPU_FX_FLAG_COLORMANAGEMENT;
+
+ if (v3d->drawtype < OB_SOLID) {
+ ssao = v3d->fx_settings.ssao;
+ v3d->fx_settings.ssao = NULL;
+ }
+
+ do_compositing = GPU_fx_compositor_initialize_passes(fx, &ar->winrct, NULL, fx_settings, scene);
+ v3d->fx_settings.fx_flag2 = fx_flag2;
+
+ if (ssao)
+ v3d->fx_settings.ssao = ssao;
+ }
+
+ /* clear opengl buffers */
+ if (do_sky) {
+ view3d_main_region_clear(scene, v3d, ar);
+ }
+ else {
+ glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ }
+
+ /* main drawing call */
+ if (do_meshes)
+ view3d_draw_objects(NULL, scene, v3d, ar, NULL, do_bgpic, true, do_compositing ? fx : NULL);
+
+ /* post process */
+ if (do_compositing) {
+ if (!winmat)
+ is_persp = rv3d->is_persp;
+ GPU_fx_do_composite_pass(fx, winmat, is_persp, scene, ofs);
+ }
+
+ if ((v3d->flag2 & V3D_RENDER_SHADOW) == 0) {
+ /* draw grease-pencil stuff */
+ ED_region_pixelspace(ar);
+
+
+ if (v3d->flag2 & V3D_SHOW_GPENCIL) {
+ /* draw grease-pencil stuff - needed to get paint-buffer shown too (since it's 2D) */
+ ED_gpencil_draw_view3d(NULL, scene, v3d, ar, false);
+ }
+
+ /* freeing the images again here could be done after the operator runs, leaving for now */
+ GPU_free_images_anim();
+ }
+
+ /* restore size */
+ ar->winx = bwinx;
+ ar->winy = bwiny;
+ ar->winrct = brect;
+
+ glPopMatrix();
+
+ UI_Theme_Restore(&theme_state);
+
+ G.f &= ~G_RENDER_OGL;
+}
+
+/**
+ * Utility func for ED_view3d_draw_offscreen
+ *
+ * \param ofs: Optional off-screen buffer, can be NULL.
+ * (avoids re-creating when doing multiple GL renders).
+ */
+ImBuf *ED_view3d_draw_offscreen_imbuf(
+ Scene *scene, View3D *v3d, ARegion *ar, int sizex, int sizey,
+ unsigned int flag, bool draw_background,
+ int alpha_mode, int samples, bool full_samples, const char *viewname,
+ /* output vars */
+ GPUFX *fx, GPUOffScreen *ofs, char err_out[256])
+{
+ RegionView3D *rv3d = ar->regiondata;
+ ImBuf *ibuf;
+ const bool draw_sky = (alpha_mode == R_ADDSKY);
+
+ /* view state */
+ GPUFXSettings fx_settings = v3d->fx_settings;
+ bool is_ortho = false;
+ float winmat[4][4];
+
+ if (ofs && ((GPU_offscreen_width(ofs) != sizex) || (GPU_offscreen_height(ofs) != sizey))) {
+ /* sizes differ, can't reuse */
+ ofs = NULL;
+ }
+
+ const bool own_ofs = (ofs == NULL);
+
+ if (own_ofs) {
+ /* bind */
+ ofs = GPU_offscreen_create(sizex, sizey, full_samples ? 0 : samples, err_out);
+ if (ofs == NULL) {
+ return NULL;
+ }
+ }
+
+ ED_view3d_draw_offscreen_init(scene, v3d, ar);
+
+ GPU_offscreen_bind(ofs, true);
+
+ /* read in pixels & stamp */
+ ibuf = IMB_allocImBuf(sizex, sizey, 32, flag);
+
+ /* render 3d view */
+ if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
+ CameraParams params;
+ Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname);
+
+ BKE_camera_params_init(&params);
+ /* fallback for non camera objects */
+ params.clipsta = v3d->near;
+ params.clipend = v3d->far;
+ BKE_camera_params_from_object(&params, camera);
+ BKE_camera_multiview_params(&scene->r, &params, camera, viewname);
+ BKE_camera_params_compute_viewplane(&params, sizex, sizey, scene->r.xasp, scene->r.yasp);
+ BKE_camera_params_compute_matrix(&params);
+
+ BKE_camera_to_gpu_dof(camera, &fx_settings);
+
+ is_ortho = params.is_ortho;
+ copy_m4_m4(winmat, params.winmat);
+ }
+ else {
+ rctf viewplane;
+ float clipsta, clipend;
+
+ is_ortho = ED_view3d_viewplane_get(v3d, rv3d, sizex, sizey, &viewplane, &clipsta, &clipend, NULL);
+ if (is_ortho) {
+ orthographic_m4(winmat, viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, -clipend, clipend);
+ }
+ else {
+ perspective_m4(winmat, viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clipsta, clipend);
+ }
+ }
+
+ if ((samples && full_samples) == 0) {
+ /* Single-pass render, common case */
+ ED_view3d_draw_offscreen(
+ scene, v3d, ar, sizex, sizey, NULL, winmat,
+ draw_background, draw_sky, !is_ortho, true, viewname,
+ fx, &fx_settings, ofs);
+
+ if (ibuf->rect_float) {
+ GPU_offscreen_read_pixels(ofs, GL_FLOAT, ibuf->rect_float);
+ }
+ else if (ibuf->rect) {
+ GPU_offscreen_read_pixels(ofs, GL_UNSIGNED_BYTE, ibuf->rect);
+ }
+ }
+ else {
+ /* Multi-pass render, use accumulation buffer & jitter for 'full' oversampling.
+ * Use because OpenGL may use a lower quality MSAA, and only over-sample edges. */
+ static float jit_ofs[32][2];
+ float winmat_jitter[4][4];
+ /* use imbuf as temp storage, before writing into it from accumulation buffer */
+ unsigned char *rect_temp = ibuf->rect ? (void *)ibuf->rect : (void *)ibuf->rect_float;
+ unsigned int *accum_buffer = MEM_mallocN(sizex * sizey * sizeof(int[4]), "accum1");
+ unsigned int i;
+ int j;
+
+ BLI_jitter_init(jit_ofs, samples);
+
+ /* first sample buffer, also initializes 'rv3d->persmat' */
+ ED_view3d_draw_offscreen(
+ scene, v3d, ar, sizex, sizey, NULL, winmat,
+ draw_background, draw_sky, !is_ortho, true, viewname,
+ fx, &fx_settings, ofs);
+ GPU_offscreen_read_pixels(ofs, GL_UNSIGNED_BYTE, rect_temp);
+
+ i = sizex * sizey * 4;
+ while (i--) {
+ accum_buffer[i] = rect_temp[i];
+ }
+
+ /* skip the first sample */
+ for (j = 1; j < samples; j++) {
+ copy_m4_m4(winmat_jitter, winmat);
+ window_translate_m4(
+ winmat_jitter, rv3d->persmat,
+ (jit_ofs[j][0] * 2.0f) / sizex,
+ (jit_ofs[j][1] * 2.0f) / sizey);
+
+ ED_view3d_draw_offscreen(
+ scene, v3d, ar, sizex, sizey, NULL, winmat_jitter,
+ draw_background, draw_sky, !is_ortho, false, viewname,
+ fx, &fx_settings, ofs);
+ GPU_offscreen_read_pixels(ofs, GL_UNSIGNED_BYTE, rect_temp);
+
+ i = sizex * sizey * 4;
+ while (i--) {
+ accum_buffer[i] += rect_temp[i];
+ }
+ }
+
+ if (ibuf->rect_float) {
+ float *rect_float = ibuf->rect_float;
+ i = sizex * sizey * 4;
+ while (i--) {
+ rect_float[i] = (float)(accum_buffer[i] / samples) * (1.0f / 255.0f);
+ }
+ }
+ else {
+ unsigned char *rect_ub = (unsigned char *)ibuf->rect;
+ i = sizex * sizey * 4;
+ while (i--) {
+ rect_ub[i] = accum_buffer[i] / samples;
+ }
+ }
+
+ MEM_freeN(accum_buffer);
+ }
+
+ /* unbind */
+ GPU_offscreen_unbind(ofs, true);
+
+ if (own_ofs) {
+ GPU_offscreen_free(ofs);
+ }
+
+ if (ibuf->rect_float && ibuf->rect)
+ IMB_rect_from_float(ibuf);
+
+ return ibuf;
+}
+
+/**
+ * Creates own fake 3d views (wrapping #ED_view3d_draw_offscreen_imbuf)
+ *
+ * \param ofs: Optional off-screen buffer can be NULL.
+ * (avoids re-creating when doing multiple GL renders).
+ *
+ * \note used by the sequencer
+ */
+ImBuf *ED_view3d_draw_offscreen_imbuf_simple(
+ Scene *scene, Object *camera, int width, int height,
+ unsigned int flag, int drawtype, bool use_solid_tex, bool use_gpencil, bool draw_background,
+ int alpha_mode, int samples, bool full_samples, const char *viewname,
+ GPUFX *fx, GPUOffScreen *ofs, char err_out[256])
+{
+ View3D v3d = {NULL};
+ ARegion ar = {NULL};
+ RegionView3D rv3d = {{{0}}};
+
+ /* connect data */
+ v3d.regionbase.first = v3d.regionbase.last = &ar;
+ ar.regiondata = &rv3d;
+ ar.regiontype = RGN_TYPE_WINDOW;
+
+ v3d.camera = camera;
+ v3d.lay = scene->lay;
+ v3d.drawtype = drawtype;
+ v3d.flag2 = V3D_RENDER_OVERRIDE;
+
+ if (use_gpencil)
+ v3d.flag2 |= V3D_SHOW_GPENCIL;
+
+ if (use_solid_tex)
+ v3d.flag2 |= V3D_SOLID_TEX;
+
+ if (draw_background)
+ v3d.flag3 |= V3D_SHOW_WORLD;
+
+ rv3d.persp = RV3D_CAMOB;
+
+ copy_m4_m4(rv3d.viewinv, v3d.camera->obmat);
+ normalize_m4(rv3d.viewinv);
+ invert_m4_m4(rv3d.viewmat, rv3d.viewinv);
+
+ {
+ CameraParams params;
+ Object *view_camera = BKE_camera_multiview_render(scene, v3d.camera, viewname);
+
+ BKE_camera_params_init(&params);
+ BKE_camera_params_from_object(&params, view_camera);
+ BKE_camera_multiview_params(&scene->r, &params, view_camera, viewname);
+ BKE_camera_params_compute_viewplane(&params, width, height, scene->r.xasp, scene->r.yasp);
+ BKE_camera_params_compute_matrix(&params);
+
+ copy_m4_m4(rv3d.winmat, params.winmat);
+ v3d.near = params.clipsta;
+ v3d.far = params.clipend;
+ v3d.lens = params.lens;
+ }
+
+ mul_m4_m4m4(rv3d.persmat, rv3d.winmat, rv3d.viewmat);
+ invert_m4_m4(rv3d.persinv, rv3d.viewinv);
+
+ return ED_view3d_draw_offscreen_imbuf(
+ scene, &v3d, &ar, width, height, flag,
+ draw_background, alpha_mode, samples, full_samples, viewname,
+ fx, ofs, err_out);
+}
+
+
+/**
+ * \note The info that this uses is updated in #ED_refresh_viewport_fps,
+ * which currently gets called during #SCREEN_OT_animation_step.
+ */
+void ED_scene_draw_fps(Scene *scene, const rcti *rect)
+{
+ ScreenFrameRateInfo *fpsi = scene->fps_info;
+ float fps;
+ char printable[16];
+ int i, tot;
+
+ if (!fpsi || !fpsi->lredrawtime || !fpsi->redrawtime)
+ return;
+
+ printable[0] = '\0';
+
+#if 0
+ /* this is too simple, better do an average */
+ fps = (float)(1.0 / (fpsi->lredrawtime - fpsi->redrawtime))
+#else
+ fpsi->redrawtimes_fps[fpsi->redrawtime_index] = (float)(1.0 / (fpsi->lredrawtime - fpsi->redrawtime));
+
+ for (i = 0, tot = 0, fps = 0.0f; i < REDRAW_FRAME_AVERAGE; i++) {
+ if (fpsi->redrawtimes_fps[i]) {
+ fps += fpsi->redrawtimes_fps[i];
+ tot++;
+ }
+ }
+ if (tot) {
+ fpsi->redrawtime_index = (fpsi->redrawtime_index + 1) % REDRAW_FRAME_AVERAGE;
+
+ //fpsi->redrawtime_index++;
+ //if (fpsi->redrawtime >= REDRAW_FRAME_AVERAGE)
+ // fpsi->redrawtime = 0;
+
+ fps = fps / tot;
+ }
+#endif
+
+ /* is this more than half a frame behind? */
+ if (fps + 0.5f < (float)(FPS)) {
+ UI_ThemeColor(TH_REDALERT);
+ BLI_snprintf(printable, sizeof(printable), IFACE_("fps: %.2f"), fps);
+ }
+ else {
+ UI_ThemeColor(TH_TEXT_HI);
+ BLI_snprintf(printable, sizeof(printable), IFACE_("fps: %i"), (int)(fps + 0.5f));
+ }
+
+#ifdef WITH_INTERNATIONAL
+ BLF_draw_default(rect->xmin + U.widget_unit, rect->ymax - U.widget_unit, 0.0f, printable, sizeof(printable));
+#else
+ BLF_draw_default_ascii(rect->xmin + U.widget_unit, rect->ymax - U.widget_unit, 0.0f, printable, sizeof(printable));
+#endif
+}
+
+static bool view3d_main_region_do_render_draw(Scene *scene)
+{
+ RenderEngineType *type = RE_engines_find(scene->r.engine);
+
+ return (type && type->view_update && type->view_draw);
+}
+
+bool ED_view3d_calc_render_border(Scene *scene, View3D *v3d, ARegion *ar, rcti *rect)
+{
+ RegionView3D *rv3d = ar->regiondata;
+ rctf viewborder;
+ bool use_border;
+
+ /* test if there is a 3d view rendering */
+ if (v3d->drawtype != OB_RENDER || !view3d_main_region_do_render_draw(scene))
+ return false;
+
+ /* test if there is a border render */
+ if (rv3d->persp == RV3D_CAMOB)
+ use_border = (scene->r.mode & R_BORDER) != 0;
+ else
+ use_border = (v3d->flag2 & V3D_RENDER_BORDER) != 0;
+
+ if (!use_border)
+ return false;
+
+ /* compute border */
+ if (rv3d->persp == RV3D_CAMOB) {
+ ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &viewborder, false);
+
+ rect->xmin = viewborder.xmin + scene->r.border.xmin * BLI_rctf_size_x(&viewborder);
+ rect->ymin = viewborder.ymin + scene->r.border.ymin * BLI_rctf_size_y(&viewborder);
+ rect->xmax = viewborder.xmin + scene->r.border.xmax * BLI_rctf_size_x(&viewborder);
+ rect->ymax = viewborder.ymin + scene->r.border.ymax * BLI_rctf_size_y(&viewborder);
+ }
+ else {
+ rect->xmin = v3d->render_border.xmin * ar->winx;
+ rect->xmax = v3d->render_border.xmax * ar->winx;
+ rect->ymin = v3d->render_border.ymin * ar->winy;
+ rect->ymax = v3d->render_border.ymax * ar->winy;
+ }
+
+ BLI_rcti_translate(rect, ar->winrct.xmin, ar->winrct.ymin);
+ BLI_rcti_isect(&ar->winrct, rect, rect);
+
+ return true;
+}
+
+/**
+ * IMPORTANT: this is deprecated, any changes made in this function should
+ * be mirrored in view3d_draw_render_draw() in view3d_draw.c
+ */
+static bool view3d_main_region_draw_engine(const bContext *C, Scene *scene,
+ ARegion *ar, View3D *v3d,
+ bool clip_border, const rcti *border_rect)
+{
+ RegionView3D *rv3d = ar->regiondata;
+ RenderEngineType *type;
+ GLint scissor[4];
+
+ /* create render engine */
+ if (!rv3d->render_engine) {
+ RenderEngine *engine;
+
+ type = RE_engines_find(scene->r.engine);
+
+ if (!(type->view_update && type->view_draw))
+ return false;
+
+ engine = RE_engine_create_ex(type, true);
+
+ engine->tile_x = scene->r.tilex;
+ engine->tile_y = scene->r.tiley;
+
+ type->view_update(engine, C);
+
+ rv3d->render_engine = engine;
+ }
+
+ /* setup view matrices */
+ VP_legacy_view3d_main_region_setup_view(scene, v3d, ar, NULL, NULL);
+
+ /* background draw */
+ ED_region_pixelspace(ar);
+
+ if (clip_border) {
+ /* for border draw, we only need to clear a subset of the 3d view */
+ if (border_rect->xmax > border_rect->xmin && border_rect->ymax > border_rect->ymin) {
+ glGetIntegerv(GL_SCISSOR_BOX, scissor);
+ glScissor(border_rect->xmin, border_rect->ymin,
+ BLI_rcti_size_x(border_rect), BLI_rcti_size_y(border_rect));
+ }
+ else {
+ return false;
+ }
+ }
+
+ glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ if (v3d->flag & V3D_DISPBGPICS)
+ view3d_draw_bgpic_test(scene, ar, v3d, false, true);
+ else
+ fdrawcheckerboard(0, 0, ar->winx, ar->winy);
+
+ /* render result draw */
+ type = rv3d->render_engine->type;
+ type->view_draw(rv3d->render_engine, C);
+
+ if (v3d->flag & V3D_DISPBGPICS)
+ view3d_draw_bgpic_test(scene, ar, v3d, true, true);
+
+ if (clip_border) {
+ /* restore scissor as it was before */
+ glScissor(scissor[0], scissor[1], scissor[2], scissor[3]);
+ }
+
+ return true;
+}
+
+static void view3d_main_region_draw_engine_info(View3D *v3d, RegionView3D *rv3d, ARegion *ar, bool render_border)
+{
+ float fill_color[4] = {0.0f, 0.0f, 0.0f, 0.25f};
+
+ if (!rv3d->render_engine || !rv3d->render_engine->text[0])
+ return;
+
+ if (render_border) {
+ /* draw darkened background color. no alpha because border render does
+ * partial redraw and will not redraw the region behind this info bar */
+ float alpha = 1.0f - fill_color[3];
+ Camera *camera = ED_view3d_camera_data_get(v3d, rv3d);
+
+ if (camera) {
+ if (camera->flag & CAM_SHOWPASSEPARTOUT) {
+ alpha *= (1.0f - camera->passepartalpha);
+ }
+ }
+
+ UI_GetThemeColor3fv(TH_HIGH_GRAD, fill_color);
+ mul_v3_fl(fill_color, alpha);
+ fill_color[3] = 1.0f;
+ }
+
+ ED_region_info_draw(ar, rv3d->render_engine->text, fill_color, true);
+}
+
+static void view3d_stereo3d_setup_offscreen(Scene *scene, View3D *v3d, ARegion *ar,
+ float winmat[4][4], const char *viewname)
+{
+ /* update the viewport matrices with the new camera */
+ if (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D) {
+ float viewmat[4][4];
+ const bool is_left = STREQ(viewname, STEREO_LEFT_NAME);
+
+ BKE_camera_multiview_view_matrix(&scene->r, v3d->camera, is_left, viewmat);
+ VP_legacy_view3d_main_region_setup_view(scene, v3d, ar, viewmat, winmat);
+ }
+ else { /* SCE_VIEWS_FORMAT_MULTIVIEW */
+ float viewmat[4][4];
+ Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname);
+
+ BKE_camera_multiview_view_matrix(&scene->r, camera, false, viewmat);
+ VP_legacy_view3d_main_region_setup_view(scene, v3d, ar, viewmat, winmat);
+ }
+}
+
+#ifdef WITH_GAMEENGINE
+static void update_lods(Scene *scene, float camera_pos[3])
+{
+ Scene *sce_iter;
+ Base *base;
+ Object *ob;
+
+ for (SETLOOPER(scene, sce_iter, base)) {
+ ob = base->object;
+ BKE_object_lod_update(ob, camera_pos);
+ }
+}
+#endif
+
+static void view3d_main_region_draw_objects(const bContext *C, Scene *scene, View3D *v3d,
+ ARegion *ar, const char **grid_unit)
+{
+ wmWindow *win = CTX_wm_window(C);
+ RegionView3D *rv3d = ar->regiondata;
+ unsigned int lay_used = v3d->lay_used;
+
+ /* post processing */
+ bool do_compositing = false;
+
+ /* shadow buffers, before we setup matrices */
+ if (draw_glsl_material(scene, NULL, v3d, v3d->drawtype)) {
+ gpu_update_lamps_shadows_world(scene, v3d);
+
+ if (BKE_scene_use_new_shading_nodes(scene) && (v3d->pbr_settings.pbr_flag & GPU_PBR_FLAG_ENABLE)) {
+ GPU_pbr_settings_validate(&v3d->pbr_settings);
+
+ if (!v3d->pbr)
+ v3d->pbr = GPU_pbr_create();
+
+ gpu_pbr_update(scene, v3d, ar);
+ }
+ }
+
+ /* reset default OpenGL lights if needed (i.e. after preferences have been altered) */
+ if (rv3d->rflag & RV3D_GPULIGHT_UPDATE) {
+ rv3d->rflag &= ~RV3D_GPULIGHT_UPDATE;
+ GPU_default_lights();
+ }
+
+ /* setup the view matrix */
+ if (VP_legacy_view3d_stereo3d_active(C, scene, v3d, rv3d))
+ VP_legacy_view3d_stereo3d_setup(scene, v3d, ar);
+ else
+ VP_legacy_view3d_main_region_setup_view(scene, v3d, ar, NULL, NULL);
+
+ rv3d->rflag &= ~RV3D_IS_GAME_ENGINE;
+#ifdef WITH_GAMEENGINE
+ if (STREQ(scene->r.engine, RE_engine_id_BLENDER_GAME)) {
+ rv3d->rflag |= RV3D_IS_GAME_ENGINE;
+
+ /* Make sure LoDs are up to date */
+ update_lods(scene, rv3d->viewinv[3]);
+ }
+#endif
+
+ /* framebuffer fx needed, we need to draw offscreen first */
+ if ((v3d->fx_settings.fx_flag || v3d->fx_settings.fx_flag2) && v3d->drawtype >= OB_SOLID) {
+ GPUFXSettings fx_settings;
+ BKE_screen_gpu_fx_validate(&v3d->fx_settings);
+ fx_settings = v3d->fx_settings;
+ if (!rv3d->compositor)
+ rv3d->compositor = GPU_fx_compositor_create();
+
+ if (rv3d->persp == RV3D_CAMOB && v3d->camera)
+ BKE_camera_to_gpu_dof(v3d->camera, &fx_settings);
+ else {
+ fx_settings.dof = NULL;
+ }
+
+ do_compositing = GPU_fx_compositor_initialize_passes(rv3d->compositor, &ar->winrct, &ar->drawrct, &fx_settings, scene);
+ }
+
+ /* clear the background */
+ view3d_main_region_clear(scene, v3d, ar);
+
+ /* enables anti-aliasing for 3D view drawing */
+ if (win->multisamples != USER_MULTISAMPLE_NONE) {
+ glEnable(GL_MULTISAMPLE);
+ }
+
+ /* main drawing call */
+ view3d_draw_objects(C, scene, v3d, ar, grid_unit, true, false, do_compositing ? rv3d->compositor : NULL);
+
+ /* post process */
+ if (do_compositing) {
+ GPU_fx_do_composite_pass(rv3d->compositor, rv3d->winmat, rv3d->is_persp, scene, NULL);
+ }
+
+ /* Disable back anti-aliasing */
+ if (win->multisamples != USER_MULTISAMPLE_NONE) {
+ glDisable(GL_MULTISAMPLE);
+ }
+
+ if (v3d->lay_used != lay_used) { /* happens when loading old files or loading with UI load */
+ /* find header and force tag redraw */
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar_header = BKE_area_find_region_type(sa, RGN_TYPE_HEADER);
+ ED_region_tag_redraw(ar_header); /* can be NULL */
+ }
+
+ if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) {
+ BDR_drawSketch(C);
+ }
+
+#ifdef WITH_INPUT_NDOF
+ if ((U.ndof_flag & NDOF_SHOW_GUIDE) && ((rv3d->viewlock & RV3D_LOCKED) == 0) && (rv3d->persp != RV3D_CAMOB))
+ /* TODO: draw something else (but not this) during fly mode */
+ draw_rotation_guide(rv3d);
+#endif
+}
+
+static bool is_cursor_visible(Scene *scene)
+{
+ Object *ob = OBACT;
+
+ /* don't draw cursor in paint modes, but with a few exceptions */
+ if (ob && ob->mode & OB_MODE_ALL_PAINT) {
+ /* exception: object is in weight paint and has deforming armature in pose mode */
+ if (ob->mode & OB_MODE_WEIGHT_PAINT) {
+ if (BKE_object_pose_armature_get(ob) != NULL) {
+ return true;
+ }
+ }
+ /* exception: object in texture paint mode, clone brush, use_clone_layer disabled */
+ else if (ob->mode & OB_MODE_TEXTURE_PAINT) {
+ const Paint *p = BKE_paint_get_active(scene);
+
+ if (p && p->brush && p->brush->imagepaint_tool == PAINT_TOOL_CLONE) {
+ if ((scene->toolsettings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_CLONE) == 0) {
+ return true;
+ }
+ }
+ }
+
+ /* no exception met? then don't draw cursor! */
+ return false;
+ }
+
+ return true;
+}
+
+static void view3d_main_region_draw_info(const bContext *C, Scene *scene,
+ ARegion *ar, View3D *v3d,
+ const char *grid_unit, bool render_border)
+{
+ wmWindowManager *wm = CTX_wm_manager(C);
+ RegionView3D *rv3d = ar->regiondata;
+ rcti rect;
+
+ /* local coordinate visible rect inside region, to accomodate overlapping ui */
+ ED_region_visible_rect(ar, &rect);
+
+ if (rv3d->persp == RV3D_CAMOB) {
+ VP_drawviewborder(scene, ar, v3d);
+ }
+ else if (v3d->flag2 & V3D_RENDER_BORDER) {
+ VP_drawrenderborder(ar, v3d);
+ }
+
+ if (v3d->flag2 & V3D_SHOW_GPENCIL) {
+ /* draw grease-pencil stuff - needed to get paint-buffer shown too (since it's 2D) */
+ ED_gpencil_draw_view3d(wm, scene, v3d, ar, false);
+ }
+
+ if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) {
+ Object *ob;
+
+ /* 3d cursor */
+ if (is_cursor_visible(scene)) {
+ drawcursor(scene, ar, v3d);
+ }
+
+ if (U.uiflag & USER_SHOW_ROTVIEWICON)
+ draw_view_axis(rv3d, &rect);
+ else
+ draw_view_icon(rv3d, &rect);
+
+ ob = OBACT;
+ if (U.uiflag & USER_DRAWVIEWINFO)
+ draw_selected_name(scene, ob, &rect);
+ }
+
+ if (rv3d->render_engine) {
+ view3d_main_region_draw_engine_info(v3d, rv3d, ar, render_border);
+ return;
+ }
+
+ if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) {
+ if ((U.uiflag & USER_SHOW_FPS) && ED_screen_animation_no_scrub(wm)) {
+ ED_scene_draw_fps(scene, &rect);
+ }
+ else if (U.uiflag & USER_SHOW_VIEWPORTNAME) {
+ draw_viewport_name(ar, v3d, &rect);
+ }
+
+ if (grid_unit) { /* draw below the viewport name */
+ char numstr[32] = "";
+
+ UI_ThemeColor(TH_TEXT_HI);
+ if (v3d->grid != 1.0f) {
+ BLI_snprintf(numstr, sizeof(numstr), "%s x %.4g", grid_unit, v3d->grid);
+ }
+
+ BLF_draw_default_ascii(rect.xmin + U.widget_unit,
+ rect.ymax - (USER_SHOW_VIEWPORTNAME ? 2 * U.widget_unit : U.widget_unit), 0.0f,
+ numstr[0] ? numstr : grid_unit, sizeof(numstr));
+ }
+ }
+}
+
+void view3d_main_region_draw_legacy(const bContext *C, ARegion *ar)
+{
+ Scene *scene = CTX_data_scene(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ const char *grid_unit = NULL;
+ rcti border_rect;
+ bool render_border, clip_border;
+
+ /* if we only redraw render border area, skip opengl draw and also
+ * don't do scissor because it's already set */
+ render_border = ED_view3d_calc_render_border(scene, v3d, ar, &border_rect);
+ clip_border = (render_border && !BLI_rcti_compare(&ar->drawrct, &border_rect));
+
+ /* draw viewport using opengl */
+ if (v3d->drawtype != OB_RENDER || !view3d_main_region_do_render_draw(scene) || clip_border) {
+ view3d_main_region_draw_objects(C, scene, v3d, ar, &grid_unit);
+
+#ifdef DEBUG_DRAW
+ bl_debug_draw();
+#endif
+ if (G.debug & G_DEBUG_SIMDATA)
+ draw_sim_debug_data(scene, v3d, ar);
+
+ ED_region_pixelspace(ar);
+ }
+
+ /* draw viewport using external renderer */
+ if (v3d->drawtype == OB_RENDER)
+ view3d_main_region_draw_engine(C, scene, ar, v3d, clip_border, &border_rect);
+
+ view3d_main_region_draw_info(C, scene, ar, v3d, grid_unit, render_border);
+
+ v3d->flag |= V3D_INVALID_BACKBUF;
+
+ BLI_assert(BLI_listbase_is_empty(&v3d->afterdraw_transp));
+ BLI_assert(BLI_listbase_is_empty(&v3d->afterdraw_xray));
+ BLI_assert(BLI_listbase_is_empty(&v3d->afterdraw_xraytransp));
+}
+
+#ifdef DEBUG_DRAW
+/* debug drawing */
+#define _DEBUG_DRAW_QUAD_TOT 1024
+#define _DEBUG_DRAW_EDGE_TOT 1024
+static float _bl_debug_draw_quads[_DEBUG_DRAW_QUAD_TOT][4][3];
+static int _bl_debug_draw_quads_tot = 0;
+static float _bl_debug_draw_edges[_DEBUG_DRAW_QUAD_TOT][2][3];
+static int _bl_debug_draw_edges_tot = 0;
+static unsigned int _bl_debug_draw_quads_color[_DEBUG_DRAW_QUAD_TOT];
+static unsigned int _bl_debug_draw_edges_color[_DEBUG_DRAW_EDGE_TOT];
+static unsigned int _bl_debug_draw_color;
+
+void bl_debug_draw_quad_clear(void)
+{
+ _bl_debug_draw_quads_tot = 0;
+ _bl_debug_draw_edges_tot = 0;
+ _bl_debug_draw_color = 0x00FF0000;
+}
+void bl_debug_color_set(const unsigned int color)
+{
+ _bl_debug_draw_color = color;
+}
+void bl_debug_draw_quad_add(const float v0[3], const float v1[3], const float v2[3], const float v3[3])
+{
+ if (_bl_debug_draw_quads_tot >= _DEBUG_DRAW_QUAD_TOT) {
+ printf("%s: max quad count hit %d!", __func__, _bl_debug_draw_quads_tot);
+ }
+ else {
+ float *pt = &_bl_debug_draw_quads[_bl_debug_draw_quads_tot][0][0];
+ copy_v3_v3(pt, v0); pt += 3;
+ copy_v3_v3(pt, v1); pt += 3;
+ copy_v3_v3(pt, v2); pt += 3;
+ copy_v3_v3(pt, v3); pt += 3;
+ _bl_debug_draw_quads_color[_bl_debug_draw_quads_tot] = _bl_debug_draw_color;
+ _bl_debug_draw_quads_tot++;
+ }
+}
+void bl_debug_draw_edge_add(const float v0[3], const float v1[3])
+{
+ if (_bl_debug_draw_quads_tot >= _DEBUG_DRAW_EDGE_TOT) {
+ printf("%s: max edge count hit %d!", __func__, _bl_debug_draw_edges_tot);
+ }
+ else {
+ float *pt = &_bl_debug_draw_edges[_bl_debug_draw_edges_tot][0][0];
+ copy_v3_v3(pt, v0); pt += 3;
+ copy_v3_v3(pt, v1); pt += 3;
+ _bl_debug_draw_edges_color[_bl_debug_draw_edges_tot] = _bl_debug_draw_color;
+ _bl_debug_draw_edges_tot++;
+ }
+}
+static void bl_debug_draw(void)
+{
+ unsigned int color;
+ if (_bl_debug_draw_quads_tot) {
+ int i;
+ color = _bl_debug_draw_quads_color[0];
+ cpack(color);
+ for (i = 0; i < _bl_debug_draw_quads_tot; i ++) {
+ if (_bl_debug_draw_quads_color[i] != color) {
+ color = _bl_debug_draw_quads_color[i];
+ cpack(color);
+ }
+ glBegin(GL_LINE_LOOP);
+ glVertex3fv(_bl_debug_draw_quads[i][0]);
+ glVertex3fv(_bl_debug_draw_quads[i][1]);
+ glVertex3fv(_bl_debug_draw_quads[i][2]);
+ glVertex3fv(_bl_debug_draw_quads[i][3]);
+ glEnd();
+ }
+ }
+ if (_bl_debug_draw_edges_tot) {
+ int i;
+ color = _bl_debug_draw_edges_color[0];
+ cpack(color);
+ glBegin(GL_LINES);
+ for (i = 0; i < _bl_debug_draw_edges_tot; i ++) {
+ if (_bl_debug_draw_edges_color[i] != color) {
+ color = _bl_debug_draw_edges_color[i];
+ cpack(color);
+ }
+ glVertex3fv(_bl_debug_draw_edges[i][0]);
+ glVertex3fv(_bl_debug_draw_edges[i][1]);
+ }
+ glEnd();
+ color = _bl_debug_draw_edges_color[0];
+ cpack(color);
+ glPointSize(4.0);
+ glBegin(GL_POINTS);
+ for (i = 0; i < _bl_debug_draw_edges_tot; i ++) {
+ if (_bl_debug_draw_edges_color[i] != color) {
+ color = _bl_debug_draw_edges_color[i];
+ cpack(color);
+ }
+ glVertex3fv(_bl_debug_draw_edges[i][0]);
+ glVertex3fv(_bl_debug_draw_edges[i][1]);
+ }
+ glEnd();
+ }
+}
+#endif
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index 9b8ca2d26da..2c4b04ebd34 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -70,7 +70,6 @@
#include "RNA_define.h"
#include "ED_armature.h"
-#include "ED_particle.h"
#include "ED_keyframing.h"
#include "ED_screen.h"
#include "ED_transform.h"
@@ -3080,9 +3079,6 @@ static int viewselected_exec(bContext *C, wmOperator *op)
else if (BKE_paint_select_face_test(ob)) {
ok = paintface_minmax(ob, min, max);
}
- else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT)) {
- ok = PE_minmax(scene, min, max);
- }
else if (ob &&
(ob->mode & (OB_MODE_SCULPT | OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT)))
{
diff --git a/source/blender/editors/space_view3d/view3d_fly.c b/source/blender/editors/space_view3d/view3d_fly.c
index 04a6aa215f4..b42afd3a7a9 100644
--- a/source/blender/editors/space_view3d/view3d_fly.c
+++ b/source/blender/editors/space_view3d/view3d_fly.c
@@ -56,6 +56,8 @@
#include "UI_interface.h"
#include "UI_resources.h"
+#include "GPU_immediate.h"
+
#include "view3d_intern.h" /* own include */
/* NOTE: these defines are saved in keymap files, do not change values but just add new ones */
@@ -257,36 +259,45 @@ static void drawFlyPixel(const struct bContext *UNUSED(C), ARegion *UNUSED(ar),
x2 = xoff + 0.55f * fly->width;
y2 = yoff + 0.55f * fly->height;
- UI_ThemeColor(TH_VIEW_OVERLAY);
- glBegin(GL_LINES);
+ VertexFormat* format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformThemeColor(TH_VIEW_OVERLAY);
+
+ immBegin(GL_LINES, 16);
+
/* bottom left */
- glVertex2f(x1, y1);
- glVertex2f(x1, y1 + 5);
+ immVertex2f(pos, x1, y1);
+ immVertex2f(pos, x1, y1 + 5);
- glVertex2f(x1, y1);
- glVertex2f(x1 + 5, y1);
+ immVertex2f(pos, x1, y1);
+ immVertex2f(pos, x1 + 5, y1);
/* top right */
- glVertex2f(x2, y2);
- glVertex2f(x2, y2 - 5);
+ immVertex2f(pos, x2, y2);
+ immVertex2f(pos, x2, y2 - 5);
- glVertex2f(x2, y2);
- glVertex2f(x2 - 5, y2);
+ immVertex2f(pos, x2, y2);
+ immVertex2f(pos, x2 - 5, y2);
/* top left */
- glVertex2f(x1, y2);
- glVertex2f(x1, y2 - 5);
+ immVertex2f(pos, x1, y2);
+ immVertex2f(pos, x1, y2 - 5);
- glVertex2f(x1, y2);
- glVertex2f(x1 + 5, y2);
+ immVertex2f(pos, x1, y2);
+ immVertex2f(pos, x1 + 5, y2);
/* bottom right */
- glVertex2f(x2, y1);
- glVertex2f(x2, y1 + 5);
+ immVertex2f(pos, x2, y1);
+ immVertex2f(pos, x2, y1 + 5);
+
+ immVertex2f(pos, x2, y1);
+ immVertex2f(pos, x2 - 5, y1);
- glVertex2f(x2, y1);
- glVertex2f(x2 - 5, y1);
- glEnd();
+ immEnd();
+ immUnbindProgram();
}
static void fly_update_header(bContext *C, wmOperator *op, FlyInfo *fly)
diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c
index 0713377d210..32e265cb981 100644
--- a/source/blender/editors/space_view3d/view3d_header.c
+++ b/source/blender/editors/space_view3d/view3d_header.c
@@ -334,8 +334,10 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C)
uiItemMenuEnumO(row, C, "OBJECT_OT_mode_set", "mode", name, icon);
}
- /* Draw type */
- uiItemR(layout, &v3dptr, "viewport_shade", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
+ if (IS_VIEWPORT_LEGACY(v3d)) {
+ /* Draw type */
+ uiItemR(layout, &v3dptr, "viewport_shade", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
+ }
if (obedit == NULL && is_paint) {
if (ob->mode & OB_MODE_ALL_PAINT) {
@@ -345,7 +347,7 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C)
}
/* Manipulators aren't used in paint modes */
- if (!ELEM(ob->mode, OB_MODE_SCULPT, OB_MODE_PARTICLE_EDIT)) {
+ if (ob->mode != OB_MODE_SCULPT) {
/* masks aren't used for sculpt and particle painting */
PointerRNA meshptr;
diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h
index 0e2cb95dd89..07f9448ca4c 100644
--- a/source/blender/editors/space_view3d/view3d_intern.h
+++ b/source/blender/editors/space_view3d/view3d_intern.h
@@ -143,10 +143,15 @@ void draw_motion_paths_cleanup(View3D *v3d);
/* drawobject.c */
void draw_object(Scene *scene, struct ARegion *ar, View3D *v3d, Base *base, const short dflag);
+void draw_mesh_object_outline(View3D *v3d, Object *ob, struct DerivedMesh *dm);
+
bool draw_glsl_material(Scene *scene, struct Object *ob, View3D *v3d, const char dt);
void draw_object_instance(Scene *scene, View3D *v3d, RegionView3D *rv3d, struct Object *ob, const char dt, int outline);
void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, struct Object *ob);
-void drawaxes(const float viewmat_local[4][4], float size, char drawtype);
+void drawaxes(const float viewmat_local[4][4], float size, char drawtype, const unsigned char color[4]);
+void drawlamp(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
+ const char dt, const short dflag, const unsigned char ob_wire_col[4],
+ const bool is_obact);
void view3d_cached_text_draw_begin(void);
void view3d_cached_text_draw_add(const float co[3],
@@ -193,11 +198,13 @@ void draw_sim_debug_data(Scene *scene, View3D *v3d, ARegion *ar);
/* view3d_draw.c */
void view3d_main_region_draw(const struct bContext *C, struct ARegion *ar);
+
+/* view3d_draw_legacy.c */
+void view3d_main_region_draw_legacy(const struct bContext *C, struct ARegion *ar);
void ED_view3d_draw_depth(Scene *scene, struct ARegion *ar, View3D *v3d, bool alphaoverride);
void ED_view3d_draw_depth_gpencil(Scene *scene, ARegion *ar, View3D *v3d);
void ED_view3d_after_add(ListBase *lb, Base *base, const short dflag);
-void circf(float x, float y, float rad);
void circ(float x, float y, float rad);
void view3d_update_depths_rect(struct ARegion *ar, struct ViewDepths *d, struct rcti *rect);
float view3d_depth_near(struct ViewDepths *d);
@@ -266,7 +273,7 @@ void ED_view3d_cameracontrol_update(
void ED_view3d_cameracontrol_release(
struct View3DCameraControl *vctrl,
const bool restore);
-Object *ED_view3d_cameracontrol_object_get(
+struct Object *ED_view3d_cameracontrol_object_get(
struct View3DCameraControl *vctrl);
/* view3d_toolbar.c */
@@ -315,5 +322,18 @@ extern unsigned char view3d_camera_border_hack_col[3];
extern bool view3d_camera_border_hack_test;
#endif
-#endif /* __VIEW3D_INTERN_H__ */
+/* temporary test for blender 2.8 viewport */
+#define IS_VIEWPORT_LEGACY(v3d) ((v3d->tmp_compat_flag & V3D_NEW_VIEWPORT) == 0)
+/* temporary for legacy viewport to work */
+void VP_legacy_drawgrid(UnitSettings *unit, ARegion *ar, View3D *v3d, const char **grid_unit);
+void VP_legacy_drawfloor(Scene *scene, View3D *v3d, const char **grid_unit, bool write_depth);
+void VP_legacy_view3d_main_region_setup_view(Scene *scene, View3D *v3d, ARegion *ar, float viewmat[4][4], float winmat[4][4]);
+bool VP_legacy_view3d_stereo3d_active(const struct bContext *C, Scene *scene, View3D *v3d, RegionView3D *rv3d);
+void VP_legacy_view3d_stereo3d_setup(Scene *scene, View3D *v3d, ARegion *ar);
+void draw_dupli_objects(Scene *scene, ARegion *ar, View3D *v3d, Base *base);
+bool VP_legacy_use_depth(Scene *scene, View3D *v3d);
+void VP_drawviewborder(Scene *scene, ARegion *ar, View3D *v3d);
+void VP_drawrenderborder(ARegion *ar, View3D *v3d);
+
+#endif /* __VIEW3D_INTERN_H__ */
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index 3239d07553f..f77e836461c 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -85,7 +85,6 @@
#include "ED_armature.h"
#include "ED_curve.h"
-#include "ED_particle.h"
#include "ED_mesh.h"
#include "ED_object.h"
#include "ED_screen.h"
@@ -836,8 +835,6 @@ static void view3d_lasso_select(bContext *C, ViewContext *vc,
else if (ob && (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT))) {
/* pass */
}
- else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT))
- PE_lasso_select(C, mcords, moves, extend, select);
else {
do_lasso_select_objects(vc, mcords, moves, extend, select);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, vc->scene);
@@ -2173,9 +2170,6 @@ static int view3d_borderselect_exec(bContext *C, wmOperator *op)
else if (vc.obact && BKE_paint_select_vert_test(vc.obact)) {
ret = do_paintvert_box_select(&vc, &rect, select, extend);
}
- else if (vc.obact && vc.obact->mode & OB_MODE_PARTICLE_EDIT) {
- ret = PE_border_select(C, &rect, select, extend);
- }
else { /* object mode with none active */
ret = do_object_pose_box_select(C, &vc, &rect, select, extend);
}
@@ -2306,8 +2300,6 @@ static int view3d_select_exec(bContext *C, wmOperator *op)
retval = ED_curve_editfont_select_pick(C, location, extend, deselect, toggle);
}
- else if (obact && obact->mode & OB_MODE_PARTICLE_EDIT)
- return PE_mouse_particles(C, location, extend, deselect, toggle);
else if (obact && BKE_paint_select_face_test(obact))
retval = paintface_mouse_select(C, obact, location, extend, deselect, toggle);
else if (BKE_paint_select_vert_test(obact))
@@ -2823,7 +2815,7 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op)
RNA_int_get(op->ptr, "y")};
if (CTX_data_edit_object(C) || BKE_paint_select_elem_test(obact) ||
- (obact && (obact->mode & (OB_MODE_PARTICLE_EDIT | OB_MODE_POSE))) )
+ (obact && (obact->mode & OB_MODE_POSE)) )
{
ViewContext vc;
@@ -2845,8 +2837,6 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op)
}
else if (obact->mode & OB_MODE_POSE)
pose_circle_select(&vc, select, mval, (float)radius);
- else
- return PE_circle_select(C, select, mval, (float)radius);
}
else if (obact && obact->mode & OB_MODE_SCULPT) {
return OPERATOR_CANCELLED;
diff --git a/source/blender/editors/space_view3d/view3d_walk.c b/source/blender/editors/space_view3d/view3d_walk.c
index 17c08ed4205..4131a5c33c7 100644
--- a/source/blender/editors/space_view3d/view3d_walk.c
+++ b/source/blender/editors/space_view3d/view3d_walk.c
@@ -57,6 +57,8 @@
#include "UI_interface.h"
#include "UI_resources.h"
+#include "GPU_immediate.h"
+
#include "view3d_intern.h" /* own include */
#ifdef WITH_INPUT_NDOF
@@ -338,24 +340,33 @@ static void drawWalkPixel(const struct bContext *UNUSED(C), ARegion *ar, void *a
yoff = walk->ar->winy / 2;
}
- UI_ThemeColor(TH_VIEW_OVERLAY);
- glBegin(GL_LINES);
+ VertexFormat* format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_INT, 2, CONVERT_INT_TO_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformThemeColor(TH_VIEW_OVERLAY);
+
+ immBegin(GL_LINES, 8);
+
/* North */
- glVertex2i(xoff, yoff + inner_length);
- glVertex2i(xoff, yoff + outter_length);
+ immVertex2i(pos, xoff, yoff + inner_length);
+ immVertex2i(pos, xoff, yoff + outter_length);
/* East */
- glVertex2i(xoff + inner_length, yoff);
- glVertex2i(xoff + outter_length, yoff);
+ immVertex2i(pos, xoff + inner_length, yoff);
+ immVertex2i(pos, xoff + outter_length, yoff);
/* South */
- glVertex2i(xoff, yoff - inner_length);
- glVertex2i(xoff, yoff - outter_length);
+ immVertex2i(pos, xoff, yoff - inner_length);
+ immVertex2i(pos, xoff, yoff - outter_length);
/* West */
- glVertex2i(xoff - inner_length, yoff);
- glVertex2i(xoff - outter_length, yoff);
- glEnd();
+ immVertex2i(pos, xoff - inner_length, yoff);
+ immVertex2i(pos, xoff - outter_length, yoff);
+
+ immEnd();
+ immUnbindProgram();
}
static void walk_update_header(bContext *C, wmOperator *op, WalkInfo *walk)
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index ef6cff19181..7ff66c21af5 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -42,6 +42,7 @@
#include "DNA_constraint_types.h"
#include "DNA_mask_types.h"
#include "DNA_movieclip_types.h"
+#include "DNA_object_types.h"
#include "DNA_scene_types.h" /* PET modes */
#include "BLI_alloca.h"
@@ -59,7 +60,6 @@
#include "BKE_editmesh_bvh.h"
#include "BKE_context.h"
#include "BKE_constraint.h"
-#include "BKE_particle.h"
#include "BKE_unit.h"
#include "BKE_mask.h"
#include "BKE_report.h"
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index a59f9dc43dd..22d6e7af7fe 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -624,7 +624,6 @@ void flushTransIntFrameActionData(TransInfo *t);
void flushTransGraphData(TransInfo *t);
void remake_graph_transdata(TransInfo *t, struct ListBase *anim_data);
void flushTransUVs(TransInfo *t);
-void flushTransParticles(TransInfo *t);
bool clipUVTransform(TransInfo *t, float vec[2], const bool resize);
void clipUVData(TransInfo *t);
void flushTransNodes(TransInfo *t);
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index 9c266890d6d..6271f80570a 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -50,6 +50,7 @@
#include "DNA_gpencil_types.h"
#include "DNA_movieclip_types.h"
#include "DNA_mask_types.h"
+#include "DNA_object_types.h"
#include "MEM_guardedalloc.h"
@@ -81,9 +82,7 @@
#include "BKE_nla.h"
#include "BKE_node.h"
#include "BKE_object.h"
-#include "BKE_particle.h"
#include "BKE_paint.h"
-#include "BKE_pointcache.h"
#include "BKE_report.h"
#include "BKE_rigidbody.h"
#include "BKE_scene.h"
@@ -96,7 +95,6 @@
#include "ED_anim_api.h"
#include "ED_armature.h"
-#include "ED_particle.h"
#include "ED_image.h"
#include "ED_keyframing.h"
#include "ED_keyframes_edit.h"
@@ -1803,174 +1801,6 @@ static void createTransLatticeVerts(TransInfo *t)
}
}
-/* ******************* particle edit **************** */
-static void createTransParticleVerts(bContext *C, TransInfo *t)
-{
- TransData *td = NULL;
- TransDataExtension *tx;
- Base *base = CTX_data_active_base(C);
- Object *ob = CTX_data_active_object(C);
- ParticleEditSettings *pset = PE_settings(t->scene);
- PTCacheEdit *edit = PE_get_current(t->scene, ob);
- ParticleSystem *psys = NULL;
- ParticleSystemModifierData *psmd = NULL;
- PTCacheEditPoint *point;
- PTCacheEditKey *key;
- float mat[4][4];
- int i, k, transformparticle;
- int count = 0, hasselected = 0;
- const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
-
- if (edit == NULL || t->settings->particle.selectmode == SCE_SELECT_PATH) return;
-
- psys = edit->psys;
-
- if (psys)
- psmd = psys_get_modifier(ob, psys);
-
- base->flag |= BA_HAS_RECALC_DATA;
-
- for (i = 0, point = edit->points; i < edit->totpoint; i++, point++) {
- point->flag &= ~PEP_TRANSFORM;
- transformparticle = 0;
-
- if ((point->flag & PEP_HIDE) == 0) {
- for (k = 0, key = point->keys; k < point->totkey; k++, key++) {
- if ((key->flag & PEK_HIDE) == 0) {
- if (key->flag & PEK_SELECT) {
- hasselected = 1;
- transformparticle = 1;
- }
- else if (is_prop_edit)
- transformparticle = 1;
- }
- }
- }
-
- if (transformparticle) {
- count += point->totkey;
- point->flag |= PEP_TRANSFORM;
- }
- }
-
- /* note: in prop mode we need at least 1 selected */
- if (hasselected == 0) return;
-
- t->total = count;
- td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(Particle Mode)");
-
- if (t->mode == TFM_BAKE_TIME)
- tx = t->ext = MEM_callocN(t->total * sizeof(TransDataExtension), "Particle_TransExtension");
- else
- tx = t->ext = NULL;
-
- unit_m4(mat);
-
- invert_m4_m4(ob->imat, ob->obmat);
-
- for (i = 0, point = edit->points; i < edit->totpoint; i++, point++) {
- TransData *head, *tail;
- head = tail = td;
-
- if (!(point->flag & PEP_TRANSFORM)) continue;
-
- if (psys && !(psys->flag & PSYS_GLOBAL_HAIR))
- psys_mat_hair_to_global(ob, psmd->dm_final, psys->part->from, psys->particles + i, mat);
-
- for (k = 0, key = point->keys; k < point->totkey; k++, key++) {
- if (key->flag & PEK_USE_WCO) {
- copy_v3_v3(key->world_co, key->co);
- mul_m4_v3(mat, key->world_co);
- td->loc = key->world_co;
- }
- else
- td->loc = key->co;
-
- copy_v3_v3(td->iloc, td->loc);
- copy_v3_v3(td->center, td->loc);
-
- if (key->flag & PEK_SELECT)
- td->flag |= TD_SELECTED;
- else if (!is_prop_edit)
- td->flag |= TD_SKIP;
-
- unit_m3(td->mtx);
- unit_m3(td->smtx);
-
- /* don't allow moving roots */
- if (k == 0 && pset->flag & PE_LOCK_FIRST && (!psys || !(psys->flag & PSYS_GLOBAL_HAIR)))
- td->protectflag |= OB_LOCK_LOC;
-
- td->ob = ob;
- td->ext = tx;
- if (t->mode == TFM_BAKE_TIME) {
- td->val = key->time;
- td->ival = *(key->time);
- /* abuse size and quat for min/max values */
- td->flag |= TD_NO_EXT;
- if (k == 0) tx->size = NULL;
- else tx->size = (key - 1)->time;
-
- if (k == point->totkey - 1) tx->quat = NULL;
- else tx->quat = (key + 1)->time;
- }
-
- td++;
- if (tx)
- tx++;
- tail++;
- }
- if (is_prop_edit && head != tail)
- calc_distanceCurveVerts(head, tail - 1);
- }
-}
-
-void flushTransParticles(TransInfo *t)
-{
- Scene *scene = t->scene;
- Object *ob = OBACT;
- PTCacheEdit *edit = PE_get_current(scene, ob);
- ParticleSystem *psys = edit->psys;
- ParticleSystemModifierData *psmd = NULL;
- PTCacheEditPoint *point;
- PTCacheEditKey *key;
- TransData *td;
- float mat[4][4], imat[4][4], co[3];
- int i, k;
- const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
-
- if (psys)
- psmd = psys_get_modifier(ob, psys);
-
- /* we do transform in world space, so flush world space position
- * back to particle local space (only for hair particles) */
- td = t->data;
- for (i = 0, point = edit->points; i < edit->totpoint; i++, point++, td++) {
- if (!(point->flag & PEP_TRANSFORM)) continue;
-
- if (psys && !(psys->flag & PSYS_GLOBAL_HAIR)) {
- psys_mat_hair_to_global(ob, psmd->dm_final, psys->part->from, psys->particles + i, mat);
- invert_m4_m4(imat, mat);
-
- for (k = 0, key = point->keys; k < point->totkey; k++, key++) {
- copy_v3_v3(co, key->world_co);
- mul_m4_v3(imat, co);
-
-
- /* optimization for proportional edit */
- if (!is_prop_edit || !compare_v3v3(key->co, co, 0.0001f)) {
- copy_v3_v3(key->co, co);
- point->flag |= PEP_EDIT_RECALC;
- }
- }
- }
- else
- point->flag |= PEP_EDIT_RECALC;
- }
-
- PE_update_object(scene, OBACT, 1);
-}
-
/* ********************* mesh ****************** */
static bool bmesh_test_dist_add(BMVert *v, BMVert *v_other,
@@ -6315,13 +6145,6 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
else if (t->options & CTX_PAINT_CURVE) {
/* pass */
}
- else if ((t->scene->basact) &&
- (ob = t->scene->basact->object) &&
- (ob->mode & OB_MODE_PARTICLE_EDIT) &&
- PE_get_current(t->scene, ob))
- {
- /* do nothing */
- }
else { /* Objects */
int i;
@@ -6329,8 +6152,6 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
for (i = 0; i < t->total; i++) {
TransData *td = t->data + i;
- ListBase pidlist;
- PTCacheID *pid;
ob = td->ob;
if (td->flag & TD_NOACTION)
@@ -6339,18 +6160,6 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
if (td->flag & TD_SKIP)
continue;
- /* flag object caches as outdated */
- BKE_ptcache_ids_from_object(&pidlist, ob, t->scene, MAX_DUPLI_RECUR);
- for (pid = pidlist.first; pid; pid = pid->next) {
- if (pid->type != PTCACHE_TYPE_PARTICLES) /* particles don't need reset on geometry change */
- pid->cache->flag |= PTCACHE_OUTDATED;
- }
- BLI_freelistN(&pidlist);
-
- /* pointcache refresh */
- if (BKE_ptcache_object_reset(t->scene, ob, PTCACHE_RESET_OUTDATED))
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
-
/* Needed for proper updating of "quick cached" dynamics. */
/* Creates troubles for moving animated objects without */
/* autokey though, probably needed is an anim sys override? */
@@ -8070,16 +7879,6 @@ void createTransData(bContext *C, TransInfo *t)
}
}
- else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT) && PE_start_edit(PE_get_current(scene, ob))) {
- createTransParticleVerts(C, t);
- t->flag |= T_POINTS;
-
- if (t->data && t->flag & T_PROP_EDIT) {
- sort_trans_data(t); // makes selected become first in array
- set_prop_dist(t, 1);
- sort_trans_data_dist(t);
- }
- }
else if (ob && (ob->mode & OB_MODE_ALL_PAINT)) {
if ((t->options & CTX_PAINT_CURVE) && !ELEM(t->mode, TFM_SHEAR, TFM_SHRINKFATTEN)) {
t->flag |= T_POINTS | T_2D_EDIT;
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index f78a23be7b8..9e9372c72ea 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -91,7 +91,6 @@
#include "ED_markers.h"
#include "ED_mesh.h"
#include "ED_object.h"
-#include "ED_particle.h"
#include "ED_screen_types.h"
#include "ED_space_api.h"
#include "ED_uvedit.h"
@@ -709,8 +708,6 @@ static void recalcData_spaceclip(TransInfo *t)
/* helper for recalcData() - for object transforms, typically in the 3D view */
static void recalcData_objects(TransInfo *t)
{
- Base *base = t->scene->basact;
-
if (t->obedit) {
if (ELEM(t->obedit->type, OB_CURVE, OB_SURF)) {
Curve *cu = t->obedit->data;
@@ -896,12 +893,6 @@ static void recalcData_objects(TransInfo *t)
else
BKE_pose_where_is(t->scene, ob);
}
- else if (base && (base->object->mode & OB_MODE_PARTICLE_EDIT) && PE_get_current(t->scene, base->object)) {
- if (t->state != TRANS_CANCEL) {
- applyProject(t);
- }
- flushTransParticles(t);
- }
else {
int i;
diff --git a/source/blender/editors/transform/transform_manipulator.c b/source/blender/editors/transform/transform_manipulator.c
index 075f311db72..adaa487a9a3 100644
--- a/source/blender/editors/transform/transform_manipulator.c
+++ b/source/blender/editors/transform/transform_manipulator.c
@@ -40,6 +40,7 @@
#include "DNA_gpencil_types.h"
#include "DNA_lattice_types.h"
#include "DNA_meta_types.h"
+#include "DNA_object_types.h"
#include "DNA_screen_types.h"
#include "DNA_scene_types.h"
#include "DNA_view3d_types.h"
@@ -54,8 +55,6 @@
#include "BKE_context.h"
#include "BKE_curve.h"
#include "BKE_global.h"
-#include "BKE_particle.h"
-#include "BKE_pointcache.h"
#include "BKE_editmesh.h"
#include "BKE_lattice.h"
#include "BKE_gpencil.h"
@@ -67,7 +66,6 @@
#include "ED_armature.h"
#include "ED_curve.h"
-#include "ED_particle.h"
#include "ED_view3d.h"
#include "ED_gpencil.h"
@@ -560,30 +558,6 @@ static int calc_manipulator_stats(const bContext *C)
else if (ob && (ob->mode & OB_MODE_ALL_PAINT)) {
/* pass */
}
- else if (ob && ob->mode & OB_MODE_PARTICLE_EDIT) {
- PTCacheEdit *edit = PE_get_current(scene, ob);
- PTCacheEditPoint *point;
- PTCacheEditKey *ek;
- int k;
-
- if (edit) {
- point = edit->points;
- for (a = 0; a < edit->totpoint; a++, point++) {
- if (point->flag & PEP_HIDE) continue;
-
- for (k = 0, ek = point->keys; k < point->totkey; k++, ek++) {
- if (ek->flag & PEK_SELECT) {
- calc_tw_center(scene, (ek->flag & PEK_USE_WCO) ? ek->world_co : ek->co);
- totsel++;
- }
- }
- }
-
- /* selection center */
- if (totsel)
- mul_v3_fl(scene->twcent, 1.0f / (float)totsel); // centroid!
- }
- }
else {
/* we need the one selected object, if its not active */
@@ -1381,38 +1355,76 @@ static void draw_manipulator_scale(
glFrontFace(GL_CCW);
}
-
-static void draw_cone(GLUquadricObj *qobj, float len, float width)
+#define NSEGMENTS 8
+static void draw_cone(float len, float width)
{
- glTranslatef(0.0, 0.0, -0.5f * len);
- gluCylinder(qobj, width, 0.0, len, 8, 1);
- gluQuadricOrientation(qobj, GLU_INSIDE);
- gluDisk(qobj, 0.0, width, 8, 1);
- gluQuadricOrientation(qobj, GLU_OUTSIDE);
- glTranslatef(0.0, 0.0, 0.5f * len);
+ /* a ring of vertices in the XY plane */
+ float p[NSEGMENTS][2];
+ for (int i = 0; i < NSEGMENTS; ++i) {
+ float angle = 2 * M_PI * ((float)i / (float)NSEGMENTS);
+ p[i][0] = width * cosf(angle);
+ p[i][1] = width * sinf(angle);
+ }
+
+ float zbase = -0.5f * len;
+ float ztop = 0.5f * len;
+
+ /* cone sides */
+ glBegin(GL_TRIANGLE_FAN);
+ glVertex3f(0, 0, ztop);
+ for (int i = 0; i < NSEGMENTS; ++i)
+ glVertex3f(p[i][0], p[i][1], zbase);
+ glVertex3f(p[0][0], p[0][1], zbase);
+ glEnd();
+
+ /* end cap */
+ glBegin(GL_TRIANGLE_FAN);
+ for (int i = NSEGMENTS - 1; i >= 0; --i)
+ glVertex3f(p[i][0], p[i][1], zbase);
+ glEnd();
}
-static void draw_cylinder(GLUquadricObj *qobj, float len, float width)
+static void draw_cylinder(float len, float width)
{
-
width *= 0.8f; // just for beauty
- glTranslatef(0.0, 0.0, -0.5f * len);
- gluCylinder(qobj, width, width, len, 8, 1);
- gluQuadricOrientation(qobj, GLU_INSIDE);
- gluDisk(qobj, 0.0, width, 8, 1);
- gluQuadricOrientation(qobj, GLU_OUTSIDE);
- glTranslatef(0.0, 0.0, len);
- gluDisk(qobj, 0.0, width, 8, 1);
- glTranslatef(0.0, 0.0, -0.5f * len);
-}
+ /* a ring of vertices in the XY plane */
+ float p[NSEGMENTS][2];
+ for (int i = 0; i < NSEGMENTS; ++i) {
+ float angle = 2 * M_PI * ((float)i / (float)NSEGMENTS);
+ p[i][0] = width * cosf(angle);
+ p[i][1] = width * sinf(angle);
+ }
+ float zbase = -0.5f * len;
+ float ztop = 0.5f * len;
+
+ /* cylinder sides */
+ glBegin(GL_TRIANGLE_STRIP);
+ for (int i = 0; i < NSEGMENTS; ++i) {
+ glVertex3f(p[i][0], p[i][1], zbase);
+ glVertex3f(p[i][0], p[i][1], ztop);
+ }
+ glVertex3f(p[0][0], p[0][1], zbase);
+ glVertex3f(p[0][0], p[0][1], ztop);
+ glEnd();
+
+ /* end caps */
+ glBegin(GL_TRIANGLE_FAN);
+ for (int i = NSEGMENTS - 1; i >= 0; --i)
+ glVertex3f(p[i][0], p[i][1], zbase);
+ glEnd();
+ glBegin(GL_TRIANGLE_FAN);
+ for (int i = 0; i < NSEGMENTS; ++i)
+ glVertex3f(p[i][0], p[i][1], ztop);
+ glEnd();
+}
+#undef NSEGMENTS
static void draw_manipulator_translate(
View3D *v3d, RegionView3D *rv3d, int drawflags, int combo, int colcode,
const bool UNUSED(is_moving), const bool is_picksel)
{
- GLUquadricObj *qobj;
float cylen = 0.01f * (float)U.tw_handlesize;
float cywid = 0.25f * cylen, dz, size;
float unitmat[4][4];
@@ -1451,63 +1463,57 @@ static void draw_manipulator_translate(
axis_order, is_picksel);
}
-
/* offset in combo mode, for rotate a bit more */
if (combo & (V3D_MANIP_ROTATE)) dz = 1.0f + 2.0f * cylen;
else if (combo & (V3D_MANIP_SCALE)) dz = 1.0f + 0.5f * cylen;
else dz = 1.0f;
- qobj = gluNewQuadric();
- gluQuadricDrawStyle(qobj, GLU_FILL);
-
for (i = 0; i < 3; i++) {
switch (axis_order[i]) {
case 0: /* Z Cone */
if (drawflags & MAN_TRANS_Z) {
+ glPushMatrix();
glTranslatef(0.0, 0.0, dz);
if (is_picksel) GPU_select_load_id(MAN_TRANS_Z);
else manipulator_setcolor(v3d, 'Z', colcode, axisBlendAngle(rv3d->tw_idot[2]));
- draw_cone(qobj, cylen, cywid);
- glTranslatef(0.0, 0.0, -dz);
+ draw_cone(cylen, cywid);
+ glPopMatrix();
}
break;
case 1: /* X Cone */
if (drawflags & MAN_TRANS_X) {
+ glPushMatrix();
glTranslatef(dz, 0.0, 0.0);
if (is_picksel) GPU_select_load_id(MAN_TRANS_X);
else manipulator_setcolor(v3d, 'X', colcode, axisBlendAngle(rv3d->tw_idot[0]));
glRotatef(90.0, 0.0, 1.0, 0.0);
- draw_cone(qobj, cylen, cywid);
- glRotatef(-90.0, 0.0, 1.0, 0.0);
- glTranslatef(-dz, 0.0, 0.0);
+ draw_cone(cylen, cywid);
+ glPopMatrix();
}
break;
case 2: /* Y Cone */
if (drawflags & MAN_TRANS_Y) {
+ glPushMatrix();
glTranslatef(0.0, dz, 0.0);
if (is_picksel) GPU_select_load_id(MAN_TRANS_Y);
else manipulator_setcolor(v3d, 'Y', colcode, axisBlendAngle(rv3d->tw_idot[1]));
glRotatef(-90.0, 1.0, 0.0, 0.0);
- draw_cone(qobj, cylen, cywid);
- glRotatef(90.0, 1.0, 0.0, 0.0);
- glTranslatef(0.0, -dz, 0.0);
+ draw_cone(cylen, cywid);
+ glPopMatrix();
}
break;
}
}
- gluDeleteQuadric(qobj);
glLoadMatrixf(rv3d->viewmat);
if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
-
}
static void draw_manipulator_rotate_cyl(
View3D *v3d, RegionView3D *rv3d, int drawflags, const int combo, const int colcode,
const bool is_moving, const bool is_picksel)
{
- GLUquadricObj *qobj;
float size;
float cylen = 0.01f * (float)U.tw_handlesize;
float cywid = 0.25f * cylen;
@@ -1525,8 +1531,6 @@ static void draw_manipulator_rotate_cyl(
glDisable(GL_DEPTH_TEST);
- qobj = gluNewQuadric();
-
/* Screen aligned view rot circle */
if (drawflags & MAN_ROT_V) {
float unitmat[4][4];
@@ -1575,54 +1579,49 @@ static void draw_manipulator_rotate_cyl(
drawflags & MAN_ROT_X, drawflags & MAN_ROT_Y, drawflags & MAN_ROT_Z,
axis_order, is_picksel);
}
-
- /* only has to be set when not in picking */
- gluQuadricDrawStyle(qobj, GLU_FILL);
}
for (i = 0; i < 3; i++) {
switch (axis_order[i]) {
case 0: /* X cylinder */
if (drawflags & MAN_ROT_X) {
+ glPushMatrix();
glTranslatef(1.0, 0.0, 0.0);
if (is_picksel) GPU_select_load_id(MAN_ROT_X);
glRotatef(90.0, 0.0, 1.0, 0.0);
manipulator_setcolor(v3d, 'X', colcode, 255);
- draw_cylinder(qobj, cylen, cywid);
- glRotatef(-90.0, 0.0, 1.0, 0.0);
- glTranslatef(-1.0, 0.0, 0.0);
+ draw_cylinder(cylen, cywid);
+ glPopMatrix();
}
break;
case 1: /* Y cylinder */
if (drawflags & MAN_ROT_Y) {
+ glPushMatrix();
glTranslatef(0.0, 1.0, 0.0);
if (is_picksel) GPU_select_load_id(MAN_ROT_Y);
glRotatef(-90.0, 1.0, 0.0, 0.0);
manipulator_setcolor(v3d, 'Y', colcode, 255);
- draw_cylinder(qobj, cylen, cywid);
- glRotatef(90.0, 1.0, 0.0, 0.0);
- glTranslatef(0.0, -1.0, 0.0);
+ draw_cylinder(cylen, cywid);
+ glPopMatrix();
}
break;
case 2: /* Z cylinder */
if (drawflags & MAN_ROT_Z) {
+ glPushMatrix();
glTranslatef(0.0, 0.0, 1.0);
if (is_picksel) GPU_select_load_id(MAN_ROT_Z);
manipulator_setcolor(v3d, 'Z', colcode, 255);
- draw_cylinder(qobj, cylen, cywid);
- glTranslatef(0.0, 0.0, -1.0);
+ draw_cylinder(cylen, cywid);
+ glPopMatrix();
}
break;
}
}
/* restore */
-
- gluDeleteQuadric(qobj);
glLoadMatrixf(rv3d->viewmat);
if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
-
}
diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c
index 90a4aa3614d..1d6a392aae6 100644
--- a/source/blender/editors/transform/transform_orientations.c
+++ b/source/blender/editors/transform/transform_orientations.c
@@ -1011,7 +1011,7 @@ int getTransformOrientation_ex(const bContext *C, float normal[3], float plane[3
result = ORIENTATION_EDGE;
}
}
- else if (ob && (ob->mode & (OB_MODE_ALL_PAINT | OB_MODE_PARTICLE_EDIT))) {
+ else if (ob && (ob->mode & OB_MODE_ALL_PAINT)) {
/* pass */
}
else {
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
index f8bb124e943..121a23a7027 100644
--- a/source/blender/editors/transform/transform_snap.c
+++ b/source/blender/editors/transform/transform_snap.c
@@ -519,8 +519,6 @@ static void initSnappingMode(TransInfo *t)
{
ToolSettings *ts = t->settings;
Object *obedit = t->obedit;
- Scene *scene = t->scene;
- Base *base_act = scene->basact;
if (t->spacetype == SPACE_NODE) {
/* force project off when not supported */
@@ -559,12 +557,6 @@ static void initSnappingMode(TransInfo *t)
t->tsnap.modeSelect = t->tsnap.snap_self ? SNAP_ALL : SNAP_NOT_ACTIVE;
}
}
- /* Particles edit mode*/
- else if (t->tsnap.applySnap != NULL && // A snapping function actually exist
- (obedit == NULL && base_act && base_act->object && base_act->object->mode & OB_MODE_PARTICLE_EDIT))
- {
- t->tsnap.modeSelect = SNAP_ALL;
- }
/* Object mode */
else if (t->tsnap.applySnap != NULL && // A snapping function actually exist
(obedit == NULL) ) // Object Mode
diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c
index 02900d7022c..c8ccb3772c5 100644
--- a/source/blender/editors/transform/transform_snap_object.c
+++ b/source/blender/editors/transform/transform_snap_object.c
@@ -1867,23 +1867,7 @@ static bool snapObjectsRay(
unsigned int ob_index = 0;
Object *obedit = use_object_edit_cage ? sctx->scene->obedit : NULL;
-
- /* Need an exception for particle edit because the base is flagged with BA_HAS_RECALC_DATA
- * which makes the loop skip it, even the derived mesh will never change
- *
- * To solve that problem, we do it first as an exception.
- * */
Base *base_act = sctx->scene->basact;
- if (base_act && base_act->object && base_act->object->mode & OB_MODE_PARTICLE_EDIT) {
- Object *ob = base_act->object;
-
- retval |= snapObject(
- sctx, ob, ob->obmat, ob_index++,
- false, snap_to, mval,
- ray_origin, ray_start, ray_normal, depth_range,
- ray_depth, dist_px,
- r_loc, r_no, r_index, r_ob, r_obmat, r_hit_list);
- }
bool ignore_object_selected = false, ignore_object_active = false;
switch (snap_select) {
diff --git a/source/blender/editors/util/CMakeLists.txt b/source/blender/editors/util/CMakeLists.txt
index c0b30f93939..321b1043595 100644
--- a/source/blender/editors/util/CMakeLists.txt
+++ b/source/blender/editors/util/CMakeLists.txt
@@ -72,7 +72,6 @@ set(SRC
../include/ED_object.h
../include/ED_outliner.h
../include/ED_paint.h
- ../include/ED_particle.h
../include/ED_physics.h
../include/ED_render.h
../include/ED_screen.h
diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c
index 1f1a778cac7..482523e56be 100644
--- a/source/blender/editors/util/ed_util.c
+++ b/source/blender/editors/util/ed_util.c
@@ -70,6 +70,8 @@
#include "ED_space_api.h"
#include "ED_util.h"
+#include "GPU_immediate.h"
+
#include "UI_interface.h"
#include "UI_resources.h"
@@ -312,15 +314,23 @@ void ED_region_draw_mouse_line_cb(const bContext *C, ARegion *ar, void *arg_info
{
wmWindow *win = CTX_wm_window(C);
const float *mval_src = (float *)arg_info;
- const int mval_dst[2] = {win->eventstate->x - ar->winrct.xmin,
- win->eventstate->y - ar->winrct.ymin};
+ const float mval_dst[2] = {win->eventstate->x - ar->winrct.xmin,
+ win->eventstate->y - ar->winrct.ymin};
- UI_ThemeColor(TH_VIEW_OVERLAY);
setlinestyle(3);
- glBegin(GL_LINES);
- glVertex2iv(mval_dst);
- glVertex2fv(mval_src);
- glEnd();
+
+ VertexFormat *format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColor(TH_VIEW_OVERLAY);
+
+ immBegin(GL_LINES, 2);
+ immVertex2fv(pos, mval_dst);
+ immVertex2fv(pos, mval_src);
+ immEnd();
+ immUnbindProgram();
+
setlinestyle(0);
}
diff --git a/source/blender/editors/util/undo.c b/source/blender/editors/util/undo.c
index ee6700666c0..805238bd2af 100644
--- a/source/blender/editors/util/undo.c
+++ b/source/blender/editors/util/undo.c
@@ -49,7 +49,6 @@
#include "BKE_screen.h"
#include "ED_armature.h"
-#include "ED_particle.h"
#include "ED_curve.h"
#include "ED_gpencil.h"
#include "ED_mball.h"
@@ -98,11 +97,6 @@ void ED_undo_push(bContext *C, const char *str)
else if (obedit->type == OB_ARMATURE)
undo_push_armature(C, str);
}
- else if (obact && obact->mode & OB_MODE_PARTICLE_EDIT) {
- if (U.undosteps == 0) return;
-
- PE_undo_push(CTX_data_scene(C), str);
- }
else if (obact && obact->mode & OB_MODE_SCULPT) {
/* do nothing for now */
}
@@ -178,12 +172,6 @@ static int ed_undo_step(bContext *C, int step, const char *undoname)
else if (obact && obact->mode & OB_MODE_SCULPT) {
ED_undo_paint_step(C, UNDO_PAINT_MESH, step, undoname);
}
- else if (obact && obact->mode & OB_MODE_PARTICLE_EDIT) {
- if (step == 1)
- PE_undo(scene);
- else
- PE_redo(scene);
- }
else if (U.uiflag & USER_GLOBALUNDO) {
// note python defines not valid here anymore.
//#ifdef WITH_PYTHON
@@ -273,9 +261,6 @@ bool ED_undo_is_valid(const bContext *C, const char *undoname)
if (ED_undo_paint_is_valid(UNDO_PAINT_MESH, undoname))
return 1;
}
- else if (obact && obact->mode & OB_MODE_PARTICLE_EDIT) {
- return PE_undo_is_valid(CTX_data_scene(C));
- }
if (U.uiflag & USER_GLOBALUNDO) {
return BKE_undo_is_valid(undoname);
@@ -435,9 +420,8 @@ void ED_undo_operator_repeat_cb_evt(bContext *C, void *arg_op, int UNUSED(arg_ev
enum {
UNDOSYSTEM_GLOBAL = 1,
UNDOSYSTEM_EDITMODE = 2,
- UNDOSYSTEM_PARTICLE = 3,
- UNDOSYSTEM_IMAPAINT = 4,
- UNDOSYSTEM_SCULPT = 5,
+ UNDOSYSTEM_IMAPAINT = 3,
+ UNDOSYSTEM_SCULPT = 4,
};
static int get_undo_system(bContext *C)
@@ -463,9 +447,7 @@ static int get_undo_system(bContext *C)
}
else {
if (obact) {
- if (obact->mode & OB_MODE_PARTICLE_EDIT)
- return UNDOSYSTEM_PARTICLE;
- else if (obact->mode & OB_MODE_TEXTURE_PAINT) {
+ if (obact->mode & OB_MODE_TEXTURE_PAINT) {
if (!ED_undo_paint_empty(UNDO_PAINT_IMAGE))
return UNDOSYSTEM_IMAPAINT;
}
@@ -491,10 +473,7 @@ static EnumPropertyItem *rna_undo_itemf(bContext *C, int undosys, int *totitem)
while (true) {
const char *name = NULL;
- if (undosys == UNDOSYSTEM_PARTICLE) {
- name = PE_undo_get_name(CTX_data_scene(C), i, &active);
- }
- else if (undosys == UNDOSYSTEM_EDITMODE) {
+ if (undosys == UNDOSYSTEM_EDITMODE) {
name = undo_editmode_get_name(C, i, &active);
}
else if (undosys == UNDOSYSTEM_IMAPAINT) {
@@ -574,10 +553,7 @@ static int undo_history_exec(bContext *C, wmOperator *op)
int undosys = get_undo_system(C);
int item = RNA_int_get(op->ptr, "item");
- if (undosys == UNDOSYSTEM_PARTICLE) {
- PE_undo_number(CTX_data_scene(C), item);
- }
- else if (undosys == UNDOSYSTEM_EDITMODE) {
+ if (undosys == UNDOSYSTEM_EDITMODE) {
undo_editmode_number(C, item + 1);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL);
}
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index d00efc3979c..effce229f7b 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -32,6 +32,8 @@ set(INC
../makesdna
../makesrna
+ ../editors/include
+
# For node muting stuff...
../nodes
../nodes/intern
@@ -47,6 +49,7 @@ set(INC_SYS
set(SRC
intern/gpu_basic_shader.c
+ intern/gpu_batch.c
intern/gpu_buffers.c
intern/gpu_codegen.c
intern/gpu_compositing.c
@@ -54,13 +57,32 @@ set(SRC
intern/gpu_draw.c
intern/gpu_extensions.c
intern/gpu_framebuffer.c
+ intern/gpu_immediate.c
intern/gpu_init_exit.c
intern/gpu_pbr.c
intern/gpu_material.c
+ intern/gpu_matrix.c
intern/gpu_probe.c
intern/gpu_select.c
intern/gpu_shader.c
intern/gpu_texture.c
+ intern/gpu_viewport.c
+
+ gawain/attrib_binding.c
+ gawain/attrib_binding.h
+ gawain/batch.c
+ gawain/batch.h
+ gawain/common.h
+ gawain/element.c
+ gawain/element.h
+ gawain/immediate.c
+ gawain/immediate.h
+ gawain/imm_util.c
+ gawain/imm_util.h
+ gawain/vertex_buffer.c
+ gawain/vertex_buffer.h
+ gawain/vertex_format.c
+ gawain/vertex_format.h
shaders/gpu_shader_fx_lib.glsl
shaders/gpu_shader_fx_ssao_frag.glsl
@@ -104,6 +126,7 @@ set(SRC
shaders/gpu_shader_downsample_maxz_vert.glsl
GPU_basic_shader.h
+ GPU_batch.h
GPU_buffers.h
GPU_compositing.h
GPU_debug.h
@@ -111,18 +134,55 @@ set(SRC
GPU_extensions.h
GPU_framebuffer.h
GPU_glew.h
+ GPU_immediate.h
GPU_init_exit.h
GPU_pbr.h
GPU_ltc.h
GPU_material.h
+ GPU_matrix.h
GPU_probe.h
GPU_select.h
GPU_shader.h
GPU_texture.h
+ GPU_viewport.h
+
intern/gpu_codegen.h
intern/gpu_private.h
)
+data_to_c_simple(shaders/gpu_shader_depth_only_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_uniform_color_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_flat_color_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_flat_color_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_smooth_color_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_smooth_color_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_image_modulate_alpha_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_image_rect_modulate_alpha_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_3D_image_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_3D_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_3D_flat_color_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_3D_smooth_color_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_3D_smooth_color_frag.glsl SRC)
+
+data_to_c_simple(shaders/gpu_shader_point_uniform_color_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_point_uniform_color_smooth_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_point_uniform_color_outline_smooth_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_point_varying_color_outline_smooth_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_point_varying_color_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_3D_point_fixed_size_varying_color_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_3D_point_varying_size_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_3D_point_varying_size_varying_color_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_3D_point_uniform_size_smooth_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_3D_point_uniform_size_outline_smooth_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_point_varying_size_varying_color_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_point_uniform_size_smooth_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_point_uniform_size_outline_smooth_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_point_uniform_size_varying_color_outline_smooth_vert.glsl SRC)
+
+data_to_c_simple(shaders/gpu_shader_text_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_text_frag.glsl SRC)
+
data_to_c_simple(shaders/gpu_shader_geometry.glsl SRC)
data_to_c_simple(shaders/gpu_shader_fire_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_smoke_frag.glsl SRC)
diff --git a/source/blender/gpu/GPU_batch.h b/source/blender/gpu/GPU_batch.h
new file mode 100644
index 00000000000..bc3017e2784
--- /dev/null
+++ b/source/blender/gpu/GPU_batch.h
@@ -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) 2016 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Mike Erwin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/* Batched geometry rendering is powered by the Gawain library.
+ * This file contains any additions or modifications specific to Blender.
+ */
+
+#pragma once
+
+#include "gawain/batch.h"
+#include "GPU_shader.h"
+
+/* Extend Batch_set_program to use Blender’s library of built-in shader programs. */
+void Batch_set_builtin_program(Batch*, GPUBuiltinShader);
diff --git a/source/blender/gpu/GPU_debug.h b/source/blender/gpu/GPU_debug.h
index 61b2bc591ce..921deaaa6d6 100644
--- a/source/blender/gpu/GPU_debug.h
+++ b/source/blender/gpu/GPU_debug.h
@@ -41,24 +41,9 @@ extern "C" {
/* prints something if debug mode is active only */
void GPU_print_error_debug(const char *str);
-/* replacement for gluErrorString */
-const char *gpuErrorString(GLenum err);
-
/* prints current OpenGL state */
void GPU_state_print(void);
-void GPU_assert_no_gl_errors(const char *file, int line, const char *str);
-
-# define GPU_ASSERT_NO_GL_ERRORS(str) GPU_assert_no_gl_errors(__FILE__, __LINE__, (str))
-
-# define GPU_CHECK_ERRORS_AROUND(glProcCall) \
- ( \
- GPU_ASSERT_NO_GL_ERRORS("Pre: " #glProcCall), \
- (glProcCall), \
- GPU_ASSERT_NO_GL_ERRORS("Post: " #glProcCall) \
- )
-
-
/* inserts a debug marker message for the debug context messaging system */
void GPU_string_marker(const char *str);
diff --git a/source/blender/gpu/GPU_draw.h b/source/blender/gpu/GPU_draw.h
index d5dbd55279d..2b07ee7fb1a 100644
--- a/source/blender/gpu/GPU_draw.h
+++ b/source/blender/gpu/GPU_draw.h
@@ -61,6 +61,13 @@ struct DupliObject;
void GPU_state_init(void);
+/* Programmable point size
+ * - shaders set their own point size when enabled
+ * - use glPointSize when disabled */
+
+void GPU_enable_program_point_size(void);
+void GPU_disable_program_point_size(void);
+
/* Material drawing
* - first the state is initialized by a particular object and
* it's materials
diff --git a/source/blender/gpu/GPU_framebuffer.h b/source/blender/gpu/GPU_framebuffer.h
index f7ffecf9511..0f752c13c76 100644
--- a/source/blender/gpu/GPU_framebuffer.h
+++ b/source/blender/gpu/GPU_framebuffer.h
@@ -50,8 +50,8 @@ struct GPUTexture;
void GPU_texture_bind_as_framebuffer(struct GPUTexture *tex);
GPUFrameBuffer *GPU_framebuffer_create(void);
-int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, struct GPUTexture *tex, int slot, char err_out[256]);
-int GPU_framebuffer_cubeface_attach(GPUFrameBuffer *fb, struct GPUTexture *tex, int slot, int cubeface, char err_out[256]);
+bool GPU_framebuffer_cubeface_attach(GPUFrameBuffer *fb, struct GPUTexture *tex, int slot, int cubeface);
+bool GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, struct GPUTexture *tex, int slot);
void GPU_framebuffer_texture_detach(struct GPUTexture *tex);
void GPU_framebuffer_slots_bind(GPUFrameBuffer *fb, int slot);
void GPU_framebuffer_texture_unbind(GPUFrameBuffer *fb, struct GPUTexture *tex);
diff --git a/source/blender/gpu/GPU_immediate.h b/source/blender/gpu/GPU_immediate.h
new file mode 100644
index 00000000000..0cb9d7929c9
--- /dev/null
+++ b/source/blender/gpu/GPU_immediate.h
@@ -0,0 +1,47 @@
+/*
+ * ***** 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) 2016 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Mike Erwin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/* Immediate mode rendering is powered by the Gawain library.
+ * This file contains any additions or modifications specific to Blender.
+ */
+
+#pragma once
+
+#include "gawain/immediate.h"
+#include "gawain/imm_util.h"
+#include "GPU_shader.h"
+
+/* Extend immBindProgram to use Blender’s library of built-in shader programs.
+ * Use immUnbindProgram() when done. */
+void immBindBuiltinProgram(GPUBuiltinShader shader_id);
+
+/*
+ * Extend immUniformColor to take Blender's themes
+ */
+void immUniformThemeColor(int color_id);
+void immUniformThemeColorShade(int color_id, int offset);
+void immUniformThemeColorShadeAlpha(int color_id, int color_offset, int alpha_offset);
+void immUniformThemeColorBlendShade(int color_id1, int color_id2, float fac, int offset);
diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h
index cc3039b558a..9252c684aeb 100644
--- a/source/blender/gpu/GPU_material.h
+++ b/source/blender/gpu/GPU_material.h
@@ -65,7 +65,6 @@ typedef struct GPUNode GPUNode;
typedef struct GPUNodeLink GPUNodeLink;
typedef struct GPUMaterial GPUMaterial;
typedef struct GPULamp GPULamp;
-typedef struct GPUParticleInfo GPUParticleInfo;
/* Functions to create GPU Materials nodes */
@@ -95,11 +94,7 @@ typedef enum GPUBuiltin {
GPU_OBCOLOR = (1 << 6),
GPU_AUTO_BUMPSCALE = (1 << 7),
GPU_CAMERA_TEXCO_FACTORS = (1 << 8),
- GPU_PARTICLE_SCALAR_PROPS = (1 << 9),
- GPU_PARTICLE_LOCATION = (1 << 10),
- GPU_PARTICLE_VELOCITY = (1 << 11),
- GPU_PARTICLE_ANG_VELOCITY = (1 << 12),
- GPU_LOC_TO_VIEW_MATRIX = (1 << 13),
+ GPU_LOC_TO_VIEW_MATRIX = (1 << 9),
GPU_INVERSE_LOC_TO_VIEW_MATRIX = (1 << 14),
GPU_PBR = (1 << 15),
} GPUBuiltin;
@@ -250,8 +245,10 @@ void GPU_material_bind(
float viewmat[4][4], float viewinv[4][4], float cameraborder[4], bool scenelock);
void GPU_material_bind_uniforms(
GPUMaterial *material, float obmat[4][4], float viewmat[4][4], float obcol[4],
- float autobumpscale, GPUParticleInfo *pi);
-void GPU_material_bind_uniforms_pbr(GPUMaterial *material, struct GPUProbe *probe, struct GPUPBR *pbr, struct GPUPBRSettings *pbr_settings);
+ float autobumpscale);
+void GPU_material_bind_uniforms_pbr(
+ GPUMaterial *material, struct GPUProbe *probe, struct GPUPBR *pbr,
+ struct GPUPBRSettings *pbr_settings);
void GPU_material_unbind(GPUMaterial *material);
bool GPU_material_bound(GPUMaterial *material);
struct Scene *GPU_material_scene(GPUMaterial *material);
@@ -412,14 +409,6 @@ void GPU_horizon_update_color(float color[3]);
void GPU_ambient_update_color(float color[3]);
void GPU_zenith_update_color(float color[3]);
-struct GPUParticleInfo
-{
- float scalprops[4];
- float location[3];
- float velocity[3];
- float angular_velocity[3];
-};
-
#ifdef WITH_OPENSUBDIV
struct DerivedMesh;
void GPU_material_update_fvar_offset(GPUMaterial *gpu_material,
diff --git a/source/blender/gpu/GPU_matrix.h b/source/blender/gpu/GPU_matrix.h
new file mode 100644
index 00000000000..3c3acc08f58
--- /dev/null
+++ b/source/blender/gpu/GPU_matrix.h
@@ -0,0 +1,143 @@
+#ifndef _GPU_MATRIX_H_
+#define _GPU_MATRIX_H_
+
+/*
+ * ***** 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) 2012 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Alexandr Kuznetsov, Jason Wilkins, Mike Erwin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/gpu/GPU_matrix.h
+ * \ingroup gpu
+ */
+
+#include "GPU_glew.h"
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* For now we support the legacy matrix stack in gpuGetMatrix functions.
+ * Will remove this after switching to core profile, which can happen after
+ * we convert all code to use the API in this file. */
+#define SUPPORT_LEGACY_MATRIX 1
+
+
+void gpuMatrixInit(void); /* called by system -- make private? */
+
+
+/* MatrixMode is conceptually different from GL_MATRIX_MODE */
+
+typedef enum {
+ MATRIX_MODE_INACTIVE,
+ MATRIX_MODE_2D,
+ MATRIX_MODE_3D
+} MatrixMode;
+
+MatrixMode gpuMatrixMode(void);
+
+void gpuMatrixBegin2D(void);
+void gpuMatrixBegin3D(void);
+void gpuMatrixEnd(void);
+/* TODO: gpuMatrixResume2D & gpuMatrixResume3D to switch modes but not reset stack */
+
+
+/* ModelView Matrix (2D or 3D) */
+
+void gpuPushMatrix(void); /* TODO: PushCopy vs PushIdentity? */
+void gpuPopMatrix(void);
+
+void gpuLoadIdentity(void);
+
+void gpuScaleUniform(float factor);
+
+
+/* 3D ModelView Matrix */
+
+void gpuLoadMatrix3D(const float m[4][4]);
+void gpuMultMatrix3D(const float m[4][4]);
+//const float *gpuGetMatrix3D(float m[4][4]);
+
+void gpuTranslate3f(float x, float y, float z);
+void gpuTranslate3fv(const float vec[3]);
+void gpuScale3f(float x, float y, float z);
+void gpuScale3fv(const float vec[3]);
+void gpuRotate3fv(float deg, const float axis[3]); /* axis of rotation should be a unit vector */
+void gpuRotateAxis(float deg, char axis); /* TODO: enum for axis? */
+
+void gpuLookAt(float eyeX, float eyeY, float eyeZ, float centerX, float centerY, float centerZ, float upX, float upY, float upZ);
+/* TODO: variant that takes eye[3], center[3], up[3] */
+
+
+/* 2D ModelView Matrix */
+
+void gpuLoadMatrix2D(const float m[3][3]);
+void gpuMultMatrix2D(const float m[3][3]);
+
+void gpuTranslate2f(float x, float y);
+void gpuTranslate2fv(const float vec[2]);
+void gpuScale2f(float x, float y);
+void gpuScale2fv(const float vec[2]);
+void gpuRotate2D(float deg);
+
+
+/* 3D Projection Matrix */
+
+void gpuOrtho(float left, float right, float bottom, float top, float near, float far);
+void gpuFrustum(float left, float right, float bottom, float top, float near, float far);
+void gpuPerspective(float fovy, float aspect, float near, float far);
+
+/* pass vector through current transform (world --> screen) */
+void gpuProject(const float obj[3], const float model[4][4], const float proj[4][4], const GLint view[4], float win[3]);
+
+/* pass vector through inverse transform (world <-- screen) */
+bool gpuUnProject(const float win[3], const float model[4][4], const float proj[4][4], const GLint view[4], float obj[3]);
+
+
+/* 2D Projection Matrix */
+
+void gpuOrtho2D(float left, float right, float bottom, float top);
+
+
+/* functions to get matrix values */
+const float *gpuGetModelViewMatrix3D(float m[4][4]);
+const float *gpuGetProjectionMatrix3D(float m[4][4]);
+const float *gpuGetModelViewProjectionMatrix3D(float m[4][4]);
+
+
+#if SUPPORT_LEGACY_MATRIX
+/* copy top matrix from each legacy stack into new fresh stack */
+void gpuMatrixBegin3D_legacy(void);
+#endif
+
+
+/* set uniform values for currently bound shader */
+void gpuBindMatrices(GLuint program);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GPU_MATRIX_H */
diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h
index b40a2dbd1ed..400c4ded08d 100644
--- a/source/blender/gpu/GPU_shader.h
+++ b/source/blender/gpu/GPU_shader.h
@@ -96,11 +96,39 @@ typedef enum GPUBuiltinShader {
GPU_SHADER_SEP_GAUSSIAN_BLUR = 1,
GPU_SHADER_SMOKE = 2,
GPU_SHADER_SMOKE_FIRE = 3,
- GPU_SHADER_MINZ_DOWNSAMPLE = 4,
- GPU_SHADER_MAXZ_DOWNSAMPLE = 5,
- GPU_SHADER_DISPLAY_SH = 6,
- GPU_SHADER_COMPUTE_SH = 7, /* This reserves the MAX_SH_SAMPLES following values */
+ GPU_SHADER_TEXT,
+
+ /* for simple 2D drawing */
+ GPU_SHADER_2D_UNIFORM_COLOR,
+ GPU_SHADER_2D_FLAT_COLOR,
+ GPU_SHADER_2D_SMOOTH_COLOR,
+ /* for simple 3D drawing */
+ GPU_SHADER_3D_UNIFORM_COLOR,
+ GPU_SHADER_3D_FLAT_COLOR,
+ GPU_SHADER_3D_SMOOTH_COLOR,
+ GPU_SHADER_3D_DEPTH_ONLY,
+ /* basic image drawing */
+ GPU_SHADER_3D_IMAGE_MODULATE_ALPHA,
+ GPU_SHADER_3D_IMAGE_RECT_MODULATE_ALPHA,
+ /* points */
+ GPU_SHADER_2D_POINT_FIXED_SIZE_UNIFORM_COLOR,
+ GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_SMOOTH,
+ GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_SMOOTH,
+ GPU_SHADER_2D_POINT_UNIFORM_SIZE_VARYING_COLOR_OUTLINE_SMOOTH,
+ GPU_SHADER_2D_POINT_VARYING_SIZE_VARYING_COLOR,
+ GPU_SHADER_3D_POINT_FIXED_SIZE_UNIFORM_COLOR,
+ GPU_SHADER_3D_POINT_FIXED_SIZE_VARYING_COLOR,
+ GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_SMOOTH,
+ GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_SMOOTH,
+ GPU_SHADER_3D_POINT_VARYING_SIZE_UNIFORM_COLOR,
+ GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR,
+
+ GPU_SHADER_MINZ_DOWNSAMPLE,
+ GPU_SHADER_MAXZ_DOWNSAMPLE,
+ GPU_SHADER_DISPLAY_SH,
+
+ GPU_SHADER_COMPUTE_SH = 28, /* This reserves the MAX_SH_SAMPLES following values */
} GPUBuiltinShader;
#define MAX_SH_SAMPLES 10
diff --git a/source/blender/gpu/GPU_viewport.h b/source/blender/gpu/GPU_viewport.h
new file mode 100644
index 00000000000..82b537e1c3d
--- /dev/null
+++ b/source/blender/gpu/GPU_viewport.h
@@ -0,0 +1,41 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s):
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file GPU_viewport.h
+ * \ingroup gpu
+ */
+
+#ifndef __GPU_VIEWPORT_H__
+#define __GPU_VIEWPORT_H__
+
+typedef struct GPUViewport GPUViewport;
+
+GPUViewport *GPU_viewport_create(void);
+
+void GPU_viewport_free(GPUViewport *viewport);
+
+#endif // __GPU_VIEWPORT_H__
diff --git a/source/blender/gpu/gawain/attrib_binding.c b/source/blender/gpu/gawain/attrib_binding.c
new file mode 100644
index 00000000000..bb42aaf66eb
--- /dev/null
+++ b/source/blender/gpu/gawain/attrib_binding.c
@@ -0,0 +1,69 @@
+
+// Gawain vertex attribute binding
+//
+// This code is part of the Gawain library, with modifications
+// specific to integration with Blender.
+//
+// Copyright 2016 Mike Erwin
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of
+// the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+#include "attrib_binding.h"
+
+#if MAX_VERTEX_ATTRIBS != 16
+ #error "attrib binding code assumes MAX_VERTEX_ATTRIBS = 16"
+#endif
+
+void clear_AttribBinding(AttribBinding* binding)
+ {
+ binding->loc_bits = 0;
+ binding->enabled_bits = 0;
+ }
+
+unsigned read_attrib_location(const AttribBinding* binding, unsigned a_idx)
+ {
+#if TRUST_NO_ONE
+ assert(a_idx < MAX_VERTEX_ATTRIBS);
+ assert(binding->enabled_bits & (1 << a_idx));
+#endif
+
+ return (binding->loc_bits >> (4 * a_idx)) & 0xF;
+ }
+
+static void write_attrib_location(AttribBinding* binding, unsigned a_idx, unsigned location)
+ {
+#if TRUST_NO_ONE
+ assert(a_idx < MAX_VERTEX_ATTRIBS);
+ assert(location < MAX_VERTEX_ATTRIBS);
+#endif
+
+ const unsigned shift = 4 * a_idx;
+ const uint64_t mask = ((uint64_t)0xF) << shift;
+ // overwrite this attrib's previous location
+ binding->loc_bits = (binding->loc_bits & ~mask) | (location << shift);
+ // mark this attrib as enabled
+ binding->enabled_bits |= 1 << a_idx;
+ }
+
+void get_attrib_locations(const VertexFormat* format, AttribBinding* binding, GLuint program)
+ {
+#if TRUST_NO_ONE
+ assert(glIsProgram(program));
+#endif
+
+ clear_AttribBinding(binding);
+
+ for (unsigned a_idx = 0; a_idx < format->attrib_ct; ++a_idx)
+ {
+ const Attrib* a = format->attribs + a_idx;
+ GLint loc = glGetAttribLocation(program, a->name);
+
+#if TRUST_NO_ONE
+ assert(loc != -1);
+ // TODO: make this a recoverable runtime error? indicates mismatch between vertex format and program
+#endif
+
+ write_attrib_location(binding, a_idx, loc);
+ }
+ }
diff --git a/source/blender/gpu/gawain/attrib_binding.h b/source/blender/gpu/gawain/attrib_binding.h
new file mode 100644
index 00000000000..9e2431ca379
--- /dev/null
+++ b/source/blender/gpu/gawain/attrib_binding.h
@@ -0,0 +1,24 @@
+
+// Gawain vertex attribute binding
+//
+// This code is part of the Gawain library, with modifications
+// specific to integration with Blender.
+//
+// Copyright 2016 Mike Erwin
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of
+// the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+#pragma once
+
+#include "vertex_format.h"
+
+typedef struct {
+ uint64_t loc_bits; // store 4 bits for each of the 16 attribs
+ uint16_t enabled_bits; // 1 bit for each attrib
+} AttribBinding;
+
+void clear_AttribBinding(AttribBinding*);
+
+void get_attrib_locations(const VertexFormat*, AttribBinding*, GLuint program);
+unsigned read_attrib_location(const AttribBinding*, unsigned a_idx);
diff --git a/source/blender/gpu/gawain/batch.c b/source/blender/gpu/gawain/batch.c
new file mode 100644
index 00000000000..3bf353e8b2d
--- /dev/null
+++ b/source/blender/gpu/gawain/batch.c
@@ -0,0 +1,124 @@
+
+// Gawain geometry batch
+//
+// This code is part of the Gawain library, with modifications
+// specific to integration with Blender.
+//
+// Copyright 2016 Mike Erwin
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of
+// the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+#include "batch.h"
+#include <stdlib.h>
+
+Batch* Batch_create(GLenum prim_type, VertexBuffer* verts, ElementList* elem)
+ {
+#if TRUST_NO_ONE
+ assert(verts != NULL);
+ assert(prim_type == GL_POINTS || prim_type == GL_LINES || prim_type == GL_TRIANGLES);
+ // we will allow other primitive types in a future update
+#endif
+
+ Batch* batch = calloc(1, sizeof(Batch));
+
+ batch->verts = verts;
+ batch->elem = elem;
+ batch->prim_type = prim_type;
+ batch->phase = READY_TO_DRAW;
+
+ return batch;
+ }
+
+void Batch_set_program(Batch* batch, GLuint program)
+ {
+ batch->program = program;
+ batch->program_dirty = true;
+ }
+
+static void Batch_update_program_bindings(Batch* batch)
+ {
+#if TRUST_NO_ONE
+ assert(glIsProgram(batch->program));
+#endif
+
+ const VertexFormat* format = &batch->verts->format;
+
+ const unsigned attrib_ct = format->attrib_ct;
+ const unsigned stride = format->stride;
+
+ for (unsigned a_idx = 0; a_idx < attrib_ct; ++a_idx)
+ {
+ const Attrib* a = format->attribs + a_idx;
+
+ const GLvoid* pointer = (const GLubyte*)0 + a->offset;
+
+ const unsigned loc = glGetAttribLocation(batch->program, a->name);
+
+ glEnableVertexAttribArray(loc);
+
+ switch (a->fetch_mode)
+ {
+ case KEEP_FLOAT:
+ case CONVERT_INT_TO_FLOAT:
+ glVertexAttribPointer(loc, a->comp_ct, a->comp_type, GL_FALSE, stride, pointer);
+ break;
+ case NORMALIZE_INT_TO_FLOAT:
+ glVertexAttribPointer(loc, a->comp_ct, a->comp_type, GL_TRUE, stride, pointer);
+ break;
+ case KEEP_INT:
+ glVertexAttribIPointer(loc, a->comp_ct, a->comp_type, stride, pointer);
+ }
+ }
+
+ batch->program_dirty = false;
+ }
+
+static void Batch_prime(Batch* batch)
+ {
+ glGenVertexArrays(1, &batch->vao_id);
+ glBindVertexArray(batch->vao_id);
+
+ VertexBuffer_use(batch->verts);
+
+ if (batch->elem)
+ ElementList_use(batch->elem);
+
+ // vertex attribs and element list remain bound to this VAO
+ }
+
+void Batch_draw(Batch* batch)
+ {
+#if TRUST_NO_ONE
+ assert(batch->phase == READY_TO_DRAW);
+#endif
+
+ if (batch->vao_id)
+ glBindVertexArray(batch->vao_id);
+ else
+ Batch_prime(batch);
+
+ if (batch->program_dirty)
+ Batch_update_program_bindings(batch);
+
+ glUseProgram(batch->program);
+
+ if (batch->elem)
+ {
+ const ElementList* el = batch->elem;
+
+#if TRACK_INDEX_RANGE
+ if (el->base_index)
+ glDrawRangeElementsBaseVertex(batch->prim_type, el->min_index, el->max_index, el->index_ct, el->index_type, 0, el->base_index);
+ else
+ glDrawRangeElements(batch->prim_type, el->min_index, el->max_index, el->index_ct, el->index_type, 0);
+#else
+ glDrawElements(batch->prim_type, el->index_ct, GL_UNSIGNED_INT, 0);
+#endif
+ }
+ else
+ glDrawArrays(batch->prim_type, 0, batch->verts->vertex_ct);
+
+ glUseProgram(0);
+ glBindVertexArray(0);
+ }
diff --git a/source/blender/gpu/gawain/batch.h b/source/blender/gpu/gawain/batch.h
new file mode 100644
index 00000000000..8b132aa3c02
--- /dev/null
+++ b/source/blender/gpu/gawain/batch.h
@@ -0,0 +1,86 @@
+
+// Gawain geometry batch
+//
+// This code is part of the Gawain library, with modifications
+// specific to integration with Blender.
+//
+// Copyright 2016 Mike Erwin
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of
+// the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+#pragma once
+
+#include "vertex_buffer.h"
+#include "element.h"
+
+typedef enum {
+ READY_TO_FORMAT,
+ READY_TO_BUILD,
+ BUILDING,
+ READY_TO_DRAW
+} BatchPhase;
+
+typedef struct {
+ // geometry
+ VertexBuffer* verts;
+ ElementList* elem; // NULL if element list not needed
+ GLenum prim_type;
+
+ // book-keeping
+ GLuint vao_id; // remembers all geometry state (vertex attrib bindings & element buffer)
+ BatchPhase phase;
+ bool program_dirty;
+
+ // state
+ GLuint program;
+} Batch;
+
+Batch* Batch_create(GLenum prim_type, VertexBuffer*, ElementList*);
+
+// TODO: void Batch_discard(Batch*);
+// must first decide how sharing of vertex buffers & index buffers should work
+
+void Batch_set_program(Batch*, GLuint program);
+// Entire batch draws with one shader program, but can be redrawn later with another program.
+// Vertex shader's inputs must be compatible with the batch's vertex format.
+
+void Batch_draw(Batch*);
+
+
+
+
+
+
+#if 0 // future plans
+
+// Can multiple batches share a VertexBuffer? Use ref count?
+
+
+// We often need a batch with its own data, to be created and discarded together.
+// WithOwn variants reduce number of system allocations.
+
+typedef struct {
+ Batch batch;
+ VertexBuffer verts; // link batch.verts to this
+} BatchWithOwnVertexBuffer;
+
+typedef struct {
+ Batch batch;
+ ElementList elem; // link batch.elem to this
+} BatchWithOwnElementList;
+
+typedef struct {
+ Batch batch;
+ ElementList elem; // link batch.elem to this
+ VertexBuffer verts; // link batch.verts to this
+} BatchWithOwnVertexBufferAndElementList;
+
+Batch* create_BatchWithOwnVertexBuffer(GLenum prim_type, VertexFormat*, unsigned v_ct, ElementList*);
+Batch* create_BatchWithOwnElementList(GLenum prim_type, VertexBuffer*, unsigned prim_ct);
+Batch* create_BatchWithOwnVertexBufferAndElementList(GLenum prim_type, VertexFormat*, unsigned v_ct, unsigned prim_ct);
+// verts: shared, own
+// elem: none, shared, own
+Batch* create_BatchInGeneral(GLenum prim_type, VertexBufferStuff, ElementListStuff);
+
+#endif // future plans
diff --git a/source/blender/gpu/gawain/common.h b/source/blender/gpu/gawain/common.h
new file mode 100644
index 00000000000..184c907967e
--- /dev/null
+++ b/source/blender/gpu/gawain/common.h
@@ -0,0 +1,41 @@
+
+// Gawain common #defines and #includes
+//
+// This code is part of the Gawain library, with modifications
+// specific to integration with Blender.
+//
+// Copyright 2016 Mike Erwin
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of
+// the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+#pragma once
+
+#define TRUST_NO_ONE 1
+
+#include <GL/glew.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#if TRUST_NO_ONE
+ #include <assert.h>
+#endif
+
+#define PER_THREAD
+// #define PER_THREAD __thread
+// MSVC uses __declspec(thread) for C code
+
+#define APPLE_LEGACY (defined(__APPLE__) && defined(WITH_GL_PROFILE_COMPAT))
+
+#if APPLE_LEGACY
+ #undef glGenVertexArrays
+ #define glGenVertexArrays glGenVertexArraysAPPLE
+
+ #undef glDeleteVertexArrays
+ #define glDeleteVertexArrays glDeleteVertexArraysAPPLE
+
+ #undef glBindVertexArray
+ #define glBindVertexArray glBindVertexArrayAPPLE
+#endif
+
+#define PRIM_NONE 0xF
diff --git a/source/blender/gpu/gawain/element.c b/source/blender/gpu/gawain/element.c
new file mode 100644
index 00000000000..953042ba110
--- /dev/null
+++ b/source/blender/gpu/gawain/element.c
@@ -0,0 +1,262 @@
+
+// Gawain element list (AKA index buffer)
+//
+// This code is part of the Gawain library, with modifications
+// specific to integration with Blender.
+//
+// Copyright 2016 Mike Erwin
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of
+// the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+#include "element.h"
+#include <stdlib.h>
+
+#define KEEP_SINGLE_COPY 1
+
+unsigned ElementList_size(const ElementList* elem)
+ {
+#if TRACK_INDEX_RANGE
+ switch (elem->index_type)
+ {
+ case GL_UNSIGNED_BYTE: return elem->index_ct * sizeof(GLubyte);
+ case GL_UNSIGNED_SHORT: return elem->index_ct * sizeof(GLushort);
+ case GL_UNSIGNED_INT: return elem->index_ct * sizeof(GLuint);
+ default:
+ #if TRUST_NO_ONE
+ assert(false);
+ #endif
+ return 0;
+ }
+
+#else
+ return elem->index_ct * sizeof(GLuint);
+#endif
+ }
+
+static void ElementList_prime(ElementList* elem)
+ {
+ glGenBuffers(1, &elem->vbo_id);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elem->vbo_id);
+ // fill with delicious data & send to GPU the first time only
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, ElementList_size(elem), elem->data, GL_STATIC_DRAW);
+
+#if KEEP_SINGLE_COPY
+ // now that GL has a copy, discard original
+ free(elem->data);
+ elem->data = NULL;
+#endif
+ }
+
+void ElementList_use(ElementList* elem)
+ {
+ if (elem->vbo_id)
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elem->vbo_id);
+ else
+ ElementList_prime(elem);
+ }
+
+void ElementListBuilder_init(ElementListBuilder* builder, GLenum prim_type, unsigned prim_ct, unsigned vertex_ct)
+ {
+ unsigned verts_per_prim = 0;
+ switch (prim_type)
+ {
+ case GL_POINTS:
+ verts_per_prim = 1;
+ break;
+ case GL_LINES:
+ verts_per_prim = 2;
+ break;
+ case GL_TRIANGLES:
+ verts_per_prim = 3;
+ break;
+ default:
+#if TRUST_NO_ONE
+ assert(false);
+#endif
+ return;
+ }
+
+ builder->max_allowed_index = vertex_ct - 1;
+ builder->max_index_ct = prim_ct * verts_per_prim;
+ builder->index_ct = 0; // start empty
+ builder->prim_type = prim_type;
+ builder->data = calloc(builder->max_index_ct, sizeof(unsigned));
+ }
+
+void add_generic_vertex(ElementListBuilder* builder, unsigned v)
+ {
+#if TRUST_NO_ONE
+ assert(builder->data != NULL);
+ assert(builder->index_ct < builder->max_index_ct);
+ assert(v <= builder->max_allowed_index);
+#endif
+
+ builder->data[builder->index_ct++] = v;
+ }
+
+void add_point_vertex(ElementListBuilder* builder, unsigned v)
+ {
+#if TRUST_NO_ONE
+ assert(builder->prim_type == GL_POINTS);
+#endif
+
+ add_generic_vertex(builder, v);
+ }
+
+void add_line_vertices(ElementListBuilder* builder, unsigned v1, unsigned v2)
+ {
+#if TRUST_NO_ONE
+ assert(builder->prim_type == GL_LINES);
+ assert(v1 != v2);
+#endif
+
+ add_generic_vertex(builder, v1);
+ add_generic_vertex(builder, v2);
+ }
+
+void add_triangle_vertices(ElementListBuilder* builder, unsigned v1, unsigned v2, unsigned v3)
+ {
+#if TRUST_NO_ONE
+ assert(builder->prim_type == GL_TRIANGLES);
+ assert(v1 != v2 && v2 != v3 && v3 != v1);
+#endif
+
+ add_generic_vertex(builder, v1);
+ add_generic_vertex(builder, v2);
+ add_generic_vertex(builder, v3);
+ }
+
+#if TRACK_INDEX_RANGE
+// Everything remains 32 bit while building to keep things simple.
+// Find min/max after, then convert to smallest index type possible.
+
+static unsigned index_range(const unsigned values[], unsigned value_ct, unsigned* min_out, unsigned* max_out)
+ {
+ unsigned min_value = values[0];
+ unsigned max_value = values[0];
+ for (unsigned i = 1; i < value_ct; ++i)
+ {
+ const unsigned value = values[i];
+ if (value < min_value)
+ min_value = value;
+ else if (value > max_value)
+ max_value = value;
+ }
+ *min_out = min_value;
+ *max_out = max_value;
+ return max_value - min_value;
+ }
+
+static void squeeze_indices_byte(const unsigned values[], ElementList* elem)
+ {
+ const unsigned index_ct = elem->index_ct;
+ GLubyte* data = malloc(index_ct * sizeof(GLubyte));
+
+ if (elem->max_index > 0xFF)
+ {
+ const unsigned base = elem->min_index;
+
+ elem->base_index = base;
+ elem->min_index = 0;
+ elem->max_index -= base;
+
+ for (unsigned i = 0; i < index_ct; ++i)
+ data[i] = (GLubyte)(values[i] - base);
+ }
+ else
+ {
+ elem->base_index = 0;
+
+ for (unsigned i = 0; i < index_ct; ++i)
+ data[i] = (GLubyte)(values[i]);
+ }
+
+ elem->data = data;
+ }
+
+static void squeeze_indices_short(const unsigned values[], ElementList* elem)
+ {
+ const unsigned index_ct = elem->index_ct;
+ GLushort* data = malloc(index_ct * sizeof(GLushort));
+
+ if (elem->max_index > 0xFFFF)
+ {
+ const unsigned base = elem->min_index;
+
+ elem->base_index = base;
+ elem->min_index = 0;
+ elem->max_index -= base;
+
+ for (unsigned i = 0; i < index_ct; ++i)
+ data[i] = (GLushort)(values[i] - base);
+ }
+ else
+ {
+ elem->base_index = 0;
+
+ for (unsigned i = 0; i < index_ct; ++i)
+ data[i] = (GLushort)(values[i]);
+ }
+
+ elem->data = data;
+ }
+
+#endif // TRACK_INDEX_RANGE
+
+void ElementList_build(ElementListBuilder* builder, ElementList* elem)
+ {
+#if TRUST_NO_ONE
+ assert(builder->data != NULL);
+#endif
+
+ elem->index_ct = builder->index_ct;
+
+#if TRACK_INDEX_RANGE
+ const unsigned range = index_range(builder->data, builder->index_ct, &elem->min_index, &elem->max_index);
+
+ if (range <= 0xFF)
+ {
+ elem->index_type = GL_UNSIGNED_BYTE;
+ squeeze_indices_byte(builder->data, elem);
+ }
+ else if (range <= 0xFFFF)
+ {
+ elem->index_type = GL_UNSIGNED_SHORT;
+ squeeze_indices_short(builder->data, elem);
+ }
+ else
+ {
+ elem->index_type = GL_UNSIGNED_INT;
+ elem->base_index = 0;
+
+ if (builder->index_ct < builder->max_index_ct)
+ {
+ builder->data = realloc(builder->data, builder->index_ct * sizeof(unsigned));
+ // TODO: realloc only if index_ct is much smaller than max_index_ct
+ }
+
+ elem->data = builder->data;
+ }
+#else
+ if (builder->index_ct < builder->max_index_ct)
+ {
+ builder->data = realloc(builder->data, builder->index_ct * sizeof(unsigned));
+ // TODO: realloc only if index_ct is much smaller than max_index_ct
+ }
+
+ elem->data = builder->data;
+#endif
+
+ // elem->data will never be *larger* than builder->data... how about converting
+ // in place to avoid extra allocation?
+
+ elem->vbo_id = 0;
+ // TODO: create GL buffer object directly, based on an input flag
+
+ // discard builder (one-time use)
+ if (builder->data != elem->data)
+ free(builder->data);
+ builder->data = NULL;
+ // other fields are safe to leave
+ }
diff --git a/source/blender/gpu/gawain/element.h b/source/blender/gpu/gawain/element.h
new file mode 100644
index 00000000000..9ba2ed2a5b1
--- /dev/null
+++ b/source/blender/gpu/gawain/element.h
@@ -0,0 +1,55 @@
+
+// Gawain element list (AKA index buffer)
+//
+// This code is part of the Gawain library, with modifications
+// specific to integration with Blender.
+//
+// Copyright 2016 Mike Erwin
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of
+// the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+#pragma once
+
+#include "common.h"
+
+#define TRACK_INDEX_RANGE 1
+
+typedef struct {
+ unsigned index_ct;
+#if TRACK_INDEX_RANGE
+ GLenum index_type;
+ unsigned min_index;
+ unsigned max_index;
+ unsigned base_index;
+#endif
+ void* data; // NULL indicates data in VRAM (unmapped) or not yet allocated
+ GLuint vbo_id; // 0 indicates not yet sent to VRAM
+} ElementList;
+
+void ElementList_use(ElementList*);
+unsigned ElementList_size(const ElementList*);
+
+typedef struct {
+ unsigned max_allowed_index;
+ unsigned max_index_ct;
+ unsigned index_ct;
+ GLenum prim_type;
+ unsigned* data;
+} ElementListBuilder;
+
+// supported primitives:
+// GL_POINTS
+// GL_LINES
+// GL_TRIANGLES
+
+void ElementListBuilder_init(ElementListBuilder*, GLenum prim_type, unsigned prim_ct, unsigned vertex_ct);
+//void ElementListBuilder_init_custom(ElementListBuilder*, GLenum prim_type, unsigned index_ct, unsigned vertex_ct);
+
+void add_generic_vertex(ElementListBuilder*, unsigned v);
+
+void add_point_vertex(ElementListBuilder*, unsigned v);
+void add_line_vertices(ElementListBuilder*, unsigned v1, unsigned v2);
+void add_triangle_vertices(ElementListBuilder*, unsigned v1, unsigned v2, unsigned v3);
+
+void ElementList_build(ElementListBuilder*, ElementList*);
diff --git a/source/blender/gpu/gawain/imm_util.c b/source/blender/gpu/gawain/imm_util.c
new file mode 100644
index 00000000000..0f253fec08b
--- /dev/null
+++ b/source/blender/gpu/gawain/imm_util.c
@@ -0,0 +1,46 @@
+
+// Gawain immediate mode drawing utilities
+//
+// This code is part of the Gawain library, with modifications
+// specific to integration with Blender.
+//
+// Copyright 2016 Mike Erwin
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of
+// the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+#include "imm_util.h"
+#include "immediate.h"
+
+
+void immRectf(unsigned pos, float x1, float y1, float x2, float y2)
+{
+ immBegin(GL_TRIANGLE_FAN, 4);
+ immVertex2f(pos, x1, y1);
+ immVertex2f(pos, x2, y1);
+ immVertex2f(pos, x2, y2);
+ immVertex2f(pos, x1, y2);
+ immEnd();
+}
+
+void immRecti(unsigned pos, int x1, int y1, int x2, int y2)
+{
+ immBegin(GL_TRIANGLE_FAN, 4);
+ immVertex2i(pos, x1, y1);
+ immVertex2i(pos, x2, y1);
+ immVertex2i(pos, x2, y2);
+ immVertex2i(pos, x1, y2);
+ immEnd();
+}
+
+#if 0 // more complete version in case we want that
+void immRecti_complete(int x1, int y1, int x2, int y2, const float color[4])
+{
+ VertexFormat *format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_INT, 2, CONVERT_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4fv(color);
+ immRecti(pos, x1, y1, x2, y2);
+ immUnbindProgram();
+}
+#endif
diff --git a/source/blender/gpu/gawain/imm_util.h b/source/blender/gpu/gawain/imm_util.h
new file mode 100644
index 00000000000..730bd7c1a3c
--- /dev/null
+++ b/source/blender/gpu/gawain/imm_util.h
@@ -0,0 +1,18 @@
+
+// Gawain immediate mode drawing utilities
+//
+// This code is part of the Gawain library, with modifications
+// specific to integration with Blender.
+//
+// Copyright 2016 Mike Erwin
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of
+// the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+#pragma once
+
+
+// Draw 2D rectangles (replaces glRect functions)
+// caller is reponsible for vertex format & shader
+void immRectf(unsigned pos, float x1, float y1, float x2, float y2);
+void immRecti(unsigned pos, int x1, int y1, int x2, int y2);
diff --git a/source/blender/gpu/gawain/immediate.c b/source/blender/gpu/gawain/immediate.c
new file mode 100644
index 00000000000..30c82fd2710
--- /dev/null
+++ b/source/blender/gpu/gawain/immediate.c
@@ -0,0 +1,776 @@
+
+// Gawain immediate mode work-alike
+//
+// This code is part of the Gawain library, with modifications
+// specific to integration with Blender.
+//
+// Copyright 2016 Mike Erwin
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of
+// the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+#include "immediate.h"
+#include "attrib_binding.h"
+#include <string.h>
+
+typedef struct {
+ // TODO: organize this struct by frequency of change (run-time)
+
+#if IMM_BATCH_COMBO
+ Batch* batch;
+#endif
+
+ // current draw call
+ GLubyte* buffer_data;
+ unsigned buffer_offset;
+ unsigned buffer_bytes_mapped;
+ unsigned vertex_ct;
+ bool strict_vertex_ct;
+ GLenum primitive;
+
+ VertexFormat vertex_format;
+
+ // current vertex
+ unsigned vertex_idx;
+ GLubyte* vertex_data;
+ uint16_t unassigned_attrib_bits; // which attributes of current vertex have not been given values?
+
+ GLuint vbo_id;
+ GLuint vao_id;
+
+ GLuint bound_program;
+ AttribBinding attrib_binding;
+ uint16_t prev_enabled_attrib_bits; // <-- only affects this VAO, so we're ok
+} Immediate;
+
+// size of internal buffer -- make this adjustable?
+#define IMM_BUFFER_SIZE (4 * 1024 * 1024)
+
+static PER_THREAD bool initialized = false;
+static PER_THREAD Immediate imm;
+
+void immInit()
+ {
+#if TRUST_NO_ONE
+ assert(!initialized);
+#endif
+
+ memset(&imm, 0, sizeof(Immediate));
+
+ glGenBuffers(1, &imm.vbo_id);
+ glBindBuffer(GL_ARRAY_BUFFER, imm.vbo_id);
+ glBufferData(GL_ARRAY_BUFFER, IMM_BUFFER_SIZE, NULL, GL_DYNAMIC_DRAW);
+
+#if APPLE_LEGACY
+ glBufferParameteriAPPLE(GL_ARRAY_BUFFER, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_FALSE);
+ glBufferParameteriAPPLE(GL_ARRAY_BUFFER, GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE);
+#endif
+
+ imm.primitive = PRIM_NONE;
+ imm.strict_vertex_ct = true;
+
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ initialized = true;
+
+ immActivate();
+ }
+
+void immActivate()
+ {
+#if TRUST_NO_ONE
+ assert(initialized);
+ assert(imm.primitive == PRIM_NONE); // make sure we're not between a Begin/End pair
+ assert(imm.vao_id == 0);
+#endif
+
+ glGenVertexArrays(1, &imm.vao_id);
+ }
+
+void immDeactivate()
+ {
+#if TRUST_NO_ONE
+ assert(initialized);
+ assert(imm.primitive == PRIM_NONE); // make sure we're not between a Begin/End pair
+ assert(imm.vao_id != 0);
+#endif
+
+ glDeleteVertexArrays(1, &imm.vao_id);
+ imm.vao_id = 0;
+ imm.prev_enabled_attrib_bits = 0;
+ }
+
+void immDestroy()
+ {
+ immDeactivate();
+ glDeleteBuffers(1, &imm.vbo_id);
+ initialized = false;
+ }
+
+VertexFormat* immVertexFormat()
+ {
+ VertexFormat_clear(&imm.vertex_format);
+ return &imm.vertex_format;
+ }
+
+void immBindProgram(GLuint program)
+ {
+#if TRUST_NO_ONE
+ assert(imm.bound_program == 0);
+#endif
+
+ if (!imm.vertex_format.packed)
+ VertexFormat_pack(&imm.vertex_format);
+
+ glUseProgram(program);
+ get_attrib_locations(&imm.vertex_format, &imm.attrib_binding, program);
+ imm.bound_program = program;
+ }
+
+void immUnbindProgram()
+ {
+#if TRUST_NO_ONE
+ assert(imm.bound_program != 0);
+#endif
+
+ glUseProgram(0);
+ imm.bound_program = 0;
+ }
+
+static bool vertex_count_makes_sense_for_primitive(unsigned vertex_ct, GLenum primitive)
+ {
+ // does vertex_ct make sense for this primitive type?
+ if (vertex_ct == 0)
+ return false;
+
+ switch (primitive)
+ {
+ case GL_POINTS:
+ return true;
+ case GL_LINES:
+ return vertex_ct % 2 == 0;
+ case GL_LINE_STRIP:
+ case GL_LINE_LOOP:
+ return vertex_ct >= 2;
+ case GL_TRIANGLES:
+ return vertex_ct % 3 == 0;
+ case GL_TRIANGLE_STRIP:
+ case GL_TRIANGLE_FAN:
+ return vertex_ct >= 3;
+ #ifdef WITH_GL_PROFILE_COMPAT
+ case GL_QUADS:
+ return vertex_ct % 4 == 0;
+ #endif
+ default:
+ return false;
+ }
+ }
+
+void immBegin(GLenum primitive, unsigned vertex_ct)
+ {
+#if TRUST_NO_ONE
+ assert(initialized);
+ assert(imm.primitive == PRIM_NONE); // make sure we haven't already begun
+ assert(vertex_count_makes_sense_for_primitive(vertex_ct, primitive));
+#endif
+
+ imm.primitive = primitive;
+ imm.vertex_ct = vertex_ct;
+ imm.vertex_idx = 0;
+ imm.unassigned_attrib_bits = imm.attrib_binding.enabled_bits;
+
+ // how many bytes do we need for this draw call?
+ const unsigned bytes_needed = vertex_buffer_size(&imm.vertex_format, vertex_ct);
+
+#if TRUST_NO_ONE
+ assert(bytes_needed <= IMM_BUFFER_SIZE);
+#endif
+
+ glBindBuffer(GL_ARRAY_BUFFER, imm.vbo_id);
+
+ // does the current buffer have enough room?
+ const unsigned available_bytes = IMM_BUFFER_SIZE - imm.buffer_offset;
+ // ensure vertex data is aligned
+ const unsigned pre_padding = padding(imm.buffer_offset, imm.vertex_format.stride); // might waste a little space, but it's safe
+ if ((bytes_needed + pre_padding) <= available_bytes)
+ imm.buffer_offset += pre_padding;
+ else
+ {
+ // orphan this buffer & start with a fresh one
+#if APPLE_LEGACY
+ glBufferData(GL_ARRAY_BUFFER, IMM_BUFFER_SIZE, NULL, GL_DYNAMIC_DRAW);
+#else
+ if (GLEW_VERSION_4_3 || GLEW_ARB_invalidate_subdata)
+ glInvalidateBufferData(imm.vbo_id);
+ else
+ glMapBufferRange(GL_ARRAY_BUFFER, 0, IMM_BUFFER_SIZE, GL_MAP_INVALIDATE_BUFFER_BIT);
+#endif
+
+ imm.buffer_offset = 0;
+ }
+
+// printf("mapping %u to %u\n", imm.buffer_offset, imm.buffer_offset + bytes_needed - 1);
+
+#if APPLE_LEGACY
+ imm.buffer_data = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY) + imm.buffer_offset;
+#else
+ imm.buffer_data = glMapBufferRange(GL_ARRAY_BUFFER, imm.buffer_offset, bytes_needed,
+ GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | (imm.strict_vertex_ct ? 0 : GL_MAP_FLUSH_EXPLICIT_BIT));
+#endif
+
+#if TRUST_NO_ONE
+ assert(imm.buffer_data != NULL);
+#endif
+
+ imm.buffer_bytes_mapped = bytes_needed;
+ imm.vertex_data = imm.buffer_data;
+ }
+
+void immBeginAtMost(GLenum primitive, unsigned vertex_ct)
+ {
+#if TRUST_NO_ONE
+ assert(vertex_ct > 0);
+#endif
+
+ imm.strict_vertex_ct = false;
+ immBegin(primitive, vertex_ct);
+ }
+
+#if IMM_BATCH_COMBO
+
+Batch* immBeginBatch(GLenum prim_type, unsigned vertex_ct)
+ {
+#if TRUST_NO_ONE
+ assert(initialized);
+ assert(imm.primitive == PRIM_NONE); // make sure we haven't already begun
+ assert(vertex_count_makes_sense_for_primitive(vertex_ct, prim_type));
+#endif
+
+ imm.primitive = prim_type;
+ imm.vertex_ct = vertex_ct;
+ imm.vertex_idx = 0;
+ imm.unassigned_attrib_bits = imm.attrib_binding.enabled_bits;
+
+ VertexBuffer* verts = VertexBuffer_create_with_format(&imm.vertex_format);
+ VertexBuffer_allocate_data(verts, vertex_ct);
+
+ imm.buffer_bytes_mapped = VertexBuffer_size(verts);
+ imm.vertex_data = verts->data;
+
+ imm.batch = Batch_create(prim_type, verts, NULL);
+ imm.batch->phase = BUILDING;
+
+ Batch_set_program(imm.batch, imm.bound_program);
+
+ return imm.batch;
+ }
+
+Batch* immBeginBatchAtMost(GLenum prim_type, unsigned vertex_ct)
+ {
+ imm.strict_vertex_ct = false;
+ return immBeginBatch(prim_type, vertex_ct);
+ }
+
+#endif // IMM_BATCH_COMBO
+
+static void immDrawSetup(void)
+ {
+ // set up VAO -- can be done during Begin or End really
+ glBindVertexArray(imm.vao_id);
+
+ // enable/disable vertex attribs as needed
+ if (imm.attrib_binding.enabled_bits != imm.prev_enabled_attrib_bits)
+ {
+ for (unsigned loc = 0; loc < MAX_VERTEX_ATTRIBS; ++loc)
+ {
+ bool is_enabled = imm.attrib_binding.enabled_bits & (1 << loc);
+ bool was_enabled = imm.prev_enabled_attrib_bits & (1 << loc);
+
+ if (is_enabled && !was_enabled)
+ {
+// printf("enabling attrib %u\n", loc);
+ glEnableVertexAttribArray(loc);
+ }
+ else if (was_enabled && !is_enabled)
+ {
+// printf("disabling attrib %u\n", loc);
+ glDisableVertexAttribArray(loc);
+ }
+ }
+
+ imm.prev_enabled_attrib_bits = imm.attrib_binding.enabled_bits;
+ }
+
+ const unsigned stride = imm.vertex_format.stride;
+
+ for (unsigned a_idx = 0; a_idx < imm.vertex_format.attrib_ct; ++a_idx)
+ {
+ const Attrib* a = imm.vertex_format.attribs + a_idx;
+
+ const unsigned offset = imm.buffer_offset + a->offset;
+ const GLvoid* pointer = (const GLubyte*)0 + offset;
+
+ const unsigned loc = read_attrib_location(&imm.attrib_binding, a_idx);
+
+// printf("specifying attrib %u '%s' with offset %u, stride %u\n", loc, a->name, offset, stride);
+
+ switch (a->fetch_mode)
+ {
+ case KEEP_FLOAT:
+ case CONVERT_INT_TO_FLOAT:
+ glVertexAttribPointer(loc, a->comp_ct, a->comp_type, GL_FALSE, stride, pointer);
+ break;
+ case NORMALIZE_INT_TO_FLOAT:
+ glVertexAttribPointer(loc, a->comp_ct, a->comp_type, GL_TRUE, stride, pointer);
+ break;
+ case KEEP_INT:
+ glVertexAttribIPointer(loc, a->comp_ct, a->comp_type, stride, pointer);
+ }
+ }
+ }
+
+void immEnd()
+ {
+#if TRUST_NO_ONE
+ assert(imm.primitive != PRIM_NONE); // make sure we're between a Begin/End pair
+#endif
+
+ unsigned buffer_bytes_used;
+ if (imm.strict_vertex_ct)
+ {
+#if TRUST_NO_ONE
+ assert(imm.vertex_idx == imm.vertex_ct); // with all vertices defined
+#endif
+ buffer_bytes_used = imm.buffer_bytes_mapped;
+ }
+ else
+ {
+#if TRUST_NO_ONE
+ assert(imm.vertex_idx <= imm.vertex_ct);
+#endif
+ // printf("used %u of %u verts,", imm.vertex_idx, imm.vertex_ct);
+ if (imm.vertex_idx == imm.vertex_ct)
+ {
+ buffer_bytes_used = imm.buffer_bytes_mapped;
+ }
+ else
+ {
+#if TRUST_NO_ONE
+ assert(imm.vertex_idx == 0 || vertex_count_makes_sense_for_primitive(imm.vertex_idx, imm.primitive));
+#endif
+ imm.vertex_ct = imm.vertex_idx;
+ buffer_bytes_used = vertex_buffer_size(&imm.vertex_format, imm.vertex_ct);
+ // unused buffer bytes are available to the next immBegin
+ // printf(" %u of %u bytes\n", buffer_bytes_used, imm.buffer_bytes_mapped);
+ }
+#if !APPLE_LEGACY
+ // tell OpenGL what range was modified so it doesn't copy the whole mapped range
+ // printf("flushing %u to %u\n", imm.buffer_offset, imm.buffer_offset + buffer_bytes_used - 1);
+ glFlushMappedBufferRange(GL_ARRAY_BUFFER, 0, buffer_bytes_used);
+#endif
+ }
+
+#if IMM_BATCH_COMBO
+ if (imm.batch)
+ {
+ if (buffer_bytes_used != imm.buffer_bytes_mapped)
+ {
+ VertexBuffer_resize_data(imm.batch->verts, imm.vertex_ct);
+ // TODO: resize only if vertex count is much smaller
+ }
+
+ imm.batch->phase = READY_TO_DRAW;
+ imm.batch = NULL; // don't free, batch belongs to caller
+ }
+ else
+#endif
+ {
+#if APPLE_LEGACY
+ // tell OpenGL what range was modified so it doesn't copy the whole buffer
+ // printf("flushing %u to %u\n", imm.buffer_offset, imm.buffer_offset + buffer_bytes_used - 1);
+ glFlushMappedBufferRangeAPPLE(GL_ARRAY_BUFFER, imm.buffer_offset, buffer_bytes_used);
+#endif
+ glUnmapBuffer(GL_ARRAY_BUFFER);
+
+ if (imm.vertex_ct > 0)
+ {
+ immDrawSetup();
+ glDrawArrays(imm.primitive, 0, imm.vertex_ct);
+ }
+
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ glBindVertexArray(0);
+
+ // prep for next immBegin
+ imm.buffer_offset += buffer_bytes_used;
+ }
+
+ // prep for next immBegin
+ imm.primitive = PRIM_NONE;
+ imm.strict_vertex_ct = true;
+ }
+
+static void setAttribValueBit(unsigned attrib_id)
+ {
+ uint16_t mask = 1 << attrib_id;
+
+#if TRUST_NO_ONE
+ assert(imm.unassigned_attrib_bits & mask); // not already set
+#endif
+
+ imm.unassigned_attrib_bits &= ~mask;
+ }
+
+
+// --- generic attribute functions ---
+
+void immAttrib1f(unsigned attrib_id, float x)
+ {
+ Attrib* attrib = imm.vertex_format.attribs + attrib_id;
+
+#if TRUST_NO_ONE
+ assert(attrib_id < imm.vertex_format.attrib_ct);
+ assert(attrib->comp_type == GL_FLOAT);
+ assert(attrib->comp_ct == 1);
+ assert(imm.vertex_idx < imm.vertex_ct);
+ assert(imm.primitive != PRIM_NONE); // make sure we're between a Begin/End pair
+#endif
+
+ setAttribValueBit(attrib_id);
+
+ float* data = (float*)(imm.vertex_data + attrib->offset);
+// printf("%s %td %p\n", __FUNCTION__, (GLubyte*)data - imm.buffer_data, data);
+
+ data[0] = x;
+ }
+
+void immAttrib2f(unsigned attrib_id, float x, float y)
+ {
+ Attrib* attrib = imm.vertex_format.attribs + attrib_id;
+
+#if TRUST_NO_ONE
+ assert(attrib_id < imm.vertex_format.attrib_ct);
+ assert(attrib->comp_type == GL_FLOAT);
+ assert(attrib->comp_ct == 2);
+ assert(imm.vertex_idx < imm.vertex_ct);
+ assert(imm.primitive != PRIM_NONE); // make sure we're between a Begin/End pair
+#endif
+
+ setAttribValueBit(attrib_id);
+
+ float* data = (float*)(imm.vertex_data + attrib->offset);
+// printf("%s %td %p\n", __FUNCTION__, (GLubyte*)data - imm.buffer_data, data);
+
+ data[0] = x;
+ data[1] = y;
+ }
+
+void immAttrib3f(unsigned attrib_id, float x, float y, float z)
+ {
+ Attrib* attrib = imm.vertex_format.attribs + attrib_id;
+
+#if TRUST_NO_ONE
+ assert(attrib_id < imm.vertex_format.attrib_ct);
+ assert(attrib->comp_type == GL_FLOAT);
+ assert(attrib->comp_ct == 3);
+ assert(imm.vertex_idx < imm.vertex_ct);
+ assert(imm.primitive != PRIM_NONE); // make sure we're between a Begin/End pair
+#endif
+
+ setAttribValueBit(attrib_id);
+
+ float* data = (float*)(imm.vertex_data + attrib->offset);
+// printf("%s %td %p\n", __FUNCTION__, (GLubyte*)data - imm.buffer_data, data);
+
+ data[0] = x;
+ data[1] = y;
+ data[2] = z;
+ }
+
+void immAttrib4f(unsigned attrib_id, float x, float y, float z, float w)
+ {
+ Attrib* attrib = imm.vertex_format.attribs + attrib_id;
+
+#if TRUST_NO_ONE
+ assert(attrib_id < imm.vertex_format.attrib_ct);
+ assert(attrib->comp_type == GL_FLOAT);
+ assert(attrib->comp_ct == 4);
+ assert(imm.vertex_idx < imm.vertex_ct);
+ assert(imm.primitive != PRIM_NONE); // make sure we're between a Begin/End pair
+#endif
+
+ setAttribValueBit(attrib_id);
+
+ float* data = (float*)(imm.vertex_data + attrib->offset);
+// printf("%s %td %p\n", __FUNCTION__, (GLubyte*)data - imm.buffer_data, data);
+
+ data[0] = x;
+ data[1] = y;
+ data[2] = z;
+ data[3] = w;
+ }
+
+void immAttrib2i(unsigned attrib_id, int x, int y)
+ {
+ Attrib* attrib = imm.vertex_format.attribs + attrib_id;
+
+#if TRUST_NO_ONE
+ assert(attrib_id < imm.vertex_format.attrib_ct);
+ assert(attrib->comp_type == GL_INT);
+ assert(attrib->comp_ct == 2);
+ assert(imm.vertex_idx < imm.vertex_ct);
+ assert(imm.primitive != PRIM_NONE); // make sure we're between a Begin/End pair
+#endif
+
+ setAttribValueBit(attrib_id);
+
+ int* data = (int*)(imm.vertex_data + attrib->offset);
+
+ data[0] = x;
+ data[1] = y;
+ }
+
+void immAttrib3fv(unsigned attrib_id, const float data[3])
+ {
+ immAttrib3f(attrib_id, data[0], data[1], data[2]);
+ }
+
+void immAttrib4fv(unsigned attrib_id, const float data[4])
+ {
+ immAttrib4f(attrib_id, data[0], data[1], data[2], data[3]);
+ }
+
+void immAttrib3ub(unsigned attrib_id, unsigned char r, unsigned char g, unsigned char b)
+ {
+ Attrib* attrib = imm.vertex_format.attribs + attrib_id;
+
+#if TRUST_NO_ONE
+ assert(attrib_id < imm.vertex_format.attrib_ct);
+ assert(attrib->comp_type == GL_UNSIGNED_BYTE);
+ assert(attrib->comp_ct == 3);
+ assert(imm.vertex_idx < imm.vertex_ct);
+ assert(imm.primitive != PRIM_NONE); // make sure we're between a Begin/End pair
+#endif
+
+ setAttribValueBit(attrib_id);
+
+ GLubyte* data = imm.vertex_data + attrib->offset;
+// printf("%s %td %p\n", __FUNCTION__, data - imm.buffer_data, data);
+
+ data[0] = r;
+ data[1] = g;
+ data[2] = b;
+ }
+
+void immAttrib4ub(unsigned attrib_id, unsigned char r, unsigned char g, unsigned char b, unsigned char a)
+ {
+ Attrib* attrib = imm.vertex_format.attribs + attrib_id;
+
+#if TRUST_NO_ONE
+ assert(attrib_id < imm.vertex_format.attrib_ct);
+ assert(attrib->comp_type == GL_UNSIGNED_BYTE);
+ assert(attrib->comp_ct == 4);
+ assert(imm.vertex_idx < imm.vertex_ct);
+ assert(imm.primitive != PRIM_NONE); // make sure we're between a Begin/End pair
+#endif
+
+ setAttribValueBit(attrib_id);
+
+ GLubyte* data = imm.vertex_data + attrib->offset;
+// printf("%s %td %p\n", __FUNCTION__, data - imm.buffer_data, data);
+
+ data[0] = r;
+ data[1] = g;
+ data[2] = b;
+ data[3] = a;
+ }
+
+void immAttrib3ubv(unsigned attrib_id, const unsigned char data[3])
+ {
+ immAttrib3ub(attrib_id, data[0], data[1], data[2]);
+ }
+
+void immAttrib4ubv(unsigned attrib_id, const unsigned char data[4])
+ {
+ immAttrib4ub(attrib_id, data[0], data[1], data[2], data[3]);
+ }
+
+void immSkipAttrib(unsigned attrib_id)
+ {
+#if TRUST_NO_ONE
+ assert(attrib_id < imm.vertex_format.attrib_ct);
+ assert(imm.vertex_idx < imm.vertex_ct);
+ assert(imm.primitive != PRIM_NONE); // make sure we're between a Begin/End pair
+#endif
+
+ setAttribValueBit(attrib_id);
+ }
+
+static void immEndVertex(void) // and move on to the next vertex
+ {
+#if TRUST_NO_ONE
+ assert(imm.primitive != PRIM_NONE); // make sure we're between a Begin/End pair
+ assert(imm.vertex_idx < imm.vertex_ct);
+#endif
+
+ // have all attribs been assigned values?
+ // if not, copy value from previous vertex
+ if (imm.unassigned_attrib_bits)
+ {
+#if TRUST_NO_ONE
+ assert(imm.vertex_idx > 0); // first vertex must have all attribs specified
+#endif
+
+ for (unsigned a_idx = 0; a_idx < imm.vertex_format.attrib_ct; ++a_idx)
+ {
+ if ((imm.unassigned_attrib_bits >> a_idx) & 1)
+ {
+ const Attrib* a = imm.vertex_format.attribs + a_idx;
+
+// printf("copying %s from vertex %u to %u\n", a->name, imm.vertex_idx - 1, imm.vertex_idx);
+
+ GLubyte* data = imm.vertex_data + a->offset;
+ memcpy(data, data - imm.vertex_format.stride, a->sz);
+ // TODO: consolidate copy of adjacent attributes
+ }
+ }
+ }
+
+ imm.vertex_idx++;
+ imm.vertex_data += imm.vertex_format.stride;
+ imm.unassigned_attrib_bits = imm.attrib_binding.enabled_bits;
+ }
+
+void immVertex2f(unsigned attrib_id, float x, float y)
+ {
+ immAttrib2f(attrib_id, x, y);
+ immEndVertex();
+ }
+
+void immVertex3f(unsigned attrib_id, float x, float y, float z)
+ {
+ immAttrib3f(attrib_id, x, y, z);
+ immEndVertex();
+ }
+
+void immVertex2i(unsigned attrib_id, int x, int y)
+ {
+ immAttrib2i(attrib_id, x, y);
+ immEndVertex();
+ }
+
+void immVertex2fv(unsigned attrib_id, const float data[2])
+ {
+ immAttrib2f(attrib_id, data[0], data[1]);
+ immEndVertex();
+ }
+
+void immVertex3fv(unsigned attrib_id, const float data[3])
+ {
+ immAttrib3f(attrib_id, data[0], data[1], data[2]);
+ immEndVertex();
+ }
+
+void immVertex2iv(unsigned attrib_id, const int data[2])
+ {
+ immAttrib2i(attrib_id, data[0], data[1]);
+ immEndVertex();
+ }
+
+
+// --- generic uniform functions ---
+
+void immUniform1f(const char* name, float x)
+ {
+ int loc = glGetUniformLocation(imm.bound_program, name);
+
+#if TRUST_NO_ONE
+ assert(loc != -1);
+#endif
+
+ glUniform1f(loc, x);
+ }
+
+void immUniform4f(const char* name, float x, float y, float z, float w)
+ {
+ int loc = glGetUniformLocation(imm.bound_program, name);
+
+#if TRUST_NO_ONE
+ assert(loc != -1);
+#endif
+
+ glUniform4f(loc, x, y, z, w);
+ }
+
+void immUniform4fv(const char* name, const float data[4])
+ {
+ int loc = glGetUniformLocation(imm.bound_program, name);
+
+#if TRUST_NO_ONE
+ assert(loc != -1);
+#endif
+
+ glUniform4fv(loc, 1, data);
+ }
+
+void immUniform1i(const char* name, int x)
+ {
+ int loc = glGetUniformLocation(imm.bound_program, name);
+
+#if TRUST_NO_ONE
+ assert(loc != -1);
+#endif
+
+ glUniform1i(loc, x);
+ }
+
+
+// --- convenience functions for setting "uniform vec4 color" ---
+
+void immUniformColor4f(float r, float g, float b, float a)
+ {
+ immUniform4f("color", r, g, b, a);
+ }
+
+void immUniformColor4fv(const float rgba[4])
+ {
+ immUniform4fv("color", rgba);
+ }
+
+void immUniformColor3f(float r, float g, float b)
+ {
+ immUniform4f("color", r, g, b, 1.0f);
+ }
+
+void immUniformColor3fv(const float rgb[3])
+ {
+ immUniform4f("color", rgb[0], rgb[1], rgb[2], 1.0f);
+ }
+
+void immUniformColor3fvAlpha(const float rgb[3], float a)
+ {
+ immUniform4f("color", rgb[0], rgb[1], rgb[2], a);
+ }
+
+// TODO: v-- treat as sRGB? --v
+
+void immUniformColor3ub(unsigned char r, unsigned char g, unsigned char b)
+ {
+ const float scale = 1.0f / 255.0f;
+ immUniform4f("color", scale * r, scale * g, scale * b, 1.0f);
+ }
+
+void immUniformColor4ub(unsigned char r, unsigned char g, unsigned char b, unsigned char a)
+ {
+ const float scale = 1.0f / 255.0f;
+ immUniform4f("color", scale * r, scale * g, scale * b, scale * a);
+ }
+
+void immUniformColor3ubv(const unsigned char rgb[3])
+ {
+ immUniformColor3ub(rgb[0], rgb[1], rgb[2]);
+ }
+
+void immUniformColor4ubv(const unsigned char rgba[4])
+ {
+ immUniformColor4ub(rgba[0], rgba[1], rgba[2], rgba[3]);
+ }
diff --git a/source/blender/gpu/gawain/immediate.h b/source/blender/gpu/gawain/immediate.h
new file mode 100644
index 00000000000..ccf7ebe9400
--- /dev/null
+++ b/source/blender/gpu/gawain/immediate.h
@@ -0,0 +1,101 @@
+
+// Gawain immediate mode work-alike
+//
+// This code is part of the Gawain library, with modifications
+// specific to integration with Blender.
+//
+// Copyright 2016 Mike Erwin
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of
+// the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+#pragma once
+
+#include "vertex_format.h"
+
+#define IMM_BATCH_COMBO 1
+
+
+VertexFormat* immVertexFormat(void); // returns a cleared vertex format, ready for add_attrib
+
+void immBindProgram(GLuint program); // every immBegin must have a program bound first
+void immUnbindProgram(void); // call after your last immEnd, or before binding another program
+
+void immBegin(GLenum primitive, unsigned vertex_ct); // must supply exactly vertex_ct vertices
+void immBeginAtMost(GLenum primitive, unsigned max_vertex_ct); // can supply fewer vertices
+void immEnd(void); // finishes and draws
+
+#if IMM_BATCH_COMBO
+#include "batch.h"
+// immBegin a batch, then use standard immFunctions as usual.
+// immEnd will finalize the batch instead of drawing.
+// Then you can draw it as many times as you like! Partially replaces the need for display lists.
+Batch* immBeginBatch(GLenum prim_type, unsigned vertex_ct);
+Batch* immBeginBatchAtMost(GLenum prim_type, unsigned vertex_ct);
+#endif
+
+
+// provide attribute values that can change per vertex
+// first vertex after immBegin must have all its attributes specified
+// skipped attributes will continue using the previous value for that attrib_id
+void immAttrib1f(unsigned attrib_id, float x);
+void immAttrib2f(unsigned attrib_id, float x, float y);
+void immAttrib3f(unsigned attrib_id, float x, float y, float z);
+void immAttrib4f(unsigned attrib_id, float x, float y, float z, float w);
+
+void immAttrib2i(unsigned attrib_id, int x, int y);
+
+void immAttrib3fv(unsigned attrib_id, const float data[3]);
+void immAttrib4fv(unsigned attrib_id, const float data[4]);
+
+void immAttrib3ub(unsigned attrib_id, unsigned char r, unsigned char g, unsigned char b);
+void immAttrib4ub(unsigned attrib_id, unsigned char r, unsigned char g, unsigned char b, unsigned char a);
+
+void immAttrib3ubv(unsigned attrib_id, const unsigned char data[4]);
+void immAttrib4ubv(unsigned attrib_id, const unsigned char data[4]);
+
+// explicitly skip an attribute
+// this advanced option kills automatic value copying for this attrib_id
+void immSkipAttrib(unsigned attrib_id);
+
+
+// provide one last attribute value & end the current vertex
+// this is most often used for 2D or 3D position (similar to glVertex)
+void immVertex2f(unsigned attrib_id, float x, float y);
+void immVertex3f(unsigned attrib_id, float x, float y, float z);
+
+void immVertex2i(unsigned attrib_id, int x, int y);
+
+void immVertex2fv(unsigned attrib_id, const float data[2]);
+void immVertex3fv(unsigned attrib_id, const float data[3]);
+
+void immVertex2iv(unsigned attrib_id, const int data[2]);
+
+
+// provide uniform values that don't change for the entire draw call
+void immUniform1i(const char* name, int x);
+void immUniform1f(const char* name, float x);
+void immUniform4f(const char* name, float x, float y, float z, float w);
+void immUniform4fv(const char* name, const float data[4]);
+
+
+// convenience functions for setting "uniform vec4 color"
+// the rgb functions have implicit alpha = 1.0
+void immUniformColor4f(float r, float g, float b, float a);
+void immUniformColor4fv(const float rgba[4]);
+void immUniformColor3f(float r, float g, float b);
+void immUniformColor3fv(const float rgb[3]);
+void immUniformColor3fvAlpha(const float rgb[3], float a);
+
+void immUniformColor3ub(unsigned char r, unsigned char g, unsigned char b);
+void immUniformColor4ub(unsigned char r, unsigned char g, unsigned char b, unsigned char a);
+void immUniformColor3ubv(const unsigned char rgb[3]);
+void immUniformColor4ubv(const unsigned char rgba[4]);
+
+
+// these are called by the system -- not part of drawing API
+
+void immInit(void);
+void immActivate(void);
+void immDeactivate(void);
+void immDestroy(void);
diff --git a/source/blender/gpu/gawain/vertex_buffer.c b/source/blender/gpu/gawain/vertex_buffer.c
new file mode 100644
index 00000000000..93d0facdf7c
--- /dev/null
+++ b/source/blender/gpu/gawain/vertex_buffer.c
@@ -0,0 +1,156 @@
+
+// Gawain geometry batch
+//
+// This code is part of the Gawain library, with modifications
+// specific to integration with Blender.
+//
+// Copyright 2016 Mike Erwin
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of
+// the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+#include "vertex_buffer.h"
+#include <stdlib.h>
+#include <string.h>
+
+#define KEEP_SINGLE_COPY 1
+
+VertexBuffer* VertexBuffer_create()
+ {
+ VertexBuffer* verts = malloc(sizeof(VertexBuffer));
+ VertexBuffer_init(verts);
+ return verts;
+ }
+
+VertexBuffer* VertexBuffer_create_with_format(const VertexFormat* format)
+ {
+ VertexBuffer* verts = VertexBuffer_create();
+ VertexFormat_copy(&verts->format, format);
+ if (!format->packed)
+ VertexFormat_pack(&verts->format);
+ return verts;
+
+ // this function might seem redundant, but there is potential for memory savings here...
+ // TODO: implement those memory savings
+ }
+
+void VertexBuffer_init(VertexBuffer* verts)
+ {
+ memset(verts, 0, sizeof(VertexBuffer));
+ }
+
+void VertexBuffer_init_with_format(VertexBuffer* verts, const VertexFormat* format)
+ {
+ VertexBuffer_init(verts);
+ VertexFormat_copy(&verts->format, format);
+ if (!format->packed)
+ VertexFormat_pack(&verts->format);
+ }
+
+unsigned VertexBuffer_size(const VertexBuffer* verts)
+ {
+ return vertex_buffer_size(&verts->format, verts->vertex_ct);
+ }
+
+void VertexBuffer_allocate_data(VertexBuffer* verts, unsigned v_ct)
+ {
+ VertexFormat* format = &verts->format;
+ if (!format->packed)
+ VertexFormat_pack(format);
+
+ verts->vertex_ct = v_ct;
+
+ // Data initially lives in main memory. Will be transferred to VRAM when we "prime" it.
+ verts->data = malloc(VertexBuffer_size(verts));
+ }
+
+void VertexBuffer_resize_data(VertexBuffer* verts, unsigned v_ct)
+ {
+#if TRUST_NO_ONE
+ assert(verts->vertex_ct != v_ct); // allow this?
+ assert(verts->data != NULL); // has already been allocated
+ assert(verts->vbo_id == 0); // has not been sent to VRAM
+#endif
+
+ verts->vertex_ct = v_ct;
+ verts->data = realloc(verts->data, VertexBuffer_size(verts));
+ // TODO: skip realloc if v_ct < existing vertex count
+ // extra space will be reclaimed, and never sent to VRAM (see VertexBuffer_prime)
+ }
+
+void setAttrib(VertexBuffer* verts, unsigned a_idx, unsigned v_idx, const void* data)
+ {
+ const VertexFormat* format = &verts->format;
+ const Attrib* a = format->attribs + a_idx;
+
+#if TRUST_NO_ONE
+ assert(a_idx < format->attrib_ct);
+ assert(v_idx < verts->vertex_ct);
+ assert(verts->data != NULL); // data must be in main mem
+#endif
+
+ memcpy((GLubyte*)verts->data + a->offset + v_idx * format->stride, data, a->sz);
+ }
+
+void fillAttrib(VertexBuffer* verts, unsigned a_idx, const void* data)
+ {
+ const VertexFormat* format = &verts->format;
+ const Attrib* a = format->attribs + a_idx;
+
+#if TRUST_NO_ONE
+ assert(a_idx < format->attrib_ct);
+#endif
+
+ const unsigned stride = a->sz; // tightly packed input data
+
+ fillAttribStride(verts, a_idx, stride, data);
+ }
+
+void fillAttribStride(VertexBuffer* verts, unsigned a_idx, unsigned stride, const void* data)
+ {
+ const VertexFormat* format = &verts->format;
+ const Attrib* a = format->attribs + a_idx;
+
+#if TRUST_NO_ONE
+ assert(a_idx < format->attrib_ct);
+ assert(verts->data != NULL); // data must be in main mem
+#endif
+
+ const unsigned vertex_ct = verts->vertex_ct;
+
+ if (format->attrib_ct == 1 && stride == format->stride)
+ {
+ // we can copy it all at once
+ memcpy(verts->data, data, vertex_ct * a->sz);
+ }
+ else
+ {
+ // we must copy it per vertex
+ for (unsigned v = 0; v < vertex_ct; ++v)
+ memcpy((GLubyte*)verts->data + a->offset + v * format->stride, (const GLubyte*)data + v * stride, a->sz);
+ }
+ }
+
+static void VertexBuffer_prime(VertexBuffer* verts)
+ {
+ const VertexFormat* format = &verts->format;
+
+ glGenBuffers(1, &verts->vbo_id);
+ glBindBuffer(GL_ARRAY_BUFFER, verts->vbo_id);
+ // fill with delicious data & send to GPU the first time only
+ glBufferData(GL_ARRAY_BUFFER, vertex_buffer_size(format, verts->vertex_ct), verts->data, GL_STATIC_DRAW);
+
+#if KEEP_SINGLE_COPY
+ // now that GL has a copy, discard original
+ free(verts->data);
+ verts->data = NULL;
+#endif
+ }
+
+void VertexBuffer_use(VertexBuffer* verts)
+ {
+ if (verts->vbo_id)
+ glBindBuffer(GL_ARRAY_BUFFER, verts->vbo_id);
+ else
+ VertexBuffer_prime(verts);
+ }
diff --git a/source/blender/gpu/gawain/vertex_buffer.h b/source/blender/gpu/gawain/vertex_buffer.h
new file mode 100644
index 00000000000..7128ec4b1af
--- /dev/null
+++ b/source/blender/gpu/gawain/vertex_buffer.h
@@ -0,0 +1,62 @@
+
+// Gawain geometry batch
+//
+// This code is part of the Gawain library, with modifications
+// specific to integration with Blender.
+//
+// Copyright 2016 Mike Erwin
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of
+// the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+#pragma once
+
+#include "vertex_format.h"
+
+// How to create a VertexBuffer:
+// 1) verts = create_VertexBuffer() or init_VertexBuffer(verts)
+// 2) add_attrib(verts->format, ...)
+// 3) allocate_vertex_data(verts, vertex_ct) <-- finalizes/packs vertex format
+// 4) fillAttrib(verts, pos, application_pos_buffer)
+// 5) prime_VertexBuffer(verts);
+
+// Is VertexBuffer always used as part of a Batch?
+
+typedef struct {
+ VertexFormat format;
+ unsigned vertex_ct;
+ GLubyte* data; // NULL indicates data in VRAM (unmapped) or not yet allocated
+ GLuint vbo_id; // 0 indicates not yet sent to VRAM
+} VertexBuffer;
+
+VertexBuffer* VertexBuffer_create(void);
+VertexBuffer* VertexBuffer_create_with_format(const VertexFormat*);
+
+void VertexBuffer_init(VertexBuffer*);
+void VertexBuffer_init_with_format(VertexBuffer*, const VertexFormat*);
+
+unsigned VertexBuffer_size(const VertexBuffer*);
+void VertexBuffer_allocate_data(VertexBuffer*, unsigned v_ct);
+void VertexBuffer_resize_data(VertexBuffer*, unsigned v_ct);
+
+// The most important setAttrib variant is the untyped one. Get it right first.
+// It takes a void* so the app developer is responsible for matching their app data types
+// to the vertex attribute's type and component count. They're in control of both, so this
+// should not be a problem.
+
+void setAttrib(VertexBuffer*, unsigned a_idx, unsigned v_idx, const void* data);
+void fillAttrib(VertexBuffer*, unsigned a_idx, const void* data); // tightly packed, non interleaved input data
+void fillAttribStride(VertexBuffer*, unsigned a_idx, unsigned stride, const void* data);
+
+// TODO: decide whether to keep the functions below
+// doesn't immediate mode satisfy these needs?
+
+// void setAttrib1f(unsigned a_idx, unsigned v_idx, float x);
+// void setAttrib2f(unsigned a_idx, unsigned v_idx, float x, float y);
+// void setAttrib3f(unsigned a_idx, unsigned v_idx, float x, float y, float z);
+// void setAttrib4f(unsigned a_idx, unsigned v_idx, float x, float y, float z, float w);
+//
+// void setAttrib3ub(unsigned a_idx, unsigned v_idx, unsigned char r, unsigned char g, unsigned char b);
+// void setAttrib4ub(unsigned a_idx, unsigned v_idx, unsigned char r, unsigned char g, unsigned char b, unsigned char a);
+
+void VertexBuffer_use(VertexBuffer*);
diff --git a/source/blender/gpu/gawain/vertex_format.c b/source/blender/gpu/gawain/vertex_format.c
new file mode 100644
index 00000000000..20a4d7d8099
--- /dev/null
+++ b/source/blender/gpu/gawain/vertex_format.c
@@ -0,0 +1,203 @@
+
+// Gawain vertex format
+//
+// This code is part of the Gawain library, with modifications
+// specific to integration with Blender.
+//
+// Copyright 2016 Mike Erwin
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of
+// the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+#include "vertex_format.h"
+#include <stdlib.h>
+#include <string.h>
+
+#define PACK_DEBUG 0
+
+#if PACK_DEBUG
+ #include <stdio.h>
+#endif
+
+void VertexFormat_clear(VertexFormat* format)
+ {
+#if TRUST_NO_ONE
+ memset(format, 0, sizeof(VertexFormat));
+#else
+ format->attrib_ct = 0;
+ format->packed = false;
+ format->name_offset = 0;
+#endif
+ }
+
+void VertexFormat_copy(VertexFormat* dest, const VertexFormat* src)
+ {
+ // copy regular struct fields
+ memcpy(dest, src, sizeof(VertexFormat));
+ }
+
+static unsigned comp_sz(GLenum type)
+ {
+#if TRUST_NO_ONE
+ assert(type >= GL_BYTE && type <= GL_FLOAT);
+#endif
+
+ const GLubyte sizes[] = {1,1,2,2,4,4,4};
+ return sizes[type - GL_BYTE];
+ }
+
+static unsigned attrib_sz(const Attrib *a)
+ {
+ return a->comp_ct * comp_sz(a->comp_type);
+ }
+
+static unsigned attrib_align(const Attrib *a)
+ {
+ unsigned c = comp_sz(a->comp_type);
+ if (a->comp_ct == 3 && c <= 2)
+ return 4 * c; // AMD HW can't fetch these well, so pad it out (other vendors too?)
+ else
+ return c; // most fetches are ok if components are naturally aligned
+ }
+
+unsigned vertex_buffer_size(const VertexFormat* format, unsigned vertex_ct)
+ {
+#if TRUST_NO_ONE
+ assert(format->packed && format->stride > 0);
+#endif
+
+ return format->stride * vertex_ct;
+ }
+
+static const char* copy_attrib_name(VertexFormat* format, const char* name)
+ {
+ // strncpy does 110% of what we need; let's do exactly 100%
+ char* name_copy = format->names + format->name_offset;
+ unsigned available = VERTEX_ATTRIB_NAMES_BUFFER_LEN - format->name_offset;
+ bool terminated = false;
+
+ for (unsigned i = 0; i < available; ++i)
+ {
+ const char c = name[i];
+ name_copy[i] = c;
+ if (c == '\0')
+ {
+ terminated = true;
+ format->name_offset += (i + 1);
+ break;
+ }
+ }
+
+#if TRUST_NO_ONE
+ assert(terminated);
+ assert(format->name_offset <= VERTEX_ATTRIB_NAMES_BUFFER_LEN);
+#endif
+
+ return name_copy;
+ }
+
+unsigned add_attrib(VertexFormat* format, const char* name, GLenum comp_type, unsigned comp_ct, VertexFetchMode fetch_mode)
+ {
+#if TRUST_NO_ONE
+ assert(format->attrib_ct < MAX_VERTEX_ATTRIBS); // there's room for more
+ assert(!format->packed); // packed means frozen/locked
+ assert(comp_ct >= 1 && comp_ct <= 4);
+ switch (comp_type)
+ {
+ case GL_FLOAT:
+ // float type can only kept as float
+ assert(fetch_mode == KEEP_FLOAT);
+ break;
+ #if 0 // enable this after switching to our own enum for comp_type
+ default:
+ // integer types can be kept as int or converted/normalized to float
+ assert(fetch_mode != KEEP_FLOAT);
+ #else
+ case GL_BYTE:
+ case GL_UNSIGNED_BYTE:
+ case GL_SHORT:
+ case GL_UNSIGNED_SHORT:
+ case GL_INT:
+ case GL_UNSIGNED_INT:
+ // integer types can be converted, normalized, or kept as int
+ assert(fetch_mode != KEEP_FLOAT);
+ break;
+ default:
+ assert(false); // invalid comp_type
+ #endif
+ }
+#endif
+
+ const unsigned attrib_id = format->attrib_ct++;
+ Attrib* attrib = format->attribs + attrib_id;
+
+ attrib->name = copy_attrib_name(format, name);
+ attrib->comp_type = comp_type;
+ attrib->comp_ct = comp_ct;
+ attrib->sz = attrib_sz(attrib);
+ attrib->offset = 0; // offsets & stride are calculated later (during pack)
+ attrib->fetch_mode = fetch_mode;
+
+ return attrib_id;
+ }
+
+unsigned padding(unsigned offset, unsigned alignment)
+ {
+ const unsigned mod = offset % alignment;
+ return (mod == 0) ? 0 : (alignment - mod);
+ }
+
+#if PACK_DEBUG
+static void show_pack(unsigned a_idx, unsigned sz, unsigned pad)
+ {
+ const char c = 'A' + a_idx;
+ for (unsigned i = 0; i < pad; ++i)
+ putchar('-');
+ for (unsigned i = 0; i < sz; ++i)
+ putchar(c);
+ }
+#endif
+
+void VertexFormat_pack(VertexFormat* format)
+ {
+ // for now, attributes are packed in the order they were added,
+ // making sure each attrib is naturally aligned (add padding where necessary)
+
+ // later we can implement more efficient packing w/ reordering
+ // (keep attrib ID order, adjust their offsets to reorder in buffer)
+
+ // TODO:
+ // realloc just enough to hold the final combo string. And just enough to
+ // hold used attribs, not all 16.
+
+ Attrib* a0 = format->attribs + 0;
+ a0->offset = 0;
+ unsigned offset = a0->sz;
+
+#if PACK_DEBUG
+ show_pack(0, a0->sz, 0);
+#endif
+
+ for (unsigned a_idx = 1; a_idx < format->attrib_ct; ++a_idx)
+ {
+ Attrib* a = format->attribs + a_idx;
+ unsigned mid_padding = padding(offset, attrib_align(a));
+ offset += mid_padding;
+ a->offset = offset;
+ offset += a->sz;
+
+#if PACK_DEBUG
+ show_pack(a_idx, a->sz, mid_padding);
+#endif
+ }
+
+ unsigned end_padding = padding(offset, attrib_align(a0));
+
+#if PACK_DEBUG
+ show_pack(0, 0, end_padding);
+ putchar('\n');
+#endif
+
+ format->stride = offset + end_padding;
+ format->packed = true;
+ }
diff --git a/source/blender/gpu/gawain/vertex_format.h b/source/blender/gpu/gawain/vertex_format.h
new file mode 100644
index 00000000000..09c79603b0c
--- /dev/null
+++ b/source/blender/gpu/gawain/vertex_format.h
@@ -0,0 +1,53 @@
+
+// Gawain vertex format
+//
+// This code is part of the Gawain library, with modifications
+// specific to integration with Blender.
+//
+// Copyright 2016 Mike Erwin
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of
+// the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+#pragma once
+
+#include "common.h"
+
+#define MAX_VERTEX_ATTRIBS 16
+#define AVG_VERTEX_ATTRIB_NAME_LEN 5
+#define VERTEX_ATTRIB_NAMES_BUFFER_LEN ((AVG_VERTEX_ATTRIB_NAME_LEN + 1) * MAX_VERTEX_ATTRIBS)
+
+typedef enum {
+ KEEP_FLOAT,
+ KEEP_INT,
+ NORMALIZE_INT_TO_FLOAT, // 127 (ubyte) -> 0.5 (and so on for other int types)
+ CONVERT_INT_TO_FLOAT // 127 (any int type) -> 127.0
+} VertexFetchMode;
+
+typedef struct {
+ GLenum comp_type;
+ unsigned comp_ct; // 1 to 4
+ unsigned sz; // size in bytes, 1 to 16
+ unsigned offset; // from beginning of vertex, in bytes
+ VertexFetchMode fetch_mode;
+ const char* name;
+} Attrib;
+
+typedef struct {
+ unsigned attrib_ct; // 0 to 16 (MAX_VERTEX_ATTRIBS)
+ unsigned stride; // stride in bytes, 1 to 256
+ bool packed;
+ Attrib attribs[MAX_VERTEX_ATTRIBS]; // TODO: variable-size attribs array
+ char names[VERTEX_ATTRIB_NAMES_BUFFER_LEN];
+ unsigned name_offset;
+} VertexFormat;
+
+void VertexFormat_clear(VertexFormat*);
+void VertexFormat_copy(VertexFormat* dest, const VertexFormat* src);
+
+unsigned add_attrib(VertexFormat*, const char* name, GLenum comp_type, unsigned comp_ct, VertexFetchMode);
+
+// for internal use
+void VertexFormat_pack(VertexFormat*);
+unsigned padding(unsigned offset, unsigned alignment);
+unsigned vertex_buffer_size(const VertexFormat*, unsigned vertex_ct);
diff --git a/source/blender/gpu/intern/gpu_basic_shader.c b/source/blender/gpu/intern/gpu_basic_shader.c
index a2b89239344..9d1e84cd44e 100644
--- a/source/blender/gpu/intern/gpu_basic_shader.c
+++ b/source/blender/gpu/intern/gpu_basic_shader.c
@@ -269,7 +269,7 @@ const GLubyte stipple_hexagon[128] = {
/* GLSL State */
-static bool USE_GLSL = false;
+static bool USE_GLSL = true;
/**
* \note this isn't part of the basic shader API,
@@ -422,23 +422,6 @@ void GPU_basic_shader_bind(int options)
{
if (USE_GLSL) {
if (options) {
- const int bound_options = GPU_MATERIAL_STATE.bound_options;
-
- /* texture options need to be set for basic shader too */
- if (options & GPU_SHADER_TEXTURE_2D) {
- glEnable(GL_TEXTURE_2D);
- }
- else if (bound_options & GPU_SHADER_TEXTURE_2D) {
- glDisable(GL_TEXTURE_2D);
- }
-
- if (options & GPU_SHADER_TEXTURE_RECT) {
- glEnable(GL_TEXTURE_RECTANGLE);
- }
- else if (bound_options & GPU_SHADER_TEXTURE_RECT) {
- glDisable(GL_TEXTURE_RECTANGLE);
- }
-
GPUShader *shader = gpu_basic_shader(options);
if (shader) {
diff --git a/source/blender/gpu/intern/gpu_batch.c b/source/blender/gpu/intern/gpu_batch.c
new file mode 100644
index 00000000000..23f9f68f1aa
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_batch.c
@@ -0,0 +1,35 @@
+/*
+ * ***** 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) 2016 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Mike Erwin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "GPU_batch.h"
+#include "gpu_shader_private.h"
+
+void Batch_set_builtin_program(Batch* batch, GPUBuiltinShader shader_id)
+{
+ GPUShader *shader = GPU_shader_get_builtin_shader(shader_id);
+ Batch_set_program(batch, shader->program);
+}
diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c
index aeb656b238b..3786e8ce739 100644
--- a/source/blender/gpu/intern/gpu_codegen.c
+++ b/source/blender/gpu/intern/gpu_codegen.c
@@ -414,16 +414,8 @@ const char *GPU_builtin_name(GPUBuiltin builtin)
return "unfobautobumpscale";
else if (builtin == GPU_CAMERA_TEXCO_FACTORS)
return "unfcameratexfactors";
- else if (builtin == GPU_PARTICLE_SCALAR_PROPS)
- return "unfparticlescalarprops";
- else if (builtin == GPU_PARTICLE_LOCATION)
- return "unfparticleco";
- else if (builtin == GPU_PARTICLE_VELOCITY)
- return "unfparticlevel";
- else if (builtin == GPU_PARTICLE_ANG_VELOCITY)
- return "unfparticleangvel";
else if (builtin == GPU_PBR)
- return "unfpbr"; /* Placeholder : does not actualy contains data */
+ return "unfpbr"; /* Placeholder : does not actualy contain data */
else
return "";
}
diff --git a/source/blender/gpu/intern/gpu_compositing.c b/source/blender/gpu/intern/gpu_compositing.c
index d1c54ea9865..c1a51b1dc17 100644
--- a/source/blender/gpu/intern/gpu_compositing.c
+++ b/source/blender/gpu/intern/gpu_compositing.c
@@ -383,9 +383,6 @@ bool GPU_fx_compositor_initialize_passes(
fx->effects = 0;
- if (!GLEW_EXT_framebuffer_object)
- return false;
-
if (!fx_settings) {
cleanup_fx_gl_data(fx, true);
return false;
@@ -612,11 +609,8 @@ bool GPU_fx_compositor_initialize_passes(
/* bind the buffers */
/* first depth buffer, because system assumes read/write buffers */
- if (!GPU_framebuffer_texture_attach(fx->gbuffer, fx->depth_buffer, 0, err_out))
- printf("%.256s\n", err_out);
-
- if (!GPU_framebuffer_texture_attach(fx->gbuffer, fx->color_buffer, 0, err_out))
- printf("%.256s\n", err_out);
+ GPU_framebuffer_texture_attach(fx->gbuffer, fx->depth_buffer, 0);
+ GPU_framebuffer_texture_attach(fx->gbuffer, fx->color_buffer, 0);
if (!GPU_framebuffer_check_valid(fx->gbuffer, err_out))
printf("%.256s\n", err_out);
@@ -661,7 +655,7 @@ static void gpu_fx_bind_render_target(int *passes_left, GPUFX *fx, struct GPUOff
}
else {
/* bind the ping buffer to the color buffer */
- GPU_framebuffer_texture_attach(fx->gbuffer, target, 0, NULL);
+ GPU_framebuffer_texture_attach(fx->gbuffer, target, 0);
}
}
@@ -690,8 +684,7 @@ void GPU_fx_compositor_setup_XRay_pass(GPUFX *fx, bool do_xray)
GPU_framebuffer_texture_detach(fx->depth_buffer);
/* first depth buffer, because system assumes read/write buffers */
- if (!GPU_framebuffer_texture_attach(fx->gbuffer, fx->depth_buffer_xray, 0, err_out))
- printf("%.256s\n", err_out);
+ GPU_framebuffer_texture_attach(fx->gbuffer, fx->depth_buffer_xray, 0);
}
@@ -701,7 +694,7 @@ void GPU_fx_compositor_XRay_resolve(GPUFX *fx)
GPU_framebuffer_texture_detach(fx->depth_buffer_xray);
/* attach regular framebuffer */
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->depth_buffer, 0, NULL);
+ GPU_framebuffer_texture_attach(fx->gbuffer, fx->depth_buffer, 0);
/* full screen quad where we will always write to depth buffer */
glPushAttrib(GL_DEPTH_BUFFER_BIT | GL_SCISSOR_BIT);
@@ -949,9 +942,9 @@ bool GPU_fx_do_composite_pass(
GPU_shader_uniform_texture(dof_shader_pass2, interface->color_uniform, src);
/* target is the downsampled coc buffer */
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_half_downsampled_near, 0, NULL);
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_half_downsampled_far, 1, NULL);
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_nearfar_coc, 2, NULL);
+ GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_half_downsampled_near, 0);
+ GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_half_downsampled_far, 1);
+ GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_nearfar_coc, 2);
/* binding takes care of setting the viewport to the downsampled size */
GPU_framebuffer_slots_bind(fx->gbuffer, 0);
@@ -995,7 +988,7 @@ bool GPU_fx_do_composite_pass(
GPU_texture_filter_mode(fx->dof_half_downsampled_far, false, false);
/* target is the downsampled coc buffer */
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_far_blur, 0, NULL);
+ GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_far_blur, 0);
GPU_texture_bind_as_framebuffer(fx->dof_far_blur);
glDisable(GL_DEPTH_TEST);
@@ -1019,7 +1012,7 @@ bool GPU_fx_do_composite_pass(
GPU_shader_uniform_vector(dof_shader_pass2, interface->select_uniform, 2, 1, selection);
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_blur, 0, NULL);
+ GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_blur, 0);
/* have to clear the buffer unfortunately */
glClear(GL_COLOR_BUFFER_BIT);
/* the draw call we all waited for, draw a point per pixel, scaled per circle of confusion */
@@ -1139,7 +1132,7 @@ bool GPU_fx_do_composite_pass(
GPU_shader_uniform_texture(dof_shader_pass1, interface->depth_uniform, fx->depth_buffer);
/* target is the downsampled coc buffer */
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_buffer, 0, NULL);
+ GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_buffer, 0);
/* binding takes care of setting the viewport to the downsampled size */
GPU_texture_bind_as_framebuffer(fx->dof_near_coc_buffer);
@@ -1179,7 +1172,7 @@ bool GPU_fx_do_composite_pass(
GPU_shader_uniform_texture(dof_shader_pass2, interface->color_uniform, fx->dof_near_coc_buffer);
/* use final buffer as a temp here */
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_final_buffer, 0, NULL);
+ GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_final_buffer, 0);
/* Drawing quad */
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
@@ -1196,7 +1189,7 @@ bool GPU_fx_do_composite_pass(
GPU_texture_bind(fx->dof_near_coc_final_buffer, numslots++);
GPU_shader_uniform_texture(dof_shader_pass2, interface->color_uniform, fx->dof_near_coc_final_buffer);
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_blurred_buffer, 0, NULL);
+ GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_blurred_buffer, 0);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
/* *unbind/detach */
@@ -1223,7 +1216,7 @@ bool GPU_fx_do_composite_pass(
GPU_texture_bind(fx->dof_near_coc_blurred_buffer, numslots++);
GPU_shader_uniform_texture(dof_shader_pass3, interface->near_coc_blurred, fx->dof_near_coc_blurred_buffer);
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_final_buffer, 0, NULL);
+ GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_final_buffer, 0);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
/* disable bindings */
@@ -1249,7 +1242,7 @@ bool GPU_fx_do_composite_pass(
GPU_shader_uniform_texture(dof_shader_pass4, interface->near_coc_downsampled, fx->dof_near_coc_final_buffer);
GPU_shader_uniform_vector(dof_shader_pass4, interface->invrendertargetdim_uniform, 2, 1, invrendertargetdim);
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_buffer, 0, NULL);
+ GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_buffer, 0);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
/* disable bindings */
diff --git a/source/blender/gpu/intern/gpu_debug.c b/source/blender/gpu/intern/gpu_debug.c
index d632e767ca9..c25103dd300 100644
--- a/source/blender/gpu/intern/gpu_debug.c
+++ b/source/blender/gpu/intern/gpu_debug.c
@@ -43,113 +43,6 @@
#include <stdlib.h>
#include <string.h>
-#define CASE_CODE_RETURN_STR(code) case code: return #code;
-
-static const char *gpu_gl_error_symbol(GLenum err)
-{
- switch (err) {
- CASE_CODE_RETURN_STR(GL_NO_ERROR)
- CASE_CODE_RETURN_STR(GL_INVALID_ENUM)
- CASE_CODE_RETURN_STR(GL_INVALID_VALUE)
- CASE_CODE_RETURN_STR(GL_INVALID_OPERATION)
- CASE_CODE_RETURN_STR(GL_STACK_OVERFLOW)
- CASE_CODE_RETURN_STR(GL_STACK_UNDERFLOW)
- CASE_CODE_RETURN_STR(GL_OUT_OF_MEMORY)
-
-#if GL_ARB_imaging
- CASE_CODE_RETURN_STR(GL_TABLE_TOO_LARGE)
-#endif
-
-#if defined(WITH_GLU)
- CASE_CODE_RETURN_STR(GLU_INVALID_ENUM)
- CASE_CODE_RETURN_STR(GLU_INVALID_VALUE)
- CASE_CODE_RETURN_STR(GLU_OUT_OF_MEMORY)
-#endif
-
- default:
- return "<unknown error>";
- }
-}
-
-#undef CASE_CODE_RETURN_STR
-
-
-static bool gpu_report_gl_errors(const char *file, int line, const char *str)
-{
- GLenum gl_error = glGetError();
-
- if (gl_error == GL_NO_ERROR) {
- return true;
- }
- else {
- /* glGetError should have cleared the error flag, so if we get the
- * same flag twice that means glGetError itself probably triggered
- * the error. This happens on Windows if the GL context is invalid.
- */
- {
- GLenum new_error = glGetError();
- if (gl_error == new_error) {
- fprintf(stderr, "GL: Possible context invalidation issue\n");
- return false;
- }
- }
-
- fprintf(stderr,
- "%s:%d: ``%s'' -> GL Error (0x%04X - %s): %s\n",
- file, line, str, gl_error,
- gpu_gl_error_symbol(gl_error),
- gpuErrorString(gl_error));
-
- return false;
- }
-}
-
-
-const char *gpuErrorString(GLenum err)
-{
- switch (err) {
- case GL_NO_ERROR:
- return "No Error";
-
- case GL_INVALID_ENUM:
- return "Invalid Enumeration";
-
- case GL_INVALID_VALUE:
- return "Invalid Value";
-
- case GL_INVALID_OPERATION:
- return "Invalid Operation";
-
- case GL_STACK_OVERFLOW:
- return "Stack Overflow";
-
- case GL_STACK_UNDERFLOW:
- return "Stack Underflow";
-
- case GL_OUT_OF_MEMORY:
- return "Out of Memory";
-
-#if GL_ARB_imaging
- case GL_TABLE_TOO_LARGE:
- return "Table Too Large";
-#endif
-
-#if defined(WITH_GLU)
- case GLU_INVALID_ENUM:
- return "Invalid Enum (GLU)";
-
- case GLU_INVALID_VALUE:
- return "Invalid Value (GLU)";
-
- case GLU_OUT_OF_MEMORY:
- return "Out of Memory (GLU)";
-#endif
-
- default:
- return "<unknown error>";
- }
-}
-
/* Debug callbacks need the same calling convention as OpenGL functions.
*/
@@ -209,11 +102,6 @@ static void APIENTRY gpu_debug_proc(
GLenum severity, GLsizei UNUSED(length),
const GLchar *message, const GLvoid *UNUSED(userParm))
{
- if (type == GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR) {
- /* Blender 2.7x uses OpenGL 2.1, we don't care if features are deprecated */
- return;
- }
-
bool backtrace = false;
switch (severity) {
@@ -239,11 +127,6 @@ static void APIENTRY gpu_debug_proc_amd(
GLenum severity, GLsizei UNUSED(length),
const GLchar *message, GLvoid *UNUSED(userParm))
{
- if (category == GL_DEBUG_CATEGORY_DEPRECATION_AMD) {
- /* Blender 2.7x uses OpenGL 2.1, we don't care if features are deprecated */
- return;
- }
-
bool backtrace = false;
switch (severity) {
@@ -410,18 +293,6 @@ void GPU_print_error_debug(const char *str)
fprintf(stderr, "GPU: %s\n", str);
}
-
-void GPU_assert_no_gl_errors(const char *file, int line, const char *str)
-{
- if (G.debug) {
- GLboolean gl_ok = gpu_report_gl_errors(file, line, str);
-
- BLI_assert(gl_ok);
- (void) gl_ok;
- }
-}
-
-
static void gpu_state_print_fl_ex(const char *name, GLenum type)
{
const unsigned char err_mark[4] = {0xff, 0xff, 0xff, 0xff};
@@ -448,7 +319,8 @@ static void gpu_state_print_fl_ex(const char *name, GLenum type)
void GPU_state_print(void)
{
- GPU_ASSERT_NO_GL_ERRORS("GPU_state_print"); /* clear any errors */
+ /* clear any errors */
+ while (glGetError() != GL_NO_ERROR) {}
gpu_state_print_fl(GL_ACCUM_ALPHA_BITS);
gpu_state_print_fl(GL_ACCUM_BLUE_BITS);
diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c
index 5d4aef59e1d..da5215ffc66 100644
--- a/source/blender/gpu/intern/gpu_draw.c
+++ b/source/blender/gpu/intern/gpu_draw.c
@@ -56,7 +56,6 @@
#include "DNA_scene_types.h"
#include "DNA_smoke_types.h"
#include "DNA_view3d_types.h"
-#include "DNA_particle_types.h"
#include "MEM_guardedalloc.h"
@@ -280,7 +279,7 @@ void GPU_set_gpu_mipmapping(int gpu_mipmap)
int old_value = GTS.gpu_mipmap;
/* only actually enable if it's supported */
- GTS.gpu_mipmap = gpu_mipmap && GLEW_EXT_framebuffer_object;
+ GTS.gpu_mipmap = gpu_mipmap;
if (old_value != GTS.gpu_mipmap) {
GPU_free_images();
@@ -304,11 +303,7 @@ void GPU_generate_mipmap(GLenum target)
glEnable(target);
}
- /* TODO: simplify when we transition to GL >= 3 */
- if (GLEW_VERSION_3_0 || GLEW_ARB_framebuffer_object)
- glGenerateMipmap(target);
- else if (GLEW_EXT_framebuffer_object)
- glGenerateMipmapEXT(target);
+ glGenerateMipmap(target);
if (is_ati && !target_enabled)
glDisable(target);
@@ -864,6 +859,7 @@ void GPU_create_gl_tex(
int tpx = rectw;
int tpy = recth;
+#if 0 /* NPOT support should be a compile-time check */
/* scale if not a power of two. this is not strictly necessary for newer
* GPUs (OpenGL version >= 2.0) since they support non-power-of-two-textures
* Then don't bother scaling for hardware that supports NPOT textures! */
@@ -887,6 +883,7 @@ void GPU_create_gl_tex(
rect = ibuf->rect;
}
}
+#endif
/* create image */
glGenTextures(1, (GLuint *)bind);
@@ -1217,8 +1214,12 @@ void GPU_paint_set_mipmap(bool mipmap)
/* check if image has been downscaled and do scaled partial update */
static bool GPU_check_scaled_image(ImBuf *ibuf, Image *ima, float *frect, int x, int y, int w, int h)
{
+#if 0 /* NPOT suport should be a compile-time check */
if ((!GPU_full_non_power_of_two_support() && !is_power_of_2_resolution(ibuf->x, ibuf->y)) ||
is_over_resolution_limit(GL_TEXTURE_2D, ibuf->x, ibuf->y))
+#else
+ if (is_over_resolution_limit(GL_TEXTURE_2D, ibuf->x, ibuf->y))
+#endif
{
int x_limit = smaller_power_of_2_limit(ibuf->x);
int y_limit = smaller_power_of_2_limit(ibuf->y);
@@ -1976,35 +1977,6 @@ void GPU_begin_object_materials(
GPU_object_material_unbind();
}
-static int GPU_get_particle_info(GPUParticleInfo *pi)
-{
- DupliObject *dob = GMS.dob;
- if (dob->particle_system) {
- int ind;
- if (dob->persistent_id[0] < dob->particle_system->totpart)
- ind = dob->persistent_id[0];
- else {
- ind = dob->particle_system->child[dob->persistent_id[0] - dob->particle_system->totpart].parent;
- }
- if (ind >= 0) {
- ParticleData *p = &dob->particle_system->particles[ind];
-
- pi->scalprops[0] = ind;
- pi->scalprops[1] = GMS.gscene->r.cfra - p->time;
- pi->scalprops[2] = p->lifetime;
- pi->scalprops[3] = p->size;
-
- copy_v3_v3(pi->location, p->state.co);
- copy_v3_v3(pi->velocity, p->state.vel);
- copy_v3_v3(pi->angular_velocity, p->state.ave);
- return 1;
- }
- else return 0;
- }
- else
- return 0;
-}
-
int GPU_object_material_bind(int nr, void *attribs)
{
GPUVertexAttribs *gattribs = attribs;
@@ -2066,7 +2038,6 @@ int GPU_object_material_bind(int nr, void *attribs)
if (gattribs && GMS.gmatbuf[nr]) {
/* bind glsl material and get attributes */
Material *mat = GMS.gmatbuf[nr];
- GPUParticleInfo particle_info;
float auto_bump_scale;
@@ -2075,18 +2046,14 @@ int GPU_object_material_bind(int nr, void *attribs)
GMS.use_ssao, GMS.parallax_correc);
GPU_material_vertex_attributes(gpumat, gattribs);
- if (GMS.dob)
- GPU_get_particle_info(&particle_info);
-
GPU_material_bind(
gpumat, GMS.gob->lay, GMS.glay, 1.0, !(GMS.gob->mode & OB_MODE_TEXTURE_PAINT),
GMS.gviewmat, GMS.gviewinv, GMS.gviewcamtexcofac, GMS.gscenelock);
auto_bump_scale = GMS.gob->derivedFinal != NULL ? GMS.gob->derivedFinal->auto_bump_scale : 1.0f;
- GPU_material_bind_uniforms(gpumat, GMS.gob->obmat, GMS.gviewmat, GMS.gob->col, auto_bump_scale, &particle_info);
+ GPU_material_bind_uniforms(gpumat, GMS.gob->obmat, GMS.gviewmat, GMS.gob->col, auto_bump_scale);
GPU_material_bind_uniforms_pbr(gpumat, GMS.gprobe, GMS.gpbr, GMS.gpbrsettings);
-
GMS.gboundmat = mat;
/* for glsl use alpha blend mode, unless it's set to solid and
@@ -2401,7 +2368,13 @@ void GPU_state_init(void)
glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
GPU_default_lights();
-
+
+ GPU_disable_program_point_size();
+
+ /* TODO: remove this when we switch to core profile */
+ glEnable(GL_POINT_SPRITE);
+
+
glDepthFunc(GL_LEQUAL);
/* scaling matrices */
glEnable(GL_NORMALIZE);
@@ -2423,7 +2396,7 @@ void GPU_state_init(void)
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-
+
glPixelTransferi(GL_MAP_COLOR, GL_FALSE);
glPixelTransferi(GL_RED_SCALE, 1);
glPixelTransferi(GL_RED_BIAS, 0);
@@ -2433,7 +2406,7 @@ void GPU_state_init(void)
glPixelTransferi(GL_BLUE_BIAS, 0);
glPixelTransferi(GL_ALPHA_SCALE, 1);
glPixelTransferi(GL_ALPHA_BIAS, 0);
-
+
glPixelTransferi(GL_DEPTH_BIAS, 0);
glPixelTransferi(GL_DEPTH_SCALE, 1);
glDepthRange(0.0, 1.0);
@@ -2451,6 +2424,26 @@ void GPU_state_init(void)
GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
}
+void GPU_enable_program_point_size()
+{
+#ifdef __APPLE__
+ /* TODO: remove this when we switch to core profile */
+ glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
+#else
+ glEnable(GL_PROGRAM_POINT_SIZE);
+#endif
+}
+
+void GPU_disable_program_point_size()
+{
+#ifdef __APPLE__
+ /* TODO: remove this when we switch to core profile */
+ glDisable(GL_VERTEX_PROGRAM_POINT_SIZE);
+#else
+ glDisable(GL_PROGRAM_POINT_SIZE);
+#endif
+}
+
#ifdef WITH_OPENSUBDIV
/* Update face-varying variables offset which might be
* different from mesh to mesh sharing the same material.
diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c
index 8a20a97c797..eea415a9da9 100644
--- a/source/blender/gpu/intern/gpu_extensions.c
+++ b/source/blender/gpu/intern/gpu_extensions.c
@@ -56,10 +56,8 @@
/* Extensions support */
/* -- extension: version of GL that absorbs it
+ * EXT_gpu_shader4: 3.0
* ARB_framebuffer object: 3.0
- * EXT_framebuffer_object: 3.0
- * EXT_framebuffer_blit: 3.0
- * EXT_framebuffer_multisample: 3.0
* EXT_framebuffer_multisample_blit_scaled: ???
* ARB_draw_instanced: 3.1
* ARB_texture_multisample: 3.2
@@ -130,8 +128,21 @@ void GPU_get_dfdy_factors(float fac[2])
void gpu_extensions_init(void)
{
- /* BLI_assert(GLEW_VERSION_2_1); */
- /* ^-- maybe a bit extreme? */
+ /* during 2.8 development each platform has its own OpenGL minimum requirements
+ * final 2.8 release will be unified on OpenGL 3.3 core profile, no required extensions
+ * see developer.blender.org/T49012 for details
+ */
+#ifdef _WIN32
+ BLI_assert(GLEW_VERSION_3_3);
+#elif defined(__APPLE__)
+ BLI_assert(GLEW_VERSION_2_1 && GLEW_EXT_gpu_shader4
+ && GLEW_ARB_framebuffer_object
+ && GLEW_ARB_draw_elements_base_vertex
+ && GLEW_APPLE_flush_buffer_range);
+#else
+ BLI_assert(GLEW_VERSION_3_3 || (GLEW_VERSION_3_0 && GLEW_ARB_draw_elements_base_vertex));
+ /* vendor driver || Mesa compatibility profile */
+#endif
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &GG.maxtextures);
@@ -246,6 +257,8 @@ void gpu_extensions_exit(void)
bool GPU_legacy_support(void)
{
/* return whether or not current GL context is compatible with legacy OpenGL */
+ /* (will be removed after switching to core profile) */
+
static bool checked = false;
static bool support = true;
diff --git a/source/blender/gpu/intern/gpu_framebuffer.c b/source/blender/gpu/intern/gpu_framebuffer.c
index 7a1125a7998..5aa7641c02f 100644
--- a/source/blender/gpu/intern/gpu_framebuffer.c
+++ b/source/blender/gpu/intern/gpu_framebuffer.c
@@ -55,44 +55,37 @@ struct GPUFrameBuffer {
static void GPU_print_framebuffer_error(GLenum status, char err_out[256])
{
+ const char *format = "GPUFrameBuffer: framebuffer status %s";
const char *err = "unknown";
+#define format_status(X) \
+ case GL_FRAMEBUFFER_##X: err = "GL_FRAMEBUFFER_"#X; \
+ break;
+
switch (status) {
- case GL_FRAMEBUFFER_COMPLETE_EXT:
- break;
- case GL_INVALID_OPERATION:
- err = "Invalid operation";
- break;
- case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
- err = "Incomplete attachment";
- break;
- case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
- err = "Unsupported framebuffer format";
- break;
- case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
- err = "Missing attachment";
- break;
- case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
- err = "Attached images must have same dimensions";
- break;
- case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
- err = "Attached images must have same format";
- break;
- case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
- err = "Missing draw buffer";
- break;
- case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
- err = "Missing read buffer";
- break;
+ /* success */
+ format_status(COMPLETE)
+ /* errors shared by OpenGL desktop & ES */
+ format_status(INCOMPLETE_ATTACHMENT)
+ format_status(INCOMPLETE_MISSING_ATTACHMENT)
+ format_status(UNSUPPORTED)
+#if 0 /* for OpenGL ES only */
+ format_status(INCOMPLETE_DIMENSIONS)
+#else /* for desktop GL only */
+ format_status(INCOMPLETE_DRAW_BUFFER)
+ format_status(INCOMPLETE_READ_BUFFER)
+ format_status(INCOMPLETE_MULTISAMPLE)
+ format_status(UNDEFINED)
+#endif
}
+#undef format_status
+
if (err_out) {
- BLI_snprintf(err_out, 256, "GPUFrameBuffer: framebuffer incomplete error %d '%s'",
- (int)status, err);
+ BLI_snprintf(err_out, 256, format, err);
}
else {
- fprintf(stderr, "GPUFrameBuffer: framebuffer incomplete error %d '%s'\n",
- (int)status, err);
+ fprintf(stderr, format, err);
}
}
@@ -102,41 +95,33 @@ GPUFrameBuffer *GPU_framebuffer_create(void)
{
GPUFrameBuffer *fb;
- if (!(GLEW_VERSION_3_0 || GLEW_ARB_framebuffer_object ||
- (GLEW_EXT_framebuffer_object && GLEW_EXT_framebuffer_blit)))
- {
- return NULL;
- }
-
fb = MEM_callocN(sizeof(GPUFrameBuffer), "GPUFrameBuffer");
- glGenFramebuffersEXT(1, &fb->object);
+ glGenFramebuffers(1, &fb->object);
if (!fb->object) {
- fprintf(stderr, "GPUFFrameBuffer: framebuffer gen failed. %d\n",
- (int)glGetError());
+ fprintf(stderr, "GPUFFrameBuffer: framebuffer gen failed.\n");
GPU_framebuffer_free(fb);
return NULL;
}
/* make sure no read buffer is enabled, so completeness check will not fail. We set those at binding time */
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
+ glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
glReadBuffer(GL_NONE);
glDrawBuffer(GL_NONE);
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
return fb;
}
-static int gpu_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int cubeface, char err_out[256])
+static int gpu_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int cubeface)
{
GLenum attachment;
- GLenum error;
if (slot >= GPU_FB_MAX_SLOTS) {
fprintf(stderr,
"Attaching to index %d framebuffer slot unsupported. "
"Use at most %d\n", slot, GPU_FB_MAX_SLOTS);
- return 0;
+ return false;
}
if ((G.debug & G_DEBUG)) {
@@ -148,16 +133,13 @@ static int gpu_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, i
}
if (GPU_texture_depth(tex))
- attachment = GL_DEPTH_ATTACHMENT_EXT;
+ attachment = GL_DEPTH_ATTACHMENT;
else
- attachment = GL_COLOR_ATTACHMENT0_EXT + slot;
+ attachment = GL_COLOR_ATTACHMENT0 + slot;
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
+ glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
GG.currentfb = fb->object;
- /* Clean glError buffer. */
- while (glGetError() != GL_NO_ERROR) {}
-
if (GPU_texture_target(tex) == GL_TEXTURE_CUBE_MAP)
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment,
GL_TEXTURE_CUBE_MAP_POSITIVE_X + cubeface, GPU_texture_opengl_bindcode(tex), 0);
@@ -165,14 +147,6 @@ static int gpu_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, i
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment,
GPU_texture_target(tex), GPU_texture_opengl_bindcode(tex), 0);
- error = glGetError();
-
- if (error == GL_INVALID_OPERATION) {
- GPU_framebuffer_restore();
- GPU_print_framebuffer_error(error, err_out);
- return 0;
- }
-
if (GPU_texture_depth(tex))
fb->depthtex = tex;
else
@@ -180,17 +154,17 @@ static int gpu_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, i
GPU_texture_framebuffer_set(tex, fb, slot);
- return 1;
+ return true;
}
-int GPU_framebuffer_cubeface_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int cubeface, char err_out[256])
+bool GPU_framebuffer_cubeface_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int cubeface)
{
- return gpu_framebuffer_texture_attach(fb, tex, slot, cubeface, err_out);
+ return gpu_framebuffer_texture_attach(fb, tex, slot, cubeface);
}
-int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, char err_out[256])
+bool GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot)
{
- return gpu_framebuffer_texture_attach(fb, tex, slot, 0, err_out);
+ return gpu_framebuffer_texture_attach(fb, tex, slot, 0);
}
void GPU_framebuffer_texture_detach(GPUTexture *tex)
@@ -203,21 +177,21 @@ void GPU_framebuffer_texture_detach(GPUTexture *tex)
return;
if (GG.currentfb != fb->object) {
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
+ glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
GG.currentfb = fb->object;
}
if (GPU_texture_depth(tex)) {
fb->depthtex = NULL;
- attachment = GL_DEPTH_ATTACHMENT_EXT;
+ attachment = GL_DEPTH_ATTACHMENT;
}
else {
BLI_assert(fb->colortex[fb_attachment] == tex);
fb->colortex[fb_attachment] = NULL;
- attachment = GL_COLOR_ATTACHMENT0_EXT + fb_attachment;
+ attachment = GL_COLOR_ATTACHMENT0 + fb_attachment;
}
- glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment, GPU_texture_target(tex), 0, 0);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GPU_texture_target(tex), 0, 0);
GPU_texture_framebuffer_set(tex, NULL, -1);
}
@@ -237,7 +211,7 @@ void GPU_texture_bind_as_framebuffer(GPUTexture *tex)
glDisable(GL_SCISSOR_TEST);
/* bind framebuffer */
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
+ glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
if (GPU_texture_depth(tex)) {
glDrawBuffer(GL_NONE);
@@ -245,8 +219,8 @@ void GPU_texture_bind_as_framebuffer(GPUTexture *tex)
}
else {
/* last bound prevails here, better allow explicit control here too */
- glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT + fb_attachment);
- glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + fb_attachment);
+ glDrawBuffer(GL_COLOR_ATTACHMENT0 + fb_attachment);
+ glReadBuffer(GL_COLOR_ATTACHMENT0 + fb_attachment);
}
if (GPU_texture_target(tex) == GL_TEXTURE_2D_MULTISAMPLE) {
@@ -275,7 +249,7 @@ void GPU_framebuffer_slots_bind(GPUFrameBuffer *fb, int slot)
for (i = 0; i < 4; i++) {
if (fb->colortex[i]) {
- attachments[numslots] = GL_COLOR_ATTACHMENT0_EXT + i;
+ attachments[numslots] = GL_COLOR_ATTACHMENT0 + i;
numslots++;
}
}
@@ -285,11 +259,11 @@ void GPU_framebuffer_slots_bind(GPUFrameBuffer *fb, int slot)
glDisable(GL_SCISSOR_TEST);
/* bind framebuffer */
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
+ glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
/* last bound prevails here, better allow explicit control here too */
glDrawBuffers(numslots, attachments);
- glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + slot);
+ glReadBuffer(GL_COLOR_ATTACHMENT0 + slot);
/* push matrices and set default viewport and matrix */
glViewport(0, 0, GPU_texture_width(fb->colortex[slot]), GPU_texture_height(fb->colortex[slot]));
@@ -316,10 +290,10 @@ void GPU_framebuffer_texture_unbind(GPUFrameBuffer *UNUSED(fb), GPUTexture *UNUS
void GPU_framebuffer_bind_no_save(GPUFrameBuffer *fb, int slot)
{
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
+ glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
/* last bound prevails here, better allow explicit control here too */
- glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT + slot);
- glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + slot);
+ glDrawBuffer(GL_COLOR_ATTACHMENT0 + slot);
+ glReadBuffer(GL_COLOR_ATTACHMENT0 + slot);
/* push matrices and set default viewport and matrix */
glViewport(0, 0, GPU_texture_width(fb->colortex[slot]), GPU_texture_height(fb->colortex[slot]));
@@ -334,22 +308,17 @@ bool GPU_framebuffer_bound(GPUFrameBuffer *fb)
bool GPU_framebuffer_check_valid(GPUFrameBuffer *fb, char err_out[256])
{
- GLenum status;
-
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
+ glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
GG.currentfb = fb->object;
-
- /* Clean glError buffer. */
- while (glGetError() != GL_NO_ERROR) {}
-
- status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
-
- if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+
+ GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
GPU_framebuffer_restore();
GPU_print_framebuffer_error(status, err_out);
return false;
}
-
+
return true;
}
@@ -367,10 +336,10 @@ void GPU_framebuffer_free(GPUFrameBuffer *fb)
}
if (fb->object) {
- glDeleteFramebuffersEXT(1, &fb->object);
+ glDeleteFramebuffers(1, &fb->object);
if (GG.currentfb == fb->object) {
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
GG.currentfb = 0;
}
}
@@ -381,7 +350,7 @@ void GPU_framebuffer_free(GPUFrameBuffer *fb)
void GPU_framebuffer_restore(void)
{
if (GG.currentfb != 0) {
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
GG.currentfb = 0;
}
}
@@ -406,8 +375,8 @@ void GPU_framebuffer_blur(
/* We do the bind ourselves rather than using GPU_framebuffer_texture_bind() to avoid
* pushing unnecessary matrices onto the OpenGL stack. */
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, blurfb->object);
- glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
+ glBindFramebuffer(GL_FRAMEBUFFER, blurfb->object);
+ glDrawBuffer(GL_COLOR_ATTACHMENT0);
/* avoid warnings from texture binding */
GG.currentfb = blurfb->object;
@@ -439,8 +408,8 @@ void GPU_framebuffer_blur(
/* Blurring vertically */
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
- glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
+ glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
+ glDrawBuffer(GL_COLOR_ATTACHMENT0);
GG.currentfb = fb->object;
@@ -546,12 +515,7 @@ GPUOffScreen *GPU_offscreen_create(int width, int height, int samples, char err_
}
if (samples) {
- if (!GLEW_EXT_framebuffer_multisample ||
- !GLEW_ARB_texture_multisample ||
- /* Only needed for GPU_offscreen_read_pixels.
- * We could add an arg if we intend to use multi-sample
- * offscreen buffers w/o reading their pixels */
- !GLEW_EXT_framebuffer_blit ||
+ if (!GLEW_ARB_texture_multisample ||
/* This is required when blitting from a multi-sampled buffers,
* even though we're not scaling. */
!GLEW_EXT_framebuffer_multisample_blit_scaled)
@@ -566,7 +530,7 @@ GPUOffScreen *GPU_offscreen_create(int width, int height, int samples, char err_
return NULL;
}
- if (!GPU_framebuffer_texture_attach(ofs->fb, ofs->depth, 0, err_out)) {
+ if (!GPU_framebuffer_texture_attach(ofs->fb, ofs->depth, 0)) {
GPU_offscreen_free(ofs);
return NULL;
}
@@ -577,7 +541,7 @@ GPUOffScreen *GPU_offscreen_create(int width, int height, int samples, char err_
return NULL;
}
- if (!GPU_framebuffer_texture_attach(ofs->fb, ofs->color, 0, err_out)) {
+ if (!GPU_framebuffer_texture_attach(ofs->fb, ofs->color, 0)) {
GPU_offscreen_free(ofs);
return NULL;
}
@@ -651,37 +615,37 @@ void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels)
#ifdef USE_FBO_CTX_SWITCH
/* read from multi-sample buffer */
- glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, ofs->color->fb->object);
- glFramebufferTexture2DEXT(
- GL_READ_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + ofs->color->fb_attachment,
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, ofs->color->fb->object);
+ glFramebufferTexture2D(
+ GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + ofs->color->fb_attachment,
GL_TEXTURE_2D_MULTISAMPLE, ofs->color->bindcode, 0);
- status = glCheckFramebufferStatusEXT(GL_READ_FRAMEBUFFER_EXT);
- if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ status = glCheckFramebufferStatusEXT(GL_READ_FRAMEBUFFER);
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
goto finally;
}
#endif
/* write into new single-sample buffer */
- glGenFramebuffersEXT(1, &fbo_blit);
- glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fbo_blit);
- glFramebufferTexture2DEXT(
- GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
+ glGenFramebuffers(1, &fbo_blit);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_blit);
+ glFramebufferTexture2D(
+ GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, tex_blit, 0);
- status = glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT);
- if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
goto finally;
}
/* perform the copy */
- glBlitFramebufferEXT(0, 0, w, h, 0, 0, w, h, GL_COLOR_BUFFER_BIT, GL_NEAREST);
+ glBlitFramebuffer(0, 0, w, h, 0, 0, w, h, GL_COLOR_BUFFER_BIT, GL_NEAREST);
/* read the results */
- glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, fbo_blit);
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo_blit);
glReadPixels(0, 0, w, h, GL_RGBA, type, pixels);
#ifdef USE_FBO_CTX_SWITCH
/* restore the original frame-bufer */
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, ofs->color->fb->object);
+ glBindFramebuffer(GL_FRAMEBUFFER, ofs->color->fb->object);
#undef USE_FBO_CTX_SWITCH
#endif
@@ -692,10 +656,8 @@ finally:
glDeleteTextures(1, &tex_blit);
}
if (fbo_blit) {
- glDeleteFramebuffersEXT(1, &fbo_blit);
+ glDeleteFramebuffers(1, &fbo_blit);
}
-
- GPU_ASSERT_NO_GL_ERRORS("Read Multi-Sample Pixels");
}
else {
glReadPixels(0, 0, w, h, GL_RGBA, type, pixels);
diff --git a/source/blender/gpu/intern/gpu_immediate.c b/source/blender/gpu/intern/gpu_immediate.c
new file mode 100644
index 00000000000..711afda1992
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_immediate.c
@@ -0,0 +1,67 @@
+/*
+ * ***** 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) 2016 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Mike Erwin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "GPU_immediate.h"
+#include "GPU_matrix.h"
+#include "UI_resources.h"
+
+#include "gpu_shader_private.h"
+
+void immBindBuiltinProgram(GPUBuiltinShader shader_id)
+{
+ GPUShader *shader = GPU_shader_get_builtin_shader(shader_id);
+ immBindProgram(shader->program);
+ gpuBindMatrices(shader->program);
+}
+
+void immUniformThemeColor(int color_id)
+{
+ float color[4];
+ UI_GetThemeColor4fv(color_id, color);
+ immUniformColor4fv(color);
+}
+
+void immUniformThemeColorShade(int color_id, int offset)
+{
+ float color[4];
+ UI_GetThemeColorShade4fv(color_id, offset, color);
+ immUniformColor4fv(color);
+}
+
+void immUniformThemeColorShadeAlpha(int color_id, int color_offset, int alpha_offset)
+{
+ float color[4];
+ UI_GetThemeColorShadeAlpha4fv(color_id, color_offset, alpha_offset, color);
+ immUniformColor4fv(color);
+}
+
+void immUniformThemeColorBlendShade(int color_id1, int color_id2, float fac, int offset)
+{
+ float color[4];
+ UI_GetThemeColorBlendShade4fv(color_id1, color_id2, fac, offset, color);
+ immUniformColor4fv(color);
+}
diff --git a/source/blender/gpu/intern/gpu_init_exit.c b/source/blender/gpu/intern/gpu_init_exit.c
index c72c83b6b07..817756a3088 100644
--- a/source/blender/gpu/intern/gpu_init_exit.c
+++ b/source/blender/gpu/intern/gpu_init_exit.c
@@ -31,7 +31,7 @@
#include "BLI_sys_types.h"
#include "GPU_init_exit.h" /* interface */
-
+#include "GPU_immediate.h"
#include "BKE_global.h"
#include "intern/gpu_codegen.h"
@@ -59,14 +59,18 @@ void GPU_init(void)
if (G.debug & G_DEBUG_GPU)
gpu_debug_init();
+ immInit();
}
void GPU_exit(void)
{
+ immDestroy();
+
if (G.debug & G_DEBUG_GPU)
gpu_debug_exit();
+
gpu_codegen_exit();
gpu_extensions_exit(); /* must come last */
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index b2345ed6545..9a0238a4cea 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -123,11 +123,6 @@ struct GPUMaterial {
int obcolloc, obautobumpscaleloc;
int cameratexcofacloc;
- int partscalarpropsloc;
- int partcoloc;
- int partvel;
- int partangvel;
-
/* Probe binding */
int brdfsamplesloc, lutsamplesloc, jitterloc;
int ltcmatloc, ltcmagloc;
@@ -334,45 +329,37 @@ static int GPU_material_construct_end(GPUMaterial *material, const char *passnam
material->obautobumpscaleloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_AUTO_BUMPSCALE));
if (material->builtins & GPU_CAMERA_TEXCO_FACTORS)
material->cameratexcofacloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_CAMERA_TEXCO_FACTORS));
- if (material->builtins & GPU_PARTICLE_SCALAR_PROPS)
- material->partscalarpropsloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_PARTICLE_SCALAR_PROPS));
- if (material->builtins & GPU_PARTICLE_LOCATION)
- material->partcoloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_PARTICLE_LOCATION));
- if (material->builtins & GPU_PARTICLE_VELOCITY)
- material->partvel = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_PARTICLE_VELOCITY));
- if (material->builtins & GPU_PARTICLE_ANG_VELOCITY)
- material->partangvel = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_PARTICLE_ANG_VELOCITY));
if (material->builtins & GPU_PBR) {
- material->brdfsamplesloc = GPU_shader_get_uniform(shader, "unfbsdfsamples");
- material->ltcmatloc = GPU_shader_get_uniform(shader, "unfltcmat");
- material->ltcmagloc = GPU_shader_get_uniform(shader, "unfltcmag");
- material->jitterloc = GPU_shader_get_uniform(shader, "unfjitter");
- material->lutsamplesloc = GPU_shader_get_uniform(shader, "unflutsamples");
- material->probeloc = GPU_shader_get_uniform(shader, "unfprobe");
- material->reflectloc = GPU_shader_get_uniform(shader, "unfreflect");
- material->refractloc = GPU_shader_get_uniform(shader, "unfrefract");
- material->lodfactorloc = GPU_shader_get_uniform(shader, "unflodfactor");
- material->shloc[0] = GPU_shader_get_uniform(shader, "unfsh0");
- material->shloc[1] = GPU_shader_get_uniform(shader, "unfsh1");
- material->shloc[2] = GPU_shader_get_uniform(shader, "unfsh2");
- material->shloc[3] = GPU_shader_get_uniform(shader, "unfsh3");
- material->shloc[4] = GPU_shader_get_uniform(shader, "unfsh4");
- material->shloc[5] = GPU_shader_get_uniform(shader, "unfsh5");
- material->shloc[6] = GPU_shader_get_uniform(shader, "unfsh6");
- material->shloc[7] = GPU_shader_get_uniform(shader, "unfsh7");
- material->shloc[8] = GPU_shader_get_uniform(shader, "unfsh8");
- material->correcmatloc = GPU_shader_get_uniform(shader, "unfprobecorrectionmat");
- material->planarreflloc = GPU_shader_get_uniform(shader, "unfplanarreflectmat");
- material->probecoloc = GPU_shader_get_uniform(shader, "unfprobepos");
- material->planarvecloc = GPU_shader_get_uniform(shader, "unfplanarvec");
- material->scenebufloc = GPU_shader_get_uniform(shader, "unfscenebuf");
- material->depthbufloc = GPU_shader_get_uniform(shader, "unfdepthbuf");
- material->backfacebufloc = GPU_shader_get_uniform(shader, "unfbackfacebuf");
- material->ssrparamsloc = GPU_shader_get_uniform(shader, "unfssrparam");
- material->pixelprojmatloc = GPU_shader_get_uniform(shader, "unfpixelprojmat");
- material->ssaoparamsloc = GPU_shader_get_uniform(shader, "unfssaoparam");
- material->clipinfoloc = GPU_shader_get_uniform(shader, "unfclip");
+ material->brdfsamplesloc= GPU_shader_get_uniform(shader, "unfbsdfsamples");
+ material->ltcmatloc= GPU_shader_get_uniform(shader, "unfltcmat");
+ material->ltcmagloc= GPU_shader_get_uniform(shader, "unfltcmag");
+ material->jitterloc= GPU_shader_get_uniform(shader, "unfjitter");
+ material->lutsamplesloc = GPU_shader_get_uniform(shader, "unflutsamples");
+ material->probeloc = GPU_shader_get_uniform(shader, "unfprobe");
+ material->reflectloc = GPU_shader_get_uniform(shader, "unfreflect");
+ material->refractloc = GPU_shader_get_uniform(shader, "unfrefract");
+ material->lodfactorloc = GPU_shader_get_uniform(shader, "unflodfactor");
+ material->shloc[0] = GPU_shader_get_uniform(shader, "unfsh0");
+ material->shloc[1] = GPU_shader_get_uniform(shader, "unfsh1");
+ material->shloc[2] = GPU_shader_get_uniform(shader, "unfsh2");
+ material->shloc[3] = GPU_shader_get_uniform(shader, "unfsh3");
+ material->shloc[4] = GPU_shader_get_uniform(shader, "unfsh4");
+ material->shloc[5] = GPU_shader_get_uniform(shader, "unfsh5");
+ material->shloc[6] = GPU_shader_get_uniform(shader, "unfsh6");
+ material->shloc[7] = GPU_shader_get_uniform(shader, "unfsh7");
+ material->shloc[8] = GPU_shader_get_uniform(shader, "unfsh8");
+ material->correcmatloc = GPU_shader_get_uniform(shader, "unfprobecorrectionmat");
+ material->planarreflloc = GPU_shader_get_uniform(shader, "unfplanarreflectmat");
+ material->probecoloc = GPU_shader_get_uniform(shader, "unfprobepos");
+ material->planarvecloc = GPU_shader_get_uniform(shader, "unfplanarvec");
+ material->scenebufloc = GPU_shader_get_uniform(shader, "unfscenebuf");
+ material->depthbufloc = GPU_shader_get_uniform(shader, "unfdepthbuf");
+ material->backfacebufloc = GPU_shader_get_uniform(shader, "unfbackfacebuf");
+ material->ssrparamsloc = GPU_shader_get_uniform(shader, "unfssrparam");
+ material->pixelprojmatloc = GPU_shader_get_uniform(shader, "unfpixelprojmat");
+ material->ssaoparamsloc = GPU_shader_get_uniform(shader, "unfssaoparam");
+ material->clipinfoloc = GPU_shader_get_uniform(shader, "unfclip");
}
return 1;
@@ -522,7 +509,7 @@ void GPU_material_bind(
void GPU_material_bind_uniforms(
GPUMaterial *material, float obmat[4][4], float viewmat[4][4], float obcol[4],
- float autobumpscale, GPUParticleInfo *pi)
+ float autobumpscale)
{
if (material->pass) {
GPUShader *shader = GPU_pass_shader(material->pass);
@@ -559,18 +546,6 @@ void GPU_material_bind_uniforms(
if (material->builtins & GPU_AUTO_BUMPSCALE) {
GPU_shader_uniform_vector(shader, material->obautobumpscaleloc, 1, 1, &autobumpscale);
}
- if (material->builtins & GPU_PARTICLE_SCALAR_PROPS) {
- GPU_shader_uniform_vector(shader, material->partscalarpropsloc, 4, 1, pi->scalprops);
- }
- if (material->builtins & GPU_PARTICLE_LOCATION) {
- GPU_shader_uniform_vector(shader, material->partcoloc, 3, 1, pi->location);
- }
- if (material->builtins & GPU_PARTICLE_VELOCITY) {
- GPU_shader_uniform_vector(shader, material->partvel, 3, 1, pi->velocity);
- }
- if (material->builtins & GPU_PARTICLE_ANG_VELOCITY) {
- GPU_shader_uniform_vector(shader, material->partangvel, 3, 1, pi->angular_velocity);
- }
}
}
@@ -3463,7 +3438,7 @@ GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par, bool use_r
return lamp;
}
- if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->depthtex, 0, NULL)) {
+ if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->depthtex, 0)) {
gpu_lamp_shadow_free(lamp);
return lamp;
}
@@ -3475,7 +3450,7 @@ GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par, bool use_r
return lamp;
}
- if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, 0, NULL)) {
+ if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, 0)) {
gpu_lamp_shadow_free(lamp);
return lamp;
}
@@ -3498,7 +3473,7 @@ GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par, bool use_r
return lamp;
}
- if (!GPU_framebuffer_texture_attach(lamp->blurfb, lamp->blurtex, 0, NULL)) {
+ if (!GPU_framebuffer_texture_attach(lamp->blurfb, lamp->blurtex, 0)) {
gpu_lamp_shadow_free(lamp);
return lamp;
}
@@ -3520,7 +3495,7 @@ GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par, bool use_r
return lamp;
}
- if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, 0, NULL)) {
+ if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, 0)) {
gpu_lamp_shadow_free(lamp);
return lamp;
}
diff --git a/source/blender/gpu/intern/gpu_matrix.c b/source/blender/gpu/intern/gpu_matrix.c
new file mode 100644
index 00000000000..9abce9d6816
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_matrix.c
@@ -0,0 +1,637 @@
+/*
+ * ***** 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 ipmlied 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) 2012 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Alexandr Kuznetsov, Jason Wilkins, Mike Erwin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/gpu/intern/gpu_matrix.c
+ * \ingroup gpu
+ */
+
+#include "GPU_matrix.h"
+
+#include "BLI_math_matrix.h"
+#include "BLI_math_rotation.h"
+#include "BLI_math_vector.h"
+
+
+#define DEBUG_MATRIX_BIND 0
+
+#define MATRIX_STACK_DEPTH 32
+
+typedef float Mat4[4][4];
+typedef float Mat3[3][3];
+
+typedef struct {
+ Mat4 ModelViewStack3D[MATRIX_STACK_DEPTH];
+ Mat4 ProjectionMatrix3D;
+
+ Mat3 ModelViewStack2D[MATRIX_STACK_DEPTH];
+ Mat3 ProjectionMatrix2D;
+
+ MatrixMode mode;
+ unsigned top; /* of current stack (would have to replicate if gpuResume2D/3D are implemented) */
+
+ /* TODO: cache of derived matrices (Normal, MVP, inverse MVP, etc)
+ * generate as needed for shaders, invalidate when original matrices change
+ *
+ * TODO: separate Model from View transform? Batches/objects have model,
+ * camera/eye has view & projection
+ */
+} MatrixState;
+
+static MatrixState state; /* TODO(merwin): make part of GPUContext, alongside immediate mode & state tracker */
+
+#define ModelView3D state.ModelViewStack3D[state.top]
+#define ModelView2D state.ModelViewStack2D[state.top]
+#define Projection3D state.ProjectionMatrix3D
+#define Projection2D state.ProjectionMatrix2D
+
+void gpuMatrixInit()
+{
+ memset(&state, 0, sizeof(MatrixState));
+}
+
+void gpuMatrixBegin2D()
+{
+ state.mode = MATRIX_MODE_2D;
+ state.top = 0;
+ unit_m3(ModelView2D);
+ gpuOrtho2D(-1.0f, +1.0f, -1.0f, +1.0f); // or identity?
+}
+
+void gpuMatrixBegin3D()
+{
+ state.mode = MATRIX_MODE_3D;
+ state.top = 0;
+ unit_m4(ModelView3D);
+ gpuOrtho(-1.0f, +1.0f, -1.0f, +1.0f, -1.0f, +1.0f); // or identity?
+}
+
+#if SUPPORT_LEGACY_MATRIX
+void gpuMatrixBegin3D_legacy()
+{
+ /* copy top matrix from each legacy stack into new fresh stack */
+ state.mode = MATRIX_MODE_3D;
+ state.top = 0;
+ glGetFloatv(GL_MODELVIEW_MATRIX, (float*)ModelView3D);
+ glGetFloatv(GL_PROJECTION_MATRIX, (float*)Projection3D);
+}
+#endif
+
+void gpuMatrixEnd()
+{
+ state.mode = MATRIX_MODE_INACTIVE;
+}
+
+
+#ifdef WITH_GPU_SAFETY
+
+/* Check if matrix is numerically good */
+static void checkmat(cosnt float *m)
+{
+ const int n = state.mode == MATRIX_MODE_3D ? 16 : 9;
+ for (int i = 0; i < n; i++) {
+#if _MSC_VER
+ BLI_assert(_finite(m[i]));
+#else
+ BLI_assert(!isinf(m[i]));
+#endif
+ }
+}
+
+#define CHECKMAT(m) checkmat((const float*)m)
+
+#else
+
+#define CHECKMAT(m)
+
+#endif
+
+
+void gpuPushMatrix()
+{
+ BLI_assert(state.mode != MATRIX_MODE_INACTIVE);
+ BLI_assert(state.top < MATRIX_STACK_DEPTH);
+ state.top++;
+ if (state.mode == MATRIX_MODE_3D)
+ copy_m4_m4(ModelView3D, state.ModelViewStack3D[state.top - 1]);
+ else
+ copy_m3_m3(ModelView2D, state.ModelViewStack2D[state.top - 1]);
+}
+
+void gpuPopMatrix()
+{
+ BLI_assert(state.mode != MATRIX_MODE_INACTIVE);
+ BLI_assert(state.top > 0);
+ state.top--;
+}
+
+void gpuLoadMatrix3D(const float m[4][4])
+{
+ BLI_assert(state.mode == MATRIX_MODE_3D);
+ copy_m4_m4(ModelView3D, m);
+ CHECKMAT(ModelView3D);
+}
+
+void gpuLoadMatrix2D(const float m[3][3])
+{
+ BLI_assert(state.mode == MATRIX_MODE_2D);
+ copy_m3_m3(ModelView2D, m);
+ CHECKMAT(ModelView2D);
+}
+
+void gpuLoadIdentity()
+{
+ switch (state.mode) {
+ case MATRIX_MODE_3D:
+ unit_m4(ModelView3D);
+ break;
+ case MATRIX_MODE_2D:
+ unit_m3(ModelView2D);
+ break;
+ default:
+ BLI_assert(false);
+ }
+}
+
+void gpuTranslate2f(float x, float y)
+{
+ Mat3 m;
+ unit_m3(m);
+ m[2][0] = x;
+ m[2][1] = y;
+ gpuMultMatrix2D(m);
+}
+
+void gpuTranslate2fv(const float vec[2])
+{
+ gpuTranslate2f(vec[0], vec[1]);
+}
+
+void gpuTranslate3f(float x, float y, float z)
+{
+#if 1
+ BLI_assert(state.mode == MATRIX_MODE_3D);
+ translate_m4(ModelView3D, x, y, z);
+ CHECKMAT(ModelView3D);
+#else /* above works well in early testing, below is generic version */
+ Mat4 m;
+ unit_m4(m);
+ m[3][0] = x;
+ m[3][1] = y;
+ m[3][2] = z;
+ gpuMultMatrix3D(m);
+#endif
+}
+
+void gpuTranslate3fv(const float vec[3])
+{
+ gpuTranslate3f(vec[0], vec[1], vec[2]);
+}
+
+void gpuScaleUniform(float factor)
+{
+ switch (state.mode) {
+ case MATRIX_MODE_3D:
+ {
+ Mat4 m;
+ scale_m4_fl(m, factor);
+ gpuMultMatrix3D(m);
+ break;
+ }
+ case MATRIX_MODE_2D:
+ {
+ #if 0
+ Mat3 m;
+ scale_m3_fl(m, factor);
+ /* this does 3D scaling in a 3x3 matrix. Can 2D scaling use this safely, or must set m[2][2] = 1.0? */
+ #else
+ Mat3 m = {{0.0f}};
+ m[0][0] = factor;
+ m[1][1] = factor;
+ m[2][2] = 1.0f;
+ #endif
+ gpuMultMatrix2D(m);
+ break;
+ }
+ default:
+ BLI_assert(false);
+ }
+}
+
+void gpuScale2f(float x, float y)
+{
+ Mat3 m = {{0.0f}};
+ m[0][0] = x;
+ m[1][1] = y;
+ m[2][2] = 1.0f;
+ gpuMultMatrix2D(m);
+}
+
+void gpuScale2fv(const float vec[2])
+{
+ gpuScale2f(vec[0], vec[1]);
+}
+
+void gpuScale3f(float x, float y, float z)
+{
+ Mat4 m = {{0.0f}};
+ m[0][0] = x;
+ m[1][1] = y;
+ m[2][2] = z;
+ m[3][3] = 1.0f;
+ gpuMultMatrix3D(m);
+}
+
+void gpuScale3fv(const float vec[3])
+{
+ gpuScale3f(vec[0], vec[1], vec[2]);
+}
+
+void gpuMultMatrix3D(const float m[4][4])
+{
+ BLI_assert(state.mode == MATRIX_MODE_3D);
+ mul_m4_m4_pre(ModelView3D, m);
+ CHECKMAT(ModelView3D);
+}
+
+void gpuMultMatrix2D(const float m[3][3])
+{
+ BLI_assert(state.mode == MATRIX_MODE_2D);
+ mul_m3_m3_pre(ModelView2D, m);
+ CHECKMAT(ModelView2D);
+}
+
+void gpuRotate3fv(float deg, const float axis[3])
+{
+ Mat4 m;
+ axis_angle_to_mat4(m, axis, DEG2RADF(deg));
+ gpuMultMatrix3D(m);
+}
+
+void gpuRotateAxis(float deg, char axis)
+{
+#if 1 /* rotate_m4 works in place, right? */
+ BLI_assert(state.mode == MATRIX_MODE_3D);
+ rotate_m4(ModelView3D, axis, DEG2RADF(deg));
+ CHECKMAT(ModelView3D);
+#else /* rotate_m4 creates a new matrix */
+ Mat4 m;
+ rotate_m4(m, axis, DEG2RADF(deg));
+ gpuMultMatrix3D(m);
+#endif
+}
+
+static void mat4_ortho_set(float m[4][4], float left, float right, float bottom, float top, float near, float far)
+{
+ m[0][0] = 2.0f / (right - left);
+ m[1][0] = 0.0f;
+ m[2][0] = 0.0f;
+ m[3][0] = -(right + left) / (right - left);
+
+ m[0][1] = 0.0f;
+ m[1][1] = 2.0f / (top - bottom);
+ m[2][1] = 0.0f;
+ m[3][1] = -(top + bottom) / (top - bottom);
+
+ m[0][2] = 0.0f;
+ m[1][2] = 0.0f;
+ m[2][2] = -2.0f / (far - near);
+ m[3][2] = -(far + near) / (far - near);
+
+ m[0][3] = 0.0f;
+ m[1][3] = 0.0f;
+ m[2][3] = 0.0f;
+ m[3][3] = 1.0f;
+}
+
+static void mat4_frustum_set(float m[][4], float left, float right, float bottom, float top, float near, float far)
+{
+ m[0][0] = 2.0f * near / (right - left);
+ m[1][0] = 0.0f;
+ m[2][0] = (right + left) / (right - left);
+ m[3][0] = 0.0f;
+
+ m[0][1] = 0.0f;
+ m[1][1] = 2.0f * near / (top - bottom);
+ m[2][1] = (top + bottom) / (top - bottom);
+ m[3][1] = 0.0f;
+
+ m[0][2] = 0.0f;
+ m[1][2] = 0.0f;
+ m[2][2] = -(far + near) / (far - near);
+ m[3][2] = -2.0f * far * near / (far - near);
+
+ m[0][3] = 0.0f;
+ m[1][3] = 0.0f;
+ m[2][3] = -1.0f;
+ m[3][3] = 0.0f;
+}
+
+static void mat4_look_from_origin(float m[4][4], float lookdir[3], float camup[3])
+{
+/* This function is loosely based on Mesa implementation.
+ *
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+ float side[3];
+
+ normalize_v3(lookdir);
+
+ cross_v3_v3v3(side, lookdir, camup);
+
+ normalize_v3(side);
+
+ cross_v3_v3v3(camup, side, lookdir);
+
+ m[0][0] = side[0];
+ m[1][0] = side[1];
+ m[2][0] = side[2];
+ m[3][0] = 0.0f;
+
+ m[0][1] = camup[0];
+ m[1][1] = camup[1];
+ m[2][1] = camup[2];
+ m[3][1] = 0.0f;
+
+ m[0][2] = -lookdir[0];
+ m[1][2] = -lookdir[1];
+ m[2][2] = -lookdir[2];
+ m[3][2] = 0.0f;
+
+ m[0][3] = 0.0f;
+ m[1][3] = 0.0f;
+ m[2][3] = 0.0f;
+ m[3][3] = 1.0f;
+}
+
+void gpuOrtho(float left, float right, float bottom, float top, float near, float far)
+{
+ BLI_assert(state.mode == MATRIX_MODE_3D);
+ mat4_ortho_set(Projection3D, left, right, bottom, top, near, far);
+ CHECKMAT(Projection3D);
+}
+
+void gpuOrtho2D(float left, float right, float bottom, float top)
+{
+ /* TODO: this function, but correct */
+ BLI_assert(state.mode == MATRIX_MODE_2D);
+ Mat4 m;
+ mat4_ortho_set(m, left, right, bottom, top, -1.0f, 1.0f);
+ copy_m3_m4(Projection2D, m);
+ CHECKMAT(Projection2D);
+}
+
+void gpuFrustum(float left, float right, float bottom, float top, float near, float far)
+{
+ BLI_assert(state.mode == MATRIX_MODE_3D);
+ mat4_frustum_set(Projection3D, left, right, bottom, top, near, far);
+ CHECKMAT(Projection3D);
+}
+
+void gpuPerspective(float fovy, float aspect, float near, float far)
+{
+ float half_height = tanf(fovy * (float)(M_PI / 360.0)) * near;
+ float half_width = half_height * aspect;
+ gpuFrustum(-half_width, +half_width, -half_height, +half_height, near, far);
+}
+
+void gpuLookAt(float eyeX, float eyeY, float eyeZ, float centerX, float centerY, float centerZ, float upX, float upY, float upZ)
+{
+ Mat4 cm;
+ float lookdir[3];
+ float camup[3] = {upX, upY, upZ};
+
+ lookdir[0] = centerX - eyeX;
+ lookdir[1] = centerY - eyeY;
+ lookdir[2] = centerZ - eyeZ;
+
+ mat4_look_from_origin(cm, lookdir, camup);
+
+ gpuMultMatrix3D(cm);
+ gpuTranslate3f(-eyeX, -eyeY, -eyeZ);
+}
+
+void gpuProject(const float obj[3], const float model[4][4], const float proj[4][4], const GLint view[4], float win[3])
+{
+ float v[4];
+
+ mul_v4_m4v3(v, model, obj);
+ mul_m4_v4(proj, v);
+
+ win[0] = view[0] + (view[2] * (v[0] + 1)) * 0.5f;
+ win[1] = view[1] + (view[3] * (v[1] + 1)) * 0.5f;
+ win[2] = (v[2] + 1) * 0.5f;
+}
+
+bool gpuUnProject(const float win[3], const float model[4][4], const float proj[4][4], const GLint view[4], float obj[3])
+{
+ float pm[4][4];
+ float in[4];
+ float out[4];
+
+ mul_m4_m4m4(pm, proj, model);
+
+ if (!invert_m4(pm)) {
+ return false;
+ }
+
+ in[0] = win[0];
+ in[1] = win[1];
+ in[2] = win[2];
+ in[3] = 1;
+
+ /* Map x and y from window coordinates */
+ in[0] = (in[0] - view[0]) / view[2];
+ in[1] = (in[1] - view[1]) / view[3];
+
+ /* Map to range -1 to +1 */
+ in[0] = 2 * in[0] - 1;
+ in[1] = 2 * in[1] - 1;
+ in[2] = 2 * in[2] - 1;
+
+ mul_v4_m4v3(out, pm, in);
+
+ if (out[3] == 0.0f) {
+ return false;
+ }
+ else {
+ out[0] /= out[3];
+ out[1] /= out[3];
+ out[2] /= out[3];
+
+ obj[0] = out[0];
+ obj[1] = out[1];
+ obj[2] = out[2];
+
+ return true;
+ }
+}
+
+const float *gpuGetModelViewMatrix3D(float m[4][4])
+{
+#if SUPPORT_LEGACY_MATRIX
+ if (state.mode == MATRIX_MODE_INACTIVE) {
+ if (m == NULL) {
+ static Mat4 temp;
+ m = temp;
+ }
+
+ glGetFloatv(GL_MODELVIEW_MATRIX, (float*)m);
+ return (const float*)m;
+ }
+#endif
+
+ BLI_assert(state.mode == MATRIX_MODE_3D);
+
+ if (m) {
+ copy_m4_m4(m, ModelView3D);
+ return (const float*)m;
+ }
+ else {
+ return (const float*)ModelView3D;
+ }
+}
+
+const float *gpuGetProjectionMatrix3D(float m[4][4])
+{
+#if SUPPORT_LEGACY_MATRIX
+ if (state.mode == MATRIX_MODE_INACTIVE) {
+ if (m == NULL) {
+ static Mat4 temp;
+ m = temp;
+ }
+
+ glGetFloatv(GL_PROJECTION_MATRIX, (float*)m);
+ return (const float*)m;
+ }
+#endif
+
+ BLI_assert(state.mode == MATRIX_MODE_3D);
+
+ if (m) {
+ copy_m4_m4(m, ModelView3D);
+ return (const float*)m;
+ }
+ else {
+ return (const float*)ModelView3D;
+ }
+}
+
+const float *gpuGetModelViewProjectionMatrix3D(float m[4][4])
+{
+#if SUPPORT_LEGACY_MATRIX
+ if (state.mode == MATRIX_MODE_INACTIVE) {
+ if (m == NULL) {
+ static Mat4 temp;
+ m = temp;
+ }
+
+ Mat4 proj;
+ glGetFloatv(GL_MODELVIEW_MATRIX, (float*)proj);
+ glGetFloatv(GL_PROJECTION_MATRIX, (float*)m);
+ mul_m4_m4_post(m, proj);
+ return (const float*)m;
+ }
+#endif
+
+ BLI_assert(state.mode == MATRIX_MODE_3D);
+
+ if (m == NULL) {
+ static Mat4 temp;
+ m = temp;
+ }
+
+ mul_m4_m4m4(m, Projection3D, ModelView3D);
+ return (const float*)m;
+}
+
+void gpuBindMatrices(GLuint program)
+{
+ /* TODO: split this into 2 functions
+ * 1) get uniform locations & determine 2D or 3D
+ */
+ GLint loc_MV = glGetUniformLocation(program, "ModelViewMatrix");
+ GLint loc_P = glGetUniformLocation(program, "ProjectionMatrix");
+ GLint loc_MVP = glGetUniformLocation(program, "ModelViewProjectionMatrix");
+
+ /* 2) set uniform values to matrix stack values
+ * program needs to be bound
+ */
+ glUseProgram(program);
+
+
+ /* call this portion before a draw call if desired matrices are dirty */
+ if (loc_MV != -1) {
+ #if DEBUG_MATRIX_BIND
+ puts("setting 3D MV matrix");
+ #endif
+
+ glUniformMatrix4fv(loc_MV, 1, GL_FALSE, gpuGetModelViewMatrix3D(NULL));
+ }
+
+ if (loc_P != -1) {
+ #if DEBUG_MATRIX_BIND
+ puts("setting 3D P matrix");
+ #endif
+
+ glUniformMatrix4fv(loc_P, 1, GL_FALSE, gpuGetProjectionMatrix3D(NULL));
+ }
+
+ if (loc_MVP != -1) {
+ #if DEBUG_MATRIX_BIND
+ puts("setting 3D MVP matrix");
+ #endif
+
+ glUniformMatrix4fv(loc_MVP, 1, GL_FALSE, gpuGetModelViewProjectionMatrix3D(NULL));
+ }
+}
diff --git a/source/blender/gpu/intern/gpu_shader.c b/source/blender/gpu/intern/gpu_shader.c
index 226595200ca..2434ecf01a4 100644
--- a/source/blender/gpu/intern/gpu_shader.c
+++ b/source/blender/gpu/intern/gpu_shader.c
@@ -36,15 +36,49 @@
#include "GPU_compositing.h"
#include "GPU_debug.h"
#include "GPU_extensions.h"
-#include "GPU_glew.h"
#include "GPU_shader.h"
#include "GPU_texture.h"
+#include "gpu_shader_private.h"
+
/* TODO(sergey): Find better default values for this constants. */
#define MAX_DEFINE_LENGTH 1024
#define MAX_EXT_DEFINE_LENGTH 1024
/* Non-generated shaders */
+extern char datatoc_gpu_shader_depth_only_frag_glsl[];
+extern char datatoc_gpu_shader_uniform_color_frag_glsl[];
+extern char datatoc_gpu_shader_flat_color_frag_glsl[];
+extern char datatoc_gpu_shader_2D_vert_glsl[];
+extern char datatoc_gpu_shader_2D_flat_color_vert_glsl[];
+extern char datatoc_gpu_shader_2D_smooth_color_vert_glsl[];
+extern char datatoc_gpu_shader_2D_smooth_color_frag_glsl[];
+extern char datatoc_gpu_shader_3D_image_vert_glsl[];
+extern char datatoc_gpu_shader_image_modulate_alpha_frag_glsl[];
+extern char datatoc_gpu_shader_image_rect_modulate_alpha_frag_glsl[];
+extern char datatoc_gpu_shader_3D_vert_glsl[];
+extern char datatoc_gpu_shader_3D_flat_color_vert_glsl[];
+extern char datatoc_gpu_shader_3D_smooth_color_vert_glsl[];
+extern char datatoc_gpu_shader_3D_smooth_color_frag_glsl[];
+
+extern char datatoc_gpu_shader_point_uniform_color_frag_glsl[];
+extern char datatoc_gpu_shader_point_uniform_color_smooth_frag_glsl[];
+extern char datatoc_gpu_shader_point_uniform_color_outline_smooth_frag_glsl[];
+extern char datatoc_gpu_shader_point_varying_color_outline_smooth_frag_glsl[];
+extern char datatoc_gpu_shader_point_varying_color_frag_glsl[];
+extern char datatoc_gpu_shader_3D_point_fixed_size_varying_color_vert_glsl[];
+extern char datatoc_gpu_shader_3D_point_varying_size_vert_glsl[];
+extern char datatoc_gpu_shader_3D_point_varying_size_varying_color_vert_glsl[];
+extern char datatoc_gpu_shader_3D_point_uniform_size_smooth_vert_glsl[];
+extern char datatoc_gpu_shader_3D_point_uniform_size_outline_smooth_vert_glsl[];
+extern char datatoc_gpu_shader_2D_point_varying_size_varying_color_vert_glsl[];
+extern char datatoc_gpu_shader_2D_point_uniform_size_smooth_vert_glsl[];
+extern char datatoc_gpu_shader_2D_point_uniform_size_outline_smooth_vert_glsl[];
+extern char datatoc_gpu_shader_2D_point_uniform_size_varying_color_outline_smooth_vert_glsl[];
+
+extern char datatoc_gpu_shader_text_vert_glsl[];
+extern char datatoc_gpu_shader_text_frag_glsl[];
+
extern char datatoc_gpu_shader_fire_frag_glsl[];
extern char datatoc_gpu_shader_smoke_vert_glsl[];
extern char datatoc_gpu_shader_smoke_frag_glsl[];
@@ -81,32 +115,43 @@ static struct GPUShadersGlobal {
GPUShader *minz_downsample;
/* cache for shader fx. Those can exist in combinations so store them here */
GPUShader *fx_shaders[MAX_FX_SHADERS * 2];
+ /* for drawing text */
+ GPUShader *text;
+ /* for drawing images */
+ GPUShader *image_modulate_alpha_3D;
+ GPUShader *image_rect_modulate_alpha_3D;
+ /* for simple 2D drawing */
+ GPUShader *uniform_color_2D;
+ GPUShader *flat_color_2D;
+ GPUShader *smooth_color_2D;
+ /* for simple 3D drawing */
+ GPUShader *uniform_color_3D;
+ GPUShader *flat_color_3D;
+ GPUShader *smooth_color_3D;
+ GPUShader *depth_only_3D;
+ /* points */
+ GPUShader *point_fixed_size_uniform_color_2D;
+ GPUShader *point_varying_size_varying_color_2D;
+ GPUShader *point_uniform_size_uniform_color_smooth_2D;
+ GPUShader *point_uniform_size_uniform_color_outline_smooth_2D;
+ GPUShader *point_uniform_size_varying_color_outline_smooth_2D;
+ GPUShader *point_fixed_size_uniform_color_3D;
+ GPUShader *point_fixed_size_varying_color_3D;
+ GPUShader *point_varying_size_uniform_color_3D;
+ GPUShader *point_varying_size_varying_color_3D;
+ GPUShader *point_uniform_size_uniform_color_smooth_3D;
+ GPUShader *point_uniform_size_uniform_color_outline_smooth_3D;
} shaders;
} GG = {{NULL}};
-/* GPUShader */
-
-struct GPUShader {
- GLuint program; /* handle for full program (links shader stages below) */
-
- GLuint vertex; /* handle for vertex shader */
- GLuint geometry; /* handle for geometry shader */
- GLuint fragment; /* handle for fragment shader */
-
- int totattrib; /* total number of attributes */
- int uniforms; /* required uniforms */
-
- void *uniform_interface; /* cached uniform interface for shader. Data depends on shader */
-};
static void shader_print_errors(const char *task, const char *log, const char **code, int totcode)
{
- int i;
int line = 1;
fprintf(stderr, "GPUShader: %s error:\n", task);
- for (i = 0; i < totcode; i++) {
+ for (int i = 0; i < totcode; i++) {
const char *c, *pos, *end = code[i] + strlen(code[i]);
if (G.debug & G_DEBUG) {
@@ -129,9 +174,9 @@ static void shader_print_errors(const char *task, const char *log, const char **
static const char *gpu_shader_version(void)
{
- if (GLEW_VERSION_3_2) {
- if (GLEW_ARB_compatibility) {
- return "#version 150 compatibility\n";
+ if (GLEW_VERSION_3_3) {
+ if (GPU_legacy_support()) {
+ return "#version 330 compatibility\n";
/* highest version that is widely supported
* gives us native geometry shaders!
* use compatibility profile so we can continue using builtin shader input/output names
@@ -142,16 +187,6 @@ static const char *gpu_shader_version(void)
/* latest version that is compatible with existing shaders */
}
}
- else if (GLEW_VERSION_3_1) {
- if (GLEW_ARB_compatibility) {
- return "#version 140\n";
- /* also need the ARB_compatibility extension, handled below */
- }
- else {
- return "#version 130\n";
- /* latest version that is compatible with existing shaders */
- }
- }
else if (GLEW_VERSION_3_0) {
return "#version 130\n";
/* GLSL 1.3 has modern syntax/keywords/datatypes so use if available
@@ -193,9 +228,8 @@ static void gpu_shader_standard_extensions(char defines[MAX_EXT_DEFINE_LENGTH],
strcat(defines, "#extension GL_ARB_draw_instanced: enable\n");
}
- if (!GLEW_VERSION_3_0 && GLEW_EXT_gpu_shader4) {
- strcat(defines, "#extension GL_EXT_gpu_shader4: enable\n");
- /* TODO: maybe require this? shaders become so much nicer */
+ if (!GLEW_VERSION_3_0) {
+ strcat(defines, "#extension GL_EXT_gpu_shader4: require\n");
}
}
}
@@ -507,20 +541,20 @@ GPUShader *GPU_shader_create_ex(const char *vertexcode,
void GPU_shader_bind(GPUShader *shader)
{
- GPU_ASSERT_NO_GL_ERRORS("Pre Shader Bind");
+ BLI_assert(shader && shader->program);
+
glUseProgram(shader->program);
- GPU_ASSERT_NO_GL_ERRORS("Post Shader Bind");
}
void GPU_shader_unbind(void)
{
- GPU_ASSERT_NO_GL_ERRORS("Pre Shader Unbind");
glUseProgram(0);
- GPU_ASSERT_NO_GL_ERRORS("Post Shader Unbind");
}
void GPU_shader_free(GPUShader *shader)
{
+ BLI_assert(shader);
+
if (shader->vertex)
glDeleteShader(shader->vertex);
if (shader->geometry)
@@ -538,6 +572,8 @@ void GPU_shader_free(GPUShader *shader)
int GPU_shader_get_uniform(GPUShader *shader, const char *name)
{
+ BLI_assert(shader && shader->program);
+
return glGetUniformLocation(shader->program, name);
}
@@ -556,16 +592,12 @@ void GPU_shader_uniform_vector(GPUShader *UNUSED(shader), int location, int leng
if (location == -1 || value == NULL)
return;
- GPU_ASSERT_NO_GL_ERRORS("Pre Uniform Vector");
-
if (length == 1) glUniform1fv(location, arraysize, value);
else if (length == 2) glUniform2fv(location, arraysize, value);
else if (length == 3) glUniform3fv(location, arraysize, value);
else if (length == 4) glUniform4fv(location, arraysize, value);
else if (length == 9) glUniformMatrix3fv(location, arraysize, 0, value);
else if (length == 16) glUniformMatrix4fv(location, arraysize, 0, value);
-
- GPU_ASSERT_NO_GL_ERRORS("Post Uniform Vector");
}
void GPU_shader_uniform_vector_int(GPUShader *UNUSED(shader), int location, int length, int arraysize, const int *value)
@@ -573,14 +605,10 @@ void GPU_shader_uniform_vector_int(GPUShader *UNUSED(shader), int location, int
if (location == -1)
return;
- GPU_ASSERT_NO_GL_ERRORS("Pre Uniform Vector");
-
if (length == 1) glUniform1iv(location, arraysize, value);
else if (length == 2) glUniform2iv(location, arraysize, value);
else if (length == 3) glUniform3iv(location, arraysize, value);
else if (length == 4) glUniform4iv(location, arraysize, value);
-
- GPU_ASSERT_NO_GL_ERRORS("Post Uniform Vector");
}
void GPU_shader_uniform_int(GPUShader *UNUSED(shader), int location, int value)
@@ -588,7 +616,7 @@ void GPU_shader_uniform_int(GPUShader *UNUSED(shader), int location, int value)
if (location == -1)
return;
- GPU_CHECK_ERRORS_AROUND(glUniform1i(location, value));
+ glUniform1i(location, value);
}
void GPU_shader_geometry_stage_primitive_io(GPUShader *shader, int input, int output, int number)
@@ -619,8 +647,6 @@ void GPU_shader_uniform_texture(GPUShader *UNUSED(shader), int location, GPUText
if (location == -1)
return;
- GPU_ASSERT_NO_GL_ERRORS("Pre Uniform Texture");
-
arbnumber = (GLenum)((GLuint)GL_TEXTURE0 + number);
if (number != 0) glActiveTexture(arbnumber);
@@ -631,17 +657,13 @@ void GPU_shader_uniform_texture(GPUShader *UNUSED(shader), int location, GPUText
glUniform1i(location, number);
glEnable(target);
if (number != 0) glActiveTexture(GL_TEXTURE0);
-
- GPU_ASSERT_NO_GL_ERRORS("Post Uniform Texture");
}
int GPU_shader_get_attribute(GPUShader *shader, const char *name)
{
- int index;
-
- GPU_CHECK_ERRORS_AROUND(index = glGetAttribLocation(shader->program, name));
+ BLI_assert(shader && shader->program);
- return index;
+ return glGetAttribLocation(shader->program, name);
}
GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
@@ -659,64 +681,215 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
sprintf(buf, "#define CUBEMAP_RES %d \n", samples);
GG.shaders.compute_sh[shadn] = GPU_shader_create(
- datatoc_gpu_shader_probe_sh_compute_vert_glsl, datatoc_gpu_shader_probe_sh_compute_frag_glsl,
+ datatoc_gpu_shader_probe_sh_compute_vert_glsl,
+ datatoc_gpu_shader_probe_sh_compute_frag_glsl,
NULL, NULL, buf, 0, 0, 0);
}
retval = GG.shaders.compute_sh[shadn];
+ goto exit;
}
- else {
- switch (shader) {
- case GPU_SHADER_VSM_STORE:
- if (!GG.shaders.vsm_store)
- GG.shaders.vsm_store = GPU_shader_create(
- datatoc_gpu_shader_vsm_store_vert_glsl, datatoc_gpu_shader_vsm_store_frag_glsl,
- NULL, NULL, NULL, 0, 0, 0);
- retval = GG.shaders.vsm_store;
- break;
- case GPU_SHADER_SEP_GAUSSIAN_BLUR:
- if (!GG.shaders.sep_gaussian_blur)
- GG.shaders.sep_gaussian_blur = GPU_shader_create(
- datatoc_gpu_shader_sep_gaussian_blur_vert_glsl,
- datatoc_gpu_shader_sep_gaussian_blur_frag_glsl,
- NULL, NULL, NULL, 0, 0, 0);
- retval = GG.shaders.sep_gaussian_blur;
- break;
- case GPU_SHADER_SMOKE:
- if (!GG.shaders.smoke)
- GG.shaders.smoke = GPU_shader_create(
- datatoc_gpu_shader_smoke_vert_glsl, datatoc_gpu_shader_smoke_frag_glsl,
- NULL, NULL, NULL, 0, 0, 0);
- retval = GG.shaders.smoke;
- break;
- case GPU_SHADER_SMOKE_FIRE:
- if (!GG.shaders.smoke_fire)
- GG.shaders.smoke_fire = GPU_shader_create(
- datatoc_gpu_shader_smoke_vert_glsl, datatoc_gpu_shader_fire_frag_glsl,
- NULL, NULL, NULL, 0, 0, 0);
- retval = GG.shaders.smoke_fire;
- break;
- case GPU_SHADER_DISPLAY_SH:
- if (!GG.shaders.display_sh)
- GG.shaders.display_sh = GPU_shader_create(
- datatoc_gpu_shader_display_sh_vert_glsl, datatoc_gpu_shader_display_sh_frag_glsl,
- NULL, NULL, NULL, 0, 0, 0);
- retval = GG.shaders.display_sh;
- break;
- case GPU_SHADER_MAXZ_DOWNSAMPLE:
- if (!GG.shaders.maxz_downsample)
- GG.shaders.maxz_downsample = GPU_shader_create(
- datatoc_gpu_shader_downsample_maxz_vert_glsl, datatoc_gpu_shader_downsample_maxz_frag_glsl,
- NULL, NULL, NULL, 0, 0, 0);
- case GPU_SHADER_MINZ_DOWNSAMPLE:
- if (!GG.shaders.minz_downsample)
- GG.shaders.minz_downsample = GPU_shader_create(
- datatoc_gpu_shader_downsample_maxz_vert_glsl, datatoc_gpu_shader_downsample_maxz_frag_glsl,
- NULL, NULL, "#define MIN;\n", 0, 0, 0);
- retval = GG.shaders.minz_downsample;
- break;
- }
+
+ switch (shader) {
+ case GPU_SHADER_VSM_STORE:
+ if (!GG.shaders.vsm_store)
+ GG.shaders.vsm_store = GPU_shader_create(
+ datatoc_gpu_shader_vsm_store_vert_glsl, datatoc_gpu_shader_vsm_store_frag_glsl,
+ NULL, NULL, NULL, 0, 0, 0);
+ retval = GG.shaders.vsm_store;
+ break;
+ case GPU_SHADER_SEP_GAUSSIAN_BLUR:
+ if (!GG.shaders.sep_gaussian_blur)
+ GG.shaders.sep_gaussian_blur = GPU_shader_create(
+ datatoc_gpu_shader_sep_gaussian_blur_vert_glsl,
+ datatoc_gpu_shader_sep_gaussian_blur_frag_glsl,
+ NULL, NULL, NULL, 0, 0, 0);
+ retval = GG.shaders.sep_gaussian_blur;
+ break;
+ case GPU_SHADER_SMOKE:
+ if (!GG.shaders.smoke)
+ GG.shaders.smoke = GPU_shader_create(
+ datatoc_gpu_shader_smoke_vert_glsl, datatoc_gpu_shader_smoke_frag_glsl,
+ NULL, NULL, NULL, 0, 0, 0);
+ retval = GG.shaders.smoke;
+ break;
+ case GPU_SHADER_SMOKE_FIRE:
+ if (!GG.shaders.smoke_fire)
+ GG.shaders.smoke_fire = GPU_shader_create(
+ datatoc_gpu_shader_smoke_vert_glsl, datatoc_gpu_shader_smoke_frag_glsl,
+ NULL, NULL, NULL, 0, 0, 0);
+ retval = GG.shaders.smoke_fire;
+ break;
+ case GPU_SHADER_TEXT:
+ if (!GG.shaders.text)
+ GG.shaders.text = GPU_shader_create(
+ datatoc_gpu_shader_text_vert_glsl,
+ datatoc_gpu_shader_text_frag_glsl,
+ NULL, NULL, NULL, 0, 0, 0);
+ retval = GG.shaders.text;
+ break;
+ case GPU_SHADER_3D_IMAGE_MODULATE_ALPHA:
+ if (!GG.shaders.image_modulate_alpha_3D)
+ GG.shaders.image_modulate_alpha_3D = GPU_shader_create(
+ datatoc_gpu_shader_3D_image_vert_glsl,
+ datatoc_gpu_shader_image_modulate_alpha_frag_glsl,
+ NULL, NULL, NULL, 0, 0, 0);
+ retval = GG.shaders.image_modulate_alpha_3D;
+ break;
+ case GPU_SHADER_3D_IMAGE_RECT_MODULATE_ALPHA:
+ if (!GG.shaders.image_rect_modulate_alpha_3D)
+ GG.shaders.image_rect_modulate_alpha_3D = GPU_shader_create(
+ datatoc_gpu_shader_3D_image_vert_glsl,
+ datatoc_gpu_shader_image_rect_modulate_alpha_frag_glsl,
+ NULL, NULL, NULL, 0, 0, 0);
+ retval = GG.shaders.image_rect_modulate_alpha_3D;
+ break;
+ case GPU_SHADER_2D_UNIFORM_COLOR:
+ if (!GG.shaders.uniform_color_2D)
+ GG.shaders.uniform_color_2D = GPU_shader_create(
+ datatoc_gpu_shader_2D_vert_glsl,
+ datatoc_gpu_shader_uniform_color_frag_glsl,
+ NULL, NULL, NULL, 0, 0, 0);
+ retval = GG.shaders.uniform_color_2D;
+ break;
+ case GPU_SHADER_2D_FLAT_COLOR:
+ if (!GG.shaders.flat_color_2D)
+ GG.shaders.flat_color_2D = GPU_shader_create(
+ datatoc_gpu_shader_2D_flat_color_vert_glsl,
+ datatoc_gpu_shader_flat_color_frag_glsl,
+ NULL, NULL, NULL, 0, 0, 0);
+ retval = GG.shaders.flat_color_2D;
+ break;
+ case GPU_SHADER_2D_SMOOTH_COLOR:
+ if (!GG.shaders.smooth_color_2D)
+ GG.shaders.smooth_color_2D = GPU_shader_create(
+ datatoc_gpu_shader_2D_smooth_color_vert_glsl,
+ datatoc_gpu_shader_2D_smooth_color_frag_glsl,
+ NULL, NULL, NULL, 0, 0, 0);
+ retval = GG.shaders.smooth_color_2D;
+ break;
+ case GPU_SHADER_3D_UNIFORM_COLOR:
+ if (!GG.shaders.uniform_color_3D)
+ GG.shaders.uniform_color_3D = GPU_shader_create(
+ datatoc_gpu_shader_3D_vert_glsl,
+ datatoc_gpu_shader_uniform_color_frag_glsl,
+ NULL, NULL, NULL, 0, 0, 0);
+ retval = GG.shaders.uniform_color_3D;
+ break;
+ case GPU_SHADER_3D_FLAT_COLOR:
+ if (!GG.shaders.flat_color_3D)
+ GG.shaders.flat_color_3D = GPU_shader_create(
+ datatoc_gpu_shader_3D_flat_color_vert_glsl,
+ datatoc_gpu_shader_flat_color_frag_glsl,
+ NULL, NULL, NULL, 0, 0, 0);
+ retval = GG.shaders.flat_color_3D;
+ break;
+ case GPU_SHADER_3D_SMOOTH_COLOR:
+ if (!GG.shaders.smooth_color_3D)
+ GG.shaders.smooth_color_3D = GPU_shader_create(
+ datatoc_gpu_shader_3D_smooth_color_vert_glsl,
+ datatoc_gpu_shader_3D_smooth_color_frag_glsl,
+ NULL, NULL, NULL, 0, 0, 0);
+ retval = GG.shaders.smooth_color_3D;
+ break;
+ case GPU_SHADER_3D_DEPTH_ONLY:
+ if (!GG.shaders.depth_only_3D)
+ GG.shaders.depth_only_3D = GPU_shader_create(
+ datatoc_gpu_shader_3D_vert_glsl,
+ datatoc_gpu_shader_depth_only_frag_glsl,
+ NULL, NULL, NULL, 0, 0, 0);
+ retval = GG.shaders.depth_only_3D;
+ break;
+ case GPU_SHADER_2D_POINT_FIXED_SIZE_UNIFORM_COLOR:
+ if (!GG.shaders.point_fixed_size_uniform_color_2D)
+ GG.shaders.point_fixed_size_uniform_color_2D = GPU_shader_create(
+ datatoc_gpu_shader_2D_vert_glsl,
+ datatoc_gpu_shader_point_uniform_color_frag_glsl,
+ NULL, NULL, NULL, 0, 0, 0);
+ retval = GG.shaders.point_fixed_size_uniform_color_2D;
+ break;
+ case GPU_SHADER_2D_POINT_VARYING_SIZE_VARYING_COLOR:
+ if (!GG.shaders.point_varying_size_varying_color_2D)
+ GG.shaders.point_varying_size_varying_color_2D = GPU_shader_create(
+ datatoc_gpu_shader_2D_point_varying_size_varying_color_vert_glsl,
+ datatoc_gpu_shader_point_varying_color_frag_glsl,
+ NULL, NULL, NULL, 0, 0, 0);
+ retval = GG.shaders.point_varying_size_varying_color_2D;
+ break;
+ case GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_SMOOTH:
+ if (!GG.shaders.point_uniform_size_uniform_color_smooth_2D)
+ GG.shaders.point_uniform_size_uniform_color_smooth_2D = GPU_shader_create(
+ datatoc_gpu_shader_2D_point_uniform_size_smooth_vert_glsl,
+ datatoc_gpu_shader_point_uniform_color_smooth_frag_glsl,
+ NULL, NULL, NULL, 0, 0, 0);
+ retval = GG.shaders.point_uniform_size_uniform_color_smooth_2D;
+ break;
+ case GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_SMOOTH:
+ if (!GG.shaders.point_uniform_size_uniform_color_outline_smooth_2D)
+ GG.shaders.point_uniform_size_uniform_color_outline_smooth_2D = GPU_shader_create(
+ datatoc_gpu_shader_2D_point_uniform_size_outline_smooth_vert_glsl,
+ datatoc_gpu_shader_point_uniform_color_outline_smooth_frag_glsl,
+ NULL, NULL, NULL, 0, 0, 0);
+ retval = GG.shaders.point_uniform_size_uniform_color_outline_smooth_2D;
+ break;
+ case GPU_SHADER_2D_POINT_UNIFORM_SIZE_VARYING_COLOR_OUTLINE_SMOOTH:
+ if (!GG.shaders.point_uniform_size_varying_color_outline_smooth_2D)
+ GG.shaders.point_uniform_size_varying_color_outline_smooth_2D = GPU_shader_create(
+ datatoc_gpu_shader_2D_point_uniform_size_varying_color_outline_smooth_vert_glsl,
+ datatoc_gpu_shader_point_varying_color_outline_smooth_frag_glsl,
+ NULL, NULL, NULL, 0, 0, 0);
+ retval = GG.shaders.point_uniform_size_varying_color_outline_smooth_2D;
+ break;
+ case GPU_SHADER_3D_POINT_FIXED_SIZE_UNIFORM_COLOR:
+ if (!GG.shaders.point_fixed_size_uniform_color_3D)
+ GG.shaders.point_fixed_size_uniform_color_3D = GPU_shader_create(
+ datatoc_gpu_shader_3D_vert_glsl,
+ datatoc_gpu_shader_point_uniform_color_frag_glsl,
+ NULL, NULL, NULL, 0, 0, 0);
+ retval = GG.shaders.point_fixed_size_uniform_color_3D;
+ break;
+ case GPU_SHADER_3D_POINT_FIXED_SIZE_VARYING_COLOR:
+ if (!GG.shaders.point_fixed_size_varying_color_3D)
+ GG.shaders.point_fixed_size_varying_color_3D = GPU_shader_create(
+ datatoc_gpu_shader_3D_point_fixed_size_varying_color_vert_glsl,
+ datatoc_gpu_shader_point_varying_color_frag_glsl,
+ NULL, NULL, NULL, 0, 0, 0);
+ retval = GG.shaders.point_fixed_size_varying_color_3D;
+ break;
+ case GPU_SHADER_3D_POINT_VARYING_SIZE_UNIFORM_COLOR:
+ if (!GG.shaders.point_varying_size_uniform_color_3D)
+ GG.shaders.point_varying_size_uniform_color_3D = GPU_shader_create(
+ datatoc_gpu_shader_3D_point_varying_size_vert_glsl,
+ datatoc_gpu_shader_point_uniform_color_frag_glsl,
+ NULL, NULL, NULL, 0, 0, 0);
+ retval = GG.shaders.point_varying_size_uniform_color_3D;
+ break;
+ case GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR:
+ if (!GG.shaders.point_varying_size_varying_color_3D)
+ GG.shaders.point_varying_size_varying_color_3D = GPU_shader_create(
+ datatoc_gpu_shader_3D_point_varying_size_varying_color_vert_glsl,
+ datatoc_gpu_shader_point_varying_color_frag_glsl,
+ NULL, NULL, NULL, 0, 0, 0);
+ retval = GG.shaders.point_varying_size_varying_color_3D;
+ break;
+ case GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_SMOOTH:
+ if (!GG.shaders.point_uniform_size_uniform_color_smooth_3D)
+ GG.shaders.point_uniform_size_uniform_color_smooth_3D = GPU_shader_create(
+ datatoc_gpu_shader_3D_point_uniform_size_smooth_vert_glsl,
+ datatoc_gpu_shader_point_uniform_color_smooth_frag_glsl,
+ NULL, NULL, NULL, 0, 0, 0);
+ retval = GG.shaders.point_uniform_size_uniform_color_smooth_3D;
+ break;
+ case GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_SMOOTH:
+ if (!GG.shaders.point_uniform_size_uniform_color_outline_smooth_3D)
+ GG.shaders.point_uniform_size_uniform_color_outline_smooth_3D = GPU_shader_create(
+ datatoc_gpu_shader_3D_point_uniform_size_outline_smooth_vert_glsl,
+ datatoc_gpu_shader_point_uniform_color_outline_smooth_frag_glsl,
+ NULL, NULL, NULL, 0, 0, 0);
+ retval = GG.shaders.point_uniform_size_uniform_color_outline_smooth_3D;
+ break;
}
+exit:
if (retval == NULL)
printf("Unable to create a GPUShader for builtin shader: %u\n", shader);
@@ -808,8 +981,6 @@ GPUShader *GPU_shader_get_builtin_fx_shader(int effect, bool persp)
void GPU_shader_free_builtin_shaders(void)
{
- int i;
-
if (GG.shaders.vsm_store) {
GPU_shader_free(GG.shaders.vsm_store);
GG.shaders.vsm_store = NULL;
@@ -830,13 +1001,6 @@ void GPU_shader_free_builtin_shaders(void)
GG.shaders.smoke_fire = NULL;
}
- for (i = 0; i < MAX_SH_SAMPLES; ++i) {
- if (GG.shaders.compute_sh[i]) {
- GPU_shader_free(GG.shaders.compute_sh[i]);
- GG.shaders.compute_sh[i] = NULL;
- }
- }
-
if (GG.shaders.display_sh) {
GPU_shader_free(GG.shaders.display_sh);
GG.shaders.display_sh = NULL;
@@ -852,12 +1016,117 @@ void GPU_shader_free_builtin_shaders(void)
GG.shaders.minz_downsample = NULL;
}
- for (i = 0; i < 2 * MAX_FX_SHADERS; ++i) {
+ if (GG.shaders.text) {
+ GPU_shader_free(GG.shaders.text);
+ GG.shaders.text = NULL;
+ }
+
+ if (GG.shaders.image_modulate_alpha_3D) {
+ GPU_shader_free(GG.shaders.image_modulate_alpha_3D);
+ GG.shaders.image_modulate_alpha_3D = NULL;
+ }
+
+ if (GG.shaders.image_rect_modulate_alpha_3D) {
+ GPU_shader_free(GG.shaders.image_rect_modulate_alpha_3D);
+ GG.shaders.image_rect_modulate_alpha_3D = NULL;
+ }
+
+ if (GG.shaders.uniform_color_2D) {
+ GPU_shader_free(GG.shaders.uniform_color_2D);
+ GG.shaders.uniform_color_2D = NULL;
+ }
+
+ if (GG.shaders.flat_color_2D) {
+ GPU_shader_free(GG.shaders.flat_color_2D);
+ GG.shaders.flat_color_2D = NULL;
+ }
+
+ if (GG.shaders.smooth_color_2D) {
+ GPU_shader_free(GG.shaders.smooth_color_2D);
+ GG.shaders.smooth_color_2D = NULL;
+ }
+
+ if (GG.shaders.uniform_color_3D) {
+ GPU_shader_free(GG.shaders.uniform_color_3D);
+ GG.shaders.uniform_color_3D = NULL;
+ }
+
+ if (GG.shaders.flat_color_3D) {
+ GPU_shader_free(GG.shaders.flat_color_3D);
+ GG.shaders.flat_color_3D = NULL;
+ }
+
+ if (GG.shaders.smooth_color_3D) {
+ GPU_shader_free(GG.shaders.smooth_color_3D);
+ GG.shaders.smooth_color_3D = NULL;
+ }
+
+ if (GG.shaders.point_fixed_size_uniform_color_2D) {
+ GPU_shader_free(GG.shaders.point_fixed_size_uniform_color_2D);
+ GG.shaders.point_fixed_size_uniform_color_2D = NULL;
+ }
+
+ if (GG.shaders.point_varying_size_varying_color_2D) {
+ GPU_shader_free(GG.shaders.point_varying_size_varying_color_2D);
+ GG.shaders.point_varying_size_varying_color_2D = NULL;
+ }
+
+ if (GG.shaders.point_uniform_size_uniform_color_smooth_2D) {
+ GPU_shader_free(GG.shaders.point_uniform_size_uniform_color_smooth_2D);
+ GG.shaders.point_uniform_size_uniform_color_smooth_2D = NULL;
+ }
+
+ if (GG.shaders.point_uniform_size_uniform_color_outline_smooth_2D) {
+ GPU_shader_free(GG.shaders.point_uniform_size_uniform_color_outline_smooth_2D);
+ GG.shaders.point_uniform_size_uniform_color_outline_smooth_2D = NULL;
+ }
+
+ if (GG.shaders.point_uniform_size_varying_color_outline_smooth_2D) {
+ GPU_shader_free(GG.shaders.point_uniform_size_varying_color_outline_smooth_2D);
+ GG.shaders.point_uniform_size_varying_color_outline_smooth_2D = NULL;
+ }
+
+ if (GG.shaders.point_fixed_size_uniform_color_3D) {
+ GPU_shader_free(GG.shaders.point_fixed_size_uniform_color_3D);
+ GG.shaders.point_fixed_size_uniform_color_3D = NULL;
+ }
+
+ if (GG.shaders.point_fixed_size_varying_color_3D) {
+ GPU_shader_free(GG.shaders.point_fixed_size_varying_color_3D);
+ GG.shaders.point_fixed_size_varying_color_3D = NULL;
+ }
+
+ if (GG.shaders.point_varying_size_uniform_color_3D) {
+ GPU_shader_free(GG.shaders.point_varying_size_uniform_color_3D);
+ GG.shaders.point_varying_size_uniform_color_3D = NULL;
+ }
+
+ if (GG.shaders.point_varying_size_varying_color_3D) {
+ GPU_shader_free(GG.shaders.point_varying_size_varying_color_3D);
+ GG.shaders.point_varying_size_varying_color_3D = NULL;
+ }
+
+ if (GG.shaders.point_uniform_size_uniform_color_smooth_3D) {
+ GPU_shader_free(GG.shaders.point_uniform_size_uniform_color_smooth_3D);
+ GG.shaders.point_uniform_size_uniform_color_smooth_3D = NULL;
+ }
+
+ if (GG.shaders.point_uniform_size_uniform_color_outline_smooth_3D) {
+ GPU_shader_free(GG.shaders.point_uniform_size_uniform_color_outline_smooth_3D);
+ GG.shaders.point_uniform_size_uniform_color_outline_smooth_3D = NULL;
+ }
+
+ for (int i = 0; i < MAX_SH_SAMPLES; ++i) {
+ if (GG.shaders.compute_sh[i]) {
+ GPU_shader_free(GG.shaders.compute_sh[i]);
+ GG.shaders.compute_sh[i] = NULL;
+ }
+ }
+
+ for (int i = 0; i < 2 * MAX_FX_SHADERS; ++i) {
if (GG.shaders.fx_shaders[i]) {
GPU_shader_free(GG.shaders.fx_shaders[i]);
GG.shaders.fx_shaders[i] = NULL;
}
}
}
-
-
diff --git a/source/blender/gpu/intern/gpu_shader_private.h b/source/blender/gpu/intern/gpu_shader_private.h
new file mode 100644
index 00000000000..d5193e09aa4
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_shader_private.h
@@ -0,0 +1,40 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file gpu_shader_private.h
+ * \ingroup gpu
+ */
+
+#pragma once
+
+#include "GPU_glew.h"
+
+struct GPUShader {
+ GLuint program; /* handle for full program (links shader stages below) */
+
+ GLuint vertex; /* handle for vertex shader */
+ GLuint geometry; /* handle for geometry shader */
+ GLuint fragment; /* handle for fragment shader */
+
+ int totattrib; /* total number of attributes */
+ int uniforms; /* required uniforms */
+
+ void *uniform_interface; /* cached uniform interface for shader. Data depends on shader */
+};
diff --git a/source/blender/gpu/intern/gpu_texture.c b/source/blender/gpu/intern/gpu_texture.c
index e6a9db5059a..a151fe847ef 100644
--- a/source/blender/gpu/intern/gpu_texture.c
+++ b/source/blender/gpu/intern/gpu_texture.c
@@ -120,21 +120,21 @@ static GPUTexture *GPU_texture_create_nD(
if (!tex->bindcode) {
if (err_out) {
- BLI_snprintf(err_out, 256, "GPUTexture: texture create failed: %d",
- (int)glGetError());
+ BLI_snprintf(err_out, 256, "GPUTexture: texture create failed");
}
else {
- fprintf(stderr, "GPUTexture: texture create failed: %d\n",
- (int)glGetError());
+ fprintf(stderr, "GPUTexture: texture create failed");
}
GPU_texture_free(tex);
return NULL;
}
+#if 0 /* this should be a compile-time check */
if (!GPU_full_non_power_of_two_support()) {
tex->w = power_of_2_max_i(tex->w);
tex->h = power_of_2_max_i(tex->h);
}
+#endif
tex->number = 0;
glBindTexture(tex->target, tex->bindcode);
@@ -366,8 +366,7 @@ GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, const f
glGenTextures(1, &tex->bindcode);
if (!tex->bindcode) {
- fprintf(stderr, "GPUTexture: texture create failed: %d\n",
- (int)glGetError());
+ fprintf(stderr, "GPUTexture: texture create failed");
GPU_texture_free(tex);
return NULL;
}
@@ -375,8 +374,6 @@ GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, const f
tex->number = 0;
glBindTexture(tex->target, tex->bindcode);
- GPU_ASSERT_NO_GL_ERRORS("3D glBindTexture");
-
type = GL_FLOAT;
if (channels == 4) {
format = GL_RGBA;
@@ -418,8 +415,6 @@ GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, const f
pixels = GPU_texture_convert_pixels(w*h*depth, fpixels);
#endif
- GPU_ASSERT_NO_GL_ERRORS("3D glTexImage3D");
-
/* hardcore stuff, 3D texture rescaling - warning, this is gonna hurt your performance a lot, but we need it
* for gooseberry */
if (rescale && fpixels) {
@@ -456,14 +451,10 @@ GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, const f
MEM_freeN(tex3d);
}
- else {
- if (fpixels) {
- glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, fpixels);
- GPU_ASSERT_NO_GL_ERRORS("3D glTexSubImage3D");
- }
+ else if (fpixels) {
+ glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, fpixels);
}
-
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
@@ -510,7 +501,7 @@ GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, int textarget
ima->gputexture[gputt] = tex;
if (!glIsTexture(tex->bindcode)) {
- GPU_ASSERT_NO_GL_ERRORS("Blender Texture Not Loaded");
+ GPU_print_error_debug("Blender Texture Not Loaded");
}
else {
GLint w, h, border;
@@ -564,7 +555,7 @@ GPUTexture *GPU_texture_from_preview(PreviewImage *prv, int mipmap)
prv->gputexture[0] = tex;
if (!glIsTexture(tex->bindcode)) {
- GPU_ASSERT_NO_GL_ERRORS("Blender Texture Not Loaded");
+ GPU_print_error_debug("Blender Texture Not Loaded");
}
else {
GLint w, h;
@@ -915,8 +906,6 @@ void GPU_texture_bind(GPUTexture *tex, int number)
if (number < 0)
return;
- GPU_ASSERT_NO_GL_ERRORS("Pre Texture Bind");
-
GLenum arbnumber = (GLenum)((GLuint)GL_TEXTURE0 + number);
if (number != 0) glActiveTexture(arbnumber);
if (tex->bindcode != 0) {
@@ -928,8 +917,6 @@ void GPU_texture_bind(GPUTexture *tex, int number)
if (number != 0) glActiveTexture(GL_TEXTURE0);
tex->number = number;
-
- GPU_ASSERT_NO_GL_ERRORS("Post Texture Bind");
}
void GPU_texture_unbind(GPUTexture *tex)
@@ -941,8 +928,6 @@ void GPU_texture_unbind(GPUTexture *tex)
if (tex->number == -1)
return;
-
- GPU_ASSERT_NO_GL_ERRORS("Pre Texture Unbind");
GLenum arbnumber = (GLenum)((GLuint)GL_TEXTURE0 + tex->number);
if (tex->number != 0) glActiveTexture(arbnumber);
@@ -951,8 +936,6 @@ void GPU_texture_unbind(GPUTexture *tex)
if (tex->number != 0) glActiveTexture(GL_TEXTURE0);
tex->number = -1;
-
- GPU_ASSERT_NO_GL_ERRORS("Post Texture Unbind");
}
int GPU_texture_bound_number(GPUTexture *tex)
@@ -970,8 +953,6 @@ void GPU_texture_filter_mode(GPUTexture *tex, bool compare, bool use_filter)
if (tex->number == -1)
return;
- GPU_ASSERT_NO_GL_ERRORS("Pre Texture Unbind");
-
GLenum arbnumber = (GLenum)((GLuint)GL_TEXTURE0 + tex->number);
if (tex->number != 0) glActiveTexture(arbnumber);
@@ -991,8 +972,6 @@ void GPU_texture_filter_mode(GPUTexture *tex, bool compare, bool use_filter)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
}
if (tex->number != 0) glActiveTexture(GL_TEXTURE0);
-
- GPU_ASSERT_NO_GL_ERRORS("Post Texture Unbind");
}
void GPU_texture_free(GPUTexture *tex)
diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c
new file mode 100644
index 00000000000..bae2fdc552d
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_viewport.c
@@ -0,0 +1,52 @@
+/*
+ * ***** 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) 2006 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s):
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/gpu/intern/gpu_viewport.c
+ * \ingroup gpu
+ *
+ * System that manages viewport drawing.
+ */
+
+#include "GPU_viewport.h"
+
+#include "MEM_guardedalloc.h"
+
+struct GPUViewport {
+ float pad[4];
+};
+
+GPUViewport *GPU_viewport_create(void)
+{
+ GPUViewport *viewport = MEM_callocN(sizeof(GPUViewport), "GPUViewport");
+ return viewport;
+}
+
+void GPU_viewport_free(GPUViewport *viewport)
+{
+ MEM_freeN(viewport);
+}
+
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_flat_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_flat_color_vert.glsl
new file mode 100644
index 00000000000..96c833f3b93
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_flat_color_vert.glsl
@@ -0,0 +1,20 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+#if __VERSION__ == 120
+ attribute vec2 pos;
+ attribute vec4 color;
+
+ flat varying vec4 finalColor;
+#else
+ in vec2 pos;
+ in vec4 color;
+
+ flat out vec4 finalColor;
+#endif
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0);
+ finalColor = color;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_outline_smooth_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_outline_smooth_vert.glsl
new file mode 100644
index 00000000000..a37ae16f837
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_outline_smooth_vert.glsl
@@ -0,0 +1,29 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+uniform float size;
+uniform float outlineWidth;
+
+#if __VERSION__ == 120
+ attribute vec2 pos;
+ varying vec4 radii;
+#else
+ in vec2 pos;
+ out vec4 radii;
+#endif
+
+void main() {
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0);
+ gl_PointSize = size;
+
+ // calculate concentric radii in pixels
+ float radius = 0.5 * size;
+
+ // start at the outside and progress toward the center
+ radii[0] = radius;
+ radii[1] = radius - 1.0;
+ radii[2] = radius - outlineWidth;
+ radii[3] = radius - outlineWidth - 1.0;
+
+ // convert to PointCoord units
+ radii /= size;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_smooth_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_smooth_vert.glsl
new file mode 100644
index 00000000000..201e5e90ecc
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_smooth_vert.glsl
@@ -0,0 +1,26 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+uniform float size;
+
+#if __VERSION__ == 120
+ attribute vec2 pos;
+ varying vec2 radii;
+#else
+ in vec2 pos;
+ out vec2 radii;
+#endif
+
+void main() {
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0);
+ gl_PointSize = size;
+
+ // calculate concentric radii in pixels
+ float radius = 0.5 * size;
+
+ // start at the outside and progress toward the center
+ radii[0] = radius;
+ radii[1] = radius - 1.0;
+
+ // convert to PointCoord units
+ radii /= size;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_varying_color_outline_smooth_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_varying_color_outline_smooth_vert.glsl
new file mode 100644
index 00000000000..d3a142cc7bd
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_varying_color_outline_smooth_vert.glsl
@@ -0,0 +1,34 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+uniform float size;
+uniform float outlineWidth;
+
+#if __VERSION__ == 120
+ attribute vec2 pos;
+ attribute vec4 color;
+ varying vec4 radii;
+ varying vec4 fillColor;
+#else
+ in vec2 pos;
+ in vec4 color;
+ out vec4 radii;
+ out vec4 fillColor;
+#endif
+
+void main() {
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0);
+ gl_PointSize = size;
+ fillColor = color;
+
+ // calculate concentric radii in pixels
+ float radius = 0.5 * size;
+
+ // start at the outside and progress toward the center
+ radii[0] = radius;
+ radii[1] = radius - 1.0;
+ radii[2] = radius - outlineWidth;
+ radii[3] = radius - outlineWidth - 1.0;
+
+ // convert to PointCoord units
+ radii /= size;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_point_varying_size_varying_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_point_varying_size_varying_color_vert.glsl
new file mode 100644
index 00000000000..42ff51e3d03
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_point_varying_size_varying_color_vert.glsl
@@ -0,0 +1,21 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+#if __VERSION__ == 120
+ attribute vec2 pos;
+ attribute float size;
+ attribute vec4 color;
+ varying vec4 finalColor;
+#else
+ in vec2 pos;
+ in float size;
+ in vec4 color;
+ out vec4 finalColor;
+#endif
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0);
+ gl_PointSize = size;
+ finalColor = color;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_smooth_color_frag.glsl b/source/blender/gpu/shaders/gpu_shader_2D_smooth_color_frag.glsl
new file mode 100644
index 00000000000..654439d1feb
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_smooth_color_frag.glsl
@@ -0,0 +1,13 @@
+
+#if __VERSION__ == 120
+ noperspective varying vec4 finalColor;
+ #define fragColor gl_FragColor
+#else
+ noperspective in vec4 finalColor;
+ out vec4 fragColor;
+#endif
+
+void main()
+{
+ fragColor = finalColor;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_smooth_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_smooth_color_vert.glsl
new file mode 100644
index 00000000000..9daf2d75016
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_smooth_color_vert.glsl
@@ -0,0 +1,20 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+#if __VERSION__ == 120
+ attribute vec2 pos;
+ attribute vec4 color;
+
+ noperspective varying vec4 finalColor;
+#else
+ in vec2 pos;
+ in vec4 color;
+
+ noperspective out vec4 finalColor;
+#endif
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0);
+ finalColor = color;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_vert.glsl
new file mode 100644
index 00000000000..4049171f73d
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_vert.glsl
@@ -0,0 +1,13 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+#if __VERSION__ == 120
+ attribute vec2 pos;
+#else
+ in vec2 pos;
+#endif
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0);
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_flat_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_flat_color_vert.glsl
new file mode 100644
index 00000000000..8c241cff5d4
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_3D_flat_color_vert.glsl
@@ -0,0 +1,20 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+#if __VERSION__ == 120
+ attribute vec3 pos;
+ attribute vec4 color;
+
+ flat varying vec4 finalColor;
+#else
+ in vec3 pos;
+ in vec4 color;
+
+ flat out vec4 finalColor;
+#endif
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ finalColor = color;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_image_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_image_vert.glsl
new file mode 100644
index 00000000000..e9f847f28b3
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_3D_image_vert.glsl
@@ -0,0 +1,18 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+#if __VERSION__ == 120
+ attribute vec2 texCoord;
+ attribute vec3 pos;
+ varying vec2 texCoord_interp;
+#else
+ in vec2 texCoord;
+ in vec3 pos;
+ out vec2 texCoord_interp;
+#endif
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos.xyz, 1.0f);
+ texCoord_interp = texCoord;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_point_fixed_size_varying_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_point_fixed_size_varying_color_vert.glsl
new file mode 100644
index 00000000000..84e77e59e90
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_3D_point_fixed_size_varying_color_vert.glsl
@@ -0,0 +1,18 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+#if __VERSION__ == 120
+ attribute vec3 pos;
+ attribute vec4 color;
+ varying vec4 finalColor;
+#else
+ in vec3 pos;
+ in vec4 color;
+ out vec4 finalColor;
+#endif
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ finalColor = color;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_outline_smooth_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_outline_smooth_vert.glsl
new file mode 100644
index 00000000000..d05920002ed
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_outline_smooth_vert.glsl
@@ -0,0 +1,29 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+uniform float size;
+uniform float outlineWidth;
+
+#if __VERSION__ == 120
+ attribute vec3 pos;
+ varying vec4 radii;
+#else
+ in vec3 pos;
+ out vec4 radii;
+#endif
+
+void main() {
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ gl_PointSize = size;
+
+ // calculate concentric radii in pixels
+ float radius = 0.5 * size;
+
+ // start at the outside and progress toward the center
+ radii[0] = radius;
+ radii[1] = radius - 1.0;
+ radii[2] = radius - outlineWidth;
+ radii[3] = radius - outlineWidth - 1.0;
+
+ // convert to PointCoord units
+ radii /= size;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_smooth_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_smooth_vert.glsl
new file mode 100644
index 00000000000..287f95b48ab
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_smooth_vert.glsl
@@ -0,0 +1,26 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+uniform float size;
+
+#if __VERSION__ == 120
+ attribute vec3 pos;
+ varying vec2 radii;
+#else
+ in vec3 pos;
+ out vec2 radii;
+#endif
+
+void main() {
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ gl_PointSize = size;
+
+ // calculate concentric radii in pixels
+ float radius = 0.5 * size;
+
+ // start at the outside and progress toward the center
+ radii[0] = radius;
+ radii[1] = radius - 1.0;
+
+ // convert to PointCoord units
+ radii /= size;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_point_varying_size_varying_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_point_varying_size_varying_color_vert.glsl
new file mode 100644
index 00000000000..7999435f0e4
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_3D_point_varying_size_varying_color_vert.glsl
@@ -0,0 +1,21 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+#if __VERSION__ == 120
+ attribute vec3 pos;
+ attribute float size;
+ attribute vec4 color;
+ varying vec4 finalColor;
+#else
+ in vec3 pos;
+ in float size;
+ in vec4 color;
+ out vec4 finalColor;
+#endif
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ gl_PointSize = size;
+ finalColor = color;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_point_varying_size_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_point_varying_size_vert.glsl
new file mode 100644
index 00000000000..1fcda765b99
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_3D_point_varying_size_vert.glsl
@@ -0,0 +1,16 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+#if __VERSION__ == 120
+ attribute vec3 pos;
+ attribute float size;
+#else
+ in vec3 pos;
+ in float size;
+#endif
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ gl_PointSize = size;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_smooth_color_frag.glsl b/source/blender/gpu/shaders/gpu_shader_3D_smooth_color_frag.glsl
new file mode 100644
index 00000000000..955a49aa7d2
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_3D_smooth_color_frag.glsl
@@ -0,0 +1,13 @@
+
+#if __VERSION__ == 120
+ varying vec4 finalColor;
+ #define fragColor gl_FragColor
+#else
+ in vec4 finalColor;
+ out vec4 fragColor;
+#endif
+
+void main()
+{
+ fragColor = finalColor;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_smooth_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_smooth_color_vert.glsl
new file mode 100644
index 00000000000..22c2cfa8b93
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_3D_smooth_color_vert.glsl
@@ -0,0 +1,20 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+#if __VERSION__ == 120
+ attribute vec3 pos;
+ attribute vec4 color;
+
+ varying vec4 finalColor;
+#else
+ in vec3 pos;
+ in vec4 color;
+
+ out vec4 finalColor;
+#endif
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ finalColor = color;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_vert.glsl
new file mode 100644
index 00000000000..32da3a99c63
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_3D_vert.glsl
@@ -0,0 +1,13 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+#if __VERSION__ == 120
+ attribute vec3 pos;
+#else
+ in vec3 pos;
+#endif
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_basic_frag.glsl b/source/blender/gpu/shaders/gpu_shader_basic_frag.glsl
index 01a335af048..ed2339736e7 100644
--- a/source/blender/gpu/shaders/gpu_shader_basic_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_basic_frag.glsl
@@ -58,7 +58,7 @@ uniform sampler2D_default texture_map;
#ifdef USE_STIPPLE
uniform int stipple_id;
#if defined(DRAW_LINE)
-varying in float t;
+varying float t;
uniform int stipple_pattern;
#endif
#endif
diff --git a/source/blender/gpu/shaders/gpu_shader_basic_geom.glsl b/source/blender/gpu/shaders/gpu_shader_basic_geom.glsl
index a88681a5fd3..13f05b340bf 100644
--- a/source/blender/gpu/shaders/gpu_shader_basic_geom.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_basic_geom.glsl
@@ -14,9 +14,9 @@ layout(line_strip, max_vertices = 10) out;
layout(triangle_strip, max_vertices = 6) out;
#endif
-varying out float t;
-varying in vec4 varying_vertex_color_line[];
-varying out vec4 varying_vertex_color;
+out float t;
+in vec4 varying_vertex_color_line[];
+out vec4 varying_vertex_color;
uniform ivec4 viewport;
uniform float line_width;
diff --git a/source/blender/gpu/shaders/gpu_shader_depth_only_frag.glsl b/source/blender/gpu/shaders/gpu_shader_depth_only_frag.glsl
new file mode 100644
index 00000000000..60e71e19004
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_depth_only_frag.glsl
@@ -0,0 +1,6 @@
+
+void main()
+{
+ // no color output, only depth (line below is implicit)
+ // gl_FragDepth = gl_FragCoord.z;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_flat_color_frag.glsl b/source/blender/gpu/shaders/gpu_shader_flat_color_frag.glsl
new file mode 100644
index 00000000000..91097d24cb2
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_flat_color_frag.glsl
@@ -0,0 +1,13 @@
+
+#if __VERSION__ == 120
+ flat varying vec4 finalColor;
+ #define fragColor gl_FragColor
+#else
+ flat in vec4 finalColor;
+ out vec4 fragColor;
+#endif
+
+void main()
+{
+ fragColor = finalColor;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_image_modulate_alpha_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_modulate_alpha_frag.glsl
new file mode 100644
index 00000000000..74e17198985
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_image_modulate_alpha_frag.glsl
@@ -0,0 +1,18 @@
+
+#if __VERSION__ == 120
+ varying vec2 texCoord_interp;
+ #define fragColor gl_FragColor
+#else
+ in vec2 texCoord_interp;
+ out vec4 fragColor;
+ #define texture2D texture
+#endif
+
+uniform float alpha;
+uniform sampler2D image;
+
+void main()
+{
+ fragColor = texture2D(image, texCoord_interp);
+ fragColor.a *= alpha;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_image_rect_modulate_alpha_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_rect_modulate_alpha_frag.glsl
new file mode 100644
index 00000000000..aae3b40efd4
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_image_rect_modulate_alpha_frag.glsl
@@ -0,0 +1,18 @@
+
+#if __VERSION__ == 120
+ varying vec2 texCoord_interp;
+ #define fragColor gl_FragColor
+#else
+ in vec2 texCoord_interp;
+ out vec4 fragColor;
+ #define texture2DRect texture
+#endif
+
+uniform float alpha;
+uniform sampler2DRect image;
+
+void main()
+{
+ fragColor = texture2DRect(image, texCoord_interp);
+ fragColor.a *= alpha;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_point_uniform_color_frag.glsl b/source/blender/gpu/shaders/gpu_shader_point_uniform_color_frag.glsl
new file mode 100644
index 00000000000..8e0c75db6bf
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_point_uniform_color_frag.glsl
@@ -0,0 +1,21 @@
+
+uniform vec4 color;
+
+#if __VERSION__ == 120
+ #define fragColor gl_FragColor
+#else
+ out vec4 fragColor;
+#endif
+
+void main()
+{
+ vec2 centered = gl_PointCoord - vec2(0.5);
+ float dist_squared = dot(centered, centered);
+ const float rad_squared = 0.25;
+
+ // round point with jaggy edges
+ if (dist_squared > rad_squared)
+ discard;
+
+ fragColor = color;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_point_uniform_color_outline_smooth_frag.glsl b/source/blender/gpu/shaders/gpu_shader_point_uniform_color_outline_smooth_frag.glsl
new file mode 100644
index 00000000000..f83785de95e
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_point_uniform_color_outline_smooth_frag.glsl
@@ -0,0 +1,36 @@
+
+uniform vec4 color;
+uniform vec4 outlineColor;
+
+#if __VERSION__ == 120
+ varying vec4 radii;
+ #define fragColor gl_FragColor
+#else
+ in vec4 radii;
+ out vec4 fragColor;
+#endif
+
+void main() {
+ float dist = length(gl_PointCoord - vec2(0.5));
+
+// transparent outside of point
+// --- 0 ---
+// smooth transition
+// --- 1 ---
+// pure outline color
+// --- 2 ---
+// smooth transition
+// --- 3 ---
+// pure point color
+// ...
+// dist = 0 at center of point
+
+ float midStroke = 0.5 * (radii[1] + radii[2]);
+
+ if (dist > midStroke) {
+ fragColor.rgb = outlineColor.rgb;
+ fragColor.a = mix(outlineColor.a, 0.0, smoothstep(radii[1], radii[0], dist));
+ }
+ else
+ fragColor = mix(color, outlineColor, smoothstep(radii[3], radii[2], dist));
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_point_uniform_color_smooth_frag.glsl b/source/blender/gpu/shaders/gpu_shader_point_uniform_color_smooth_frag.glsl
new file mode 100644
index 00000000000..8c8d81f6997
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_point_uniform_color_smooth_frag.glsl
@@ -0,0 +1,25 @@
+
+uniform vec4 color;
+
+#if __VERSION__ == 120
+ varying vec2 radii;
+ #define fragColor gl_FragColor
+#else
+ in vec2 radii;
+ out vec4 fragColor;
+#endif
+
+void main() {
+ float dist = length(gl_PointCoord - vec2(0.5));
+
+// transparent outside of point
+// --- 0 ---
+// smooth transition
+// --- 1 ---
+// pure point color
+// ...
+// dist = 0 at center of point
+
+ fragColor.rgb = color.rgb;
+ fragColor.a = mix(color.a, 0.0, smoothstep(radii[1], radii[0], dist));
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_point_varying_color_frag.glsl b/source/blender/gpu/shaders/gpu_shader_point_varying_color_frag.glsl
new file mode 100644
index 00000000000..91092a9f727
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_point_varying_color_frag.glsl
@@ -0,0 +1,21 @@
+
+#if __VERSION__ == 120
+ varying vec4 finalColor;
+ #define fragColor gl_FragColor
+#else
+ in vec4 finalColor;
+ out vec4 fragColor;
+#endif
+
+void main()
+{
+ vec2 centered = gl_PointCoord - vec2(0.5);
+ float dist_squared = dot(centered, centered);
+ const float rad_squared = 0.25;
+
+ // round point with jaggy edges
+ if (dist_squared > rad_squared)
+ discard;
+
+ fragColor = finalColor;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_point_varying_color_outline_smooth_frag.glsl b/source/blender/gpu/shaders/gpu_shader_point_varying_color_outline_smooth_frag.glsl
new file mode 100644
index 00000000000..d6cbe2d9a22
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_point_varying_color_outline_smooth_frag.glsl
@@ -0,0 +1,37 @@
+
+uniform vec4 outlineColor;
+
+#if __VERSION__ == 120
+ varying vec4 radii;
+ varying vec4 fillColor;
+ #define fragColor gl_FragColor
+#else
+ in vec4 radii;
+ in vec4 fillColor;
+ out vec4 fragColor;
+#endif
+
+void main() {
+ float dist = length(gl_PointCoord - vec2(0.5));
+
+// transparent outside of point
+// --- 0 ---
+// smooth transition
+// --- 1 ---
+// pure outline color
+// --- 2 ---
+// smooth transition
+// --- 3 ---
+// pure fill color
+// ...
+// dist = 0 at center of point
+
+ float midStroke = 0.5 * (radii[1] + radii[2]);
+
+ if (dist > midStroke) {
+ fragColor.rgb = outlineColor.rgb;
+ fragColor.a = mix(outlineColor.a, 0.0, smoothstep(radii[1], radii[0], dist));
+ }
+ else
+ fragColor = mix(fillColor, outlineColor, smoothstep(radii[3], radii[2], dist));
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_text_frag.glsl b/source/blender/gpu/shaders/gpu_shader_text_frag.glsl
new file mode 100644
index 00000000000..9283d682767
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_text_frag.glsl
@@ -0,0 +1,22 @@
+
+#if __VERSION__ == 120
+ flat varying vec4 color_flat;
+ noperspective varying vec2 texCoord_interp;
+ #define fragColor gl_FragColor
+#else
+ flat in vec4 color_flat;
+ noperspective in vec2 texCoord_interp;
+ out vec4 fragColor;
+ #define texture2D texture
+#endif
+
+uniform sampler2D glyph;
+
+void main()
+{
+ // input color replaces texture color
+ fragColor.rgb = color_flat.rgb;
+
+ // modulate input alpha & texture alpha
+ fragColor.a = color_flat.a * texture2D(glyph, texCoord_interp).a;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_text_vert.glsl b/source/blender/gpu/shaders/gpu_shader_text_vert.glsl
new file mode 100644
index 00000000000..44568f28c8e
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_text_vert.glsl
@@ -0,0 +1,24 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+#if __VERSION__ == 120
+ attribute vec2 pos;
+ attribute vec2 texCoord;
+ attribute vec4 color;
+ flat varying vec4 color_flat;
+ noperspective varying vec2 texCoord_interp;
+#else
+ in vec2 pos;
+ in vec2 texCoord;
+ in vec4 color;
+ flat out vec4 color_flat;
+ noperspective out vec2 texCoord_interp;
+#endif
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0);
+
+ color_flat = color;
+ texCoord_interp = texCoord;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_uniform_color_frag.glsl b/source/blender/gpu/shaders/gpu_shader_uniform_color_frag.glsl
new file mode 100644
index 00000000000..af200bf8661
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_uniform_color_frag.glsl
@@ -0,0 +1,13 @@
+
+uniform vec4 color;
+
+#if __VERSION__ == 120
+ #define fragColor gl_FragColor
+#else
+ out vec4 fragColor;
+#endif
+
+void main()
+{
+ fragColor = color;
+}
diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h
index 5c1bfc229da..45eb31235f5 100644
--- a/source/blender/makesdna/DNA_ID.h
+++ b/source/blender/makesdna/DNA_ID.h
@@ -239,7 +239,6 @@ typedef enum ID_Type {
ID_AC = MAKE_ID2('A', 'C'), /* bAction */
ID_NT = MAKE_ID2('N', 'T'), /* bNodeTree */
ID_BR = MAKE_ID2('B', 'R'), /* Brush */
- ID_PA = MAKE_ID2('P', 'A'), /* ParticleSettings */
ID_GD = MAKE_ID2('G', 'D'), /* bGPdata, (Grease Pencil) */
ID_WM = MAKE_ID2('W', 'M'), /* WindowManager */
ID_MC = MAKE_ID2('M', 'C'), /* MovieClip */
@@ -377,8 +376,7 @@ enum {
FILTER_ID_TXT = (1 << 24),
FILTER_ID_VF = (1 << 25),
FILTER_ID_WO = (1 << 26),
- FILTER_ID_PA = (1 << 27),
- FILTER_ID_CF = (1 << 28),
+ FILTER_ID_CF = (1 << 27),
};
/* IMPORTANT: this enum matches the order currently use in set_lisbasepointers,
@@ -408,7 +406,6 @@ enum {
INDEX_ID_PAL,
INDEX_ID_PC,
INDEX_ID_BR,
- INDEX_ID_PA,
INDEX_ID_SPK,
INDEX_ID_WO,
INDEX_ID_MC,
diff --git a/source/blender/makesdna/DNA_boid_types.h b/source/blender/makesdna/DNA_boid_types.h
deleted file mode 100644
index f1930ffd643..00000000000
--- a/source/blender/makesdna/DNA_boid_types.h
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * ***** 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) 2009 by Janne Karhu.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file DNA_boid_types.h
- * \ingroup DNA
- */
-
-#ifndef __DNA_BOID_TYPES_H__
-#define __DNA_BOID_TYPES_H__
-
-#include "DNA_listBase.h"
-
-typedef enum BoidRuleType {
- eBoidRuleType_None = 0,
- eBoidRuleType_Goal = 1, /* go to goal assigned object or loudest assigned signal source */
- eBoidRuleType_Avoid = 2, /* get away from assigned object or loudest assigned signal source */
- eBoidRuleType_AvoidCollision = 3, /* manoeuver to avoid collisions with other boids and deflector object in near future */
- eBoidRuleType_Separate = 4, /* keep from going through other boids */
- eBoidRuleType_Flock = 5, /* move to center of neighbors and match their velocity */
- eBoidRuleType_FollowLeader = 6, /* follow a boid or assigned object */
- eBoidRuleType_AverageSpeed = 7, /* maintain speed, flight level or wander*/
- eBoidRuleType_Fight = 8, /* go to closest enemy and attack when in range */
- //eBoidRuleType_Protect = 9, /* go to enemy closest to target and attack when in range */
- //eBoidRuleType_Hide = 10, /* find a deflector move to it's other side from closest enemy */
- //eBoidRuleType_FollowPath = 11, /* move along a assigned curve or closest curve in a group */
- //eBoidRuleType_FollowWall = 12, /* move next to a deflector object's in direction of it's tangent */
- NUM_BOID_RULE_TYPES
-} BoidRuleType;
-
-/* boidrule->flag */
-#define BOIDRULE_CURRENT 1
-#define BOIDRULE_IN_AIR 4
-#define BOIDRULE_ON_LAND 8
-typedef struct BoidRule {
- struct BoidRule *next, *prev;
- int type, flag;
- char name[32];
-} BoidRule;
-#define BRULE_GOAL_AVOID_PREDICT 1
-#define BRULE_GOAL_AVOID_ARRIVE 2
-#define BRULE_GOAL_AVOID_SIGNAL 4
-typedef struct BoidRuleGoalAvoid {
- BoidRule rule;
- struct Object *ob;
- int options;
- float fear_factor;
-
- /* signals */
- int signal_id, channels;
-} BoidRuleGoalAvoid;
-#define BRULE_ACOLL_WITH_BOIDS 1
-#define BRULE_ACOLL_WITH_DEFLECTORS 2
-typedef struct BoidRuleAvoidCollision {
- BoidRule rule;
- int options;
- float look_ahead;
-} BoidRuleAvoidCollision;
-#define BRULE_LEADER_IN_LINE 1
-typedef struct BoidRuleFollowLeader {
- BoidRule rule;
- struct Object *ob;
- float loc[3], oloc[3];
- float cfra, distance;
- int options, queue_size;
-} BoidRuleFollowLeader;
-typedef struct BoidRuleAverageSpeed {
- BoidRule rule;
- float wander, level, speed, rt;
-} BoidRuleAverageSpeed;
-typedef struct BoidRuleFight {
- BoidRule rule;
- float distance, flee_distance;
-} BoidRuleFight;
-
-typedef enum BoidMode {
- eBoidMode_InAir = 0,
- eBoidMode_OnLand = 1,
- eBoidMode_Climbing = 2,
- eBoidMode_Falling = 3,
- eBoidMode_Liftoff = 4,
- NUM_BOID_MODES
-} BoidMode;
-
-
-typedef struct BoidData {
- float health, acc[3];
- short state_id, mode;
-} BoidData;
-
-// planned for near future
-//typedef enum BoidConditionMode {
-// eBoidConditionType_Then = 0,
-// eBoidConditionType_And = 1,
-// eBoidConditionType_Or = 2,
-// NUM_BOID_CONDITION_MODES
-//} BoidConditionMode;
-//typedef enum BoidConditionType {
-// eBoidConditionType_None = 0,
-// eBoidConditionType_Signal = 1,
-// eBoidConditionType_NoSignal = 2,
-// eBoidConditionType_HealthBelow = 3,
-// eBoidConditionType_HealthAbove = 4,
-// eBoidConditionType_See = 5,
-// eBoidConditionType_NotSee = 6,
-// eBoidConditionType_StateTime = 7,
-// eBoidConditionType_Touching = 8,
-// NUM_BOID_CONDITION_TYPES
-//} BoidConditionType;
-//typedef struct BoidCondition {
-// struct BoidCondition *next, *prev;
-// int state_id;
-// short type, mode;
-// float threshold, probability;
-//
-// /* signals */
-// int signal_id, channels;
-//} BoidCondition;
-
-typedef enum BoidRulesetType {
- eBoidRulesetType_Fuzzy = 0,
- eBoidRulesetType_Random = 1,
- eBoidRulesetType_Average = 2,
- NUM_BOID_RULESET_TYPES
-} BoidRulesetType;
-#define BOIDSTATE_CURRENT 1
-typedef struct BoidState {
- struct BoidState *next, *prev;
- ListBase rules;
- ListBase conditions;
- ListBase actions;
- char name[32];
- int id, flag;
-
- /* rules */
- int ruleset_type;
- float rule_fuzziness;
-
- /* signal */
- int signal_id, channels;
- float volume, falloff;
-} BoidState;
-
-// planned for near future
-//typedef struct BoidSignal {
-// struct BoidSignal *next, *prev;
-// float loc[3];
-// float volume, falloff;
-// int id;
-//} BoidSignal;
-//typedef struct BoidSignalDefine {
-// struct BoidSignalDefine *next, *prev;
-// int id, rt;
-// char name[32];
-//} BoidSignalDefine;
-
-//typedef struct BoidSimulationData {
-// ListBase signal_defines;/* list of defined signals */
-// ListBase signals[20]; /* gathers signals from all channels */
-// struct KDTree *signaltrees[20];
-// char channel_names[20][32];
-// int last_signal_id; /* used for incrementing signal ids */
-// int flag; /* switches for drawing stuff */
-//} BoidSimulationData;
-
-typedef struct BoidSettings {
- int options, last_state_id;
-
- float landing_smoothness, height;
- float banking, pitch;
-
- float health, aggression;
- float strength, accuracy, range;
-
- /* flying related */
- float air_min_speed, air_max_speed;
- float air_max_acc, air_max_ave;
- float air_personal_space;
-
- /* walk/run related */
- float land_jump_speed, land_max_speed;
- float land_max_acc, land_max_ave;
- float land_personal_space;
- float land_stick_force;
-
- struct ListBase states;
-} BoidSettings;
-
-/* boidsettings->options */
-#define BOID_ALLOW_FLIGHT 1
-#define BOID_ALLOW_LAND 2
-#define BOID_ALLOW_CLIMB 4
-
-/* boidrule->options */
-//#define BOID_RULE_FOLLOW_LINE 1 /* follow leader */
-//#define BOID_RULE_PREDICT 2 /* goal/avoid */
-//#define BOID_RULE_ARRIVAL 4 /* goal */
-//#define BOID_RULE_LAND 8 /* goal */
-//#define BOID_RULE_WITH_BOIDS 16 /* avoid collision */
-//#define BOID_RULE_WITH_DEFLECTORS 32 /* avoid collision */
-
-#endif
diff --git a/source/blender/makesdna/DNA_dynamicpaint_types.h b/source/blender/makesdna/DNA_dynamicpaint_types.h
index 17553e98817..071b576eda5 100644
--- a/source/blender/makesdna/DNA_dynamicpaint_types.h
+++ b/source/blender/makesdna/DNA_dynamicpaint_types.h
@@ -108,8 +108,6 @@ typedef struct DynamicPaintSurface {
struct EffectorWeights *effector_weights;
/* cache */
- struct PointCache *pointcache;
- struct ListBase ptcaches;
int current_frame;
/* surface */
@@ -230,7 +228,6 @@ enum {
typedef struct DynamicPaintBrushSettings {
struct DynamicPaintModifierData *pmd; /* for fast RNA access */
struct DerivedMesh *dm;
- struct ParticleSystem *psys;
struct Material *mat;
int flags;
diff --git a/source/blender/makesdna/DNA_gpencil_types.h b/source/blender/makesdna/DNA_gpencil_types.h
index 23b73424da5..180dd5577ce 100644
--- a/source/blender/makesdna/DNA_gpencil_types.h
+++ b/source/blender/makesdna/DNA_gpencil_types.h
@@ -295,6 +295,7 @@ typedef struct bGPdata {
short sbuffer_sflag; /* flags for stroke that cache represents */
void *sbuffer; /* stroke buffer (can hold GP_STROKE_BUFFER_MAX) */
float scolor[4]; /* buffer color using palettes */
+ float sfill[4]; /* buffer fill color */
char pad[6]; /* padding for compiler alignment error */
short sflag; /* settings for palette color */
diff --git a/source/blender/makesdna/DNA_ipo_types.h b/source/blender/makesdna/DNA_ipo_types.h
index 374104d8b13..9e246075e7d 100644
--- a/source/blender/makesdna/DNA_ipo_types.h
+++ b/source/blender/makesdna/DNA_ipo_types.h
@@ -407,45 +407,6 @@ typedef struct Ipo {
#define FLUIDSIM_VEL_FORCE_STR 12
#define FLUIDSIM_VEL_FORCE_RADIUS 13
-/* ******************** */
-/* particle ipos */
-
-/* ******* Particle (ID_PA) ******** */
-#define PART_TOTIPO 25
-#define PART_TOTNAM 25
-
-#define PART_EMIT_FREQ 1
-/* #define PART_EMIT_LIFE 2 */ /*UNUSED*/
-#define PART_EMIT_VEL 3
-#define PART_EMIT_AVE 4
-/* #define PART_EMIT_SIZE 5 */ /*UNUSED*/
-
-#define PART_AVE 6
-#define PART_SIZE 7
-#define PART_DRAG 8
-#define PART_BROWN 9
-#define PART_DAMP 10
-#define PART_LENGTH 11
-#define PART_CLUMP 12
-
-#define PART_GRAV_X 13
-#define PART_GRAV_Y 14
-#define PART_GRAV_Z 15
-
-#define PART_KINK_AMP 16
-#define PART_KINK_FREQ 17
-#define PART_KINK_SHAPE 18
-
-#define PART_BB_TILT 19
-
-#define PART_PD_FSTR 20
-#define PART_PD_FFALL 21
-#define PART_PD_FMAXD 22
-
-#define PART_PD2_FSTR 23
-#define PART_PD2_FFALL 24
-#define PART_PD2_FMAXD 25
-
/* -------------------- Defines: Flags and Types ------------------ */
diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h
index 9187b76f012..87321e9fd93 100644
--- a/source/blender/makesdna/DNA_modifier_types.h
+++ b/source/blender/makesdna/DNA_modifier_types.h
@@ -52,8 +52,8 @@ typedef enum ModifierType {
eModifierType_Smooth = 16,
eModifierType_Cast = 17,
eModifierType_MeshDeform = 18,
- eModifierType_ParticleSystem = 19,
- eModifierType_ParticleInstance = 20,
+ /*eModifierType_ParticleSystem = 19,*/ /* DEPRECATED */
+ /*eModifierType_ParticleInstance = 20,*/ /* DEPRECATED */
eModifierType_Explode = 21,
eModifierType_Cloth = 22,
eModifierType_Collision = 23,
@@ -593,8 +593,6 @@ typedef struct ClothModifierData {
struct Cloth *clothObject; /* The internal data structure for cloth. */
struct ClothSimSettings *sim_parms; /* definition is in DNA_cloth_types.h */
struct ClothCollSettings *coll_parms; /* definition is in DNA_cloth_types.h */
- struct PointCache *point_cache; /* definition is in DNA_object_force.h */
- struct ListBase ptcaches;
/* XXX nasty hack, remove once hair can be separated from cloth modifier data */
struct ClothHairData *hairdata;
/* grid geometry values of hair continuum */
@@ -714,41 +712,6 @@ enum {
MOD_MDEF_SURFACE = 1,
};
-typedef struct ParticleSystemModifierData {
- ModifierData modifier;
-
- struct ParticleSystem *psys;
- struct DerivedMesh *dm_final; /* Final DM - its topology may differ from orig mesh. */
- struct DerivedMesh *dm_deformed; /* Deformed-onle DM - its topology is same as orig mesh one. */
- int totdmvert, totdmedge, totdmface;
- short flag, pad;
-} ParticleSystemModifierData;
-
-typedef enum {
- eParticleSystemFlag_Pars = (1 << 0),
- eParticleSystemFlag_psys_updated = (1 << 1),
- eParticleSystemFlag_file_loaded = (1 << 2),
-} ParticleSystemModifierFlag;
-
-typedef enum {
- eParticleInstanceFlag_Parents = (1 << 0),
- eParticleInstanceFlag_Children = (1 << 1),
- eParticleInstanceFlag_Path = (1 << 2),
- eParticleInstanceFlag_Unborn = (1 << 3),
- eParticleInstanceFlag_Alive = (1 << 4),
- eParticleInstanceFlag_Dead = (1 << 5),
- eParticleInstanceFlag_KeepShape = (1 << 6),
- eParticleInstanceFlag_UseSize = (1 << 7),
-} ParticleInstanceModifierFlag;
-
-typedef struct ParticleInstanceModifierData {
- ModifierData modifier;
-
- struct Object *ob;
- short psys, flag, axis, pad;
- float position, random_position;
-} ParticleInstanceModifierData;
-
typedef enum {
eExplodeFlag_CalcFaces = (1 << 0),
eExplodeFlag_PaSize = (1 << 1),
@@ -783,7 +746,6 @@ typedef struct FluidsimModifierData {
ModifierData modifier;
struct FluidsimSettings *fss; /* definition is in DNA_object_fluidsim.h */
- struct PointCache *point_cache; /* definition is in DNA_object_force.h */
} FluidsimModifierData;
typedef struct ShrinkwrapModifierData {
diff --git a/source/blender/makesdna/DNA_object_fluidsim.h b/source/blender/makesdna/DNA_object_fluidsim.h
index a714195dd5d..958aea86339 100644
--- a/source/blender/makesdna/DNA_object_fluidsim.h
+++ b/source/blender/makesdna/DNA_object_fluidsim.h
@@ -151,7 +151,7 @@ typedef struct FluidsimSettings {
#define OB_FLUIDSIM_OBSTACLE 8
#define OB_FLUIDSIM_INFLOW 16
#define OB_FLUIDSIM_OUTFLOW 32
-#define OB_FLUIDSIM_PARTICLE 64
+#define OB_FLUIDSIM_PARTICLE 64 /* DEPRECATED */
#define OB_FLUIDSIM_CONTROL 128
#define OB_TYPEFLAG_START 7
diff --git a/source/blender/makesdna/DNA_object_force.h b/source/blender/makesdna/DNA_object_force.h
index 59acefeffe4..71988d10ecf 100644
--- a/source/blender/makesdna/DNA_object_force.h
+++ b/source/blender/makesdna/DNA_object_force.h
@@ -127,87 +127,6 @@ typedef struct EffectorWeights {
/* EffectorWeights->flag */
#define EFF_WEIGHT_DO_HAIR 1
-/* Point cache file data types:
- * - used as (1<<flag) so poke jahka if you reach the limit of 15
- * - to add new data types update:
- * * BKE_ptcache_data_size()
- * * ptcache_file_init_pointers()
- */
-#define BPHYS_DATA_INDEX 0
-#define BPHYS_DATA_LOCATION 1
-#define BPHYS_DATA_SMOKE_LOW 1
-#define BPHYS_DATA_VELOCITY 2
-#define BPHYS_DATA_SMOKE_HIGH 2
-#define BPHYS_DATA_ROTATION 3
-#define BPHYS_DATA_DYNAMICPAINT 3
-#define BPHYS_DATA_AVELOCITY 4 /* used for particles */
-#define BPHYS_DATA_XCONST 4 /* used for cloth */
-#define BPHYS_DATA_SIZE 5
-#define BPHYS_DATA_TIMES 6
-#define BPHYS_DATA_BOIDS 7
-
-#define BPHYS_TOT_DATA 8
-
-#define BPHYS_EXTRA_FLUID_SPRINGS 1
-
-typedef struct PTCacheExtra {
- struct PTCacheExtra *next, *prev;
- unsigned int type, totdata;
- void *data;
-} PTCacheExtra;
-
-typedef struct PTCacheMem {
- struct PTCacheMem *next, *prev;
- unsigned int frame, totpoint;
- unsigned int data_types, flag;
-
- void *data[8]; /* BPHYS_TOT_DATA */
- void *cur[8]; /* BPHYS_TOT_DATA */
-
- struct ListBase extradata;
-} PTCacheMem;
-
-typedef struct PointCache {
- struct PointCache *next, *prev;
- int flag; /* generic flag */
-
- int step; /* The number of frames between cached frames.
- * This should probably be an upper bound for a per point adaptive step in the future,
- * buf for now it's the same for all points. Without adaptivity this can effect the perceived
- * simulation quite a bit though. If for example particles are colliding with a horizontal
- * plane (with high damping) they quickly come to a stop on the plane, however there are still
- * forces acting on the particle (gravity and collisions), so the particle velocity isn't necessarily
- * zero for the whole duration of the frame even if the particle seems stationary. If all simulation
- * frames aren't cached (step > 1) these velocities are interpolated into movement for the non-cached
- * frames. The result will look like the point is oscillating around the collision location. So for
- * now cache step should be set to 1 for accurate reproduction of collisions.
- */
-
- int simframe; /* current frame of simulation (only if SIMULATION_VALID) */
- int startframe; /* simulation start frame */
- int endframe; /* simulation end frame */
- int editframe; /* frame being edited (runtime only) */
- int last_exact; /* last exact frame that's cached */
- int last_valid; /* used for editing cache - what is the last baked frame */
- int pad;
-
- /* for external cache files */
- int totpoint; /* number of cached points */
- int index; /* modifier stack index */
- short compression, rt;
-
- char name[64];
- char prev_name[64];
- char info[64];
- char path[1024]; /* file path, 1024 = FILE_MAX */
- char *cached_frames; /* array of length endframe-startframe+1 with flags to indicate cached frames */
- /* can be later used for other per frame flags too if needed */
- struct ListBase mem_cache;
-
- struct PTCacheEdit *edit;
- void (*free_edit)(struct PTCacheEdit *edit); /* free callback */
-} PointCache;
-
typedef struct SBVertex {
float vec[4];
} SBVertex;
@@ -336,9 +255,6 @@ typedef struct SoftBody {
float shearstiff;
float inpush;
- struct PointCache *pointcache;
- struct ListBase ptcaches;
-
struct Group *collision_group;
struct EffectorWeights *effector_weights;
@@ -394,31 +310,6 @@ typedef struct SoftBody {
#define PFIELD_Z_POS 1
#define PFIELD_Z_NEG 2
-/* pointcache->flag */
-#define PTCACHE_BAKED 1
-#define PTCACHE_OUTDATED 2
-#define PTCACHE_SIMULATION_VALID 4
-#define PTCACHE_BAKING 8
-//#define PTCACHE_BAKE_EDIT 16
-//#define PTCACHE_BAKE_EDIT_ACTIVE 32
-#define PTCACHE_DISK_CACHE 64
-//#define PTCACHE_QUICK_CACHE 128 /* removed since 2.64 - [#30974], could be added back in a more useful way */
-#define PTCACHE_FRAMES_SKIPPED 256
-#define PTCACHE_EXTERNAL 512
-#define PTCACHE_READ_INFO 1024
-/* don't use the filename of the blendfile the data is linked from (write a local cache) */
-#define PTCACHE_IGNORE_LIBPATH 2048
-/* high resolution cache is saved for smoke for backwards compatibility, so set this flag to know it's a "fake" cache */
-#define PTCACHE_FAKE_SMOKE (1<<12)
-#define PTCACHE_IGNORE_CLEAR (1<<13)
-
-/* PTCACHE_OUTDATED + PTCACHE_FRAMES_SKIPPED */
-#define PTCACHE_REDO_NEEDED 258
-
-#define PTCACHE_COMPRESS_NO 0
-#define PTCACHE_COMPRESS_LZO 1
-#define PTCACHE_COMPRESS_LZMA 2
-
/* ob->softflag */
#define OB_SB_ENABLE 1 /* deprecated, use modifier */
#define OB_SB_GOAL 2
diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h
index 85903cabd1a..c54b424abae 100644
--- a/source/blender/makesdna/DNA_object_types.h
+++ b/source/blender/makesdna/DNA_object_types.h
@@ -51,7 +51,6 @@ struct Material;
struct PartDeflect;
struct SoftBody;
struct FluidsimSettings;
-struct ParticleSystem;
struct DerivedMesh;
struct SculptSession;
struct bGPdata;
@@ -263,7 +262,6 @@ typedef struct Object {
ListBase constraints; /* object constraints */
ListBase nlastrips DNA_DEPRECATED; // XXX deprecated... old animation system
ListBase hooks DNA_DEPRECATED; // XXX deprecated... old animation system
- ListBase particlesystem; /* particle systems */
struct PartDeflect *pd; /* particle deflector/attractor/collision data */
struct SoftBody *soft; /* if exists, saved in file */
@@ -350,9 +348,6 @@ typedef struct DupliObject {
/* persistent identifier for a dupli object, for inter-frame matching of
* objects with motion blur, or inter-update matching for syncing */
int persistent_id[16]; /* 2*MAX_DUPLI_RECUR */
-
- /* particle this dupli was generated from */
- struct ParticleSystem *particle_system;
} DupliObject;
/* **************** OBJECT ********************* */
@@ -712,7 +707,7 @@ typedef enum ObjectMode {
OB_MODE_VERTEX_PAINT = 1 << 2,
OB_MODE_WEIGHT_PAINT = 1 << 3,
OB_MODE_TEXTURE_PAINT = 1 << 4,
- OB_MODE_PARTICLE_EDIT = 1 << 5,
+ /*OB_MODE_PARTICLE_EDIT = 1 << 5,*/ /* DEPRECATED */
OB_MODE_POSE = 1 << 6,
OB_MODE_GPENCIL = 1 << 7, /* NOTE: Just a dummy to make the UI nicer */
} ObjectMode;
diff --git a/source/blender/makesdna/DNA_outliner_types.h b/source/blender/makesdna/DNA_outliner_types.h
index 984e3334414..c26c236b978 100644
--- a/source/blender/makesdna/DNA_outliner_types.h
+++ b/source/blender/makesdna/DNA_outliner_types.h
@@ -50,11 +50,14 @@ typedef struct TreeStore {
} TreeStore;
/* TreeStoreElem->flag */
-#define TSE_CLOSED 1
-#define TSE_SELECTED 2
-#define TSE_TEXTBUT 4
-#define TSE_CHILDSEARCH 8
-#define TSE_SEARCHMATCH 16
+enum {
+ TSE_CLOSED = (1 << 0),
+ TSE_SELECTED = (1 << 1),
+ TSE_TEXTBUT = (1 << 2),
+ TSE_CHILDSEARCH = (1 << 3),
+ TSE_SEARCHMATCH = (1 << 4),
+ TSE_HIGHLIGHTED = (1 << 5),
+};
/* TreeStoreElem->types */
#define TSE_NLA 1 /* NO ID */
@@ -87,7 +90,7 @@ typedef struct TreeStore {
#define TSE_SEQUENCE 26 /* NO ID */
#define TSE_SEQ_STRIP 27 /* NO ID */
#define TSE_SEQUENCE_DUP 28 /* NO ID */
-#define TSE_LINKED_PSYS 29
+/* #define TSE_LINKED_PSYS 29 */ /* DEPRECATED */
#define TSE_RNA_STRUCT 30 /* NO ID */
#define TSE_RNA_PROPERTY 31 /* NO ID */
#define TSE_RNA_ARRAY_ELEM 32 /* NO ID */
diff --git a/source/blender/makesdna/DNA_particle_types.h b/source/blender/makesdna/DNA_particle_types.h
deleted file mode 100644
index 1deb9bf3787..00000000000
--- a/source/blender/makesdna/DNA_particle_types.h
+++ /dev/null
@@ -1,613 +0,0 @@
-/*
- * ***** 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) 2007 by Janne Karhu.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file DNA_particle_types.h
- * \ingroup DNA
- */
-
-#ifndef __DNA_PARTICLE_TYPES_H__
-#define __DNA_PARTICLE_TYPES_H__
-
-#include "DNA_defs.h"
-#include "DNA_ID.h"
-#include "DNA_boid_types.h"
-
-struct AnimData;
-
-typedef struct HairKey {
- float co[3]; /* location of hair vertex */
- float time; /* time along hair, default 0-100 */
- float weight; /* softbody weight */
- short editflag; /* saved particled edit mode flags */
- short pad;
- float world_co[3];
-} HairKey;
-
-typedef struct ParticleKey { /* when changed update size of struct to copy_particleKey()!! */
- float co[3]; /* location */
- float vel[3]; /* velocity */
- float rot[4]; /* rotation quaternion */
- float ave[3]; /* angular velocity */
- float time; /* when this key happens */
-} ParticleKey;
-
-typedef struct BoidParticle {
- struct Object *ground;
- struct BoidData data;
- float gravity[3];
- float wander[3];
- float rt;
-} BoidParticle;
-
-typedef struct ParticleSpring {
- float rest_length;
- unsigned int particle_index[2], delete_flag;
-} ParticleSpring;
-
-/* Child particles are created around or between parent particles */
-typedef struct ChildParticle {
- int num, parent; /* num is face index on the final derived mesh */
- int pa[4]; /* nearest particles to the child, used for the interpolation */
- float w[4]; /* interpolation weights for the above particles */
- float fuv[4], foffset; /* face vertex weights and offset */
- float rt;
-} ChildParticle;
-
-typedef struct ParticleTarget {
- struct ParticleTarget *next, *prev;
- struct Object *ob;
- int psys;
- short flag, mode;
- float time, duration;
-} ParticleTarget;
-
-typedef struct ParticleDupliWeight {
- struct ParticleDupliWeight *next, *prev;
- struct Object *ob;
- short count;
- short flag;
- short index, rt; /* only updated on file save and used on file load */
-} ParticleDupliWeight;
-
-typedef struct ParticleData {
- ParticleKey state; /* current global coordinates */
-
- ParticleKey prev_state; /* previous state */
-
- HairKey *hair; /* hair vertices */
-
- ParticleKey *keys; /* keyed keys */
-
- BoidParticle *boid; /* boids data */
-
- int totkey; /* amount of hair or keyed keys*/
-
- float time, lifetime; /* dietime is not nescessarily time+lifetime as */
- float dietime; /* particles can die unnaturally (collision) */
-
- /* WARNING! Those two indices, when not affected to vertices, are for !!! TESSELLATED FACES !!!, not POLYGONS! */
- int num; /* index to vert/edge/face */
- int num_dmcache; /* index to derived mesh data (face) to avoid slow lookups */
-
- float fuv[4], foffset; /* coordinates on face/edge number "num" and depth along*/
- /* face normal for volume emission */
-
- float size; /* size and multiplier so that we can update size when ever */
-
- float sphdensity; /* density of sph particle */
- int pad;
-
- int hair_index;
- short flag;
- short alive; /* the life state of a particle */
-} ParticleData;
-
-typedef struct SPHFluidSettings {
- /*Particle Fluid*/
- float radius, spring_k, rest_length;
- float plasticity_constant, yield_ratio;
- float plasticity_balance, yield_balance;
- float viscosity_omega, viscosity_beta;
- float stiffness_k, stiffness_knear, rest_density;
- float buoyancy;
- int flag, spring_frames;
- short solver;
- short pad[3];
-} SPHFluidSettings;
-
-/* fluid->flag */
-#define SPH_VISCOELASTIC_SPRINGS 1
-#define SPH_CURRENT_REST_LENGTH 2
-#define SPH_FAC_REPULSION 4
-#define SPH_FAC_DENSITY 8
-#define SPH_FAC_RADIUS 16
-#define SPH_FAC_VISCOSITY 32
-#define SPH_FAC_REST_LENGTH 64
-
-/* fluid->solver (numerical ID field, not bitfield) */
-#define SPH_SOLVER_DDR 0
-#define SPH_SOLVER_CLASSICAL 1
-
-typedef struct ParticleSettings {
- ID id;
- struct AnimData *adt;
-
- struct BoidSettings *boids;
- struct SPHFluidSettings *fluid;
-
- struct EffectorWeights *effector_weights;
- struct Group *collision_group;
-
- int flag, rt;
- short type, from, distr, texact;
- /* physics modes */
- short phystype, rotmode, avemode, reactevent;
- int draw, pad1;
- short draw_as, draw_size, childtype, pad2;
- short ren_as, subframes, draw_col;
- /* number of path segments, power of 2 except */
- short draw_step, ren_step;
- short hair_step, keys_step;
-
- /* adaptive path rendering */
- short adapt_angle, adapt_pix;
-
- short disp, omat, interpolation, integrator;
- short rotfrom DNA_DEPRECATED;
- short kink, kink_axis;
-
- /* billboards */
- short bb_align, bb_uv_split, bb_anim, bb_split_offset;
- float bb_tilt, bb_rand_tilt, bb_offset[2], bb_size[2], bb_vel_head, bb_vel_tail;
-
- /* draw color */
- float color_vec_max;
-
- /* simplification */
- short simplify_flag, simplify_refsize;
- float simplify_rate, simplify_transition;
- float simplify_viewport;
-
- /* time and emission */
- float sta, end, lifetime, randlife;
- float timetweak, courant_target;
- float jitfac, eff_hair, grid_rand, ps_offset[1];
- int totpart, userjit, grid_res, effector_amount;
- short time_flag, time_pad[3];
-
- /* initial velocity factors */
- float normfac, obfac, randfac, partfac, tanfac, tanphase, reactfac;
- float ob_vel[3];
- float avefac, phasefac, randrotfac, randphasefac;
- /* physical properties */
- float mass, size, randsize;
- /* global physical properties */
- float acc[3], dragfac, brownfac, dampfac;
- /* length */
- float randlength;
- /* children */
- int child_flag;
- int pad3;
- int child_nbr, ren_child_nbr;
- float parents, childsize, childrandsize;
- float childrad, childflat;
- /* clumping */
- float clumpfac, clumppow;
- /* kink */
- float kink_amp, kink_freq, kink_shape, kink_flat;
- float kink_amp_clump;
- int kink_extra_steps, pad4;
- float kink_axis_random, kink_amp_random;
- /* rough */
- float rough1, rough1_size;
- float rough2, rough2_size, rough2_thres;
- float rough_end, rough_end_shape;
- /* length */
- float clength, clength_thres;
- /* parting */
- float parting_fac;
- float parting_min, parting_max;
- /* branching */
- float branch_thres;
- /* drawing stuff */
- float draw_line[2];
- float path_start, path_end;
- int trail_count;
- /* keyed particles */
- int keyed_loops;
- struct CurveMapping *clumpcurve;
- struct CurveMapping *roughcurve;
- float clump_noise_size;
-
- /* hair dynamics */
- float bending_random;
-
- struct MTex *mtex[18]; /* MAX_MTEX */
-
- struct Group *dup_group;
- struct ListBase dupliweights;
- struct Group *eff_group DNA_DEPRECATED; // deprecated
- struct Object *dup_ob;
- struct Object *bb_ob;
- struct Ipo *ipo DNA_DEPRECATED; /* old animation system, deprecated for 2.5 */
- struct PartDeflect *pd;
- struct PartDeflect *pd2;
-
- /* modified dm support */
- short use_modifier_stack;
- short pad5[3];
-
-} ParticleSettings;
-
-typedef struct ParticleSystem {
- /* note1: make sure all (runtime) are NULL's in 'copy_particlesystem' XXX, this function is no more! - need to invstigate */
- /* note2: make sure any uses of this struct in DNA are accounted for in 'BKE_object_copy_particlesystems' */
-
- struct ParticleSystem *next, *prev;
-
- ParticleSettings *part; /* particle settings */
-
- ParticleData *particles; /* (parent) particles */
- ChildParticle *child; /* child particles */
-
- struct PTCacheEdit *edit; /* particle editmode (runtime) */
- void (*free_edit)(struct PTCacheEdit *edit); /* free callback */
-
- struct ParticleCacheKey **pathcache; /* path cache (runtime) */
- struct ParticleCacheKey **childcache; /* child cache (runtime) */
- ListBase pathcachebufs, childcachebufs; /* buffers for the above */
-
- struct ClothModifierData *clmd; /* cloth simulation for hair */
- struct DerivedMesh *hair_in_dm, *hair_out_dm; /* input/output for cloth simulation */
-
- struct Object *target_ob;
-
- struct LatticeDeformData *lattice_deform_data; /* run-time only lattice deformation data */
-
- struct Object *parent; /* particles from global space -> parent space */
-
- struct ListBase targets; /* used for keyed and boid physics */
-
- char name[64]; /* particle system name, MAX_NAME */
-
- float imat[4][4]; /* used for duplicators */
- float cfra, tree_frame, bvhtree_frame;
- int seed, child_seed;
- int flag, totpart, totunexist, totchild, totcached, totchildcache;
- short recalc, target_psys, totkeyed, bakespace;
-
- char bb_uvname[3][64]; /* billboard uv name, MAX_CUSTOMDATA_LAYER_NAME */
-
- /* if you change these remember to update array lengths to PSYS_TOT_VG! */
- short vgroup[12], vg_neg, rt3; /* vertex groups, 0==disable, 1==starting index */
-
- /* temporary storage during render */
- struct ParticleRenderData *renderdata;
-
- /* point cache */
- struct PointCache *pointcache;
- struct ListBase ptcaches;
-
- struct ListBase *effectors;
-
- ParticleSpring *fluid_springs;
- int tot_fluidsprings, alloc_fluidsprings;
-
- struct KDTree *tree; /* used for interactions with self and other systems */
- struct BVHTree *bvhtree; /* used for interactions with self and other systems */
-
- struct ParticleDrawData *pdd;
-
- float dt_frac; /* current time step, as a fraction of a frame */
- float _pad; /* spare capacity */
-} ParticleSystem;
-
-typedef enum eParticleDrawFlag {
- PART_DRAW_VEL = (1 << 0),
- PART_DRAW_GLOBAL_OB = (1 << 1),
- PART_DRAW_SIZE = (1 << 2),
- PART_DRAW_EMITTER = (1 << 3), /* render emitter also */
- PART_DRAW_HEALTH = (1 << 4),
- PART_ABS_PATH_TIME = (1 << 5),
- PART_DRAW_COUNT_GR = (1 << 6),
- PART_DRAW_BB_LOCK = (1 << 7), /* used with billboards */
- PART_DRAW_ROTATE_OB = (1 << 7), /* used with dupliobjects/groups */
- PART_DRAW_PARENT = (1 << 8),
- PART_DRAW_NUM = (1 << 9),
- PART_DRAW_RAND_GR = (1 << 10),
- PART_DRAW_REN_ADAPT = (1 << 11),
- PART_DRAW_VEL_LENGTH = (1 << 12),
- PART_DRAW_MAT_COL = (1 << 13), /* deprecated, but used in do_versions */
- PART_DRAW_WHOLE_GR = (1 << 14),
- PART_DRAW_REN_STRAND = (1 << 15),
- PART_DRAW_NO_SCALE_OB = (1 << 16), /* used with dupliobjects/groups */
- PART_DRAW_GUIDE_HAIRS = (1 << 17),
- PART_DRAW_HAIR_GRID = (1 << 18),
-} eParticleDrawFlag;
-
-/* part->type */
-/* hair is allways baked static in object/geometry space */
-/* other types (normal particles) are in global space and not static baked */
-#define PART_EMITTER 0
-//#define PART_REACTOR 1
-#define PART_HAIR 2
-#define PART_FLUID 3
-
-/* part->flag */
-#define PART_REACT_STA_END 1
-#define PART_REACT_MULTIPLE 2
-
-//#define PART_LOOP 4 /* not used anymore */
- /* for dopesheet */
-#define PART_DS_EXPAND 8
-
-#define PART_HAIR_REGROW 16 /* regrow hair for each frame */
-
-#define PART_UNBORN 32 /*show unborn particles*/
-#define PART_DIED 64 /*show died particles*/
-
-#define PART_TRAND 128
-#define PART_EDISTR 256 /* particle/face from face areas */
-
-#define PART_ROTATIONS 512 /* calculate particle rotations (and store them in pointcache) */
-#define PART_DIE_ON_COL (1<<12)
-#define PART_SIZE_DEFL (1<<13) /* swept sphere deflections */
-#define PART_ROT_DYN (1<<14) /* dynamic rotation */
-#define PART_SIZEMASS (1<<16)
-
-#define PART_HIDE_ADVANCED_HAIR (1<<15)
-
-//#define PART_ABS_TIME (1<<17)
-//#define PART_GLOB_TIME (1<<18)
-
-#define PART_BOIDS_2D (1<<19)
-
-//#define PART_BRANCHING (1<<20)
-//#define PART_ANIM_BRANCHING (1<<21)
-
-#define PART_HAIR_BSPLINE 1024
-
-#define PART_GRID_HEXAGONAL (1<<24)
-#define PART_GRID_INVERT (1<<26)
-
-#define PART_CHILD_EFFECT (1<<27)
-#define PART_CHILD_LONG_HAIR (1<<28)
-/* #define PART_CHILD_RENDER (1<<29) */ /*UNUSED*/
-#define PART_CHILD_GUIDE (1<<30)
-
-#define PART_SELF_EFFECT (1<<22)
-
-/* part->from */
-#define PART_FROM_VERT 0
-#define PART_FROM_FACE 1
-#define PART_FROM_VOLUME 2
-/* #define PART_FROM_PARTICLE 3 deprecated! */
-#define PART_FROM_CHILD 4
-
-/* part->distr */
-#define PART_DISTR_JIT 0
-#define PART_DISTR_RAND 1
-#define PART_DISTR_GRID 2
-
-/* part->phystype */
-#define PART_PHYS_NO 0
-#define PART_PHYS_NEWTON 1
-#define PART_PHYS_KEYED 2
-#define PART_PHYS_BOIDS 3
-#define PART_PHYS_FLUID 4
-
-/* part->kink */
-typedef enum eParticleKink {
- PART_KINK_NO = 0,
- PART_KINK_CURL = 1,
- PART_KINK_RADIAL = 2,
- PART_KINK_WAVE = 3,
- PART_KINK_BRAID = 4,
- PART_KINK_SPIRAL = 5,
-} eParticleKink;
-
-/* part->child_flag */
-typedef enum eParticleChildFlag {
- PART_CHILD_USE_CLUMP_NOISE = (1<<0),
- PART_CHILD_USE_CLUMP_CURVE = (1<<1),
- PART_CHILD_USE_ROUGH_CURVE = (1<<2),
-} eParticleChildFlag;
-
-/* part->draw_col */
-#define PART_DRAW_COL_NONE 0
-#define PART_DRAW_COL_MAT 1
-#define PART_DRAW_COL_VEL 2
-#define PART_DRAW_COL_ACC 3
-
-
-/* part->simplify_flag */
-#define PART_SIMPLIFY_ENABLE 1
-#define PART_SIMPLIFY_VIEWPORT 2
-
-/* part->time_flag */
-#define PART_TIME_AUTOSF 1 /* Automatic subframes */
-
-/* part->bb_align */
-#define PART_BB_X 0
-#define PART_BB_Y 1
-#define PART_BB_Z 2
-#define PART_BB_VIEW 3
-#define PART_BB_VEL 4
-
-/* part->bb_anim */
-#define PART_BB_ANIM_NONE 0
-#define PART_BB_ANIM_AGE 1
-#define PART_BB_ANIM_ANGLE 2
-#define PART_BB_ANIM_FRAME 3
-
-/* part->bb_split_offset */
-#define PART_BB_OFF_NONE 0
-#define PART_BB_OFF_LINEAR 1
-#define PART_BB_OFF_RANDOM 2
-
-/* part->draw_as */
-/* part->ren_as*/
-#define PART_DRAW_NOT 0
-#define PART_DRAW_DOT 1
-#define PART_DRAW_HALO 1
-#define PART_DRAW_CIRC 2
-#define PART_DRAW_CROSS 3
-#define PART_DRAW_AXIS 4
-#define PART_DRAW_LINE 5
-#define PART_DRAW_PATH 6
-#define PART_DRAW_OB 7
-#define PART_DRAW_GR 8
-#define PART_DRAW_BB 9
-#define PART_DRAW_REND 10
-
-/* part->integrator */
-#define PART_INT_EULER 0
-#define PART_INT_MIDPOINT 1
-#define PART_INT_RK4 2
-#define PART_INT_VERLET 3
-
-/* part->rotmode */
-#define PART_ROT_NOR 1
-#define PART_ROT_VEL 2
-#define PART_ROT_GLOB_X 3
-#define PART_ROT_GLOB_Y 4
-#define PART_ROT_GLOB_Z 5
-#define PART_ROT_OB_X 6
-#define PART_ROT_OB_Y 7
-#define PART_ROT_OB_Z 8
-#define PART_ROT_NOR_TAN 9
-
-/* part->avemode */
-#define PART_AVE_VELOCITY 1
-#define PART_AVE_RAND 2
-#define PART_AVE_HORIZONTAL 3
-#define PART_AVE_VERTICAL 4
-#define PART_AVE_GLOBAL_X 5
-#define PART_AVE_GLOBAL_Y 6
-#define PART_AVE_GLOBAL_Z 7
-
-/* part->reactevent */
-#define PART_EVENT_DEATH 0
-#define PART_EVENT_COLLIDE 1
-#define PART_EVENT_NEAR 2
-
-/* part->childtype */
-#define PART_CHILD_PARTICLES 1
-#define PART_CHILD_FACES 2
-
-/* psys->recalc */
-/* starts from (1 << 3) so that the first bits can be ob->recalc */
-#define PSYS_RECALC_REDO (1 << 3) /* only do pathcache etc */
-#define PSYS_RECALC_RESET (1 << 4) /* reset everything including pointcache */
-#define PSYS_RECALC_TYPE (1 << 5) /* handle system type change */
-#define PSYS_RECALC_CHILD (1 << 6) /* only child settings changed */
-#define PSYS_RECALC_PHYS (1 << 7) /* physics type changed */
-#define PSYS_RECALC (PSYS_RECALC_REDO | PSYS_RECALC_RESET | PSYS_RECALC_TYPE | PSYS_RECALC_CHILD | PSYS_RECALC_PHYS)
-
-/* psys->flag */
-#define PSYS_CURRENT 1
-#define PSYS_GLOBAL_HAIR 2
-#define PSYS_HAIR_DYNAMICS 4
-#define PSYS_KEYED_TIMING 8
-//#define PSYS_ENABLED 16 /* deprecated */
-#define PSYS_HAIR_UPDATED 32 /* signal for updating hair particle mode */
-#define PSYS_DRAWING 64
-#define PSYS_USE_IMAT 128
-#define PSYS_DELETE 256 /* remove particlesystem as soon as possible */
-#define PSYS_HAIR_DONE 512
-#define PSYS_KEYED 1024
-#define PSYS_EDITED 2048
-//#define PSYS_PROTECT_CACHE 4096 /* deprecated */
-#define PSYS_DISABLED 8192
-#define PSYS_OB_ANIM_RESTORE 16384 /* runtime flag */
-
-/* pars->flag */
-#define PARS_UNEXIST 1
-#define PARS_NO_DISP 2
-//#define PARS_STICKY 4 /* deprecated */
-#define PARS_REKEY 8
-
-/* pars->alive */
-//#define PARS_KILLED 0 /* deprecated */
-#define PARS_DEAD 1
-#define PARS_UNBORN 2
-#define PARS_ALIVE 3
-#define PARS_DYING 4
-
-/* ParticleDupliWeight->flag */
-#define PART_DUPLIW_CURRENT 1
-
-/* psys->vg */
-#define PSYS_TOT_VG 12
-
-#define PSYS_VG_DENSITY 0
-#define PSYS_VG_VEL 1
-#define PSYS_VG_LENGTH 2
-#define PSYS_VG_CLUMP 3
-#define PSYS_VG_KINK 4
-#define PSYS_VG_ROUGH1 5
-#define PSYS_VG_ROUGH2 6
-#define PSYS_VG_ROUGHE 7
-#define PSYS_VG_SIZE 8
-#define PSYS_VG_TAN 9
-#define PSYS_VG_ROT 10
-#define PSYS_VG_EFFECTOR 11
-
-/* ParticleTarget->flag */
-#define PTARGET_CURRENT 1
-#define PTARGET_VALID 2
-
-/* ParticleTarget->mode */
-#define PTARGET_MODE_NEUTRAL 0
-#define PTARGET_MODE_FRIEND 1
-#define PTARGET_MODE_ENEMY 2
-
-/* mapto */
-typedef enum eParticleTextureInfluence {
- /* init */
- PAMAP_TIME = (1<<0), /* emission time */
- PAMAP_LIFE = (1<<1), /* life time */
- PAMAP_DENS = (1<<2), /* density */
- PAMAP_SIZE = (1<<3), /* physical size */
- PAMAP_INIT = (PAMAP_TIME | PAMAP_LIFE | PAMAP_DENS | PAMAP_SIZE),
- /* reset */
- PAMAP_IVEL = (1<<5), /* initial velocity */
- /* physics */
- PAMAP_FIELD = (1<<6), /* force fields */
- PAMAP_GRAVITY = (1<<10),
- PAMAP_DAMP = (1<<11),
- PAMAP_PHYSICS = (PAMAP_FIELD | PAMAP_GRAVITY | PAMAP_DAMP),
- /* children */
- PAMAP_CLUMP = (1<<7),
- PAMAP_KINK_FREQ = (1<<8),
- PAMAP_KINK_AMP = (1<<12),
- PAMAP_ROUGH = (1<<9),
- PAMAP_LENGTH = (1<<4),
- PAMAP_CHILD = (PAMAP_CLUMP | PAMAP_KINK_FREQ | PAMAP_KINK_AMP | PAMAP_ROUGH | PAMAP_LENGTH),
-} eParticleTextureInfluence;
-
-#endif
diff --git a/source/blender/makesdna/DNA_rigidbody_types.h b/source/blender/makesdna/DNA_rigidbody_types.h
index 5d76ffe57b5..934028f2e5f 100644
--- a/source/blender/makesdna/DNA_rigidbody_types.h
+++ b/source/blender/makesdna/DNA_rigidbody_types.h
@@ -58,9 +58,6 @@ typedef struct RigidBodyWorld {
int pad;
float ltime; /* last frame world was evaluated for (internal) */
- /* cache */
- struct PointCache *pointcache;
- struct ListBase ptcaches;
int numbodies; /* number of objects in rigid body group */
short steps_per_second; /* number of simulation steps thaken per second */
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index 94f23197293..a21aee25eff 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -1046,39 +1046,6 @@ typedef struct ImagePaintSettings {
} ImagePaintSettings;
/* ------------------------------------------- */
-/* Particle Edit */
-
-/* Settings for a Particle Editing Brush */
-typedef struct ParticleBrushData {
- short size; /* common setting */
- short step, invert, count; /* for specific brushes only */
- int flag;
- float strength;
-} ParticleBrushData;
-
-/* Particle Edit Mode Settings */
-typedef struct ParticleEditSettings {
- short flag;
- short totrekey;
- short totaddkey;
- short brushtype;
-
- ParticleBrushData brush[7]; /* 7 = PE_TOT_BRUSH */
- void *paintcursor; /* runtime */
-
- float emitterdist, rt;
-
- int selectmode;
- int edittype;
-
- int draw_step, fade_frames;
-
- struct Scene *scene;
- struct Object *object;
- struct Object *shape_object;
-} ParticleEditSettings;
-
-/* ------------------------------------------- */
/* Sculpt */
/* Sculpt */
@@ -1434,9 +1401,6 @@ typedef struct ToolSettings {
/* Image Paint (8 byttse aligned please!) */
struct ImagePaintSettings imapaint;
- /* Particle Editing */
- struct ParticleEditSettings particle;
-
/* Transform Proportional Area of Effect */
float proportional_size;
diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h
index e208ef39719..2efb9d1f1ac 100644
--- a/source/blender/makesdna/DNA_screen_types.h
+++ b/source/blender/makesdna/DNA_screen_types.h
@@ -265,9 +265,10 @@ typedef struct ARegion {
ListBase ui_previews; /* uiPreview */
ListBase handlers; /* wmEventHandler */
ListBase panels_category; /* Panel categories runtime */
-
+
+ struct wmManipulatorMap *manipulator_map; /* manipulator-map of this region */
struct wmTimer *regiontimer; /* blend in/out */
-
+
char *headerstr; /* use this string to draw info */
void *regiondata; /* XXX 2.50, need spacedata equivalent? */
} ARegion;
diff --git a/source/blender/makesdna/DNA_smoke_types.h b/source/blender/makesdna/DNA_smoke_types.h
index ba7f73c2f63..68b7f559fce 100644
--- a/source/blender/makesdna/DNA_smoke_types.h
+++ b/source/blender/makesdna/DNA_smoke_types.h
@@ -171,9 +171,6 @@ typedef struct SmokeDomainSettings {
char data_depth;
char pad[2];
- /* Smoke uses only one cache from now on (index [0]), but keeping the array for now for reading old files. */
- struct PointCache *point_cache[2]; /* definition is in DNA_object_force.h */
- struct ListBase ptcaches[2];
struct EffectorWeights *effector_weights;
int border_collisions; /* How domain border collisions are handled */
float time_scale;
@@ -224,7 +221,6 @@ typedef struct SmokeDomainSettings {
typedef struct SmokeFlowSettings {
struct SmokeModifierData *smd; /* for fast RNA access */
struct DerivedMesh *dm;
- struct ParticleSystem *psys;
struct Tex *noise_texture;
/* initial velocity */
diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h
index 5e015544dc9..d1b1074e479 100644
--- a/source/blender/makesdna/DNA_space_types.h
+++ b/source/blender/makesdna/DNA_space_types.h
@@ -174,7 +174,7 @@ typedef enum eSpaceButtons_Context {
BCONTEXT_DATA = 4,
BCONTEXT_MATERIAL = 5,
BCONTEXT_TEXTURE = 6,
- BCONTEXT_PARTICLE = 7,
+ /*BCONTEXT_PARTICLE = 7,*/ /* DEPRECATED */
BCONTEXT_PHYSICS = 8,
BCONTEXT_BONE = 9,
BCONTEXT_MODIFIER = 10,
diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h
index e018b66dd60..30d81df07ef 100644
--- a/source/blender/makesdna/DNA_userdef_types.h
+++ b/source/blender/makesdna/DNA_userdef_types.h
@@ -490,6 +490,7 @@ typedef struct UserDef {
short tb_leftmouse, tb_rightmouse;
struct SolidLight light[3];
short tw_hotspot, tw_flag, tw_handlesize, tw_size;
+ short manipulator_scale, pad3[3];
short textimeout, texcollectrate;
short wmdrawmethod; /* removed wmpad */
short dragthreshold;
@@ -748,7 +749,7 @@ typedef enum eDupli_ID_Flags {
USER_DUP_TEX = (1 << 8),
USER_DUP_ARM = (1 << 9),
USER_DUP_ACT = (1 << 10),
- USER_DUP_PSYS = (1 << 11)
+ /*USER_DUP_PSYS = (1 << 11),*/ /* DEPRECATED */
} eDupli_ID_Flags;
/* gameflags */
@@ -782,8 +783,6 @@ typedef enum eText_Draw_Options {
USER_TEXT_DISABLE_AA = (1 << 0),
} eText_Draw_Options;
-/* tw_flag (transform widget) */
-
/* gp_settings (Grease Pencil Settings) */
typedef enum eGP_UserdefSettings {
GP_PAINT_DOSMOOTH = (1 << 0),
diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h
index dbb5f102d14..e42dd12cae1 100644
--- a/source/blender/makesdna/DNA_view3d_types.h
+++ b/source/blender/makesdna/DNA_view3d_types.h
@@ -45,6 +45,7 @@ struct SmoothView3DStore;
struct wmTimer;
struct Material;
struct GPUFX;
+struct GPUViewport;
struct GPUSSR;
/* This is needed to not let VC choke on near and far... old
@@ -112,7 +113,7 @@ typedef struct RegionView3D {
struct wmTimer *smooth_timer;
- /* transform widget matrix */
+ /* transform manipulator matrix */
float twmat[4][4];
float viewquat[4]; /* view rotation, must be kept normalized */
@@ -148,6 +149,7 @@ typedef struct RegionView3D {
float rot_axis[3];
struct GPUFX *compositor;
+ struct GPUViewport *viewport;
} RegionView3D;
/* 3D ViewPort Struct */
@@ -203,7 +205,7 @@ typedef struct View3D {
short gridsubdiv; /* Number of subdivisions in the grid between each highlighted grid line */
char gridflag;
- /* transform widget info */
+ /* transform manipulator info */
char twtype, twmode, twflag;
short flag3;
@@ -218,8 +220,11 @@ typedef struct View3D {
char multiview_eye; /* multiview current eye - for internal use */
- /* built-in shader effects (eGPUFXFlags) */
- char pad3[4];
+ /* XXX tmp flags for 2.8 viewport transition to avoid compatibility issues that would be caused by
+ * using usual flag bitfields (which are saved to files). Can be removed when not needed anymore. */
+ char tmp_compat_flag;
+
+ char pad3[3];
/* note, 'fx_settings.dof' is currently _not_ allocated,
* instead set (temporarily) from camera */
@@ -330,6 +335,11 @@ typedef struct View3D {
#define V3D_PROBE_CAPTURE (1 << 3) /* runtime flag */
#define V3D_FLIP_NORMALS (1 << 4) /* invert culling during reflection pass */
+/* View3d->tmp_compat_flag */
+enum {
+ V3D_NEW_VIEWPORT = (1 << 0),
+};
+
/* View3D->around */
enum {
/* center of the bounding box */
diff --git a/source/blender/makesdna/intern/makesdna.c b/source/blender/makesdna/intern/makesdna.c
index 2cea8715a65..0f7ed8c0bc0 100644
--- a/source/blender/makesdna/intern/makesdna.c
+++ b/source/blender/makesdna/intern/makesdna.c
@@ -114,12 +114,10 @@ static const char *includefiles[] = {
"DNA_color_types.h",
"DNA_brush_types.h",
"DNA_customdata_types.h",
- "DNA_particle_types.h",
"DNA_cloth_types.h",
"DNA_gpencil_types.h",
"DNA_windowmanager_types.h",
"DNA_anim_types.h",
- "DNA_boid_types.h",
"DNA_smoke_types.h",
"DNA_speaker_types.h",
"DNA_movieclip_types.h",
@@ -1326,12 +1324,10 @@ int main(int argc, char **argv)
#include "DNA_color_types.h"
#include "DNA_brush_types.h"
#include "DNA_customdata_types.h"
-#include "DNA_particle_types.h"
#include "DNA_cloth_types.h"
#include "DNA_gpencil_types.h"
#include "DNA_windowmanager_types.h"
#include "DNA_anim_types.h"
-#include "DNA_boid_types.h"
#include "DNA_smoke_types.h"
#include "DNA_speaker_types.h"
#include "DNA_movieclip_types.h"
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index 44d1a6bfaaf..4a08e6b9b57 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -78,15 +78,6 @@ extern StructRNA RNA_BezierSplinePoint;
extern StructRNA RNA_BlendData;
extern StructRNA RNA_BlendTexture;
extern StructRNA RNA_BlenderRNA;
-extern StructRNA RNA_BoidRule;
-extern StructRNA RNA_BoidRuleAverageSpeed;
-extern StructRNA RNA_BoidRuleAvoid;
-extern StructRNA RNA_BoidRuleAvoidCollision;
-extern StructRNA RNA_BoidRuleFight;
-extern StructRNA RNA_BoidRuleFollowLeader;
-extern StructRNA RNA_BoidRuleGoal;
-extern StructRNA RNA_BoidSettings;
-extern StructRNA RNA_BoidState;
extern StructRNA RNA_Bone;
extern StructRNA RNA_BoneGroup;
extern StructRNA RNA_BooleanModifier;
@@ -100,7 +91,6 @@ extern StructRNA RNA_CacheFile;
extern StructRNA RNA_Camera;
extern StructRNA RNA_CastModifier;
extern StructRNA RNA_ChildOfConstraint;
-extern StructRNA RNA_ChildParticle;
extern StructRNA RNA_ClampToConstraint;
extern StructRNA RNA_ClothCollisionSettings;
extern StructRNA RNA_ClothModifier;
@@ -460,21 +450,7 @@ extern StructRNA RNA_PaintCurve;
extern StructRNA RNA_Palette;
extern StructRNA RNA_PaletteColor;
extern StructRNA RNA_Panel;
-extern StructRNA RNA_Particle;
-extern StructRNA RNA_ParticleBrush;
-extern StructRNA RNA_ParticleDupliWeight;
-extern StructRNA RNA_ParticleEdit;
-extern StructRNA RNA_ParticleFluidSettings;
-extern StructRNA RNA_ParticleHairKey;
-extern StructRNA RNA_ParticleInstanceModifier;
-extern StructRNA RNA_ParticleKey;
-extern StructRNA RNA_ParticleSettings;
-extern StructRNA RNA_ParticleSettingsTextureSlot;
-extern StructRNA RNA_ParticleSystem;
-extern StructRNA RNA_ParticleSystemModifier;
-extern StructRNA RNA_ParticleTarget;
extern StructRNA RNA_PivotConstraint;
-extern StructRNA RNA_PointCache;
extern StructRNA RNA_PointDensity;
extern StructRNA RNA_PointDensityTexture;
extern StructRNA RNA_PointLamp;
diff --git a/source/blender/makesrna/RNA_enum_types.h b/source/blender/makesrna/RNA_enum_types.h
index 1c9b3593d17..27da7392cbd 100644
--- a/source/blender/makesrna/RNA_enum_types.h
+++ b/source/blender/makesrna/RNA_enum_types.h
@@ -59,7 +59,6 @@ extern EnumPropertyItem rna_enum_space_type_items[];
extern EnumPropertyItem rna_enum_region_type_items[];
extern EnumPropertyItem rna_enum_object_modifier_type_items[];
extern EnumPropertyItem rna_enum_constraint_type_items[];
-extern EnumPropertyItem rna_enum_boidrule_type_items[];
extern EnumPropertyItem rna_enum_sequence_modifier_type_items[];
extern EnumPropertyItem rna_enum_modifier_triangulate_quad_method_items[];
diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt
index 0f3ea27a7f9..cc3fd2ce324 100644
--- a/source/blender/makesrna/intern/CMakeLists.txt
+++ b/source/blender/makesrna/intern/CMakeLists.txt
@@ -36,7 +36,6 @@ set(DEFSRC
rna_animation.c
rna_animviz.c
rna_armature.c
- rna_boid.c
rna_brush.c
rna_cachefile.c
rna_camera.c
@@ -70,7 +69,6 @@ set(DEFSRC
rna_object_force.c
rna_packedfile.c
rna_palette.c
- rna_particle.c
rna_pose.c
rna_property.c
rna_render.c
diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c
index 569c1ee5f3f..b2b97ce85d9 100644
--- a/source/blender/makesrna/intern/makesrna.c
+++ b/source/blender/makesrna/intern/makesrna.c
@@ -3299,7 +3299,6 @@ static RNAProcessItem PROCESS_ITEMS[] = {
{"rna_animviz.c", NULL, RNA_def_animviz},
{"rna_actuator.c", "rna_actuator_api.c", RNA_def_actuator},
{"rna_armature.c", "rna_armature_api.c", RNA_def_armature},
- {"rna_boid.c", NULL, RNA_def_boid},
{"rna_brush.c", NULL, RNA_def_brush},
{"rna_cachefile.c", NULL, RNA_def_cachefile},
{"rna_camera.c", "rna_camera_api.c", RNA_def_camera},
@@ -3331,7 +3330,6 @@ static RNAProcessItem PROCESS_ITEMS[] = {
{"rna_object_force.c", NULL, RNA_def_object_force},
{"rna_packedfile.c", NULL, RNA_def_packedfile},
{"rna_palette.c", NULL, RNA_def_palette},
- {"rna_particle.c", NULL, RNA_def_particle},
{"rna_pose.c", "rna_pose_api.c", RNA_def_pose},
{"rna_property.c", NULL, RNA_def_gameproperty},
{"rna_render.c", NULL, RNA_def_render},
diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c
index 280ad4aa9b1..c63fbf272d8 100644
--- a/source/blender/makesrna/intern/rna_ID.c
+++ b/source/blender/makesrna/intern/rna_ID.c
@@ -72,7 +72,6 @@ EnumPropertyItem rna_enum_id_type_items[] = {
{ID_OB, "OBJECT", ICON_OBJECT_DATA, "Object", ""},
{ID_PC, "PAINTCURVE", ICON_CURVE_BEZCURVE, "Paint Curve", ""},
{ID_PAL, "PALETTE", ICON_COLOR, "Palette", ""},
- {ID_PA, "PARTICLE", ICON_PARTICLE_DATA, "Particle", ""},
{ID_SCE, "SCENE", ICON_SCENE_DATA, "Scene", ""},
{ID_SCR, "SCREEN", ICON_SPLITSCREEN, "Screen", ""},
{ID_SO, "SOUND", ICON_PLAY_AUDIO, "Sound", ""},
@@ -158,7 +157,6 @@ short RNA_type_to_ID_code(StructRNA *type)
if (RNA_struct_is_a(type, &RNA_Mask)) return ID_MSK;
if (RNA_struct_is_a(type, &RNA_NodeTree)) return ID_NT;
if (RNA_struct_is_a(type, &RNA_Object)) return ID_OB;
- if (RNA_struct_is_a(type, &RNA_ParticleSettings)) return ID_PA;
if (RNA_struct_is_a(type, &RNA_Palette)) return ID_PAL;
if (RNA_struct_is_a(type, &RNA_PaintCurve)) return ID_PC;
if (RNA_struct_is_a(type, &RNA_Scene)) return ID_SCE;
@@ -198,7 +196,6 @@ StructRNA *ID_code_to_RNA_type(short idcode)
case ID_MSK: return &RNA_Mask;
case ID_NT: return &RNA_NodeTree;
case ID_OB: return &RNA_Object;
- case ID_PA: return &RNA_ParticleSettings;
case ID_PAL: return &RNA_Palette;
case ID_PC: return &RNA_PaintCurve;
case ID_SCE: return &RNA_Scene;
@@ -315,15 +312,6 @@ static void rna_ID_update_tag(ID *id, ReportList *reports, int flag)
return;
}
break;
- /* Could add particle updates later */
-#if 0
- case ID_PA:
- if (flag & ~(OB_RECALC_ALL | PSYS_RECALC)) {
- BKE_report(reports, RPT_ERROR, "'Refresh' incompatible with ParticleSettings ID type");
- return;
- }
- break;
-#endif
default:
BKE_report(reports, RPT_ERROR, "This ID type is not compatible with any 'refresh' options");
return;
diff --git a/source/blender/makesrna/intern/rna_action.c b/source/blender/makesrna/intern/rna_action.c
index 3f2c0f3d434..6c3ac935076 100644
--- a/source/blender/makesrna/intern/rna_action.c
+++ b/source/blender/makesrna/intern/rna_action.c
@@ -476,12 +476,6 @@ static void rna_def_dopesheet(BlenderRNA *brna)
RNA_def_property_ui_icon(prop, ICON_SCENE_DATA, 0);
RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
- prop = RNA_def_property(srna, "show_particles", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_negative_sdna(prop, NULL, "filterflag", ADS_FILTER_NOPART);
- RNA_def_property_ui_text(prop, "Display Particle", "Include visualization of particle related animation data");
- RNA_def_property_ui_icon(prop, ICON_PARTICLE_DATA, 0);
- RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
-
prop = RNA_def_property(srna, "show_metaballs", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "filterflag", ADS_FILTER_NOMBA);
RNA_def_property_ui_text(prop, "Display Metaball", "Include visualization of metaball related animation data");
diff --git a/source/blender/makesrna/intern/rna_boid.c b/source/blender/makesrna/intern/rna_boid.c
deleted file mode 100644
index 72f67b86c23..00000000000
--- a/source/blender/makesrna/intern/rna_boid.c
+++ /dev/null
@@ -1,674 +0,0 @@
-/*
- * ***** 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) 2009 by Janne Karhu.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/makesrna/intern/rna_boid.c
- * \ingroup RNA
- */
-
-#include <float.h>
-#include <limits.h>
-#include <stdlib.h>
-
-#include "DNA_scene_types.h"
-#include "DNA_boid_types.h"
-#include "DNA_object_types.h"
-#include "DNA_particle_types.h"
-
-#include "BLI_utildefines.h"
-
-#include "RNA_define.h"
-#include "RNA_enum_types.h"
-
-#include "rna_internal.h"
-
-#include "WM_api.h"
-#include "WM_types.h"
-
-EnumPropertyItem rna_enum_boidrule_type_items[] = {
- {eBoidRuleType_Goal, "GOAL", 0, "Goal", "Go to assigned object or loudest assigned signal source"},
- {eBoidRuleType_Avoid, "AVOID", 0, "Avoid", "Get away from assigned object or loudest assigned signal source"},
- {eBoidRuleType_AvoidCollision, "AVOID_COLLISION", 0, "Avoid Collision",
- "Maneuver to avoid collisions with other boids and deflector objects in "
- "near future"},
- {eBoidRuleType_Separate, "SEPARATE", 0, "Separate", "Keep from going through other boids"},
- {eBoidRuleType_Flock, "FLOCK", 0, "Flock", "Move to center of neighbors and match their velocity"},
- {eBoidRuleType_FollowLeader, "FOLLOW_LEADER", 0, "Follow Leader", "Follow a boid or assigned object"},
- {eBoidRuleType_AverageSpeed, "AVERAGE_SPEED", 0, "Average Speed", "Maintain speed, flight level or wander"},
- {eBoidRuleType_Fight, "FIGHT", 0, "Fight", "Go to closest enemy and attack when in range"},
-#if 0
- {eBoidRuleType_Protect, "PROTECT", 0, "Protect", "Go to enemy closest to target and attack when in range"},
- {eBoidRuleType_Hide, "HIDE", 0, "Hide", "Find a deflector move to it's other side from closest enemy"},
- {eBoidRuleType_FollowPath, "FOLLOW_PATH", 0, "Follow Path",
- "Move along a assigned curve or closest curve in a group"},
- {eBoidRuleType_FollowWall, "FOLLOW_WALL", 0, "Follow Wall",
- "Move next to a deflector object's in direction of it's tangent"},
-#endif
- {0, NULL, 0, NULL, NULL}
-};
-
-#ifndef RNA_RUNTIME
-static EnumPropertyItem boidruleset_type_items[] = {
- {eBoidRulesetType_Fuzzy, "FUZZY", 0, "Fuzzy",
- "Rules are gone through top to bottom (only the first rule which effect is above "
- "fuzziness threshold is evaluated)"},
- {eBoidRulesetType_Random, "RANDOM", 0, "Random", "A random rule is selected for each boid"},
- {eBoidRulesetType_Average, "AVERAGE", 0, "Average", "All rules are averaged"},
- {0, NULL, 0, NULL, NULL}
-};
-#endif
-
-
-#ifdef RNA_RUNTIME
-
-#include "BLI_math_base.h"
-
-#include "BKE_context.h"
-#include "BKE_depsgraph.h"
-#include "BKE_particle.h"
-
-static void rna_Boids_reset(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
-{
- if (ptr->type == &RNA_ParticleSystem) {
- ParticleSystem *psys = (ParticleSystem *)ptr->data;
-
- psys->recalc = PSYS_RECALC_RESET;
-
- DAG_id_tag_update(ptr->id.data, OB_RECALC_DATA);
- }
- else
- DAG_id_tag_update(ptr->id.data, OB_RECALC_DATA | PSYS_RECALC_RESET);
-
- WM_main_add_notifier(NC_OBJECT | ND_PARTICLE | NA_EDITED, NULL);
-}
-static void rna_Boids_reset_deps(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
-{
- if (ptr->type == &RNA_ParticleSystem) {
- ParticleSystem *psys = (ParticleSystem *)ptr->data;
-
- psys->recalc = PSYS_RECALC_RESET;
-
- DAG_id_tag_update(ptr->id.data, OB_RECALC_DATA);
- }
- else
- DAG_id_tag_update(ptr->id.data, OB_RECALC_DATA | PSYS_RECALC_RESET);
-
- DAG_relations_tag_update(bmain);
-
- WM_main_add_notifier(NC_OBJECT | ND_PARTICLE | NA_EDITED, NULL);
-}
-
-static StructRNA *rna_BoidRule_refine(struct PointerRNA *ptr)
-{
- BoidRule *rule = (BoidRule *)ptr->data;
-
- switch (rule->type) {
- case eBoidRuleType_Goal:
- return &RNA_BoidRuleGoal;
- case eBoidRuleType_Avoid:
- return &RNA_BoidRuleAvoid;
- case eBoidRuleType_AvoidCollision:
- return &RNA_BoidRuleAvoidCollision;
- case eBoidRuleType_FollowLeader:
- return &RNA_BoidRuleFollowLeader;
- case eBoidRuleType_AverageSpeed:
- return &RNA_BoidRuleAverageSpeed;
- case eBoidRuleType_Fight:
- return &RNA_BoidRuleFight;
- default:
- return &RNA_BoidRule;
- }
-}
-
-static char *rna_BoidRule_path(PointerRNA *ptr)
-{
- BoidRule *rule = (BoidRule *)ptr->data;
- char name_esc[sizeof(rule->name) * 2];
-
- BLI_strescape(name_esc, rule->name, sizeof(name_esc));
-
- return BLI_sprintfN("rules[\"%s\"]", name_esc); /* XXX not unique */
-}
-
-static PointerRNA rna_BoidState_active_boid_rule_get(PointerRNA *ptr)
-{
- BoidState *state = (BoidState *)ptr->data;
- BoidRule *rule = (BoidRule *)state->rules.first;
-
- for (; rule; rule = rule->next) {
- if (rule->flag & BOIDRULE_CURRENT)
- return rna_pointer_inherit_refine(ptr, &RNA_BoidRule, rule);
- }
- return rna_pointer_inherit_refine(ptr, &RNA_BoidRule, NULL);
-}
-static void rna_BoidState_active_boid_rule_index_range(PointerRNA *ptr, int *min, int *max,
- int *UNUSED(softmin), int *UNUSED(softmax))
-{
- BoidState *state = (BoidState *)ptr->data;
- *min = 0;
- *max = max_ii(0, BLI_listbase_count(&state->rules) - 1);
-}
-
-static int rna_BoidState_active_boid_rule_index_get(PointerRNA *ptr)
-{
- BoidState *state = (BoidState *)ptr->data;
- BoidRule *rule = (BoidRule *)state->rules.first;
- int i = 0;
-
- for (; rule; rule = rule->next, i++) {
- if (rule->flag & BOIDRULE_CURRENT)
- return i;
- }
- return 0;
-}
-
-static void rna_BoidState_active_boid_rule_index_set(struct PointerRNA *ptr, int value)
-{
- BoidState *state = (BoidState *)ptr->data;
- BoidRule *rule = (BoidRule *)state->rules.first;
- int i = 0;
-
- for (; rule; rule = rule->next, i++) {
- if (i == value)
- rule->flag |= BOIDRULE_CURRENT;
- else
- rule->flag &= ~BOIDRULE_CURRENT;
- }
-}
-
-static int particle_id_check(PointerRNA *ptr)
-{
- ID *id = ptr->id.data;
-
- return (GS(id->name) == ID_PA);
-}
-
-static char *rna_BoidSettings_path(PointerRNA *ptr)
-{
- BoidSettings *boids = (BoidSettings *)ptr->data;
-
- if (particle_id_check(ptr)) {
- ParticleSettings *part = (ParticleSettings *)ptr->id.data;
-
- if (part->boids == boids)
- return BLI_sprintfN("boids");
- }
- return NULL;
-}
-
-static PointerRNA rna_BoidSettings_active_boid_state_get(PointerRNA *ptr)
-{
- BoidSettings *boids = (BoidSettings *)ptr->data;
- BoidState *state = (BoidState *)boids->states.first;
-
- for (; state; state = state->next) {
- if (state->flag & BOIDSTATE_CURRENT)
- return rna_pointer_inherit_refine(ptr, &RNA_BoidState, state);
- }
- return rna_pointer_inherit_refine(ptr, &RNA_BoidState, NULL);
-}
-static void rna_BoidSettings_active_boid_state_index_range(PointerRNA *ptr, int *min, int *max,
- int *UNUSED(softmin), int *UNUSED(softmax))
-{
- BoidSettings *boids = (BoidSettings *)ptr->data;
- *min = 0;
- *max = max_ii(0, BLI_listbase_count(&boids->states) - 1);
-}
-
-static int rna_BoidSettings_active_boid_state_index_get(PointerRNA *ptr)
-{
- BoidSettings *boids = (BoidSettings *)ptr->data;
- BoidState *state = (BoidState *)boids->states.first;
- int i = 0;
-
- for (; state; state = state->next, i++) {
- if (state->flag & BOIDSTATE_CURRENT)
- return i;
- }
- return 0;
-}
-
-static void rna_BoidSettings_active_boid_state_index_set(struct PointerRNA *ptr, int value)
-{
- BoidSettings *boids = (BoidSettings *)ptr->data;
- BoidState *state = (BoidState *)boids->states.first;
- int i = 0;
-
- for (; state; state = state->next, i++) {
- if (i == value)
- state->flag |= BOIDSTATE_CURRENT;
- else
- state->flag &= ~BOIDSTATE_CURRENT;
- }
-}
-
-#else
-
-static void rna_def_boidrule_goal(BlenderRNA *brna)
-{
- StructRNA *srna;
- PropertyRNA *prop;
-
- srna = RNA_def_struct(brna, "BoidRuleGoal", "BoidRule");
- RNA_def_struct_ui_text(srna, "Goal", "");
- RNA_def_struct_sdna(srna, "BoidRuleGoalAvoid");
-
- prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
- RNA_def_property_pointer_sdna(prop, NULL, "ob");
- RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Object", "Goal object");
- RNA_def_property_update(prop, 0, "rna_Boids_reset_deps");
-
- prop = RNA_def_property(srna, "use_predict", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "options", BRULE_GOAL_AVOID_PREDICT);
- RNA_def_property_ui_text(prop, "Predict", "Predict target movement");
- RNA_def_property_update(prop, 0, "rna_Boids_reset");
-}
-
-static void rna_def_boidrule_avoid(BlenderRNA *brna)
-{
- StructRNA *srna;
- PropertyRNA *prop;
-
- srna = RNA_def_struct(brna, "BoidRuleAvoid", "BoidRule");
- RNA_def_struct_ui_text(srna, "Avoid", "");
- RNA_def_struct_sdna(srna, "BoidRuleGoalAvoid");
-
- prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
- RNA_def_property_pointer_sdna(prop, NULL, "ob");
- RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Object", "Object to avoid");
- RNA_def_property_update(prop, 0, "rna_Boids_reset_deps");
-
- prop = RNA_def_property(srna, "use_predict", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "options", BRULE_GOAL_AVOID_PREDICT);
- RNA_def_property_ui_text(prop, "Predict", "Predict target movement");
- RNA_def_property_update(prop, 0, "rna_Boids_reset");
-
- prop = RNA_def_property(srna, "fear_factor", PROP_FLOAT, PROP_NONE);
- RNA_def_property_range(prop, 0.0f, 100.0f);
- RNA_def_property_ui_text(prop, "Fear factor", "Avoid object if danger from it is above this threshold");
- RNA_def_property_update(prop, 0, "rna_Boids_reset");
-}
-
-static void rna_def_boidrule_avoid_collision(BlenderRNA *brna)
-{
- StructRNA *srna;
- PropertyRNA *prop;
-
- srna = RNA_def_struct(brna, "BoidRuleAvoidCollision", "BoidRule");
- RNA_def_struct_ui_text(srna, "Avoid Collision", "");
-
- prop = RNA_def_property(srna, "use_avoid", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "options", BRULE_ACOLL_WITH_BOIDS);
- RNA_def_property_ui_text(prop, "Boids", "Avoid collision with other boids");
- RNA_def_property_update(prop, 0, "rna_Boids_reset");
-
- prop = RNA_def_property(srna, "use_avoid_collision", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "options", BRULE_ACOLL_WITH_DEFLECTORS);
- RNA_def_property_ui_text(prop, "Deflectors", "Avoid collision with deflector objects");
- RNA_def_property_update(prop, 0, "rna_Boids_reset");
-
- prop = RNA_def_property(srna, "look_ahead", PROP_FLOAT, PROP_NONE);
- RNA_def_property_range(prop, 0.0f, 100.0f);
- RNA_def_property_ui_text(prop, "Look ahead", "Time to look ahead in seconds");
- RNA_def_property_update(prop, 0, "rna_Boids_reset");
-}
-
-static void rna_def_boidrule_follow_leader(BlenderRNA *brna)
-{
- StructRNA *srna;
- PropertyRNA *prop;
-
- srna = RNA_def_struct(brna, "BoidRuleFollowLeader", "BoidRule");
- RNA_def_struct_ui_text(srna, "Follow Leader", "");
-
- prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
- RNA_def_property_pointer_sdna(prop, NULL, "ob");
- RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Object", "Follow this object instead of a boid");
- RNA_def_property_update(prop, 0, "rna_Boids_reset_deps");
-
- prop = RNA_def_property(srna, "distance", PROP_FLOAT, PROP_NONE);
- RNA_def_property_range(prop, 0.0f, 100.0f);
- RNA_def_property_ui_text(prop, "Distance", "Distance behind leader to follow");
- RNA_def_property_update(prop, 0, "rna_Boids_reset");
-
- prop = RNA_def_property(srna, "queue_count", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "queue_size");
- RNA_def_property_range(prop, 0.0f, 100.0f);
- RNA_def_property_ui_text(prop, "Queue Size", "How many boids in a line");
- RNA_def_property_update(prop, 0, "rna_Boids_reset");
-
- prop = RNA_def_property(srna, "use_line", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "options", BRULE_LEADER_IN_LINE);
- RNA_def_property_ui_text(prop, "Line", "Follow leader in a line");
- RNA_def_property_update(prop, 0, "rna_Boids_reset");
-}
-
-static void rna_def_boidrule_average_speed(BlenderRNA *brna)
-{
- StructRNA *srna;
- PropertyRNA *prop;
-
- srna = RNA_def_struct(brna, "BoidRuleAverageSpeed", "BoidRule");
- RNA_def_struct_ui_text(srna, "Average Speed", "");
-
- prop = RNA_def_property(srna, "wander", PROP_FLOAT, PROP_NONE);
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Wander", "How fast velocity's direction is randomized");
- RNA_def_property_update(prop, 0, "rna_Boids_reset");
-
- prop = RNA_def_property(srna, "level", PROP_FLOAT, PROP_NONE);
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Level", "How much velocity's z-component is kept constant");
- RNA_def_property_update(prop, 0, "rna_Boids_reset");
-
- prop = RNA_def_property(srna, "speed", PROP_FLOAT, PROP_NONE);
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Speed", "Percentage of maximum speed");
- RNA_def_property_update(prop, 0, "rna_Boids_reset");
-}
-
-static void rna_def_boidrule_fight(BlenderRNA *brna)
-{
- StructRNA *srna;
- PropertyRNA *prop;
-
- srna = RNA_def_struct(brna, "BoidRuleFight", "BoidRule");
- RNA_def_struct_ui_text(srna, "Fight", "");
-
- prop = RNA_def_property(srna, "distance", PROP_FLOAT, PROP_NONE);
- RNA_def_property_range(prop, 0.0f, 100.0f);
- RNA_def_property_ui_text(prop, "Fight Distance", "Attack boids at max this distance");
- RNA_def_property_update(prop, 0, "rna_Boids_reset");
-
- prop = RNA_def_property(srna, "flee_distance", PROP_FLOAT, PROP_NONE);
- RNA_def_property_range(prop, 0.0f, 100.0f);
- RNA_def_property_ui_text(prop, "Flee Distance", "Flee to this distance");
- RNA_def_property_update(prop, 0, "rna_Boids_reset");
-}
-
-static void rna_def_boidrule(BlenderRNA *brna)
-{
- StructRNA *srna;
- PropertyRNA *prop;
-
- /* data */
- srna = RNA_def_struct(brna, "BoidRule", NULL);
- RNA_def_struct_ui_text(srna, "Boid Rule", "");
- RNA_def_struct_refine_func(srna, "rna_BoidRule_refine");
- RNA_def_struct_path_func(srna, "rna_BoidRule_path");
-
- /* strings */
- prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
- RNA_def_property_ui_text(prop, "Name", "Boid rule name");
- RNA_def_struct_name_property(srna, prop);
-
- /* enums */
- prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_enum_sdna(prop, NULL, "type");
- RNA_def_property_enum_items(prop, rna_enum_boidrule_type_items);
- RNA_def_property_ui_text(prop, "Type", "");
-
- /* flags */
- prop = RNA_def_property(srna, "use_in_air", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", BOIDRULE_IN_AIR);
- RNA_def_property_ui_text(prop, "In Air", "Use rule when boid is flying");
- RNA_def_property_update(prop, 0, "rna_Boids_reset");
-
- prop = RNA_def_property(srna, "use_on_land", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", BOIDRULE_ON_LAND);
- RNA_def_property_ui_text(prop, "On Land", "Use rule when boid is on land");
- RNA_def_property_update(prop, 0, "rna_Boids_reset");
-
- /*prop = RNA_def_property(srna, "show_expanded", PROP_BOOLEAN, PROP_NONE); */
- /*RNA_def_property_boolean_sdna(prop, NULL, "mode", eModifierMode_Expanded); */
- /*RNA_def_property_ui_text(prop, "Expanded", "Set modifier expanded in the user interface"); */
-
- /* types */
- rna_def_boidrule_goal(brna);
- rna_def_boidrule_avoid(brna);
- rna_def_boidrule_avoid_collision(brna);
- rna_def_boidrule_follow_leader(brna);
- rna_def_boidrule_average_speed(brna);
- rna_def_boidrule_fight(brna);
-}
-
-static void rna_def_boidstate(BlenderRNA *brna)
-{
- StructRNA *srna;
- PropertyRNA *prop;
-
- srna = RNA_def_struct(brna, "BoidState", NULL);
- RNA_def_struct_ui_text(srna, "Boid State", "Boid state for boid physics");
-
- prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
- RNA_def_property_ui_text(prop, "Name", "Boid state name");
- RNA_def_struct_name_property(srna, prop);
-
- prop = RNA_def_property(srna, "ruleset_type", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_items(prop, boidruleset_type_items);
- RNA_def_property_ui_text(prop, "Rule Evaluation", "How the rules in the list are evaluated");
-
- prop = RNA_def_property(srna, "rules", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_struct_type(prop, "BoidRule");
- RNA_def_property_ui_text(prop, "Boid Rules", "");
-
- prop = RNA_def_property(srna, "active_boid_rule", PROP_POINTER, PROP_NONE);
- RNA_def_property_struct_type(prop, "BoidRule");
- RNA_def_property_pointer_funcs(prop, "rna_BoidState_active_boid_rule_get", NULL, NULL, NULL);
- RNA_def_property_ui_text(prop, "Active Boid Rule", "");
-
- prop = RNA_def_property(srna, "active_boid_rule_index", PROP_INT, PROP_UNSIGNED);
- RNA_def_property_int_funcs(prop, "rna_BoidState_active_boid_rule_index_get",
- "rna_BoidState_active_boid_rule_index_set",
- "rna_BoidState_active_boid_rule_index_range");
- RNA_def_property_ui_text(prop, "Active Boid Rule Index", "");
-
- prop = RNA_def_property(srna, "rule_fuzzy", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "rule_fuzziness");
- RNA_def_property_range(prop, 0.0, 1.0);
- RNA_def_property_ui_text(prop, "Rule Fuzziness", "");
- RNA_def_property_update(prop, 0, "rna_Boids_reset");
-
- prop = RNA_def_property(srna, "volume", PROP_FLOAT, PROP_NONE);
- RNA_def_property_range(prop, 0.0, 100.0);
- RNA_def_property_ui_text(prop, "Volume", "");
- RNA_def_property_update(prop, 0, "rna_Boids_reset");
-
- prop = RNA_def_property(srna, "falloff", PROP_FLOAT, PROP_NONE);
- RNA_def_property_range(prop, 0.0, 10.0);
- RNA_def_property_ui_text(prop, "Falloff", "");
- RNA_def_property_update(prop, 0, "rna_Boids_reset");
-}
-static void rna_def_boid_settings(BlenderRNA *brna)
-{
- StructRNA *srna;
- PropertyRNA *prop;
-
- srna = RNA_def_struct(brna, "BoidSettings", NULL);
- RNA_def_struct_path_func(srna, "rna_BoidSettings_path");
- RNA_def_struct_ui_text(srna, "Boid Settings", "Settings for boid physics");
-
- prop = RNA_def_property(srna, "land_smooth", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "landing_smoothness");
- RNA_def_property_range(prop, 0.0, 10.0);
- RNA_def_property_ui_text(prop, "Landing Smoothness", "How smoothly the boids land");
- RNA_def_property_update(prop, 0, "rna_Boids_reset");
-
- prop = RNA_def_property(srna, "bank", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "banking");
- RNA_def_property_range(prop, 0.0, 2.0);
- RNA_def_property_ui_text(prop, "Banking", "Amount of rotation around velocity vector on turns");
- RNA_def_property_update(prop, 0, "rna_Boids_reset");
-
- prop = RNA_def_property(srna, "pitch", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "pitch");
- RNA_def_property_range(prop, 0.0, 2.0);
- RNA_def_property_ui_text(prop, "Pitch", "Amount of rotation around side vector");
- RNA_def_property_update(prop, 0, "rna_Boids_reset");
-
- prop = RNA_def_property(srna, "height", PROP_FLOAT, PROP_NONE);
- RNA_def_property_range(prop, 0.0, 2.0);
- RNA_def_property_ui_text(prop, "Height", "Boid height relative to particle size");
- RNA_def_property_update(prop, 0, "rna_Boids_reset");
-
- /* states */
- prop = RNA_def_property(srna, "states", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_struct_type(prop, "BoidState");
- RNA_def_property_ui_text(prop, "Boid States", "");
-
- prop = RNA_def_property(srna, "active_boid_state", PROP_POINTER, PROP_NONE);
- RNA_def_property_struct_type(prop, "BoidRule");
- RNA_def_property_pointer_funcs(prop, "rna_BoidSettings_active_boid_state_get", NULL, NULL, NULL);
- RNA_def_property_ui_text(prop, "Active Boid Rule", "");
-
- prop = RNA_def_property(srna, "active_boid_state_index", PROP_INT, PROP_UNSIGNED);
- RNA_def_property_int_funcs(prop, "rna_BoidSettings_active_boid_state_index_get",
- "rna_BoidSettings_active_boid_state_index_set",
- "rna_BoidSettings_active_boid_state_index_range");
- RNA_def_property_ui_text(prop, "Active Boid State Index", "");
-
- /* character properties */
- prop = RNA_def_property(srna, "health", PROP_FLOAT, PROP_NONE);
- RNA_def_property_range(prop, 0.0, 100.0);
- RNA_def_property_ui_text(prop, "Health", "Initial boid health when born");
- RNA_def_property_update(prop, 0, "rna_Boids_reset");
-
- prop = RNA_def_property(srna, "strength", PROP_FLOAT, PROP_NONE);
- RNA_def_property_range(prop, 0.0, 100.0);
- RNA_def_property_ui_text(prop, "Strength", "Maximum caused damage on attack per second");
- RNA_def_property_update(prop, 0, "rna_Boids_reset");
-
- prop = RNA_def_property(srna, "aggression", PROP_FLOAT, PROP_NONE);
- RNA_def_property_range(prop, 0.0, 100.0);
- RNA_def_property_ui_text(prop, "Aggression", "Boid will fight this times stronger enemy");
- RNA_def_property_update(prop, 0, "rna_Boids_reset");
-
- prop = RNA_def_property(srna, "accuracy", PROP_FLOAT, PROP_NONE);
- RNA_def_property_range(prop, 0.0, 1.0);
- RNA_def_property_ui_text(prop, "Accuracy", "Accuracy of attack");
- RNA_def_property_update(prop, 0, "rna_Boids_reset");
-
- prop = RNA_def_property(srna, "range", PROP_FLOAT, PROP_NONE);
- RNA_def_property_range(prop, 0.0, 100.0);
- RNA_def_property_ui_text(prop, "Range", "Maximum distance from which a boid can attack");
- RNA_def_property_update(prop, 0, "rna_Boids_reset");
-
- /* physical properties */
- prop = RNA_def_property(srna, "air_speed_min", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "air_min_speed");
- RNA_def_property_range(prop, 0.0, 1.0);
- RNA_def_property_ui_text(prop, "Min Air Speed", "Minimum speed in air (relative to maximum speed)");
- RNA_def_property_update(prop, 0, "rna_Boids_reset");
-
- prop = RNA_def_property(srna, "air_speed_max", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "air_max_speed");
- RNA_def_property_range(prop, 0.0, 100.0);
- RNA_def_property_ui_text(prop, "Max Air Speed", "Maximum speed in air");
- RNA_def_property_update(prop, 0, "rna_Boids_reset");
-
- prop = RNA_def_property(srna, "air_acc_max", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "air_max_acc");
- RNA_def_property_range(prop, 0.0, 1.0);
- RNA_def_property_ui_text(prop, "Max Air Acceleration", "Maximum acceleration in air (relative to maximum speed)");
- RNA_def_property_update(prop, 0, "rna_Boids_reset");
-
- prop = RNA_def_property(srna, "air_ave_max", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "air_max_ave");
- RNA_def_property_range(prop, 0.0, 1.0);
- RNA_def_property_ui_text(prop, "Max Air Angular Velocity",
- "Maximum angular velocity in air (relative to 180 degrees)");
- RNA_def_property_update(prop, 0, "rna_Boids_reset");
-
- prop = RNA_def_property(srna, "air_personal_space", PROP_FLOAT, PROP_NONE);
- RNA_def_property_range(prop, 0.0, 10.0);
- RNA_def_property_ui_text(prop, "Air Personal Space", "Radius of boids personal space in air (% of particle size)");
- RNA_def_property_update(prop, 0, "rna_Boids_reset");
-
- prop = RNA_def_property(srna, "land_jump_speed", PROP_FLOAT, PROP_NONE);
- RNA_def_property_range(prop, 0.0, 100.0);
- RNA_def_property_ui_text(prop, "Jump Speed", "Maximum speed for jumping");
- RNA_def_property_update(prop, 0, "rna_Boids_reset");
-
- prop = RNA_def_property(srna, "land_speed_max", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "land_max_speed");
- RNA_def_property_range(prop, 0.0, 100.0);
- RNA_def_property_ui_text(prop, "Max Land Speed", "Maximum speed on land");
- RNA_def_property_update(prop, 0, "rna_Boids_reset");
-
- prop = RNA_def_property(srna, "land_acc_max", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "land_max_acc");
- RNA_def_property_range(prop, 0.0, 1.0);
- RNA_def_property_ui_text(prop, "Max Land Acceleration",
- "Maximum acceleration on land (relative to maximum speed)");
- RNA_def_property_update(prop, 0, "rna_Boids_reset");
-
- prop = RNA_def_property(srna, "land_ave_max", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "land_max_ave");
- RNA_def_property_range(prop, 0.0, 1.0);
- RNA_def_property_ui_text(prop, "Max Land Angular Velocity",
- "Maximum angular velocity on land (relative to 180 degrees)");
- RNA_def_property_update(prop, 0, "rna_Boids_reset");
-
- prop = RNA_def_property(srna, "land_personal_space", PROP_FLOAT, PROP_NONE);
- RNA_def_property_range(prop, 0.0, 10.0);
- RNA_def_property_ui_text(prop, "Land Personal Space",
- "Radius of boids personal space on land (% of particle size)");
- RNA_def_property_update(prop, 0, "rna_Boids_reset");
-
- prop = RNA_def_property(srna, "land_stick_force", PROP_FLOAT, PROP_NONE);
- RNA_def_property_range(prop, 0.0, 1000.0);
- RNA_def_property_ui_text(prop, "Land Stick Force", "How strong a force must be to start effecting a boid on land");
- RNA_def_property_update(prop, 0, "rna_Boids_reset");
-
- /* options */
- prop = RNA_def_property(srna, "use_flight", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "options", BOID_ALLOW_FLIGHT);
- RNA_def_property_ui_text(prop, "Allow Flight", "Allow boids to move in air");
- RNA_def_property_update(prop, 0, "rna_Boids_reset");
-
- prop = RNA_def_property(srna, "use_land", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "options", BOID_ALLOW_LAND);
- RNA_def_property_ui_text(prop, "Allow Land", "Allow boids to move on land");
- RNA_def_property_update(prop, 0, "rna_Boids_reset");
-
- prop = RNA_def_property(srna, "use_climb", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "options", BOID_ALLOW_CLIMB);
- RNA_def_property_ui_text(prop, "Allow Climbing", "Allow boids to climb goal objects");
- RNA_def_property_update(prop, 0, "rna_Boids_reset");
-}
-
-void RNA_def_boid(BlenderRNA *brna)
-{
- rna_def_boidrule(brna);
- rna_def_boidstate(brna);
- rna_def_boid_settings(brna);
-}
-
-#endif
diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c
index 6351b4ebeeb..e03e46422a3 100644
--- a/source/blender/makesrna/intern/rna_color.c
+++ b/source/blender/makesrna/intern/rna_color.c
@@ -47,7 +47,6 @@
#include "DNA_movieclip_types.h"
#include "DNA_node_types.h"
#include "DNA_object_types.h"
-#include "DNA_particle_types.h"
#include "DNA_sequence_types.h"
#include "MEM_guardedalloc.h"
@@ -346,13 +345,6 @@ static void rna_ColorRamp_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *
WM_main_add_notifier(NC_LINESTYLE, linestyle);
break;
}
- case ID_PA:
- {
- ParticleSettings *part = ptr->id.data;
-
- DAG_id_tag_update(&part->id, OB_RECALC_DATA | PSYS_RECALC_REDO);
- WM_main_add_notifier(NC_OBJECT | ND_PARTICLE | NA_EDITED, part);
- }
default:
break;
}
diff --git a/source/blender/makesrna/intern/rna_context.c b/source/blender/makesrna/intern/rna_context.c
index d7a679e9702..1021aa60654 100644
--- a/source/blender/makesrna/intern/rna_context.c
+++ b/source/blender/makesrna/intern/rna_context.c
@@ -147,7 +147,6 @@ void RNA_def_context(BlenderRNA *brna)
{CTX_MODE_PAINT_WEIGHT, "PAINT_WEIGHT", 0, "Weight Paint", ""},
{CTX_MODE_PAINT_VERTEX, "PAINT_VERTEX", 0, "Vertex Paint", ""},
{CTX_MODE_PAINT_TEXTURE, "PAINT_TEXTURE", 0, "Texture Paint", ""},
- {CTX_MODE_PARTICLE, "PARTICLE", 0, "Particle", ""},
{CTX_MODE_OBJECT, "OBJECT", 0, "Object", ""},
{0, NULL, 0, NULL, NULL}
};
diff --git a/source/blender/makesrna/intern/rna_dynamicpaint.c b/source/blender/makesrna/intern/rna_dynamicpaint.c
index fc2b028e829..70554bd603b 100644
--- a/source/blender/makesrna/intern/rna_dynamicpaint.c
+++ b/source/blender/makesrna/intern/rna_dynamicpaint.c
@@ -56,7 +56,6 @@ EnumPropertyItem rna_enum_prop_dynamicpaint_type_items[] = {
#include "BKE_context.h"
#include "BKE_depsgraph.h"
-#include "BKE_particle.h"
static char *rna_DynamicPaintCanvasSettings_path(PointerRNA *ptr)
@@ -101,11 +100,6 @@ static void rna_DynamicPaint_redoModifier(Main *UNUSED(bmain), Scene *UNUSED(sce
DAG_id_tag_update(ptr->id.data, OB_RECALC_DATA);
}
-static void rna_DynamicPaintSurfaces_updateFrames(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
-{
- dynamicPaint_cacheUpdateFrames((DynamicPaintSurface *)ptr->data);
-}
-
static void rna_DynamicPaintSurface_reset(Main *bmain, Scene *scene, PointerRNA *ptr)
{
dynamicPaint_resetSurface(scene, (DynamicPaintSurface *)ptr->data);
@@ -184,20 +178,20 @@ static void rna_DynamicPaint_surfaces_begin(CollectionPropertyIterator *iter, Po
rna_iterator_listbase_begin(iter, &canvas->surfaces, NULL);
}
-static int rna_Surface_active_point_index_get(PointerRNA *ptr)
+static int rna_Surface_active_index_get(PointerRNA *ptr)
{
DynamicPaintCanvasSettings *canvas = (DynamicPaintCanvasSettings *)ptr->data;
return canvas->active_sur;
}
-static void rna_Surface_active_point_index_set(struct PointerRNA *ptr, int value)
+static void rna_Surface_active_index_set(struct PointerRNA *ptr, int value)
{
DynamicPaintCanvasSettings *canvas = (DynamicPaintCanvasSettings *)ptr->data;
canvas->active_sur = value;
return;
}
-static void rna_Surface_active_point_range(PointerRNA *ptr, int *min, int *max,
+static void rna_Surface_active_range(PointerRNA *ptr, int *min, int *max,
int *UNUSED(softmin), int *UNUSED(softmax))
{
DynamicPaintCanvasSettings *canvas = (DynamicPaintCanvasSettings *)ptr->data;
@@ -222,7 +216,7 @@ static void rna_DynamicPaint_uvlayer_set(PointerRNA *ptr, const char *value)
}
}
-/* is point cache used */
+/* is cache used */
static int rna_DynamicPaint_is_cache_user_get(PointerRNA *ptr)
{
DynamicPaintSurface *surface = (DynamicPaintSurface *)ptr->data;
@@ -311,9 +305,9 @@ static void rna_def_canvas_surfaces(BlenderRNA *brna, PropertyRNA *cprop)
prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_UNSIGNED);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_int_funcs(prop, "rna_Surface_active_point_index_get", "rna_Surface_active_point_index_set",
- "rna_Surface_active_point_range");
- RNA_def_property_ui_text(prop, "Active Point Cache Index", "");
+ RNA_def_property_int_funcs(prop, "rna_Surface_active_index_get", "rna_Surface_active_index_set",
+ "rna_Surface_active_range");
+ RNA_def_property_ui_text(prop, "Active Surface Index", "");
prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "DynamicPaintSurface");
@@ -473,7 +467,7 @@ static void rna_def_canvas_surface(BlenderRNA *brna)
RNA_def_property_range(prop, 1.0, MAXFRAMEF);
RNA_def_property_ui_range(prop, 1.0, 9999, 1, -1);
RNA_def_property_ui_text(prop, "Start Frame", "Simulation start frame");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_DynamicPaintSurfaces_updateFrames");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, NULL);
prop = RNA_def_property(srna, "frame_end", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "end_frame");
@@ -481,7 +475,7 @@ static void rna_def_canvas_surface(BlenderRNA *brna)
RNA_def_property_range(prop, 1.0, MAXFRAMEF);
RNA_def_property_ui_range(prop, 1.0, 9999.0, 1, -1);
RNA_def_property_ui_text(prop, "End Frame", "Simulation end frame");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_DynamicPaintSurfaces_updateFrames");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, NULL);
prop = RNA_def_property(srna, "frame_substeps", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "substeps");
@@ -722,13 +716,6 @@ static void rna_def_canvas_surface(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_DPAINT_WAVE_OPEN_BORDERS);
RNA_def_property_ui_text(prop, "Open Borders", "Pass waves through mesh edges");
-
- /* cache */
- prop = RNA_def_property(srna, "point_cache", PROP_POINTER, PROP_NONE);
- RNA_def_property_flag(prop, PROP_NEVER_NULL);
- RNA_def_property_pointer_sdna(prop, NULL, "pointcache");
- RNA_def_property_ui_text(prop, "Point Cache", "");
-
/* is cache used */
prop = RNA_def_property(srna, "is_cache_user", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_funcs(prop, "rna_DynamicPaint_is_cache_user_get", NULL);
@@ -955,38 +942,6 @@ static void rna_def_dynamic_paint_brush_settings(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_DPAINT_NEGATE_VOLUME);
RNA_def_property_ui_text(prop, "Negate Volume", "Negate influence inside the volume");
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_DynamicPaint_redoModifier");
-
-
- /*
- * Particle
- */
- prop = RNA_def_property(srna, "particle_system", PROP_POINTER, PROP_NONE);
- RNA_def_property_pointer_sdna(prop, NULL, "psys");
- RNA_def_property_struct_type(prop, "ParticleSystem");
- RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Particle Systems", "The particle system to paint with");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_DynamicPaint_reset_dependency");
-
-
- prop = RNA_def_property(srna, "use_particle_radius", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_DPAINT_PART_RAD);
- RNA_def_property_ui_text(prop, "Use Particle Radius", "Use radius from particle settings");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_DynamicPaint_redoModifier");
-
- prop = RNA_def_property(srna, "solid_radius", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "particle_radius");
- RNA_def_property_range(prop, 0.01, 10.0);
- RNA_def_property_ui_range(prop, 0.01, 2.0, 5, 3);
- RNA_def_property_ui_text(prop, "Solid Radius", "Radius that will be painted solid");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_DynamicPaint_redoModifier");
-
- prop = RNA_def_property(srna, "smooth_radius", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "particle_smooth");
- RNA_def_property_range(prop, 0.0, 10.0);
- RNA_def_property_ui_range(prop, 0.0, 1.0, 5, -1);
- RNA_def_property_ui_text(prop, "Smooth Radius", "Smooth falloff added after solid radius");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_DynamicPaint_redoModifier");
-
/*
* Color ramps
diff --git a/source/blender/makesrna/intern/rna_fluidsim.c b/source/blender/makesrna/intern/rna_fluidsim.c
index 091950a8e66..06dec0998a5 100644
--- a/source/blender/makesrna/intern/rna_fluidsim.c
+++ b/source/blender/makesrna/intern/rna_fluidsim.c
@@ -43,16 +43,14 @@
#include "MEM_guardedalloc.h"
+#include "DNA_object_types.h"
#include "DNA_scene_types.h"
-#include "DNA_particle_types.h"
#include "BKE_depsgraph.h"
#include "BKE_fluidsim.h"
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_modifier.h"
-#include "BKE_particle.h"
-#include "BKE_pointcache.h"
static StructRNA *rna_FluidSettings_refine(struct PointerRNA *ptr)
{
@@ -121,54 +119,10 @@ static void rna_FluidSettings_update_type(Main *bmain, Scene *scene, PointerRNA
{
Object *ob = (Object *)ptr->id.data;
FluidsimModifierData *fluidmd;
- ParticleSystemModifierData *psmd;
- ParticleSystem *psys, *next_psys;
- ParticleSettings *part;
fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim);
fluidmd->fss->flag &= ~OB_FLUIDSIM_REVERSE; /* clear flag */
- /* remove fluidsim particle system */
- if (fluidmd->fss->type & OB_FLUIDSIM_PARTICLE) {
- for (psys = ob->particlesystem.first; psys; psys = psys->next)
- if (psys->part->type == PART_FLUID)
- break;
-
- if (ob->type == OB_MESH && !psys) {
- /* add particle system */
- part = psys_new_settings("ParticleSettings", bmain);
- psys = MEM_callocN(sizeof(ParticleSystem), "particle_system");
-
- part->type = PART_FLUID;
- psys->part = part;
- psys->pointcache = BKE_ptcache_add(&psys->ptcaches);
- BLI_strncpy(psys->name, "FluidParticles", sizeof(psys->name));
- BLI_addtail(&ob->particlesystem, psys);
-
- /* add modifier */
- psmd = (ParticleSystemModifierData *)modifier_new(eModifierType_ParticleSystem);
- BLI_strncpy(psmd->modifier.name, "FluidParticleSystem", sizeof(psmd->modifier.name));
- psmd->psys = psys;
- BLI_addtail(&ob->modifiers, psmd);
- modifier_unique_name(&ob->modifiers, (ModifierData *)psmd);
- }
- }
- else {
- for (psys = ob->particlesystem.first; psys; psys = next_psys) {
- next_psys = psys->next;
- if (psys->part->type == PART_FLUID) {
- /* clear modifier */
- psmd = psys_get_modifier(ob, psys);
- BLI_remlink(&ob->modifiers, psmd);
- modifier_free((ModifierData *)psmd);
-
- /* clear particle system */
- BLI_remlink(&ob->particlesystem, psys);
- psys_free(ob, psys);
- }
- }
- }
-
rna_fluid_update(bmain, scene, ptr);
}
diff --git a/source/blender/makesrna/intern/rna_image_api.c b/source/blender/makesrna/intern/rna_image_api.c
index 2d967e544d6..58b51040b4e 100644
--- a/source/blender/makesrna/intern/rna_image_api.c
+++ b/source/blender/makesrna/intern/rna_image_api.c
@@ -251,6 +251,8 @@ static int rna_Image_gl_load(Image *image, ReportList *reports, int frame, int f
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (GLint)filter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (GLint)mag);
+ /* TODO(merwin): validate input (dimensions, filter, mag) before calling OpenGL
+ * instead of trusting input & testing for error after */
error = glGetError();
if (error) {
diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h
index 76455adbc78..c406aa987e5 100644
--- a/source/blender/makesrna/intern/rna_internal.h
+++ b/source/blender/makesrna/intern/rna_internal.h
@@ -164,7 +164,6 @@ void RNA_def_object(struct BlenderRNA *brna);
void RNA_def_object_force(struct BlenderRNA *brna);
void RNA_def_packedfile(struct BlenderRNA *brna);
void RNA_def_palette(struct BlenderRNA *brna);
-void RNA_def_particle(struct BlenderRNA *brna);
void RNA_def_pose(struct BlenderRNA *brna);
void RNA_def_render(struct BlenderRNA *brna);
void RNA_def_rigidbody(struct BlenderRNA *brna);
@@ -327,7 +326,6 @@ void RNA_def_main_speakers(BlenderRNA *brna, PropertyRNA *cprop);
void RNA_def_main_sounds(BlenderRNA *brna, PropertyRNA *cprop);
void RNA_def_main_armatures(BlenderRNA *brna, PropertyRNA *cprop);
void RNA_def_main_actions(BlenderRNA *brna, PropertyRNA *cprop);
-void RNA_def_main_particles(BlenderRNA *brna, PropertyRNA *cprop);
void RNA_def_main_palettes(BlenderRNA *brna, PropertyRNA *cprop);
void RNA_def_main_gpencil(BlenderRNA *brna, PropertyRNA *cprop);
void RNA_def_main_movieclips(BlenderRNA *brna, PropertyRNA *cprop);
diff --git a/source/blender/makesrna/intern/rna_main.c b/source/blender/makesrna/intern/rna_main.c
index d432f086dba..59f079b4259 100644
--- a/source/blender/makesrna/intern/rna_main.c
+++ b/source/blender/makesrna/intern/rna_main.c
@@ -239,12 +239,6 @@ static void rna_Main_brush_begin(CollectionPropertyIterator *iter, PointerRNA *p
rna_iterator_listbase_begin(iter, &bmain->brush, NULL);
}
-static void rna_Main_particle_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
-{
- Main *bmain = (Main *)ptr->data;
- rna_iterator_listbase_begin(iter, &bmain->particle, NULL);
-}
-
static void rna_Main_palettes_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
Main *bmain = (Main *)ptr->data;
@@ -360,7 +354,6 @@ void RNA_def_main(BlenderRNA *brna)
{"sounds", "Sound", "rna_Main_sound_begin", "Sounds", "Sound data-blocks", RNA_def_main_sounds},
{"armatures", "Armature", "rna_Main_armature_begin", "Armatures", "Armature data-blocks", RNA_def_main_armatures},
{"actions", "Action", "rna_Main_action_begin", "Actions", "Action data-blocks", RNA_def_main_actions},
- {"particles", "ParticleSettings", "rna_Main_particle_begin", "Particles", "Particle data-blocks", RNA_def_main_particles},
{"palettes", "Palette", "rna_Main_palettes_begin", "Palettes", "Palette data-blocks", RNA_def_main_palettes},
{"grease_pencil", "GreasePencil", "rna_Main_gpencil_begin", "Grease Pencil", "Grease Pencil data-blocks", RNA_def_main_gpencil},
{"movieclips", "MovieClip", "rna_Main_movieclips_begin", "Movie Clips", "Movie Clip data-blocks", RNA_def_main_movieclips},
diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c
index cc290eab59d..e5cea63db1f 100644
--- a/source/blender/makesrna/intern/rna_main_api.c
+++ b/source/blender/makesrna/intern/rna_main_api.c
@@ -74,7 +74,6 @@
#include "BKE_lattice.h"
#include "BKE_mball.h"
#include "BKE_world.h"
-#include "BKE_particle.h"
#include "BKE_paint.h"
#include "BKE_font.h"
#include "BKE_node.h"
@@ -100,7 +99,6 @@
#include "DNA_lattice_types.h"
#include "DNA_meta_types.h"
#include "DNA_world_types.h"
-#include "DNA_particle_types.h"
#include "DNA_vfont_types.h"
#include "DNA_node_types.h"
#include "DNA_movieclip_types.h"
@@ -444,13 +442,6 @@ static bAction *rna_Main_actions_new(Main *bmain, const char *name)
return act;
}
-static ParticleSettings *rna_Main_particles_new(Main *bmain, const char *name)
-{
- ParticleSettings *part = psys_new_settings(name, bmain);
- id_us_min(&part->id);
- return part;
-}
-
static Palette *rna_Main_palettes_new(Main *bmain, const char *name)
{
Palette *palette = BKE_palette_add(bmain, name);
@@ -529,7 +520,6 @@ RNA_MAIN_ID_TAG_FUNCS_DEF(speakers, speaker, ID_SPK)
RNA_MAIN_ID_TAG_FUNCS_DEF(sounds, sound, ID_SO)
RNA_MAIN_ID_TAG_FUNCS_DEF(armatures, armature, ID_AR)
RNA_MAIN_ID_TAG_FUNCS_DEF(actions, action, ID_AC)
-RNA_MAIN_ID_TAG_FUNCS_DEF(particles, particle, ID_PA)
RNA_MAIN_ID_TAG_FUNCS_DEF(palettes, palettes, ID_PAL)
RNA_MAIN_ID_TAG_FUNCS_DEF(gpencil, gpencil, ID_GD)
RNA_MAIN_ID_TAG_FUNCS_DEF(movieclips, movieclip, ID_MC)
@@ -1478,42 +1468,6 @@ void RNA_def_main_actions(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_boolean_funcs(prop, "rna_Main_actions_is_updated_get", NULL);
}
-void RNA_def_main_particles(BlenderRNA *brna, PropertyRNA *cprop)
-{
- StructRNA *srna;
- FunctionRNA *func;
- PropertyRNA *parm;
- PropertyRNA *prop;
-
- RNA_def_property_srna(cprop, "BlendDataParticles");
- srna = RNA_def_struct(brna, "BlendDataParticles", NULL);
- RNA_def_struct_sdna(srna, "Main");
- RNA_def_struct_ui_text(srna, "Main Particle Settings", "Collection of particle settings");
-
- func = RNA_def_function(srna, "new", "rna_Main_particles_new");
- RNA_def_function_ui_description(func, "Add a new particle settings instance to the main database");
- parm = RNA_def_string(func, "name", "ParticleSettings", 0, "", "New name for the data-block");
- RNA_def_property_flag(parm, PROP_REQUIRED);
- /* return type */
- parm = RNA_def_pointer(func, "particle", "ParticleSettings", "", "New particle settings 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 particle settings instance from the current blendfile");
- parm = RNA_def_pointer(func, "particle", "ParticleSettings", "", "Particle Settings to remove");
- RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
- RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
- RNA_def_boolean(func, "do_unlink", false, "", "Unlink all usages of those particle settings before deleting them");
-
- func = RNA_def_function(srna, "tag", "rna_Main_particles_tag");
- parm = RNA_def_boolean(func, "value", 0, "Value", "");
- RNA_def_property_flag(parm, PROP_REQUIRED);
-
- prop = RNA_def_property(srna, "is_updated", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_boolean_funcs(prop, "rna_Main_particles_is_updated_get", NULL);
-}
void RNA_def_main_palettes(BlenderRNA *brna, PropertyRNA *cprop)
{
StructRNA *srna;
diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c
index 34ca6a12fc3..6cd9fe8f525 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -114,8 +114,6 @@ EnumPropertyItem rna_enum_object_modifier_type_items[] = {
{eModifierType_Explode, "EXPLODE", ICON_MOD_EXPLODE, "Explode", ""},
{eModifierType_Fluidsim, "FLUID_SIMULATION", ICON_MOD_FLUIDSIM, "Fluid Simulation", ""},
{eModifierType_Ocean, "OCEAN", ICON_MOD_OCEAN, "Ocean", ""},
- {eModifierType_ParticleInstance, "PARTICLE_INSTANCE", ICON_MOD_PARTICLES, "Particle Instance", ""},
- {eModifierType_ParticleSystem, "PARTICLE_SYSTEM", ICON_MOD_PARTICLES, "Particle System", ""},
{eModifierType_Smoke, "SMOKE", ICON_MOD_SMOKE, "Smoke", ""},
{eModifierType_Softbody, "SOFT_BODY", ICON_MOD_SOFT, "Soft Body", ""},
{eModifierType_Surface, "SURFACE", ICON_MOD_PHYSICS, "Surface", ""},
@@ -279,7 +277,6 @@ EnumPropertyItem rna_enum_axis_flag_xyz_items[] = {
#ifdef RNA_RUNTIME
-#include "DNA_particle_types.h"
#include "DNA_curve_types.h"
#include "DNA_smoke_types.h"
@@ -289,7 +286,6 @@ EnumPropertyItem rna_enum_axis_flag_xyz_items[] = {
#include "BKE_library.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
-#include "BKE_particle.h"
#ifdef WITH_ALEMBIC
# include "ABC_alembic.h"
@@ -342,10 +338,6 @@ static StructRNA *rna_Modifier_refine(struct PointerRNA *ptr)
return &RNA_CastModifier;
case eModifierType_MeshDeform:
return &RNA_MeshDeformModifier;
- case eModifierType_ParticleSystem:
- return &RNA_ParticleSystemModifier;
- case eModifierType_ParticleInstance:
- return &RNA_ParticleInstanceModifier;
case eModifierType_Explode:
return &RNA_ExplodeModifier;
case eModifierType_Cloth:
@@ -707,12 +699,6 @@ static PointerRNA rna_SoftBodyModifier_settings_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_SoftBodySettings, ob->soft);
}
-static PointerRNA rna_SoftBodyModifier_point_cache_get(PointerRNA *ptr)
-{
- Object *ob = (Object *)ptr->id.data;
- return rna_pointer_inherit_refine(ptr, &RNA_PointCache, ob->soft->pointcache);
-}
-
static PointerRNA rna_CollisionModifier_settings_get(PointerRNA *ptr)
{
Object *ob = (Object *)ptr->id.data;
@@ -1885,12 +1871,6 @@ static void rna_def_modifier_softbody(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "SoftBodySettings");
RNA_def_property_pointer_funcs(prop, "rna_SoftBodyModifier_settings_get", NULL, NULL, NULL);
RNA_def_property_ui_text(prop, "Soft Body Settings", "");
-
- prop = RNA_def_property(srna, "point_cache", PROP_POINTER, PROP_NONE);
- RNA_def_property_flag(prop, PROP_NEVER_NULL);
- RNA_def_property_struct_type(prop, "PointCache");
- RNA_def_property_pointer_funcs(prop, "rna_SoftBodyModifier_point_cache_get", NULL, NULL, NULL);
- RNA_def_property_ui_text(prop, "Soft Body Point Cache", "");
}
static void rna_def_modifier_boolean(BlenderRNA *brna)
@@ -2551,104 +2531,6 @@ static void rna_def_modifier_meshdeform(BlenderRNA *brna)
#endif
}
-static void rna_def_modifier_particlesystem(BlenderRNA *brna)
-{
- StructRNA *srna;
- PropertyRNA *prop;
-
- srna = RNA_def_struct(brna, "ParticleSystemModifier", "Modifier");
- RNA_def_struct_ui_text(srna, "ParticleSystem Modifier", "Particle system simulation modifier");
- RNA_def_struct_sdna(srna, "ParticleSystemModifierData");
- RNA_def_struct_ui_icon(srna, ICON_MOD_PARTICLES);
-
- prop = RNA_def_property(srna, "particle_system", PROP_POINTER, PROP_NONE);
- RNA_def_property_flag(prop, PROP_NEVER_NULL);
- RNA_def_property_pointer_sdna(prop, NULL, "psys");
- RNA_def_property_ui_text(prop, "Particle System", "Particle System that this modifier controls");
-}
-
-static void rna_def_modifier_particleinstance(BlenderRNA *brna)
-{
- StructRNA *srna;
- PropertyRNA *prop;
-
- srna = RNA_def_struct(brna, "ParticleInstanceModifier", "Modifier");
- RNA_def_struct_ui_text(srna, "ParticleInstance Modifier", "Particle system instancing modifier");
- RNA_def_struct_sdna(srna, "ParticleInstanceModifierData");
- RNA_def_struct_ui_icon(srna, ICON_MOD_PARTICLES);
-
- prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
- RNA_def_property_pointer_sdna(prop, NULL, "ob");
- RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_Mesh_object_poll");
- RNA_def_property_ui_text(prop, "Object", "Object that has the particle system");
- RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
- RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
-
- prop = RNA_def_property(srna, "particle_system_index", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "psys");
- RNA_def_property_range(prop, 1, 10);
- RNA_def_property_ui_text(prop, "Particle System Number", "");
- RNA_def_property_update(prop, 0, "rna_Modifier_update");
-
- prop = RNA_def_property(srna, "axis", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "axis");
- RNA_def_property_enum_items(prop, rna_enum_axis_xyz_items);
- RNA_def_property_ui_text(prop, "Axis", "Pole axis for rotation");
- RNA_def_property_update(prop, 0, "rna_Modifier_update");
-
- prop = RNA_def_property(srna, "use_normal", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", eParticleInstanceFlag_Parents);
- RNA_def_property_ui_text(prop, "Normal", "Create instances from normal particles");
- RNA_def_property_update(prop, 0, "rna_Modifier_update");
-
- prop = RNA_def_property(srna, "use_children", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", eParticleInstanceFlag_Children);
- RNA_def_property_ui_text(prop, "Children", "Create instances from child particles");
- RNA_def_property_update(prop, 0, "rna_Modifier_update");
-
- prop = RNA_def_property(srna, "use_path", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", eParticleInstanceFlag_Path);
- RNA_def_property_ui_text(prop, "Path", "Create instances along particle paths");
- RNA_def_property_update(prop, 0, "rna_Modifier_update");
-
- prop = RNA_def_property(srna, "show_unborn", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", eParticleInstanceFlag_Unborn);
- RNA_def_property_ui_text(prop, "Unborn", "Show instances when particles are unborn");
- RNA_def_property_update(prop, 0, "rna_Modifier_update");
-
- prop = RNA_def_property(srna, "show_alive", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", eParticleInstanceFlag_Alive);
- RNA_def_property_ui_text(prop, "Alive", "Show instances when particles are alive");
- RNA_def_property_update(prop, 0, "rna_Modifier_update");
-
- prop = RNA_def_property(srna, "show_dead", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", eParticleInstanceFlag_Dead);
- RNA_def_property_ui_text(prop, "Dead", "Show instances when particles are dead");
- RNA_def_property_update(prop, 0, "rna_Modifier_update");
-
- prop = RNA_def_property(srna, "use_preserve_shape", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", eParticleInstanceFlag_KeepShape);
- RNA_def_property_ui_text(prop, "Keep Shape", "Don't stretch the object");
- RNA_def_property_update(prop, 0, "rna_Modifier_update");
-
- prop = RNA_def_property(srna, "use_size", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", eParticleInstanceFlag_UseSize);
- RNA_def_property_ui_text(prop, "Size", "Use particle size to scale the instances");
- RNA_def_property_update(prop, 0, "rna_Modifier_update");
-
- prop = RNA_def_property(srna, "position", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "position");
- RNA_def_property_range(prop, 0.0, 1.0);
- RNA_def_property_ui_text(prop, "Position", "Position along path");
- RNA_def_property_update(prop, 0, "rna_Modifier_update");
-
- prop = RNA_def_property(srna, "random_position", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "random_position");
- RNA_def_property_range(prop, 0.0, 1.0);
- RNA_def_property_ui_text(prop, "Random Position", "Randomize position along path");
- RNA_def_property_update(prop, 0, "rna_Modifier_update");
-}
-
static void rna_def_modifier_explode(BlenderRNA *brna)
{
StructRNA *srna;
@@ -2725,10 +2607,6 @@ static void rna_def_modifier_cloth(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "ClothSolverResult");
RNA_def_property_pointer_sdna(prop, NULL, "solver_result");
RNA_def_property_ui_text(prop, "Solver Result", "");
-
- prop = RNA_def_property(srna, "point_cache", PROP_POINTER, PROP_NONE);
- RNA_def_property_flag(prop, PROP_NEVER_NULL);
- RNA_def_property_ui_text(prop, "Point Cache", "");
prop = RNA_def_property(srna, "hair_grid_min", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "hair_grid_min");
@@ -4761,8 +4639,6 @@ void RNA_def_modifier(BlenderRNA *brna)
rna_def_modifier_correctivesmooth(brna);
rna_def_modifier_cast(brna);
rna_def_modifier_meshdeform(brna);
- rna_def_modifier_particlesystem(brna);
- rna_def_modifier_particleinstance(brna);
rna_def_modifier_explode(brna);
rna_def_modifier_cloth(brna);
rna_def_modifier_collision(brna);
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index 47e9d989dbf..e68f75a1399 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -38,7 +38,6 @@
#include "DNA_mesh_types.h"
#include "DNA_node_types.h"
#include "DNA_object_types.h"
-#include "DNA_particle_types.h"
#include "DNA_text_types.h"
#include "DNA_texture_types.h"
@@ -3013,36 +3012,6 @@ static void rna_CompositorNodeScale_update(Main *bmain, Scene *scene, PointerRNA
rna_Node_update(bmain, scene, ptr);
}
-static PointerRNA rna_ShaderNodePointDensity_psys_get(PointerRNA *ptr)
-{
- bNode *node = ptr->data;
- NodeShaderTexPointDensity *shader_point_density = node->storage;
- Object *ob = (Object *)node->id;
- ParticleSystem *psys = NULL;
- PointerRNA value;
-
- if (ob && shader_point_density->particle_system) {
- psys = BLI_findlink(&ob->particlesystem, shader_point_density->particle_system - 1);
- }
-
- RNA_pointer_create(&ob->id, &RNA_ParticleSystem, psys, &value);
- return value;
-}
-
-static void rna_ShaderNodePointDensity_psys_set(PointerRNA *ptr, PointerRNA value)
-{
- bNode *node = ptr->data;
- NodeShaderTexPointDensity *shader_point_density = node->storage;
- Object *ob = (Object *)node->id;
-
- if (ob && value.id.data == ob) {
- shader_point_density->particle_system = BLI_findindex(&ob->particlesystem, value.data) + 1;
- }
- else {
- shader_point_density->particle_system = 0;
- }
-}
-
static int point_density_particle_color_source_from_shader(NodeShaderTexPointDensity *shader_point_density)
{
switch (shader_point_density->color_source) {
@@ -4086,14 +4055,6 @@ static void def_sh_tex_pointdensity(StructRNA *srna)
RNA_def_property_ui_text(prop, "Point Source", "Point data to use as renderable point density");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
- prop = RNA_def_property(srna, "particle_system", PROP_POINTER, PROP_NONE);
- RNA_def_property_ui_text(prop, "Particle System", "Particle System to render as points");
- RNA_def_property_struct_type(prop, "ParticleSystem");
- RNA_def_property_pointer_funcs(prop, "rna_ShaderNodePointDensity_psys_get",
- "rna_ShaderNodePointDensity_psys_set", NULL, NULL);
- RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
-
prop = RNA_def_property(srna, "resolution", PROP_INT, PROP_NONE);
RNA_def_property_range(prop, 1, 32768);
RNA_def_property_ui_text(prop, "Resolution", "Resolution used by the texture holding the point density");
diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c
index d6a7427865f..87c33ea81d8 100644
--- a/source/blender/makesrna/intern/rna_object.c
+++ b/source/blender/makesrna/intern/rna_object.c
@@ -69,7 +69,6 @@ EnumPropertyItem rna_enum_object_mode_items[] = {
{OB_MODE_VERTEX_PAINT, "VERTEX_PAINT", ICON_VPAINT_HLT, "Vertex Paint", ""},
{OB_MODE_WEIGHT_PAINT, "WEIGHT_PAINT", ICON_WPAINT_HLT, "Weight Paint", ""},
{OB_MODE_TEXTURE_PAINT, "TEXTURE_PAINT", ICON_TPAINT_HLT, "Texture Paint", ""},
- {OB_MODE_PARTICLE_EDIT, "PARTICLE_EDIT", ICON_PARTICLEMODE, "Particle Edit", ""},
{OB_MODE_GPENCIL, "GPENCIL_EDIT", ICON_GREASEPENCIL, "Edit Strokes", "Edit Grease Pencil Strokes"},
{0, NULL, 0, NULL, NULL}
};
@@ -189,12 +188,10 @@ EnumPropertyItem rna_enum_object_axis_items[] = {
#include "BKE_object.h"
#include "BKE_material.h"
#include "BKE_mesh.h"
-#include "BKE_particle.h"
#include "BKE_scene.h"
#include "BKE_deform.h"
#include "ED_object.h"
-#include "ED_particle.h"
#include "ED_curve.h"
#include "ED_lattice.h"
@@ -805,34 +802,6 @@ static int rna_Object_active_material_editable(PointerRNA *ptr, const char **UNU
return is_editable ? PROP_EDITABLE : 0;
}
-
-static void rna_Object_active_particle_system_index_range(PointerRNA *ptr, int *min, int *max,
- int *UNUSED(softmin), int *UNUSED(softmax))
-{
- Object *ob = (Object *)ptr->id.data;
- *min = 0;
- *max = max_ii(0, BLI_listbase_count(&ob->particlesystem) - 1);
-}
-
-static int rna_Object_active_particle_system_index_get(PointerRNA *ptr)
-{
- Object *ob = (Object *)ptr->id.data;
- return psys_get_current_num(ob);
-}
-
-static void rna_Object_active_particle_system_index_set(PointerRNA *ptr, int value)
-{
- Object *ob = (Object *)ptr->id.data;
- psys_set_current_num(ob, value);
-}
-
-static void rna_Object_particle_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr)
-{
- Object *ob = (Object *)ptr->id.data;
-
- PE_current_changed(scene, ob);
-}
-
/* rotation - axis-angle */
static void rna_Object_rotation_axis_angle_get(PointerRNA *ptr, float *value)
{
@@ -1153,13 +1122,6 @@ static void rna_GameObjectSettings_physics_type_set(PointerRNA *ptr, int value)
WM_main_add_notifier(NC_OBJECT | ND_DRAW, ptr->id.data);
}
-static PointerRNA rna_Object_active_particle_system_get(PointerRNA *ptr)
-{
- Object *ob = (Object *)ptr->id.data;
- ParticleSystem *psys = psys_get_current(ob);
- return rna_pointer_inherit_refine(ptr, &RNA_ParticleSystem, psys);
-}
-
static PointerRNA rna_Object_game_settings_get(PointerRNA *ptr)
{
return rna_pointer_inherit_refine(ptr, &RNA_GameObjectSettings, ptr->id.data);
@@ -2104,37 +2066,6 @@ static void rna_def_object_modifiers(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_function_ui_description(func, "Remove all modifiers from the object");
}
-/* object.particle_systems */
-static void rna_def_object_particle_systems(BlenderRNA *brna, PropertyRNA *cprop)
-{
- StructRNA *srna;
-
- PropertyRNA *prop;
-
- /* FunctionRNA *func; */
- /* PropertyRNA *parm; */
-
- RNA_def_property_srna(cprop, "ParticleSystems");
- srna = RNA_def_struct(brna, "ParticleSystems", NULL);
- RNA_def_struct_sdna(srna, "Object");
- RNA_def_struct_ui_text(srna, "Particle Systems", "Collection of particle systems");
-
- prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
- RNA_def_property_struct_type(prop, "ParticleSystem");
- RNA_def_property_pointer_funcs(prop, "rna_Object_active_particle_system_get", NULL, NULL, NULL);
- RNA_def_property_ui_text(prop, "Active Particle System", "Active particle system being displayed");
- RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
-
- prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_UNSIGNED);
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_int_funcs(prop, "rna_Object_active_particle_system_index_get",
- "rna_Object_active_particle_system_index_set",
- "rna_Object_active_particle_system_index_range");
- RNA_def_property_ui_text(prop, "Active Particle System Index", "Index of active particle system slot");
- RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_particle_update");
-}
-
-
/* object.vertex_groups */
static void rna_def_object_vertex_groups(BlenderRNA *brna, PropertyRNA *cprop)
{
@@ -2679,13 +2610,6 @@ static void rna_def_object(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "SoftBodySettings");
RNA_def_property_ui_text(prop, "Soft Body Settings", "Settings for soft body simulation");
- prop = RNA_def_property(srna, "particle_systems", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_collection_sdna(prop, NULL, "particlesystem", NULL);
- RNA_def_property_struct_type(prop, "ParticleSystem");
- RNA_def_property_ui_text(prop, "Particle Systems", "Particle systems emitted from the object");
- rna_def_object_particle_systems(brna, prop);
-
-
prop = RNA_def_property(srna, "rigid_body", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "rigidbody_object");
RNA_def_property_struct_type(prop, "RigidBodyObject");
@@ -3059,10 +2983,6 @@ static void rna_def_dupli_object(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Persistent ID", "Persistent identifier for inter-frame matching of objects with motion blur");
- prop = RNA_def_property(srna, "particle_system", PROP_POINTER, PROP_NONE);
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Particle System", "Particle system that this dupli object was instanced from");
-
prop = RNA_def_property(srna, "orco", PROP_FLOAT, PROP_TRANSLATION);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Generated Coordinates", "Generated coordinates in parent object space");
diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c
index b66556109e6..84360ba4386 100644
--- a/source/blender/makesrna/intern/rna_object_api.c
+++ b/source/blender/makesrna/intern/rna_object_api.c
@@ -146,54 +146,9 @@ static Mesh *rna_Object_to_mesh(
return rna_Main_meshes_new_from_object(G.main, reports, sce, ob, apply_modifiers, settings, calc_tessface, calc_undeformed);
}
-/* mostly a copy from convertblender.c */
-static void dupli_render_particle_set(Scene *scene, Object *ob, int level, int enable)
-{
- /* ugly function, but we need to set particle systems to their render
- * settings before calling object_duplilist, to get render level duplis */
- Group *group;
- GroupObject *go;
- ParticleSystem *psys;
- DerivedMesh *dm;
- float mat[4][4];
-
- unit_m4(mat);
-
- if (level >= MAX_DUPLI_RECUR)
- return;
-
- if (ob->transflag & OB_DUPLIPARTS) {
- for (psys = ob->particlesystem.first; psys; psys = psys->next) {
- if (ELEM(psys->part->ren_as, PART_DRAW_OB, PART_DRAW_GR)) {
- if (enable)
- psys_render_set(ob, psys, mat, mat, 1, 1, 0.f);
- else
- psys_render_restore(ob, psys);
- }
- }
-
- if (enable) {
- /* this is to make sure we get render level duplis in groups:
- * the derivedmesh must be created before init_render_mesh,
- * since object_duplilist does dupliparticles before that */
- dm = mesh_create_derived_render(scene, ob, CD_MASK_BAREMESH | CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL);
- dm->release(dm);
-
- for (psys = ob->particlesystem.first; psys; psys = psys->next)
- psys_get_modifier(ob, psys)->flag &= ~eParticleSystemFlag_psys_updated;
- }
- }
-
- if (ob->dup_group == NULL) return;
- group = ob->dup_group;
-
- for (go = group->gobject.first; go; go = go->next)
- dupli_render_particle_set(scene, go->ob, level + 1, enable);
-}
/* When no longer needed, duplilist should be freed with Object.free_duplilist */
static void rna_Object_create_duplilist(Object *ob, ReportList *reports, Scene *sce, int settings)
{
- bool for_render = (settings == DAG_EVAL_RENDER);
EvaluationContext eval_ctx;
DEG_evaluation_context_init(&eval_ctx, settings);
@@ -209,11 +164,7 @@ static void rna_Object_create_duplilist(Object *ob, ReportList *reports, Scene *
free_object_duplilist(ob->duplilist);
ob->duplilist = NULL;
}
- if (for_render)
- dupli_render_particle_set(sce, ob, 0, 1);
ob->duplilist = object_duplilist(&eval_ctx, sce, ob);
- if (for_render)
- dupli_render_particle_set(sce, ob, 0, 0);
/* ob->duplilist should now be freed with Object.free_duplilist */
}
diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c
index 1d89f7535c4..ad927073871 100644
--- a/source/blender/makesrna/intern/rna_object_force.c
+++ b/source/blender/makesrna/intern/rna_object_force.c
@@ -29,7 +29,6 @@
#include "DNA_cloth_types.h"
#include "DNA_object_types.h"
#include "DNA_object_force.h"
-#include "DNA_particle_types.h"
#include "DNA_scene_types.h"
#include "DNA_smoke_types.h"
@@ -91,233 +90,16 @@ static EnumPropertyItem empty_vortex_shape_items[] = {
#include "MEM_guardedalloc.h"
+#include "DNA_dynamicpaint_types.h"
#include "DNA_modifier_types.h"
#include "DNA_texture_types.h"
#include "BKE_context.h"
#include "BKE_modifier.h"
-#include "BKE_pointcache.h"
#include "BKE_depsgraph.h"
#include "ED_object.h"
-static void rna_Cache_change(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
-{
- Object *ob = (Object *)ptr->id.data;
- PointCache *cache = (PointCache *)ptr->data;
- PTCacheID *pid = NULL;
- ListBase pidlist;
-
- if (!ob)
- return;
-
- cache->flag |= PTCACHE_OUTDATED;
-
- BKE_ptcache_ids_from_object(&pidlist, ob, NULL, 0);
-
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
-
- for (pid = pidlist.first; pid; pid = pid->next) {
- if (pid->cache == cache)
- break;
- }
-
- if (pid) {
- /* Just make sure this wasn't changed. */
- if (pid->type == PTCACHE_TYPE_SMOKE_DOMAIN)
- cache->step = 1;
- BKE_ptcache_update_info(pid);
- }
-
- BLI_freelistN(&pidlist);
-}
-
-static void rna_Cache_toggle_disk_cache(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
-{
- Object *ob = (Object *)ptr->id.data;
- PointCache *cache = (PointCache *)ptr->data;
- PTCacheID *pid = NULL;
- ListBase pidlist;
-
- if (!ob)
- return;
-
- BKE_ptcache_ids_from_object(&pidlist, ob, NULL, 0);
-
- for (pid = pidlist.first; pid; pid = pid->next) {
- if (pid->cache == cache)
- break;
- }
-
- /* smoke can only use disk cache */
- if (pid && pid->type != PTCACHE_TYPE_SMOKE_DOMAIN)
- BKE_ptcache_toggle_disk_cache(pid);
- else
- cache->flag ^= PTCACHE_DISK_CACHE;
-
- BLI_freelistN(&pidlist);
-}
-
-static void rna_Cache_idname_change(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
-{
- Object *ob = (Object *)ptr->id.data;
- PointCache *cache = (PointCache *)ptr->data;
- PTCacheID *pid = NULL, *pid2 = NULL;
- ListBase pidlist;
- bool use_new_name = true;
-
- if (!ob)
- return;
-
- /* TODO: check for proper characters */
-
- BKE_ptcache_ids_from_object(&pidlist, ob, NULL, 0);
-
- if (cache->flag & PTCACHE_EXTERNAL) {
- for (pid = pidlist.first; pid; pid = pid->next) {
- if (pid->cache == cache)
- break;
- }
-
- if (!pid)
- return;
-
- BKE_ptcache_load_external(pid);
-
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
- WM_main_add_notifier(NC_OBJECT | ND_POINTCACHE, ob);
- }
- else {
- for (pid = pidlist.first; pid; pid = pid->next) {
- if (pid->cache == cache)
- pid2 = pid;
- else if (cache->name[0] != '\0' && STREQ(cache->name, pid->cache->name)) {
- /*TODO: report "name exists" to user */
- BLI_strncpy(cache->name, cache->prev_name, sizeof(cache->name));
- use_new_name = false;
- }
- }
-
- if (use_new_name) {
- BLI_filename_make_safe(cache->name);
-
- if (pid2 && cache->flag & PTCACHE_DISK_CACHE) {
- char old_name[80];
- char new_name[80];
-
- BLI_strncpy(old_name, cache->prev_name, sizeof(old_name));
- BLI_strncpy(new_name, cache->name, sizeof(new_name));
-
- BKE_ptcache_disk_cache_rename(pid2, old_name, new_name);
- }
-
- BLI_strncpy(cache->prev_name, cache->name, sizeof(cache->prev_name));
- }
- }
-
- BLI_freelistN(&pidlist);
-}
-
-static void rna_Cache_list_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
-{
- PointCache *cache = ptr->data;
- ListBase lb;
-
- while (cache->prev)
- cache = cache->prev;
-
- lb.first = cache;
- lb.last = NULL; /* not used by listbase_begin */
-
- rna_iterator_listbase_begin(iter, &lb, NULL);
-}
-static void rna_Cache_active_point_cache_index_range(PointerRNA *ptr, int *min, int *max,
- int *UNUSED(softmin), int *UNUSED(softmax))
-{
- Object *ob = ptr->id.data;
- PointCache *cache = ptr->data;
- PTCacheID *pid;
- ListBase pidlist;
-
- BKE_ptcache_ids_from_object(&pidlist, ob, NULL, 0);
-
- *min = 0;
- *max = 0;
-
- for (pid = pidlist.first; pid; pid = pid->next) {
- if (pid->cache == cache) {
- *max = max_ii(0, BLI_listbase_count(pid->ptcaches) - 1);
- break;
- }
- }
-
- BLI_freelistN(&pidlist);
-}
-
-static int rna_Cache_active_point_cache_index_get(PointerRNA *ptr)
-{
- Object *ob = ptr->id.data;
- PointCache *cache = ptr->data;
- PTCacheID *pid;
- ListBase pidlist;
- int num = 0;
-
- BKE_ptcache_ids_from_object(&pidlist, ob, NULL, 0);
-
- for (pid = pidlist.first; pid; pid = pid->next) {
- if (pid->cache == cache) {
- num = BLI_findindex(pid->ptcaches, cache);
- break;
- }
- }
-
- BLI_freelistN(&pidlist);
-
- return num;
-}
-
-static void rna_Cache_active_point_cache_index_set(struct PointerRNA *ptr, int value)
-{
- Object *ob = ptr->id.data;
- PointCache *cache = ptr->data;
- PTCacheID *pid;
- ListBase pidlist;
-
- BKE_ptcache_ids_from_object(&pidlist, ob, NULL, 0);
-
- for (pid = pidlist.first; pid; pid = pid->next) {
- if (pid->cache == cache) {
- *(pid->cache_ptr) = BLI_findlink(pid->ptcaches, value);
- break;
- }
- }
-
- BLI_freelistN(&pidlist);
-}
-
-static void rna_PointCache_frame_step_range(PointerRNA *ptr, int *min, int *max,
- int *UNUSED(softmin), int *UNUSED(softmax))
-{
- Object *ob = ptr->id.data;
- PointCache *cache = ptr->data;
- PTCacheID *pid;
- ListBase pidlist;
-
- *min = 1;
- *max = 20;
-
- BKE_ptcache_ids_from_object(&pidlist, ob, NULL, 0);
-
- for (pid = pidlist.first; pid; pid = pid->next) {
- if (pid->cache == cache) {
- *max = pid->max_step;
- break;
- }
- }
-
- BLI_freelistN(&pidlist);
-}
-
static char *rna_CollisionSettings_path(PointerRNA *UNUSED(ptr))
{
/* both methods work ok, but return the shorter path */
@@ -477,53 +259,25 @@ static char *rna_SoftBodySettings_path(PointerRNA *ptr)
return BLI_sprintfN("modifiers[\"%s\"].settings", name_esc);
}
-static int particle_id_check(PointerRNA *ptr)
-{
- ID *id = ptr->id.data;
-
- return (GS(id->name) == ID_PA);
-}
-
static void rna_FieldSettings_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- if (particle_id_check(ptr)) {
- ParticleSettings *part = (ParticleSettings *)ptr->id.data;
-
- if (part->pd->forcefield != PFIELD_TEXTURE && part->pd->tex) {
- id_us_min(&part->pd->tex->id);
- part->pd->tex = NULL;
- }
-
- if (part->pd2 && part->pd2->forcefield != PFIELD_TEXTURE && part->pd2->tex) {
- id_us_min(&part->pd2->tex->id);
- part->pd2->tex = NULL;
- }
-
- DAG_id_tag_update(&part->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME | PSYS_RECALC_RESET);
- WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL);
+ Object *ob = (Object *)ptr->id.data;
+ if (ob->pd->forcefield != PFIELD_TEXTURE && ob->pd->tex) {
+ id_us_min(&ob->pd->tex->id);
+ ob->pd->tex = NULL;
}
- else {
- Object *ob = (Object *)ptr->id.data;
- if (ob->pd->forcefield != PFIELD_TEXTURE && ob->pd->tex) {
- id_us_min(&ob->pd->tex->id);
- ob->pd->tex = NULL;
- }
-
- DAG_id_tag_update(&ob->id, OB_RECALC_OB);
- WM_main_add_notifier(NC_OBJECT | ND_DRAW, ob);
- }
+ DAG_id_tag_update(&ob->id, OB_RECALC_OB);
+ WM_main_add_notifier(NC_OBJECT | ND_DRAW, ob);
}
static void rna_FieldSettings_shape_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
- if (!particle_id_check(ptr)) {
- Object *ob = (Object *)ptr->id.data;
- ED_object_check_force_modifiers(bmain, scene, ob);
- WM_main_add_notifier(NC_OBJECT | ND_DRAW, ob);
- WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ob);
- }
+ Object *ob = (Object *)ptr->id.data;
+ ED_object_check_force_modifiers(bmain, scene, ob);
+ WM_main_add_notifier(NC_OBJECT | ND_DRAW, ob);
+ WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ob);
}
static void rna_FieldSettings_type_set(PointerRNA *ptr, int value)
@@ -532,46 +286,39 @@ static void rna_FieldSettings_type_set(PointerRNA *ptr, int value)
part_deflect->forcefield = value;
- if (!particle_id_check(ptr)) {
- Object *ob = (Object *)ptr->id.data;
- ob->pd->forcefield = value;
- if (ELEM(value, PFIELD_WIND, PFIELD_VORTEX)) {
- ob->empty_drawtype = OB_SINGLE_ARROW;
- }
- else {
- ob->empty_drawtype = OB_PLAINAXES;
- }
+ Object *ob = (Object *)ptr->id.data;
+ ob->pd->forcefield = value;
+ if (ELEM(value, PFIELD_WIND, PFIELD_VORTEX)) {
+ ob->empty_drawtype = OB_SINGLE_ARROW;
+ }
+ else {
+ ob->empty_drawtype = OB_PLAINAXES;
}
}
static void rna_FieldSettings_dependency_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
- if (particle_id_check(ptr)) {
- DAG_id_tag_update((ID *)ptr->id.data, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME | PSYS_RECALC_RESET);
- }
- else {
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->id.data;
- /* do this before scene sort, that one checks for CU_PATH */
+ /* do this before scene sort, that one checks for CU_PATH */
#if 0 /* XXX */
- if (ob->type == OB_CURVE && ob->pd->forcefield == PFIELD_GUIDE) {
- Curve *cu = ob->data;
- cu->flag |= (CU_PATH | CU_3D);
- do_curvebuts(B_CU3D); /* all curves too */
- }
+ if (ob->type == OB_CURVE && ob->pd->forcefield == PFIELD_GUIDE) {
+ Curve *cu = ob->data;
+ cu->flag |= (CU_PATH | CU_3D);
+ do_curvebuts(B_CU3D); /* all curves too */
+ }
#endif
- rna_FieldSettings_shape_update(bmain, scene, ptr);
+ rna_FieldSettings_shape_update(bmain, scene, ptr);
- DAG_relations_tag_update(bmain);
+ DAG_relations_tag_update(bmain);
- if (ob->type == OB_CURVE && ob->pd->forcefield == PFIELD_GUIDE)
- DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
- else
- DAG_id_tag_update(&ob->id, OB_RECALC_OB);
+ if (ob->type == OB_CURVE && ob->pd->forcefield == PFIELD_GUIDE)
+ DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ else
+ DAG_id_tag_update(&ob->id, OB_RECALC_OB);
- WM_main_add_notifier(NC_OBJECT | ND_DRAW, ob);
- }
+ WM_main_add_notifier(NC_OBJECT | ND_DRAW, ob);
}
static char *rna_FieldSettings_path(PointerRNA *ptr)
@@ -580,22 +327,12 @@ static char *rna_FieldSettings_path(PointerRNA *ptr)
/* Check through all possible places the settings can be to find the right one */
- if (particle_id_check(ptr)) {
- /* particle system force field */
- ParticleSettings *part = (ParticleSettings *)ptr->id.data;
-
- if (part->pd == pd)
- return BLI_sprintfN("force_field_1");
- else if (part->pd2 == pd)
- return BLI_sprintfN("force_field_2");
- }
- else {
- /* object force field */
- Object *ob = (Object *)ptr->id.data;
-
- if (ob->pd == pd)
- return BLI_sprintfN("field");
- }
+ /* object force field */
+ Object *ob = (Object *)ptr->id.data;
+
+ if (ob->pd == pd)
+ return BLI_sprintfN("field");
+
return NULL;
}
@@ -603,25 +340,15 @@ static void rna_EffectorWeight_update(Main *UNUSED(bmain), Scene *UNUSED(scene),
{
ID *id = ptr->id.data;
- if (id && GS(id->name) == ID_SCE) {
- Scene *scene = (Scene *)id;
- Base *base;
-
- for (base = scene->base.first; base; base = base->next) {
- BKE_ptcache_object_reset(scene, base->object, PTCACHE_RESET_DEPSGRAPH);
- }
- }
- else {
- DAG_id_tag_update(id, OB_RECALC_DATA | PSYS_RECALC_RESET);
- WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL);
- }
+ DAG_id_tag_update(id, OB_RECALC_DATA);
+ WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL);
}
static void rna_EffectorWeight_dependency_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
DAG_relations_tag_update(bmain);
- DAG_id_tag_update((ID *)ptr->id.data, OB_RECALC_DATA | PSYS_RECALC_RESET);
+ DAG_id_tag_update((ID *)ptr->id.data, OB_RECALC_DATA);
WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL);
}
@@ -631,68 +358,59 @@ static char *rna_EffectorWeight_path(PointerRNA *ptr)
EffectorWeights *ew = (EffectorWeights *)ptr->data;
/* Check through all possible places the settings can be to find the right one */
- if (particle_id_check(ptr)) {
- /* particle effector weights */
- ParticleSettings *part = (ParticleSettings *)ptr->id.data;
-
- if (part->effector_weights == ew)
- return BLI_sprintfN("effector_weights");
- }
- else {
- Object *ob = (Object *)ptr->id.data;
- ModifierData *md;
-
- /* check softbody modifier */
- md = (ModifierData *)modifiers_findByType(ob, eModifierType_Softbody);
- if (md) {
- /* no pointer from modifier data to actual softbody storage, would be good to add */
- if (ob->soft->effector_weights == ew) {
- char name_esc[sizeof(md->name) * 2];
- BLI_strescape(name_esc, md->name, sizeof(name_esc));
- return BLI_sprintfN("modifiers[\"%s\"].settings.effector_weights", name_esc);
- }
+ Object *ob = (Object *)ptr->id.data;
+ ModifierData *md;
+
+ /* check softbody modifier */
+ md = (ModifierData *)modifiers_findByType(ob, eModifierType_Softbody);
+ if (md) {
+ /* no pointer from modifier data to actual softbody storage, would be good to add */
+ if (ob->soft->effector_weights == ew) {
+ char name_esc[sizeof(md->name) * 2];
+ BLI_strescape(name_esc, md->name, sizeof(name_esc));
+ return BLI_sprintfN("modifiers[\"%s\"].settings.effector_weights", name_esc);
}
-
- /* check cloth modifier */
- md = (ModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
- if (md) {
- ClothModifierData *cmd = (ClothModifierData *)md;
- if (cmd->sim_parms->effector_weights == ew) {
- char name_esc[sizeof(md->name) * 2];
- BLI_strescape(name_esc, md->name, sizeof(name_esc));
- return BLI_sprintfN("modifiers[\"%s\"].settings.effector_weights", name_esc);
- }
+ }
+
+ /* check cloth modifier */
+ md = (ModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
+ if (md) {
+ ClothModifierData *cmd = (ClothModifierData *)md;
+ if (cmd->sim_parms->effector_weights == ew) {
+ char name_esc[sizeof(md->name) * 2];
+ BLI_strescape(name_esc, md->name, sizeof(name_esc));
+ return BLI_sprintfN("modifiers[\"%s\"].settings.effector_weights", name_esc);
}
-
- /* check smoke modifier */
- md = (ModifierData *)modifiers_findByType(ob, eModifierType_Smoke);
- if (md) {
- SmokeModifierData *smd = (SmokeModifierData *)md;
- if (smd->domain->effector_weights == ew) {
- char name_esc[sizeof(md->name) * 2];
- BLI_strescape(name_esc, md->name, sizeof(name_esc));
- return BLI_sprintfN("modifiers[\"%s\"].settings.effector_weights", name_esc);
- }
+ }
+
+ /* check smoke modifier */
+ md = (ModifierData *)modifiers_findByType(ob, eModifierType_Smoke);
+ if (md) {
+ SmokeModifierData *smd = (SmokeModifierData *)md;
+ if (smd->domain->effector_weights == ew) {
+ char name_esc[sizeof(md->name) * 2];
+ BLI_strescape(name_esc, md->name, sizeof(name_esc));
+ return BLI_sprintfN("modifiers[\"%s\"].settings.effector_weights", name_esc);
}
+ }
- /* check dynamic paint modifier */
- md = (ModifierData *)modifiers_findByType(ob, eModifierType_DynamicPaint);
- if (md) {
- DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md;
+ /* check dynamic paint modifier */
+ md = (ModifierData *)modifiers_findByType(ob, eModifierType_DynamicPaint);
+ if (md) {
+ DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md;
- if (pmd->canvas) {
- DynamicPaintSurface *surface = pmd->canvas->surfaces.first;
+ if (pmd->canvas) {
+ DynamicPaintSurface *surface = pmd->canvas->surfaces.first;
- for (; surface; surface = surface->next) {
- if (surface->effector_weights == ew) {
- char name_esc[sizeof(md->name) * 2];
- char name_esc_surface[sizeof(surface->name) * 2];
+ for (; surface; surface = surface->next) {
+ if (surface->effector_weights == ew) {
+ char name_esc[sizeof(md->name) * 2];
+ char name_esc_surface[sizeof(surface->name) * 2];
- BLI_strescape(name_esc, md->name, sizeof(name_esc));
- BLI_strescape(name_esc_surface, surface->name, sizeof(name_esc_surface));
- return BLI_sprintfN("modifiers[\"%s\"].canvas_settings.canvas_surfaces[\"%s\"]"
- ".effector_weights", name_esc, name_esc_surface);
- }
+ BLI_strescape(name_esc, md->name, sizeof(name_esc));
+ BLI_strescape(name_esc_surface, surface->name, sizeof(name_esc_surface));
+ return BLI_sprintfN("modifiers[\"%s\"].canvas_settings.canvas_surfaces[\"%s\"]"
+ ".effector_weights", name_esc, name_esc_surface);
}
}
}
@@ -741,9 +459,6 @@ static EnumPropertyItem *rna_Effector_shape_itemf(bContext *UNUSED(C), PointerRN
{
Object *ob = NULL;
- if (particle_id_check(ptr))
- return empty_shape_items;
-
ob = (Object *)ptr->id.data;
if (ob->type == OB_CURVE) {
@@ -768,140 +483,6 @@ static EnumPropertyItem *rna_Effector_shape_itemf(bContext *UNUSED(C), PointerRN
#else
-/* ptcache.point_caches */
-static void rna_def_ptcache_point_caches(BlenderRNA *brna, PropertyRNA *cprop)
-{
- StructRNA *srna;
- PropertyRNA *prop;
-
- /* FunctionRNA *func; */
- /* PropertyRNA *parm; */
-
- RNA_def_property_srna(cprop, "PointCaches");
- srna = RNA_def_struct(brna, "PointCaches", NULL);
- RNA_def_struct_sdna(srna, "PointCache");
- RNA_def_struct_ui_text(srna, "Point Caches", "Collection of point caches");
-
- prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_UNSIGNED);
- RNA_def_property_int_funcs(prop, "rna_Cache_active_point_cache_index_get",
- "rna_Cache_active_point_cache_index_set",
- "rna_Cache_active_point_cache_index_range");
- RNA_def_property_ui_text(prop, "Active Point Cache Index", "");
- RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_change");
-}
-
-static void rna_def_pointcache(BlenderRNA *brna)
-{
- StructRNA *srna;
- PropertyRNA *prop;
-
- static EnumPropertyItem point_cache_compress_items[] = {
- {PTCACHE_COMPRESS_NO, "NO", 0, "No", "No compression"},
- {PTCACHE_COMPRESS_LZO, "LIGHT", 0, "Light", "Fast but not so effective compression"},
- {PTCACHE_COMPRESS_LZMA, "HEAVY", 0, "Heavy", "Effective but slow compression"},
- {0, NULL, 0, NULL, NULL}
- };
-
- srna = RNA_def_struct(brna, "PointCache", NULL);
- RNA_def_struct_ui_text(srna, "Point Cache", "Point cache for physics simulations");
- RNA_def_struct_ui_icon(srna, ICON_PHYSICS);
-
- prop = RNA_def_property(srna, "frame_start", PROP_INT, PROP_TIME);
- RNA_def_property_int_sdna(prop, NULL, "startframe");
- RNA_def_property_range(prop, -MAXFRAME, MAXFRAME);
- RNA_def_property_ui_range(prop, 1, MAXFRAME, 1, 1);
- RNA_def_property_ui_text(prop, "Start", "Frame on which the simulation starts");
-
- prop = RNA_def_property(srna, "frame_end", PROP_INT, PROP_TIME);
- RNA_def_property_int_sdna(prop, NULL, "endframe");
- RNA_def_property_range(prop, 1, MAXFRAME);
- RNA_def_property_ui_text(prop, "End", "Frame on which the simulation stops");
-
- prop = RNA_def_property(srna, "frame_step", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "step");
- RNA_def_property_range(prop, 1, 20);
- RNA_def_property_int_funcs(prop, NULL, NULL, "rna_PointCache_frame_step_range");
- RNA_def_property_ui_text(prop, "Cache Step", "Number of frames between cached frames");
- RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_change");
-
- prop = RNA_def_property(srna, "index", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "index");
- RNA_def_property_range(prop, -1, 100);
- RNA_def_property_ui_text(prop, "Cache Index", "Index number of cache files");
- RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_idname_change");
-
- prop = RNA_def_property(srna, "compression", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_items(prop, point_cache_compress_items);
- RNA_def_property_ui_text(prop, "Cache Compression", "Compression method to be used");
-
- /* flags */
- prop = RNA_def_property(srna, "is_baked", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", PTCACHE_BAKED);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
-
- prop = RNA_def_property(srna, "is_baking", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", PTCACHE_BAKING);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
-
- prop = RNA_def_property(srna, "use_disk_cache", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", PTCACHE_DISK_CACHE);
- RNA_def_property_ui_text(prop, "Disk Cache", "Save cache files to disk (.blend file must be saved first)");
- RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_toggle_disk_cache");
-
- prop = RNA_def_property(srna, "is_outdated", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", PTCACHE_OUTDATED);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Cache is outdated", "");
-
- prop = RNA_def_property(srna, "is_frame_skip", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", PTCACHE_FRAMES_SKIPPED);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
-
- prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
- RNA_def_property_string_sdna(prop, NULL, "name");
- RNA_def_property_ui_text(prop, "Name", "Cache name");
- RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_idname_change");
- RNA_def_struct_name_property(srna, prop);
-
- prop = RNA_def_property(srna, "filepath", PROP_STRING, PROP_DIRPATH);
- RNA_def_property_string_sdna(prop, NULL, "path");
- RNA_def_property_ui_text(prop, "File Path", "Cache file path");
- RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_idname_change");
-
- /* removed, see PTCACHE_QUICK_CACHE */
-#if 0
- prop = RNA_def_property(srna, "use_quick_cache", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", PTCACHE_QUICK_CACHE);
- RNA_def_property_ui_text(prop, "Quick Cache", "Update simulation with cache steps");
- RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_change");
-#endif
-
- prop = RNA_def_property(srna, "info", PROP_STRING, PROP_NONE);
- RNA_def_property_string_sdna(prop, NULL, "info");
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Cache Info", "Info on current cache status");
-
- prop = RNA_def_property(srna, "use_external", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", PTCACHE_EXTERNAL);
- RNA_def_property_ui_text(prop, "External", "Read cache from an external location");
- RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_idname_change");
-
- prop = RNA_def_property(srna, "use_library_path", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", PTCACHE_IGNORE_LIBPATH);
- RNA_def_property_ui_text(prop, "Library Path",
- "Use this file's path for the disk cache when library linked into another file "
- "(for local bakes per scene file, disable this option)");
- RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_idname_change");
-
- prop = RNA_def_property(srna, "point_caches", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_collection_funcs(prop, "rna_Cache_list_begin", "rna_iterator_listbase_next",
- "rna_iterator_listbase_end", "rna_iterator_listbase_get",
- NULL, NULL, NULL, NULL);
- RNA_def_property_struct_type(prop, "PointCache");
- RNA_def_property_ui_text(prop, "Point Cache List", "Point cache list");
- rna_def_ptcache_point_caches(brna, prop);
-}
-
static void rna_def_collision(BlenderRNA *brna)
{
StructRNA *srna;
@@ -1871,7 +1452,6 @@ static void rna_def_softbody(BlenderRNA *brna)
void RNA_def_object_force(BlenderRNA *brna)
{
- rna_def_pointcache(brna);
rna_def_collision(brna);
rna_def_effector_weight(brna);
rna_def_field(brna);
diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c
deleted file mode 100644
index 5e3fa4b467d..00000000000
--- a/source/blender/makesrna/intern/rna_particle.c
+++ /dev/null
@@ -1,3571 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Contributor(s): Blender Foundation (2008).
- *
- * Adaptive time step
- * Copyright 2011 AutoCRC
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/makesrna/intern/rna_particle.c
- * \ingroup RNA
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <limits.h>
-
-#include "DNA_material_types.h"
-#include "DNA_meshdata_types.h"
-#include "DNA_modifier_types.h"
-#include "DNA_cloth_types.h"
-#include "DNA_particle_types.h"
-#include "DNA_object_force.h"
-#include "DNA_object_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_boid_types.h"
-#include "DNA_texture_types.h"
-
-#include "RNA_define.h"
-#include "RNA_enum_types.h"
-
-#include "BLT_translation.h"
-
-#include "rna_internal.h"
-
-#include "WM_types.h"
-#include "WM_api.h"
-
-#ifdef RNA_RUNTIME
-static EnumPropertyItem part_from_items[] = {
- {PART_FROM_VERT, "VERT", 0, "Verts", ""},
- {PART_FROM_FACE, "FACE", 0, "Faces", ""},
- {PART_FROM_VOLUME, "VOLUME", 0, "Volume", ""},
- {0, NULL, 0, NULL, NULL}
-};
-#endif
-
-#ifndef RNA_RUNTIME
-static EnumPropertyItem part_reactor_from_items[] = {
- {PART_FROM_VERT, "VERT", 0, "Verts", ""},
- {PART_FROM_FACE, "FACE", 0, "Faces", ""},
- {PART_FROM_VOLUME, "VOLUME", 0, "Volume", ""},
- {0, NULL, 0, NULL, NULL}
-};
-#endif
-
-static EnumPropertyItem part_dist_items[] = {
- {PART_DISTR_JIT, "JIT", 0, "Jittered", ""},
- {PART_DISTR_RAND, "RAND", 0, "Random", ""},
- {PART_DISTR_GRID, "GRID", 0, "Grid", ""},
- {0, NULL, 0, NULL, NULL}
-};
-
-#ifdef RNA_RUNTIME
-static EnumPropertyItem part_hair_dist_items[] = {
- {PART_DISTR_JIT, "JIT", 0, "Jittered", ""},
- {PART_DISTR_RAND, "RAND", 0, "Random", ""},
- {0, NULL, 0, NULL, NULL}
-};
-#endif
-
-static EnumPropertyItem part_draw_as_items[] = {
- {PART_DRAW_NOT, "NONE", 0, "None", ""},
- {PART_DRAW_REND, "RENDER", 0, "Rendered", ""},
- {PART_DRAW_DOT, "DOT", 0, "Point", ""},
- {PART_DRAW_CIRC, "CIRC", 0, "Circle", ""},
- {PART_DRAW_CROSS, "CROSS", 0, "Cross", ""},
- {PART_DRAW_AXIS, "AXIS", 0, "Axis", ""},
- {0, NULL, 0, NULL, NULL}
-};
-
-#ifdef RNA_RUNTIME
-static EnumPropertyItem part_hair_draw_as_items[] = {
- {PART_DRAW_NOT, "NONE", 0, "None", ""},
- {PART_DRAW_REND, "RENDER", 0, "Rendered", ""},
- {PART_DRAW_PATH, "PATH", 0, "Path", ""},
- {0, NULL, 0, NULL, NULL}
-};
-#endif
-
-static EnumPropertyItem part_ren_as_items[] = {
- {PART_DRAW_NOT, "NONE", 0, "None", ""},
- {PART_DRAW_HALO, "HALO", 0, "Halo", ""},
- {PART_DRAW_LINE, "LINE", 0, "Line", ""},
- {PART_DRAW_PATH, "PATH", 0, "Path", ""},
- {PART_DRAW_OB, "OBJECT", 0, "Object", ""},
- {PART_DRAW_GR, "GROUP", 0, "Group", ""},
- {PART_DRAW_BB, "BILLBOARD", 0, "Billboard", ""},
- {0, NULL, 0, NULL, NULL}
-};
-
-#ifdef RNA_RUNTIME
-static EnumPropertyItem part_hair_ren_as_items[] = {
- {PART_DRAW_NOT, "NONE", 0, "None", ""},
- {PART_DRAW_PATH, "PATH", 0, "Path", ""},
- {PART_DRAW_OB, "OBJECT", 0, "Object", ""},
- {PART_DRAW_GR, "GROUP", 0, "Group", ""},
- {0, NULL, 0, NULL, NULL}
-};
-#endif
-
-#ifdef RNA_RUNTIME
-
-#include "BLI_math.h"
-
-#include "BKE_context.h"
-#include "BKE_cloth.h"
-#include "BKE_colortools.h"
-#include "BKE_deform.h"
-#include "BKE_depsgraph.h"
-#include "BKE_DerivedMesh.h"
-#include "BKE_cdderivedmesh.h"
-#include "BKE_effect.h"
-#include "BKE_material.h"
-#include "BKE_modifier.h"
-#include "BKE_particle.h"
-#include "BKE_pointcache.h"
-#include "BKE_texture.h"
-
-/* use for object space hair get/set */
-static void rna_ParticleHairKey_location_object_info(PointerRNA *ptr, ParticleSystemModifierData **psmd_pt,
- ParticleData **pa_pt)
-{
- HairKey *hkey = (HairKey *)ptr->data;
- Object *ob = (Object *)ptr->id.data;
- ModifierData *md;
- ParticleSystemModifierData *psmd = NULL;
- ParticleSystem *psys;
- ParticleData *pa;
- int i;
-
- *psmd_pt = NULL;
- *pa_pt = NULL;
-
- /* given the pointer HairKey *hkey, we iterate over all particles in all
- * particle systems in the object "ob" in order to find
- * - the ParticleSystemData to which the HairKey (and hence the particle)
- * belongs (will be stored in psmd_pt)
- * - the ParticleData to which the HairKey belongs (will be stored in pa_pt)
- *
- * not a very efficient way of getting hair key location data,
- * but it's the best we've got at the present
- *
- * IDEAS: include additional information in pointerRNA beforehand,
- * for example a pointer to the ParticleStstemModifierData to which the
- * hairkey belongs.
- */
-
- for (md = ob->modifiers.first; md; md = md->next) {
- if (md->type == eModifierType_ParticleSystem) {
- psmd = (ParticleSystemModifierData *) md;
- if (psmd && psmd->dm_final && psmd->psys) {
- psys = psmd->psys;
- for (i = 0, pa = psys->particles; i < psys->totpart; i++, pa++) {
- /* hairkeys are stored sequentially in memory, so we can
- * find if it's the same particle by comparing pointers,
- * without having to iterate over them all */
- if ((hkey >= pa->hair) && (hkey < pa->hair + pa->totkey)) {
- *psmd_pt = psmd;
- *pa_pt = pa;
- return;
- }
- }
- }
- }
- }
-}
-
-static void rna_ParticleHairKey_location_object_get(PointerRNA *ptr, float *values)
-{
- HairKey *hkey = (HairKey *)ptr->data;
- Object *ob = (Object *)ptr->id.data;
- ParticleSystemModifierData *psmd;
- ParticleData *pa;
-
- rna_ParticleHairKey_location_object_info(ptr, &psmd, &pa);
-
- if (pa) {
- DerivedMesh *hairdm = (psmd->psys->flag & PSYS_HAIR_DYNAMICS) ? psmd->psys->hair_out_dm : NULL;
-
- if (hairdm) {
- MVert *mvert = CDDM_get_vert(hairdm, pa->hair_index + (hkey - pa->hair));
- copy_v3_v3(values, mvert->co);
- }
- else {
- float hairmat[4][4];
- psys_mat_hair_to_object(ob, psmd->dm_final, psmd->psys->part->from, pa, hairmat);
- copy_v3_v3(values, hkey->co);
- mul_m4_v3(hairmat, values);
- }
- }
- else {
- zero_v3(values);
- }
-}
-
-static void rna_ParticleHairKey_location_object_set(PointerRNA *ptr, const float *values)
-{
- HairKey *hkey = (HairKey *)ptr->data;
- Object *ob = (Object *)ptr->id.data;
- ParticleSystemModifierData *psmd;
- ParticleData *pa;
-
- rna_ParticleHairKey_location_object_info(ptr, &psmd, &pa);
-
- if (pa) {
- DerivedMesh *hairdm = (psmd->psys->flag & PSYS_HAIR_DYNAMICS) ? psmd->psys->hair_out_dm : NULL;
-
- if (hairdm) {
- MVert *mvert = CDDM_get_vert(hairdm, pa->hair_index + (hkey - pa->hair));
- copy_v3_v3(mvert->co, values);
- }
- else {
- float hairmat[4][4];
- float imat[4][4];
-
- psys_mat_hair_to_object(ob, psmd->dm_final, psmd->psys->part->from, pa, hairmat);
- invert_m4_m4(imat, hairmat);
- copy_v3_v3(hkey->co, values);
- mul_m4_v3(imat, hkey->co);
- }
- }
- else {
- zero_v3(hkey->co);
- }
-}
-
-static void rna_ParticleHairKey_co_object(HairKey *hairkey, Object *object, ParticleSystemModifierData *modifier, ParticleData *particle,
- float n_co[3])
-{
-
- DerivedMesh *hairdm = (modifier->psys->flag & PSYS_HAIR_DYNAMICS) ? modifier->psys->hair_out_dm : NULL;
- if (particle) {
- if (hairdm) {
- MVert *mvert = CDDM_get_vert(hairdm, particle->hair_index + (hairkey - particle->hair));
- copy_v3_v3(n_co, mvert->co);
- }
- else {
- float hairmat[4][4];
- psys_mat_hair_to_object(object, modifier->dm_final, modifier->psys->part->from, particle, hairmat);
- copy_v3_v3(n_co, hairkey->co);
- mul_m4_v3(hairmat, n_co);
- }
- }
- else {
- zero_v3(n_co);
- }
-}
-
-static void rna_Particle_uv_on_emitter(ParticleData *particle, ReportList *reports,
- ParticleSystemModifierData *modifier, float r_uv[2])
-{
- /*psys_particle_on_emitter(psmd, part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, co, nor, 0, 0, sd.orco, 0);*/
-
- /* get uvco & mcol */
- int num = particle->num_dmcache;
- int from = modifier->psys->part->from;
-
- if (!CustomData_has_layer(&modifier->dm_final->loopData, CD_MLOOPUV)) {
- BKE_report(reports, RPT_ERROR, "Mesh has no UV data");
- return;
- }
- DM_ensure_tessface(modifier->dm_final); /* BMESH - UNTIL MODIFIER IS UPDATED FOR MPoly */
-
- if (num == DMCACHE_NOTFOUND)
- if (particle->num < modifier->dm_final->getNumTessFaces(modifier->dm_final))
- num = particle->num;
-
- /* get uvco */
- if (r_uv && ELEM(from, PART_FROM_FACE, PART_FROM_VOLUME)) {
-
- if (num != DMCACHE_NOTFOUND) {
- MFace *mface;
- MTFace *mtface;
-
- mface = modifier->dm_final->getTessFaceData(modifier->dm_final, num, CD_MFACE);
- mtface = (MTFace *)CustomData_get_layer_n(&modifier->dm_final->faceData, CD_MTFACE, 0);
-
- if (mface && mtface) {
- mtface += num;
- psys_interpolate_uvs(mtface, mface->v4, particle->fuv, r_uv);
- return;
- }
- }
- }
-
- r_uv[0] = 0.0f;
- r_uv[1] = 0.0f;
-}
-
-static void rna_ParticleSystem_co_hair(ParticleSystem *particlesystem, Object *object,
- int particle_no, int step, float n_co[3])
-{
- ParticleSettings *part = NULL;
- ParticleData *pars = NULL;
- ParticleCacheKey *cache = NULL;
- int totchild = 0;
- int path_nbr = 0;
- int totpart;
- int max_k = 0;
- int step_nbr = 0;
-
- if (particlesystem == NULL)
- return;
-
- part = particlesystem->part;
- pars = particlesystem->particles;
-
- if (particlesystem->renderdata) {
- step_nbr = part->ren_step;
- totchild = particlesystem->totchild;
- }
- else {
- step_nbr = part->draw_step;
- totchild = (int)((float)particlesystem->totchild * (float)(part->disp) / 100.0f);
- }
-
- if (part == NULL || pars == NULL || !psys_check_enabled(object, particlesystem, particlesystem->renderdata != NULL))
- return;
-
- if (part->ren_as == PART_DRAW_OB || part->ren_as == PART_DRAW_GR || part->ren_as == PART_DRAW_NOT)
- return;
-
- /* can happen for disconnected/global hair */
- if (part->type == PART_HAIR && !particlesystem->childcache)
- totchild = 0;
-
- totpart = particlesystem->totpart;
-
- if (particle_no >= totpart + totchild)
- return;
-
- if (part->ren_as == PART_DRAW_PATH && particlesystem->pathcache)
- path_nbr = 1 << step_nbr;
- if (part->kink == PART_KINK_SPIRAL)
- path_nbr += part->kink_extra_steps;
-
- if (particle_no < totpart) {
-
- if (path_nbr) {
- cache = particlesystem->pathcache[particle_no];
- max_k = (int)cache->segments;
- }
-
- }
- else {
-
- if (path_nbr) {
- cache = particlesystem->childcache[particle_no - totpart];
-
- if (cache->segments < 0)
- max_k = 0;
- else
- max_k = (int)cache->segments;
- }
- }
-
- /*strands key loop data stored in cache + step->co*/
- if (path_nbr) {
- if (step >= 0 && step <= path_nbr) {
- if (step <= max_k) {
- copy_v3_v3(n_co, (cache + step)->co);
- mul_m4_v3(particlesystem->imat, n_co);
- mul_m4_v3(object->obmat, n_co);
- }
- }
- }
-
-}
-
-
-static EnumPropertyItem *rna_Particle_Material_itemf(bContext *C, PointerRNA *UNUSED(ptr),
- PropertyRNA *UNUSED(prop), bool *r_free)
-{
- Object *ob = CTX_data_pointer_get(C, "object").data;
- Material *ma;
- EnumPropertyItem *item = NULL;
- EnumPropertyItem tmp = {0, "", 0, "", ""};
- int totitem = 0;
- int i;
-
- if (ob && ob->totcol > 0) {
- for (i = 1; i <= ob->totcol; i++) {
- ma = give_current_material(ob, i);
- tmp.value = i;
- tmp.icon = ICON_MATERIAL_DATA;
- if (ma) {
- tmp.name = ma->id.name + 2;
- tmp.identifier = tmp.name;
- }
- else {
- tmp.name = "Default Material";
- tmp.identifier = tmp.name;
- }
- RNA_enum_item_add(&item, &totitem, &tmp);
- }
- }
- else {
- tmp.value = 1;
- tmp.icon = ICON_MATERIAL_DATA;
- tmp.name = "Default Material";
- tmp.identifier = tmp.name;
- RNA_enum_item_add(&item, &totitem, &tmp);
- }
-
- RNA_enum_item_end(&item, &totitem);
- *r_free = true;
-
- return item;
-}
-
-/* return < 0 means invalid (no matching tessellated face could be found). */
-static int rna_ParticleSystem_tessfaceidx_on_emitter(ParticleSystem *particlesystem,
- ParticleSystemModifierData *modifier, ParticleData *particle,
- int particle_no, float (**r_fuv)[4])
-{
- ParticleSettings *part = NULL;
- int totpart;
- int totchild = 0;
- int totface;
- int num = -1;
-
- DM_ensure_tessface(modifier->dm_final); /* BMESH - UNTIL MODIFIER IS UPDATED FOR MPoly */
- totface = modifier->dm_final->getNumTessFaces(modifier->dm_final);
-
- /* 1. check that everything is ok & updated */
- if (!particlesystem || !totface) {
- return num;
- }
-
- part = particlesystem->part;
-
- if (particlesystem->renderdata) {
- totchild = particlesystem->totchild;
- }
- else {
- totchild = (int)((float)particlesystem->totchild * (float)(part->disp) / 100.0f);
- }
-
- /* can happen for disconnected/global hair */
- if (part->type == PART_HAIR && !particlesystem->childcache)
- totchild = 0;
-
- totpart = particlesystem->totpart;
-
- if (particle_no >= totpart + totchild)
- return num;
-
- /* 2. get matching face index. */
- if (particle_no < totpart) {
- num = (ELEM(particle->num_dmcache, DMCACHE_ISCHILD, DMCACHE_NOTFOUND)) ? particle->num : particle->num_dmcache;
-
- if (ELEM(part->from, PART_FROM_FACE, PART_FROM_VOLUME)) {
- if (num != DMCACHE_NOTFOUND && num < totface) {
- *r_fuv = &particle->fuv;
- return num;
- }
- }
- }
- else {
- ChildParticle *cpa = particlesystem->child + particle_no - totpart;
- num = cpa->num;
-
- if (part->childtype == PART_CHILD_FACES) {
- if (ELEM(part->from, PART_FROM_FACE, PART_FROM_VOLUME)) {
- if (num != DMCACHE_NOTFOUND && num < totface) {
- *r_fuv = &cpa->fuv;
- return num;
- }
- }
- }
- else {
- ParticleData *parent = particlesystem->particles + cpa->parent;
- num = parent->num_dmcache;
-
- if (num == DMCACHE_NOTFOUND)
- num = parent->num;
-
- if (ELEM(part->from, PART_FROM_FACE, PART_FROM_VOLUME)) {
- if (num != DMCACHE_NOTFOUND && num < totface) {
- *r_fuv = &parent->fuv;
- return num;
- }
- }
- }
- }
-
- return -1;
-}
-
-static void rna_ParticleSystem_uv_on_emitter(ParticleSystem *particlesystem, ReportList *reports,
- ParticleSystemModifierData *modifier, ParticleData *particle,
- int particle_no, int uv_no, float r_uv[2])
-{
- if (!CustomData_has_layer(&modifier->dm_final->loopData, CD_MLOOPUV)) {
- BKE_report(reports, RPT_ERROR, "Mesh has no UV data");
- zero_v2(r_uv);
- return;
- }
-
- {
- float (*fuv)[4];
- /* Note all sanity checks are done in this helper func. */
- const int num = rna_ParticleSystem_tessfaceidx_on_emitter(particlesystem, modifier, particle,
- particle_no, &fuv);
-
- if (num < 0) {
- /* No matching face found. */
- zero_v2(r_uv);
- }
- else {
- MFace *mface = modifier->dm_final->getTessFaceData(modifier->dm_final, num, CD_MFACE);
- MTFace *mtface = (MTFace *)CustomData_get_layer_n(&modifier->dm_final->faceData, CD_MTFACE, uv_no);
-
- psys_interpolate_uvs(&mtface[num], mface->v4, *fuv, r_uv);
- }
- }
-}
-
-static void rna_ParticleSystem_mcol_on_emitter(ParticleSystem *particlesystem, ReportList *reports,
- ParticleSystemModifierData *modifier, ParticleData *particle,
- int particle_no, int vcol_no, float r_mcol[3])
-{
- if (!CustomData_has_layer(&modifier->dm_final->loopData, CD_MLOOPCOL)) {
- BKE_report(reports, RPT_ERROR, "Mesh has no VCol data");
- zero_v3(r_mcol);
- return;
- }
-
- {
- float (*fuv)[4];
- /* Note all sanity checks are done in this helper func. */
- const int num = rna_ParticleSystem_tessfaceidx_on_emitter(particlesystem, modifier, particle,
- particle_no, &fuv);
-
- if (num < 0) {
- /* No matching face found. */
- zero_v3(r_mcol);
- }
- else {
- MFace *mface = modifier->dm_final->getTessFaceData(modifier->dm_final, num, CD_MFACE);
- MCol *mc = (MCol *)CustomData_get_layer_n(&modifier->dm_final->faceData, CD_MCOL, vcol_no);
- MCol mcol;
-
- psys_interpolate_mcol(&mc[num * 4], mface->v4, *fuv, &mcol);
- r_mcol[0] = (float)mcol.b / 255.0f;
- r_mcol[1] = (float)mcol.g / 255.0f;
- r_mcol[2] = (float)mcol.r / 255.0f;
- }
- }
-}
-
-static void rna_ParticleSystem_set_resolution(ParticleSystem *particlesystem, Scene *scene, Object *object, int resolution)
-{
- if (resolution == eModifierMode_Render) {
- ParticleSystemModifierData *psmd = psys_get_modifier(object, particlesystem);
- float mat[4][4];
-
- unit_m4(mat);
-
- psys_render_set(object, particlesystem, mat, mat, 1, 1, 0.f);
- psmd->flag &= ~eParticleSystemFlag_psys_updated;
- particle_system_update(scene, object, particlesystem, true);
- }
- else {
- ParticleSystemModifierData *psmd = psys_get_modifier(object, particlesystem);
-
- if (particlesystem->renderdata) {
- psys_render_restore(object, particlesystem);
- }
-
- psmd->flag &= ~eParticleSystemFlag_psys_updated;
- particle_system_update(scene, object, particlesystem, false);
- }
-}
-
-static void particle_recalc(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr, short flag)
-{
- if (ptr->type == &RNA_ParticleSystem) {
- ParticleSystem *psys = (ParticleSystem *)ptr->data;
-
- psys->recalc = flag;
-
- DAG_id_tag_update(ptr->id.data, OB_RECALC_DATA);
- }
- else
- DAG_id_tag_update(ptr->id.data, OB_RECALC_DATA | flag);
-
- WM_main_add_notifier(NC_OBJECT | ND_PARTICLE | NA_EDITED, NULL);
-}
-static void rna_Particle_redo(Main *bmain, Scene *scene, PointerRNA *ptr)
-{
- particle_recalc(bmain, scene, ptr, PSYS_RECALC_REDO);
-}
-
-static void rna_Particle_redo_dependency(Main *bmain, Scene *scene, PointerRNA *ptr)
-{
- DAG_relations_tag_update(bmain);
- rna_Particle_redo(bmain, scene, ptr);
-}
-
-static void rna_Particle_reset(Main *bmain, Scene *scene, PointerRNA *ptr)
-{
- particle_recalc(bmain, scene, ptr, PSYS_RECALC_RESET);
-}
-
-static void rna_Particle_reset_dependency(Main *bmain, Scene *scene, PointerRNA *ptr)
-{
- DAG_relations_tag_update(bmain);
- rna_Particle_reset(bmain, scene, ptr);
-}
-
-static void rna_Particle_change_type(Main *bmain, Scene *scene, PointerRNA *ptr)
-{
- particle_recalc(bmain, scene, ptr, PSYS_RECALC_RESET | PSYS_RECALC_TYPE);
-}
-
-static void rna_Particle_change_physics(Main *bmain, Scene *scene, PointerRNA *ptr)
-{
- particle_recalc(bmain, scene, ptr, PSYS_RECALC_RESET | PSYS_RECALC_PHYS);
-}
-
-static void rna_Particle_redo_child(Main *bmain, Scene *scene, PointerRNA *ptr)
-{
- particle_recalc(bmain, scene, ptr, PSYS_RECALC_CHILD);
-}
-
-static void rna_Particle_cloth_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
-{
- Object *ob = (Object *)ptr->id.data;
-
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
- WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ob);
-}
-
-
-static ParticleSystem *rna_particle_system_for_target(Object *ob, ParticleTarget *target)
-{
- ParticleSystem *psys;
- ParticleTarget *pt;
-
- for (psys = ob->particlesystem.first; psys; psys = psys->next)
- for (pt = psys->targets.first; pt; pt = pt->next)
- if (pt == target)
- return psys;
-
- return NULL;
-}
-
-static void rna_Particle_target_reset(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
-{
- if (ptr->type == &RNA_ParticleTarget) {
- Object *ob = (Object *)ptr->id.data;
- ParticleTarget *pt = (ParticleTarget *)ptr->data;
- ParticleSystem *kpsys = NULL, *psys = rna_particle_system_for_target(ob, pt);
-
- if (pt->ob == ob || pt->ob == NULL) {
- kpsys = BLI_findlink(&ob->particlesystem, pt->psys - 1);
-
- if (kpsys)
- pt->flag |= PTARGET_VALID;
- else
- pt->flag &= ~PTARGET_VALID;
- }
- else {
- if (pt->ob)
- kpsys = BLI_findlink(&pt->ob->particlesystem, pt->psys - 1);
-
- if (kpsys)
- pt->flag |= PTARGET_VALID;
- else
- pt->flag &= ~PTARGET_VALID;
- }
-
- psys->recalc = PSYS_RECALC_RESET;
-
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
- DAG_relations_tag_update(bmain);
- }
-
- WM_main_add_notifier(NC_OBJECT | ND_PARTICLE | NA_EDITED, NULL);
-}
-
-static void rna_Particle_target_redo(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
-{
- if (ptr->type == &RNA_ParticleTarget) {
- Object *ob = (Object *)ptr->id.data;
- ParticleTarget *pt = (ParticleTarget *)ptr->data;
- ParticleSystem *psys = rna_particle_system_for_target(ob, pt);
-
- psys->recalc = PSYS_RECALC_REDO;
-
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
- WM_main_add_notifier(NC_OBJECT | ND_PARTICLE | NA_EDITED, NULL);
- }
-}
-
-static void rna_Particle_hair_dynamics(Main *bmain, Scene *scene, PointerRNA *ptr)
-{
- Object *ob = (Object *)ptr->id.data;
- ParticleSystem *psys = (ParticleSystem *)ptr->data;
-
- if (psys && !psys->clmd) {
- psys->clmd = (ClothModifierData *)modifier_new(eModifierType_Cloth);
- psys->clmd->sim_parms->goalspring = 0.0f;
- psys->clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_GOAL | CLOTH_SIMSETTINGS_FLAG_NO_SPRING_COMPRESS;
- psys->clmd->coll_parms->flags &= ~CLOTH_COLLSETTINGS_FLAG_SELF;
- rna_Particle_redo(bmain, scene, ptr);
- }
- else
- WM_main_add_notifier(NC_OBJECT | ND_PARTICLE | NA_EDITED, NULL);
-
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
-}
-static PointerRNA rna_particle_settings_get(PointerRNA *ptr)
-{
- ParticleSystem *psys = (ParticleSystem *)ptr->data;
- ParticleSettings *part = psys->part;
-
- return rna_pointer_inherit_refine(ptr, &RNA_ParticleSettings, part);
-}
-
-static void rna_particle_settings_set(PointerRNA *ptr, PointerRNA value)
-{
- ParticleSystem *psys = (ParticleSystem *)ptr->data;
- int old_type = 0;
-
-
- if (psys->part) {
- old_type = psys->part->type;
- id_us_min(&psys->part->id);
- }
-
- psys->part = (ParticleSettings *)value.data;
-
- if (psys->part) {
- id_us_plus(&psys->part->id);
- psys_check_boid_data(psys);
- if (old_type != psys->part->type)
- psys->recalc |= PSYS_RECALC_TYPE;
- }
-}
-static void rna_Particle_abspathtime_update(Main *bmain, Scene *scene, PointerRNA *ptr)
-{
- ParticleSettings *settings = (ParticleSettings *)ptr->data;
- float delta = settings->end + settings->lifetime - settings->sta;
- if (settings->draw & PART_ABS_PATH_TIME) {
- settings->path_start = settings->sta + settings->path_start * delta;
- settings->path_end = settings->sta + settings->path_end * delta;
- }
- else {
- settings->path_start = (settings->path_start - settings->sta) / delta;
- settings->path_end = (settings->path_end - settings->sta) / delta;
- }
- rna_Particle_redo(bmain, scene, ptr);
-}
-static void rna_PartSettings_start_set(struct PointerRNA *ptr, float value)
-{
- ParticleSettings *settings = (ParticleSettings *)ptr->data;
-
- /* check for clipping */
- if (value > settings->end)
- value = settings->end;
-
- /*if (settings->type==PART_REACTOR && value < 1.0) */
- /* value = 1.0; */
- /*else */
- if (value < MINAFRAMEF)
- value = MINAFRAMEF;
-
- settings->sta = value;
-}
-
-static void rna_PartSettings_end_set(struct PointerRNA *ptr, float value)
-{
- ParticleSettings *settings = (ParticleSettings *)ptr->data;
-
- /* check for clipping */
- if (value < settings->sta)
- value = settings->sta;
-
- settings->end = value;
-}
-
-static void rna_PartSetings_timestep_set(struct PointerRNA *ptr, float value)
-{
- ParticleSettings *settings = (ParticleSettings *)ptr->data;
-
- settings->timetweak = value / 0.04f;
-}
-
-static float rna_PartSettings_timestep_get(struct PointerRNA *ptr)
-{
- ParticleSettings *settings = (ParticleSettings *)ptr->data;
-
- return settings->timetweak * 0.04f;
-}
-
-static void rna_PartSetting_hairlength_set(struct PointerRNA *ptr, float value)
-{
- ParticleSettings *settings = (ParticleSettings *)ptr->data;
- settings->normfac = value / 4.f;
-}
-
-static float rna_PartSetting_hairlength_get(struct PointerRNA *ptr)
-{
- ParticleSettings *settings = (ParticleSettings *)ptr->data;
- return settings->normfac * 4.f;
-}
-
-static void rna_PartSetting_linelentail_set(struct PointerRNA *ptr, float value)
-{
- ParticleSettings *settings = (ParticleSettings *)ptr->data;
- settings->draw_line[0] = value;
-}
-
-static float rna_PartSetting_linelentail_get(struct PointerRNA *ptr)
-{
- ParticleSettings *settings = (ParticleSettings *)ptr->data;
- return settings->draw_line[0];
-}
-static void rna_PartSetting_pathstartend_range(PointerRNA *ptr, float *min, float *max,
- float *UNUSED(softmin), float *UNUSED(softmax))
-{
- ParticleSettings *settings = (ParticleSettings *)ptr->data;
-
- if (settings->type == PART_HAIR) {
- *min = 0.0f;
- *max = (settings->draw & PART_ABS_PATH_TIME) ? 100.0f : 1.0f;
- }
- else {
- *min = (settings->draw & PART_ABS_PATH_TIME) ? settings->sta : 0.0f;
- *max = (settings->draw & PART_ABS_PATH_TIME) ? MAXFRAMEF : 1.0f;
- }
-}
-static void rna_PartSetting_linelenhead_set(struct PointerRNA *ptr, float value)
-{
- ParticleSettings *settings = (ParticleSettings *)ptr->data;
- settings->draw_line[1] = value;
-}
-
-static float rna_PartSetting_linelenhead_get(struct PointerRNA *ptr)
-{
- ParticleSettings *settings = (ParticleSettings *)ptr->data;
- return settings->draw_line[1];
-}
-
-
-static int rna_PartSettings_is_fluid_get(PointerRNA *ptr)
-{
- ParticleSettings *part = (ParticleSettings *)ptr->data;
-
- return part->type == PART_FLUID;
-}
-
-static void rna_ParticleSettings_use_clump_curve_update(Main *bmain, Scene *scene, PointerRNA *ptr)
-{
- ParticleSettings *part = ptr->data;
-
- if (part->child_flag & PART_CHILD_USE_CLUMP_CURVE) {
- if (!part->clumpcurve) {
- BKE_particlesettings_clump_curve_init(part);
- }
- }
-
- rna_Particle_redo_child(bmain, scene, ptr);
-}
-
-static void rna_ParticleSettings_use_roughness_curve_update(Main *bmain, Scene *scene, PointerRNA *ptr)
-{
- ParticleSettings *part = ptr->data;
-
- if (part->child_flag & PART_CHILD_USE_ROUGH_CURVE) {
- if (!part->roughcurve) {
- BKE_particlesettings_rough_curve_init(part);
- }
- }
-
- rna_Particle_redo_child(bmain, scene, ptr);
-}
-
-static void rna_ParticleSystem_name_set(PointerRNA *ptr, const char *value)
-{
- Object *ob = ptr->id.data;
- ParticleSystem *part = (ParticleSystem *)ptr->data;
-
- /* copy the new name into the name slot */
- BLI_strncpy_utf8(part->name, value, sizeof(part->name));
-
- BLI_uniquename(&ob->particlesystem, part, DATA_("ParticleSystem"), '.', offsetof(ParticleSystem, name),
- sizeof(part->name));
-}
-
-static PointerRNA rna_ParticleSystem_active_particle_target_get(PointerRNA *ptr)
-{
- ParticleSystem *psys = (ParticleSystem *)ptr->data;
- ParticleTarget *pt = psys->targets.first;
-
- for (; pt; pt = pt->next) {
- if (pt->flag & PTARGET_CURRENT)
- return rna_pointer_inherit_refine(ptr, &RNA_ParticleTarget, pt);
- }
- return rna_pointer_inherit_refine(ptr, &RNA_ParticleTarget, NULL);
-}
-static void rna_ParticleSystem_active_particle_target_index_range(PointerRNA *ptr, int *min, int *max,
- int *UNUSED(softmin), int *UNUSED(softmax))
-{
- ParticleSystem *psys = (ParticleSystem *)ptr->data;
- *min = 0;
- *max = max_ii(0, BLI_listbase_count(&psys->targets) - 1);
-}
-
-static int rna_ParticleSystem_active_particle_target_index_get(PointerRNA *ptr)
-{
- ParticleSystem *psys = (ParticleSystem *)ptr->data;
- ParticleTarget *pt = psys->targets.first;
- int i = 0;
-
- for (; pt; pt = pt->next, i++)
- if (pt->flag & PTARGET_CURRENT)
- return i;
-
- return 0;
-}
-
-static void rna_ParticleSystem_active_particle_target_index_set(struct PointerRNA *ptr, int value)
-{
- ParticleSystem *psys = (ParticleSystem *)ptr->data;
- ParticleTarget *pt = psys->targets.first;
- int i = 0;
-
- for (; pt; pt = pt->next, i++) {
- if (i == value)
- pt->flag |= PTARGET_CURRENT;
- else
- pt->flag &= ~PTARGET_CURRENT;
- }
-}
-
-static void rna_ParticleTarget_name_get(PointerRNA *ptr, char *str)
-{
- ParticleTarget *pt = ptr->data;
-
- if (pt->flag & PTARGET_VALID) {
- ParticleSystem *psys = NULL;
-
- if (pt->ob)
- psys = BLI_findlink(&pt->ob->particlesystem, pt->psys - 1);
- else {
- Object *ob = (Object *) ptr->id.data;
- psys = BLI_findlink(&ob->particlesystem, pt->psys - 1);
- }
-
- if (psys) {
- if (pt->ob)
- sprintf(str, "%s: %s", pt->ob->id.name + 2, psys->name);
- else
- strcpy(str, psys->name);
- }
- else
- strcpy(str, "Invalid target!");
- }
- else
- strcpy(str, "Invalid target!");
-}
-
-static int rna_ParticleTarget_name_length(PointerRNA *ptr)
-{
- char tstr[MAX_ID_NAME + MAX_ID_NAME + 64];
-
- rna_ParticleTarget_name_get(ptr, tstr);
-
- return strlen(tstr);
-}
-
-static int particle_id_check(PointerRNA *ptr)
-{
- ID *id = ptr->id.data;
-
- return (GS(id->name) == ID_PA);
-}
-
-static char *rna_SPHFluidSettings_path(PointerRNA *ptr)
-{
- SPHFluidSettings *fluid = (SPHFluidSettings *)ptr->data;
-
- if (particle_id_check(ptr)) {
- ParticleSettings *part = (ParticleSettings *)ptr->id.data;
-
- if (part->fluid == fluid)
- return BLI_sprintfN("fluid");
- }
- return NULL;
-}
-
-static int rna_ParticleSystem_multiple_caches_get(PointerRNA *ptr)
-{
- ParticleSystem *psys = (ParticleSystem *)ptr->data;
-
- return (psys->ptcaches.first != psys->ptcaches.last);
-}
-static int rna_ParticleSystem_editable_get(PointerRNA *ptr)
-{
- ParticleSystem *psys = (ParticleSystem *)ptr->data;
-
- return psys_check_edited(psys);
-}
-static int rna_ParticleSystem_edited_get(PointerRNA *ptr)
-{
- ParticleSystem *psys = (ParticleSystem *)ptr->data;
-
- if (psys->part && psys->part->type == PART_HAIR)
- return (psys->flag & PSYS_EDITED || (psys->edit && psys->edit->edited));
- else
- return (psys->pointcache->edit && psys->pointcache->edit->edited);
-}
-static PointerRNA rna_ParticleDupliWeight_active_get(PointerRNA *ptr)
-{
- ParticleSettings *part = (ParticleSettings *)ptr->id.data;
- ParticleDupliWeight *dw = part->dupliweights.first;
-
- for (; dw; dw = dw->next) {
- if (dw->flag & PART_DUPLIW_CURRENT)
- return rna_pointer_inherit_refine(ptr, &RNA_ParticleDupliWeight, dw);
- }
- return rna_pointer_inherit_refine(ptr, &RNA_ParticleTarget, NULL);
-}
-static void rna_ParticleDupliWeight_active_index_range(PointerRNA *ptr, int *min, int *max,
- int *UNUSED(softmin), int *UNUSED(softmax))
-{
- ParticleSettings *part = (ParticleSettings *)ptr->id.data;
- *min = 0;
- *max = max_ii(0, BLI_listbase_count(&part->dupliweights) - 1);
-}
-
-static int rna_ParticleDupliWeight_active_index_get(PointerRNA *ptr)
-{
- ParticleSettings *part = (ParticleSettings *)ptr->id.data;
- ParticleDupliWeight *dw = part->dupliweights.first;
- int i = 0;
-
- for (; dw; dw = dw->next, i++)
- if (dw->flag & PART_DUPLIW_CURRENT)
- return i;
-
- return 0;
-}
-
-static void rna_ParticleDupliWeight_active_index_set(struct PointerRNA *ptr, int value)
-{
- ParticleSettings *part = (ParticleSettings *)ptr->id.data;
- ParticleDupliWeight *dw = part->dupliweights.first;
- int i = 0;
-
- for (; dw; dw = dw->next, i++) {
- if (i == value)
- dw->flag |= PART_DUPLIW_CURRENT;
- else
- dw->flag &= ~PART_DUPLIW_CURRENT;
- }
-}
-
-static void rna_ParticleDupliWeight_name_get(PointerRNA *ptr, char *str)
-{
- ParticleDupliWeight *dw = ptr->data;
-
- if (dw->ob)
- sprintf(str, "%s: %i", dw->ob->id.name + 2, dw->count);
- else
- strcpy(str, "No object");
-}
-
-static int rna_ParticleDupliWeight_name_length(PointerRNA *ptr)
-{
- char tstr[MAX_ID_NAME + 64];
-
- rna_ParticleDupliWeight_name_get(ptr, tstr);
-
- return strlen(tstr);
-}
-
-static EnumPropertyItem *rna_Particle_from_itemf(bContext *UNUSED(C), PointerRNA *UNUSED(ptr),
- PropertyRNA *UNUSED(prop), bool *UNUSED(r_free))
-{
- /*if (part->type==PART_REACTOR) */
- /* return part_reactor_from_items; */
- /*else */
- return part_from_items;
-}
-
-static EnumPropertyItem *rna_Particle_dist_itemf(bContext *UNUSED(C), PointerRNA *ptr,
- PropertyRNA *UNUSED(prop), bool *UNUSED(r_free))
-{
- ParticleSettings *part = ptr->id.data;
-
- if (part->type == PART_HAIR)
- return part_hair_dist_items;
- else
- return part_dist_items;
-}
-
-static EnumPropertyItem *rna_Particle_draw_as_itemf(bContext *UNUSED(C), PointerRNA *ptr,
- PropertyRNA *UNUSED(prop), bool *UNUSED(r_free))
-{
- ParticleSettings *part = ptr->id.data;
-
- if (part->type == PART_HAIR)
- return part_hair_draw_as_items;
- else
- return part_draw_as_items;
-}
-
-static EnumPropertyItem *rna_Particle_ren_as_itemf(bContext *UNUSED(C), PointerRNA *ptr,
- PropertyRNA *UNUSED(prop), bool *UNUSED(r_free))
-{
- ParticleSettings *part = ptr->id.data;
-
- if (part->type == PART_HAIR)
- return part_hair_ren_as_items;
- else
- return part_ren_as_items;
-}
-
-static PointerRNA rna_Particle_field1_get(PointerRNA *ptr)
-{
- ParticleSettings *part = (ParticleSettings *)ptr->id.data;
-
- /* weak */
- if (!part->pd)
- part->pd = object_add_collision_fields(0);
-
- return rna_pointer_inherit_refine(ptr, &RNA_FieldSettings, part->pd);
-}
-
-static PointerRNA rna_Particle_field2_get(PointerRNA *ptr)
-{
- ParticleSettings *part = (ParticleSettings *)ptr->id.data;
-
- /* weak */
- if (!part->pd2)
- part->pd2 = object_add_collision_fields(0);
-
- return rna_pointer_inherit_refine(ptr, &RNA_FieldSettings, part->pd2);
-}
-
-static void psys_vg_name_get__internal(PointerRNA *ptr, char *value, int index)
-{
- Object *ob = ptr->id.data;
- ParticleSystem *psys = (ParticleSystem *)ptr->data;
-
- if (psys->vgroup[index] > 0) {
- bDeformGroup *defGroup = BLI_findlink(&ob->defbase, psys->vgroup[index] - 1);
-
- if (defGroup) {
- strcpy(value, defGroup->name);
- return;
- }
- }
-
- value[0] = '\0';
-}
-static int psys_vg_name_len__internal(PointerRNA *ptr, int index)
-{
- Object *ob = ptr->id.data;
- ParticleSystem *psys = (ParticleSystem *)ptr->data;
-
- if (psys->vgroup[index] > 0) {
- bDeformGroup *defGroup = BLI_findlink(&ob->defbase, psys->vgroup[index] - 1);
-
- if (defGroup) {
- return strlen(defGroup->name);
- }
- }
- return 0;
-}
-static void psys_vg_name_set__internal(PointerRNA *ptr, const char *value, int index)
-{
- Object *ob = ptr->id.data;
- ParticleSystem *psys = (ParticleSystem *)ptr->data;
-
- if (value[0] == '\0') {
- psys->vgroup[index] = 0;
- }
- else {
- int defgrp_index = defgroup_name_index(ob, value);
-
- if (defgrp_index == -1)
- return;
-
- psys->vgroup[index] = defgrp_index + 1;
- }
-}
-
-static char *rna_ParticleSystem_path(PointerRNA *ptr)
-{
- ParticleSystem *psys = (ParticleSystem *)ptr->data;
- char name_esc[sizeof(psys->name) * 2];
-
- BLI_strescape(name_esc, psys->name, sizeof(name_esc));
- return BLI_sprintfN("particle_systems[\"%s\"]", name_esc);
-}
-
-static void rna_ParticleSettings_mtex_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
-{
- ParticleSettings *part = (ParticleSettings *)ptr->data;
- rna_iterator_array_begin(iter, (void *)part->mtex, sizeof(MTex *), MAX_MTEX, 0, NULL);
-}
-
-static PointerRNA rna_ParticleSettings_active_texture_get(PointerRNA *ptr)
-{
- ParticleSettings *part = (ParticleSettings *)ptr->data;
- Tex *tex;
-
- tex = give_current_particle_texture(part);
- return rna_pointer_inherit_refine(ptr, &RNA_Texture, tex);
-}
-
-static void rna_ParticleSettings_active_texture_set(PointerRNA *ptr, PointerRNA value)
-{
- ParticleSettings *part = (ParticleSettings *)ptr->data;
-
- set_current_particle_texture(part, value.data);
-}
-
-/* irritating string functions for each index :/ */
-static void rna_ParticleVGroup_name_get_0(PointerRNA *ptr, char *value) { psys_vg_name_get__internal(ptr, value, 0); }
-static void rna_ParticleVGroup_name_get_1(PointerRNA *ptr, char *value) { psys_vg_name_get__internal(ptr, value, 1); }
-static void rna_ParticleVGroup_name_get_2(PointerRNA *ptr, char *value) { psys_vg_name_get__internal(ptr, value, 2); }
-static void rna_ParticleVGroup_name_get_3(PointerRNA *ptr, char *value) { psys_vg_name_get__internal(ptr, value, 3); }
-static void rna_ParticleVGroup_name_get_4(PointerRNA *ptr, char *value) { psys_vg_name_get__internal(ptr, value, 4); }
-static void rna_ParticleVGroup_name_get_5(PointerRNA *ptr, char *value) { psys_vg_name_get__internal(ptr, value, 5); }
-static void rna_ParticleVGroup_name_get_6(PointerRNA *ptr, char *value) { psys_vg_name_get__internal(ptr, value, 6); }
-static void rna_ParticleVGroup_name_get_7(PointerRNA *ptr, char *value) { psys_vg_name_get__internal(ptr, value, 7); }
-static void rna_ParticleVGroup_name_get_8(PointerRNA *ptr, char *value) { psys_vg_name_get__internal(ptr, value, 8); }
-static void rna_ParticleVGroup_name_get_9(PointerRNA *ptr, char *value) { psys_vg_name_get__internal(ptr, value, 9); }
-static void rna_ParticleVGroup_name_get_10(PointerRNA *ptr, char *value) { psys_vg_name_get__internal(ptr, value, 10); }
-static void rna_ParticleVGroup_name_get_11(PointerRNA *ptr, char *value) { psys_vg_name_get__internal(ptr, value, 11); }
-
-static int rna_ParticleVGroup_name_len_0(PointerRNA *ptr) { return psys_vg_name_len__internal(ptr, 0); }
-static int rna_ParticleVGroup_name_len_1(PointerRNA *ptr) { return psys_vg_name_len__internal(ptr, 1); }
-static int rna_ParticleVGroup_name_len_2(PointerRNA *ptr) { return psys_vg_name_len__internal(ptr, 2); }
-static int rna_ParticleVGroup_name_len_3(PointerRNA *ptr) { return psys_vg_name_len__internal(ptr, 3); }
-static int rna_ParticleVGroup_name_len_4(PointerRNA *ptr) { return psys_vg_name_len__internal(ptr, 4); }
-static int rna_ParticleVGroup_name_len_5(PointerRNA *ptr) { return psys_vg_name_len__internal(ptr, 5); }
-static int rna_ParticleVGroup_name_len_6(PointerRNA *ptr) { return psys_vg_name_len__internal(ptr, 6); }
-static int rna_ParticleVGroup_name_len_7(PointerRNA *ptr) { return psys_vg_name_len__internal(ptr, 7); }
-static int rna_ParticleVGroup_name_len_8(PointerRNA *ptr) { return psys_vg_name_len__internal(ptr, 8); }
-static int rna_ParticleVGroup_name_len_9(PointerRNA *ptr) { return psys_vg_name_len__internal(ptr, 9); }
-static int rna_ParticleVGroup_name_len_10(PointerRNA *ptr) { return psys_vg_name_len__internal(ptr, 10); }
-static int rna_ParticleVGroup_name_len_11(PointerRNA *ptr) { return psys_vg_name_len__internal(ptr, 11); }
-
-static void rna_ParticleVGroup_name_set_0(PointerRNA *ptr, const char *value) { psys_vg_name_set__internal(ptr, value, 0); }
-static void rna_ParticleVGroup_name_set_1(PointerRNA *ptr, const char *value) { psys_vg_name_set__internal(ptr, value, 1); }
-static void rna_ParticleVGroup_name_set_2(PointerRNA *ptr, const char *value) { psys_vg_name_set__internal(ptr, value, 2); }
-static void rna_ParticleVGroup_name_set_3(PointerRNA *ptr, const char *value) { psys_vg_name_set__internal(ptr, value, 3); }
-static void rna_ParticleVGroup_name_set_4(PointerRNA *ptr, const char *value) { psys_vg_name_set__internal(ptr, value, 4); }
-static void rna_ParticleVGroup_name_set_5(PointerRNA *ptr, const char *value) { psys_vg_name_set__internal(ptr, value, 5); }
-static void rna_ParticleVGroup_name_set_6(PointerRNA *ptr, const char *value) { psys_vg_name_set__internal(ptr, value, 6); }
-static void rna_ParticleVGroup_name_set_7(PointerRNA *ptr, const char *value) { psys_vg_name_set__internal(ptr, value, 7); }
-static void rna_ParticleVGroup_name_set_8(PointerRNA *ptr, const char *value) { psys_vg_name_set__internal(ptr, value, 8); }
-static void rna_ParticleVGroup_name_set_9(PointerRNA *ptr, const char *value) { psys_vg_name_set__internal(ptr, value, 9); }
-static void rna_ParticleVGroup_name_set_10(PointerRNA *ptr, const char *value) { psys_vg_name_set__internal(ptr, value, 10); }
-static void rna_ParticleVGroup_name_set_11(PointerRNA *ptr, const char *value) { psys_vg_name_set__internal(ptr, value, 11); }
-
-
-#else
-
-static void rna_def_particle_hair_key(BlenderRNA *brna)
-{
- StructRNA *srna;
- PropertyRNA *prop;
- FunctionRNA *func;
-
- srna = RNA_def_struct(brna, "ParticleHairKey", NULL);
- RNA_def_struct_sdna(srna, "HairKey");
- RNA_def_struct_ui_text(srna, "Particle Hair Key", "Particle key for hair particle system");
-
- prop = RNA_def_property(srna, "time", PROP_FLOAT, PROP_UNSIGNED);
- RNA_def_property_ui_text(prop, "Time", "Relative time of key over hair length");
-
- prop = RNA_def_property(srna, "weight", PROP_FLOAT, PROP_UNSIGNED);
- RNA_def_property_range(prop, 0.0, 1.0);
- RNA_def_property_ui_text(prop, "Weight", "Weight for cloth simulation");
-
- prop = RNA_def_property(srna, "co", PROP_FLOAT, PROP_TRANSLATION);
- RNA_def_property_array(prop, 3);
- RNA_def_property_ui_text(prop, "Location (Object Space)", "Location of the hair key in object space");
- RNA_def_property_float_funcs(prop, "rna_ParticleHairKey_location_object_get",
- "rna_ParticleHairKey_location_object_set", NULL);
-
- prop = RNA_def_property(srna, "co_local", PROP_FLOAT, PROP_TRANSLATION);
- RNA_def_property_float_sdna(prop, NULL, "co");
- RNA_def_property_ui_text(prop, "Location",
- "Location of the hair key in its local coordinate system, "
- "relative to the emitting face");
-
- /* Aided co func */
- func = RNA_def_function(srna, "co_object", "rna_ParticleHairKey_co_object");
- RNA_def_function_ui_description(func, "Obtain hairkey location with particle and modifier data");
-
- prop = RNA_def_pointer(func, "object", "Object", "", "Object");
- RNA_def_property_flag(prop, PROP_REQUIRED | PROP_NEVER_NULL);
- prop = RNA_def_pointer(func, "modifier", "ParticleSystemModifier", "", "Particle modifier");
- RNA_def_property_flag(prop, PROP_REQUIRED | PROP_NEVER_NULL);
- prop = RNA_def_pointer(func, "particle", "Particle", "", "hair particle");
- RNA_def_property_flag(prop, PROP_REQUIRED | PROP_NEVER_NULL);
-
- prop = RNA_def_float_vector(func, "co", 3, NULL, -FLT_MAX, FLT_MAX, "Co",
- "Exported hairkey location", -1e4, 1e4);
- RNA_def_property_flag(prop, PROP_THICK_WRAP);
- RNA_def_function_output(func, prop);
-}
-
-static void rna_def_particle_key(BlenderRNA *brna)
-{
- StructRNA *srna;
- PropertyRNA *prop;
-
- srna = RNA_def_struct(brna, "ParticleKey", NULL);
- RNA_def_struct_ui_text(srna, "Particle Key", "Key location for a particle over time");
-
- prop = RNA_def_property(srna, "location", PROP_FLOAT, PROP_TRANSLATION);
- RNA_def_property_float_sdna(prop, NULL, "co");
- RNA_def_property_ui_text(prop, "Location", "Key location");
-
- prop = RNA_def_property(srna, "velocity", PROP_FLOAT, PROP_VELOCITY);
- RNA_def_property_float_sdna(prop, NULL, "vel");
- RNA_def_property_ui_text(prop, "Velocity", "Key velocity");
-
- prop = RNA_def_property(srna, "rotation", PROP_FLOAT, PROP_QUATERNION);
- RNA_def_property_float_sdna(prop, NULL, "rot");
- RNA_def_property_ui_text(prop, "Rotation", "Key rotation quaternion");
-
- prop = RNA_def_property(srna, "angular_velocity", PROP_FLOAT, PROP_VELOCITY);
- RNA_def_property_float_sdna(prop, NULL, "ave");
- RNA_def_property_ui_text(prop, "Angular Velocity", "Key angular velocity");
-
- prop = RNA_def_property(srna, "time", PROP_FLOAT, PROP_UNSIGNED);
- RNA_def_property_ui_text(prop, "Time", "Time of key over the simulation");
-}
-
-static void rna_def_child_particle(BlenderRNA *brna)
-{
- StructRNA *srna;
- /*PropertyRNA *prop; */
-
- srna = RNA_def_struct(brna, "ChildParticle", NULL);
- RNA_def_struct_ui_text(srna, "Child Particle",
- "Child particle interpolated from simulated or edited particles");
-
-/* int num, parent; *//* num is face index on the final derived mesh */
-
-/* int pa[4]; *//* nearest particles to the child, used for the interpolation */
-/* float w[4]; *//* interpolation weights for the above particles */
-/* float fuv[4], foffset; *//* face vertex weights and offset */
-/* float rand[3]; */
-}
-
-static void rna_def_particle(BlenderRNA *brna)
-{
- StructRNA *srna;
- PropertyRNA *prop;
- FunctionRNA *func;
-
- static EnumPropertyItem alive_items[] = {
- /*{PARS_KILLED, "KILLED", 0, "Killed", ""}, */
- {PARS_DEAD, "DEAD", 0, "Dead", ""},
- {PARS_UNBORN, "UNBORN", 0, "Unborn", ""},
- {PARS_ALIVE, "ALIVE", 0, "Alive", ""},
- {PARS_DYING, "DYING", 0, "Dying", ""},
- {0, NULL, 0, NULL, NULL}
- };
-
- srna = RNA_def_struct(brna, "Particle", NULL);
- RNA_def_struct_sdna(srna, "ParticleData");
- RNA_def_struct_ui_text(srna, "Particle", "Particle in a particle system");
-
- /* Particle State & Previous State */
- prop = RNA_def_property(srna, "location", PROP_FLOAT, PROP_TRANSLATION);
- RNA_def_property_float_sdna(prop, NULL, "state.co");
- RNA_def_property_ui_text(prop, "Particle Location", "");
-
- prop = RNA_def_property(srna, "velocity", PROP_FLOAT, PROP_VELOCITY);
- RNA_def_property_float_sdna(prop, NULL, "state.vel");
- RNA_def_property_ui_text(prop, "Particle Velocity", "");
-
- prop = RNA_def_property(srna, "angular_velocity", PROP_FLOAT, PROP_VELOCITY);
- RNA_def_property_float_sdna(prop, NULL, "state.ave");
- RNA_def_property_ui_text(prop, "Angular Velocity", "");
-
- prop = RNA_def_property(srna, "rotation", PROP_FLOAT, PROP_QUATERNION);
- RNA_def_property_float_sdna(prop, NULL, "state.rot");
- RNA_def_property_ui_text(prop, "Rotation", "");
-
- prop = RNA_def_property(srna, "prev_location", PROP_FLOAT, PROP_TRANSLATION);
- RNA_def_property_float_sdna(prop, NULL, "prev_state.co");
- RNA_def_property_ui_text(prop, "Previous Particle Location", "");
-
- prop = RNA_def_property(srna, "prev_velocity", PROP_FLOAT, PROP_VELOCITY);
- RNA_def_property_float_sdna(prop, NULL, "prev_state.vel");
- RNA_def_property_ui_text(prop, "Previous Particle Velocity", "");
-
- prop = RNA_def_property(srna, "prev_angular_velocity", PROP_FLOAT, PROP_VELOCITY);
- RNA_def_property_float_sdna(prop, NULL, "prev_state.ave");
- RNA_def_property_ui_text(prop, "Previous Angular Velocity", "");
-
- prop = RNA_def_property(srna, "prev_rotation", PROP_FLOAT, PROP_QUATERNION);
- RNA_def_property_float_sdna(prop, NULL, "prev_state.rot");
- RNA_def_property_ui_text(prop, "Previous Rotation", "");
-
- /* Hair & Keyed Keys */
-
- prop = RNA_def_property(srna, "hair_keys", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_collection_sdna(prop, NULL, "hair", "totkey");
- RNA_def_property_struct_type(prop, "ParticleHairKey");
- RNA_def_property_ui_text(prop, "Hair", "");
-
- prop = RNA_def_property(srna, "particle_keys", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_collection_sdna(prop, NULL, "keys", "totkey");
- RNA_def_property_struct_type(prop, "ParticleKey");
- RNA_def_property_ui_text(prop, "Keyed States", "");
-/* */
-/* float fuv[4], foffset; *//* coordinates on face/edge number "num" and depth along*/
-/* *//* face normal for volume emission */
-
- prop = RNA_def_property(srna, "birth_time", PROP_FLOAT, PROP_TIME);
- RNA_def_property_float_sdna(prop, NULL, "time");
-/* RNA_def_property_range(prop, lowerLimitf, upperLimitf); */
- RNA_def_property_ui_text(prop, "Birth Time", "");
-
- prop = RNA_def_property(srna, "lifetime", PROP_FLOAT, PROP_TIME);
-/* RNA_def_property_range(prop, lowerLimitf, upperLimitf); */
- RNA_def_property_ui_text(prop, "Lifetime", "");
-
- prop = RNA_def_property(srna, "die_time", PROP_FLOAT, PROP_TIME);
- RNA_def_property_float_sdna(prop, NULL, "dietime");
-/* RNA_def_property_range(prop, lowerLimitf, upperLimitf); */
- RNA_def_property_ui_text(prop, "Die Time", "");
-
- prop = RNA_def_property(srna, "size", PROP_FLOAT, PROP_NONE);
-/* RNA_def_property_range(prop, lowerLimitf, upperLimitf); */
- RNA_def_property_ui_text(prop, "Size", "");
-
-/* */
-/* int num; *//* index to vert/edge/face */
-/* int num_dmcache; *//* index to derived mesh data (face) to avoid slow lookups */
-/* int pad; */
-/* */
-/* int totkey; */
-
- /* flag */
- prop = RNA_def_property(srna, "is_exist", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", PARS_UNEXIST);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Exists", "");
-
- prop = RNA_def_property(srna, "is_visible", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", PARS_NO_DISP);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Visible", "");
-
- prop = RNA_def_property(srna, "alive_state", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "alive");
- RNA_def_property_enum_items(prop, alive_items);
- RNA_def_property_ui_text(prop, "Alive State", "");
-
-/* short rt2; */
-
-/* UVs */
- func = RNA_def_function(srna, "uv_on_emitter", "rna_Particle_uv_on_emitter");
- RNA_def_function_ui_description(func, "Obtain uv for particle on derived mesh");
- RNA_def_function_flag(func, FUNC_USE_REPORTS);
- prop = RNA_def_pointer(func, "modifier", "ParticleSystemModifier", "", "Particle modifier");
- RNA_def_property_flag(prop, PROP_REQUIRED | PROP_NEVER_NULL);
- prop = RNA_def_property(func, "uv", PROP_FLOAT, PROP_COORDS);
- RNA_def_property_array(prop, 2);
- RNA_def_property_flag(prop, PROP_THICK_WRAP);
- RNA_def_function_output(func, prop);
-}
-
-static void rna_def_particle_dupliweight(BlenderRNA *brna)
-{
- StructRNA *srna;
- PropertyRNA *prop;
-
- srna = RNA_def_struct(brna, "ParticleDupliWeight", NULL);
- RNA_def_struct_ui_text(srna, "Particle Dupliobject Weight", "Weight of a particle dupliobject in a group");
- RNA_def_struct_sdna(srna, "ParticleDupliWeight");
-
- prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
- RNA_def_property_string_funcs(prop, "rna_ParticleDupliWeight_name_get",
- "rna_ParticleDupliWeight_name_length", NULL);
- RNA_def_property_ui_text(prop, "Name", "Particle dupliobject name");
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_struct_name_property(srna, prop);
-
- prop = RNA_def_property(srna, "count", PROP_INT, PROP_UNSIGNED);
- RNA_def_property_range(prop, 0, SHRT_MAX);
- RNA_def_property_ui_text(prop, "Count",
- "The number of times this object is repeated with respect to other objects");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-}
-
-static void rna_def_fluid_settings(BlenderRNA *brna)
-{
- StructRNA *srna;
- PropertyRNA *prop;
-
- static EnumPropertyItem sph_solver_items[] = {
- {SPH_SOLVER_DDR, "DDR", 0, "Double-Density", "An artistic solver with strong surface tension effects (original)"},
- {SPH_SOLVER_CLASSICAL, "CLASSICAL", 0, "Classical", "A more physically-accurate solver"},
- {0, NULL, 0, NULL, NULL}
- };
-
- srna = RNA_def_struct(brna, "SPHFluidSettings", NULL);
- RNA_def_struct_path_func(srna, "rna_SPHFluidSettings_path");
- RNA_def_struct_ui_text(srna, "SPH Fluid Settings", "Settings for particle fluids physics");
-
- /* Fluid settings */
- prop = RNA_def_property(srna, "solver", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "solver");
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_enum_items(prop, sph_solver_items);
- RNA_def_property_ui_text(prop, "SPH Solver", "The code used to calculate internal forces on particles");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "spring_force", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "spring_k");
- RNA_def_property_range(prop, 0.0f, 100.0f);
- RNA_def_property_ui_range(prop, 0.0f, 10.0f, 1, 3);
- RNA_def_property_ui_text(prop, "Spring Force", "Spring force");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "fluid_radius", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "radius");
- RNA_def_property_range(prop, 0.0f, 20.0f);
- RNA_def_property_ui_range(prop, 0.0f, 2.0f, 1, 3);
- RNA_def_property_ui_text(prop, "Interaction Radius", "Fluid interaction radius");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "rest_length", PROP_FLOAT, PROP_NONE);
- RNA_def_property_range(prop, 0.0f, 2.0f);
- RNA_def_property_ui_text(prop, "Rest Length", "Spring rest length (factor of particle radius)");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "use_viscoelastic_springs", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", SPH_VISCOELASTIC_SPRINGS);
- RNA_def_property_ui_text(prop, "Viscoelastic Springs", "Use viscoelastic springs instead of Hooke's springs");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "use_initial_rest_length", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", SPH_CURRENT_REST_LENGTH);
- RNA_def_property_ui_text(prop, "Initial Rest Length",
- "Use the initial length as spring rest length instead of 2 * particle size");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "plasticity", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "plasticity_constant");
- RNA_def_property_range(prop, 0.0f, 100.0f);
- RNA_def_property_ui_text(prop, "Plasticity",
- "How much the spring rest length can change after the elastic limit is crossed");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "yield_ratio", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "yield_ratio");
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Elastic Limit",
- "How much the spring has to be stretched/compressed in order to change it's rest length");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "spring_frames", PROP_INT, PROP_NONE);
- RNA_def_property_range(prop, 0.0f, 100.0f);
- RNA_def_property_ui_text(prop, "Spring Frames",
- "Create springs for this number of frames since particles birth (0 is always)");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- /* Viscosity */
- prop = RNA_def_property(srna, "linear_viscosity", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "viscosity_omega");
- RNA_def_property_range(prop, 0.0f, 100.0f);
- RNA_def_property_ui_range(prop, 0.0f, 10.0f, 1, 3);
- RNA_def_property_ui_text(prop, "Viscosity", "Linear viscosity");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "stiff_viscosity", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "viscosity_beta");
- RNA_def_property_range(prop, 0.0f, 100.0f);
- RNA_def_property_ui_range(prop, 0.0f, 2.0f, 1, 3);
- RNA_def_property_ui_text(prop, "Stiff viscosity", "Creates viscosity for expanding fluid");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- /* Double density relaxation */
- prop = RNA_def_property(srna, "stiffness", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "stiffness_k");
- RNA_def_property_range(prop, 0.0f, 1000.0f);
- RNA_def_property_ui_range(prop, 0.0f, 10.0f, 1, 3);
- RNA_def_property_ui_text(prop, "Stiffness", "How incompressible the fluid is (speed of sound)");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "repulsion", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "stiffness_knear");
- RNA_def_property_range(prop, 0.0f, 100.0f);
- RNA_def_property_ui_range(prop, 0.0f, 2.0f, 1, 3);
- RNA_def_property_ui_text(prop, "Repulsion Factor",
- "How strongly the fluid tries to keep from clustering (factor of stiffness)");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "rest_density", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "rest_density");
- RNA_def_property_range(prop, 0.0f, 10000.0f);
- RNA_def_property_ui_range(prop, 0.0f, 2.0f, 1, 3);
- RNA_def_property_ui_text(prop, "Rest Density", "Fluid rest density");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- /* Buoyancy */
- prop = RNA_def_property(srna, "buoyancy", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "buoyancy");
- RNA_def_property_range(prop, 0.0f, 10.0f);
- RNA_def_property_ui_range(prop, 0.0f, 1.0f, 1, 3);
- RNA_def_property_ui_text(prop, "Buoyancy",
- "Artificial buoyancy force in negative gravity direction based on pressure "
- "differences inside the fluid");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- /* Factor flags */
-
- prop = RNA_def_property(srna, "factor_repulsion", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", SPH_FAC_REPULSION);
- RNA_def_property_ui_text(prop, "Factor Repulsion", "Repulsion is a factor of stiffness");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "use_factor_density", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", SPH_FAC_DENSITY);
- RNA_def_property_ui_text(prop, "Factor Density",
- "Density is calculated as a factor of default density (depends on particle size)");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "factor_radius", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", SPH_FAC_RADIUS);
- RNA_def_property_ui_text(prop, "Factor Radius", "Interaction radius is a factor of 4 * particle size");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "factor_stiff_viscosity", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", SPH_FAC_VISCOSITY);
- RNA_def_property_ui_text(prop, "Factor Stiff Viscosity", "Stiff viscosity is a factor of normal viscosity");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "factor_rest_length", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", SPH_FAC_REST_LENGTH);
- RNA_def_property_ui_text(prop, "Factor Rest Length", "Spring rest length is a factor of 2 * particle size");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-}
-
-static void rna_def_particle_settings_mtex(BlenderRNA *brna)
-{
- StructRNA *srna;
- PropertyRNA *prop;
-
- static EnumPropertyItem texco_items[] = {
- {TEXCO_GLOB, "GLOBAL", 0, "Global", "Use global coordinates for the texture coordinates"},
- {TEXCO_OBJECT, "OBJECT", 0, "Object", "Use linked object's coordinates for texture coordinates"},
- {TEXCO_UV, "UV", 0, "UV", "Use UV coordinates for texture coordinates"},
- {TEXCO_ORCO, "ORCO", 0, "Generated", "Use the original undeformed coordinates of the object"},
- {TEXCO_STRAND, "STRAND", 0, "Strand / Particle",
- "Use normalized strand texture coordinate (1D) or particle age (X) and trail position (Y)"},
- {0, NULL, 0, NULL, NULL}
- };
-
- static EnumPropertyItem prop_mapping_items[] = {
- {MTEX_FLAT, "FLAT", 0, "Flat", "Map X and Y coordinates directly"},
- {MTEX_CUBE, "CUBE", 0, "Cube", "Map using the normal vector"},
- {MTEX_TUBE, "TUBE", 0, "Tube", "Map with Z as central axis"},
- {MTEX_SPHERE, "SPHERE", 0, "Sphere", "Map with Z as central axis"},
- {0, NULL, 0, NULL, NULL}
- };
-
- static EnumPropertyItem prop_x_mapping_items[] = {
- {0, "NONE", 0, "None", ""},
- {1, "X", 0, "X", ""},
- {2, "Y", 0, "Y", ""},
- {3, "Z", 0, "Z", ""},
- {0, NULL, 0, NULL, NULL}
- };
-
- static EnumPropertyItem prop_y_mapping_items[] = {
- {0, "NONE", 0, "None", ""},
- {1, "X", 0, "X", ""},
- {2, "Y", 0, "Y", ""},
- {3, "Z", 0, "Z", ""},
- {0, NULL, 0, NULL, NULL}
- };
-
- static EnumPropertyItem prop_z_mapping_items[] = {
- {0, "NONE", 0, "None", ""},
- {1, "X", 0, "X", ""},
- {2, "Y", 0, "Y", ""},
- {3, "Z", 0, "Z", ""},
- {0, NULL, 0, NULL, NULL}
- };
-
- srna = RNA_def_struct(brna, "ParticleSettingsTextureSlot", "TextureSlot");
- RNA_def_struct_sdna(srna, "MTex");
- RNA_def_struct_ui_text(srna, "Particle Settings Texture Slot",
- "Texture slot for textures in a Particle Settings data-block");
-
- prop = RNA_def_property(srna, "texture_coords", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "texco");
- RNA_def_property_enum_items(prop, texco_items);
- RNA_def_property_ui_text(prop, "Texture Coordinates",
- "Texture coordinates used to map the texture onto the background");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
- RNA_def_property_pointer_sdna(prop, NULL, "object");
- RNA_def_property_struct_type(prop, "Object");
- RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Object", "Object to use for mapping with Object texture coordinates");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "uv_layer", PROP_STRING, PROP_NONE);
- RNA_def_property_string_sdna(prop, NULL, "uvname");
- RNA_def_property_ui_text(prop, "UV Map", "UV map to use for mapping with UV texture coordinates");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "mapping_x", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "projx");
- RNA_def_property_enum_items(prop, prop_x_mapping_items);
- RNA_def_property_ui_text(prop, "X Mapping", "");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "mapping_y", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "projy");
- RNA_def_property_enum_items(prop, prop_y_mapping_items);
- RNA_def_property_ui_text(prop, "Y Mapping", "");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "mapping_z", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "projz");
- RNA_def_property_enum_items(prop, prop_z_mapping_items);
- RNA_def_property_ui_text(prop, "Z Mapping", "");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "mapping", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_items(prop, prop_mapping_items);
- RNA_def_property_ui_text(prop, "Mapping", "");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- /* map to */
- prop = RNA_def_property(srna, "use_map_time", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "mapto", PAMAP_TIME);
- RNA_def_property_ui_text(prop, "Emission Time", "Affect the emission time of the particles");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "use_map_life", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "mapto", PAMAP_LIFE);
- RNA_def_property_ui_text(prop, "Life Time", "Affect the life time of the particles");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "use_map_density", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "mapto", PAMAP_DENS);
- RNA_def_property_ui_text(prop, "Density", "Affect the density of the particles");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "use_map_size", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "mapto", PAMAP_SIZE);
- RNA_def_property_ui_text(prop, "Size", "Affect the particle size");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "use_map_velocity", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "mapto", PAMAP_IVEL);
- RNA_def_property_ui_text(prop, "Initial Velocity", "Affect the particle initial velocity");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "use_map_field", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "mapto", PAMAP_FIELD);
- RNA_def_property_ui_text(prop, "Force Field", "Affect the particle force fields");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "use_map_gravity", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "mapto", PAMAP_GRAVITY);
- RNA_def_property_ui_text(prop, "Gravity", "Affect the particle gravity");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "use_map_damp", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "mapto", PAMAP_DAMP);
- RNA_def_property_ui_text(prop, "Damp", "Affect the particle velocity damping");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
-
- prop = RNA_def_property(srna, "use_map_clump", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "mapto", PAMAP_CLUMP);
- RNA_def_property_ui_text(prop, "Clump", "Affect the child clumping");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "use_map_kink_amp", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "mapto", PAMAP_KINK_AMP);
- RNA_def_property_ui_text(prop, "Kink Amplitude", "Affect the child kink amplitude");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
-
- prop = RNA_def_property(srna, "use_map_kink_freq", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "mapto", PAMAP_KINK_FREQ);
- RNA_def_property_ui_text(prop, "Kink Frequency", "Affect the child kink frequency");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
-
- prop = RNA_def_property(srna, "use_map_rough", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "mapto", PAMAP_ROUGH);
- RNA_def_property_ui_text(prop, "Rough", "Affect the child rough");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
-
- prop = RNA_def_property(srna, "use_map_length", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "mapto", PAMAP_LENGTH);
- RNA_def_property_ui_text(prop, "Length", "Affect the child hair length");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
-
-
- /* influence factors */
- prop = RNA_def_property(srna, "time_factor", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "timefac");
- RNA_def_property_ui_range(prop, 0, 1, 10, 3);
- RNA_def_property_ui_text(prop, "Emission Time Factor", "Amount texture affects particle emission time");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "life_factor", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "lifefac");
- RNA_def_property_ui_range(prop, 0, 1, 10, 3);
- RNA_def_property_ui_text(prop, "Life Time Factor", "Amount texture affects particle life time");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "density_factor", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "padensfac");
- RNA_def_property_ui_range(prop, 0, 1, 10, 3);
- RNA_def_property_ui_text(prop, "Density Factor", "Amount texture affects particle density");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "size_factor", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "sizefac");
- RNA_def_property_ui_range(prop, 0, 1, 10, 3);
- RNA_def_property_ui_text(prop, "Size Factor", "Amount texture affects physical particle size");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "velocity_factor", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "ivelfac");
- RNA_def_property_ui_range(prop, 0, 1, 10, 3);
- RNA_def_property_ui_text(prop, "Velocity Factor", "Amount texture affects particle initial velocity");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
-
- prop = RNA_def_property(srna, "field_factor", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "fieldfac");
- RNA_def_property_ui_range(prop, 0, 1, 10, 3);
- RNA_def_property_ui_text(prop, "Field Factor", "Amount texture affects particle force fields");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "gravity_factor", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "gravityfac");
- RNA_def_property_ui_range(prop, 0, 1, 10, 3);
- RNA_def_property_ui_text(prop, "Gravity Factor", "Amount texture affects particle gravity");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "damp_factor", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "dampfac");
- RNA_def_property_ui_range(prop, 0, 1, 10, 3);
- RNA_def_property_ui_text(prop, "Damp Factor", "Amount texture affects particle damping");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
-
- prop = RNA_def_property(srna, "length_factor", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "lengthfac");
- RNA_def_property_ui_range(prop, 0, 1, 10, 3);
- RNA_def_property_ui_text(prop, "Length Factor", "Amount texture affects child hair length");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
-
- prop = RNA_def_property(srna, "clump_factor", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "clumpfac");
- RNA_def_property_ui_range(prop, 0, 1, 10, 3);
- RNA_def_property_ui_text(prop, "Clump Factor", "Amount texture affects child clump");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
-
- prop = RNA_def_property(srna, "kink_amp_factor", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "kinkampfac");
- RNA_def_property_ui_range(prop, 0, 1, 10, 3);
- RNA_def_property_ui_text(prop, "Kink Amplitude Factor", "Amount texture affects child kink amplitude");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
-
- prop = RNA_def_property(srna, "kink_freq_factor", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "kinkfac");
- RNA_def_property_ui_range(prop, 0, 1, 10, 3);
- RNA_def_property_ui_text(prop, "Kink Frequency Factor", "Amount texture affects child kink frequency");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
-
- prop = RNA_def_property(srna, "rough_factor", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "roughfac");
- RNA_def_property_ui_range(prop, 0, 1, 10, 3);
- RNA_def_property_ui_text(prop, "Rough Factor", "Amount texture affects child roughness");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
-}
-
-static void rna_def_particle_settings(BlenderRNA *brna)
-{
- StructRNA *srna;
- PropertyRNA *prop;
-
- static EnumPropertyItem type_items[] = {
- {PART_EMITTER, "EMITTER", 0, "Emitter", ""},
- /*{PART_REACTOR, "REACTOR", 0, "Reactor", ""}, */
- {PART_HAIR, "HAIR", 0, "Hair", ""},
- {0, NULL, 0, NULL, NULL}
- };
-
- static EnumPropertyItem phys_type_items[] = {
- {PART_PHYS_NO, "NO", 0, "No", ""},
- {PART_PHYS_NEWTON, "NEWTON", 0, "Newtonian", ""},
- {PART_PHYS_KEYED, "KEYED", 0, "Keyed", ""},
- {PART_PHYS_BOIDS, "BOIDS", 0, "Boids", ""},
- {PART_PHYS_FLUID, "FLUID", 0, "Fluid", ""},
- {0, NULL, 0, NULL, NULL}
- };
-
- static EnumPropertyItem rot_mode_items[] = {
- {0, "NONE", 0, "None", ""},
- {PART_ROT_NOR, "NOR", 0, "Normal", ""},
- {PART_ROT_NOR_TAN, "NOR_TAN", 0, "Normal-Tangent", ""},
- {PART_ROT_VEL, "VEL", 0, "Velocity / Hair", ""},
- {PART_ROT_GLOB_X, "GLOB_X", 0, "Global X", ""},
- {PART_ROT_GLOB_Y, "GLOB_Y", 0, "Global Y", ""},
- {PART_ROT_GLOB_Z, "GLOB_Z", 0, "Global Z", ""},
- {PART_ROT_OB_X, "OB_X", 0, "Object X", ""},
- {PART_ROT_OB_Y, "OB_Y", 0, "Object Y", ""},
- {PART_ROT_OB_Z, "OB_Z", 0, "Object Z", ""},
- {0, NULL, 0, NULL, NULL}
- };
-
- static EnumPropertyItem ave_mode_items[] = {
- {0, "NONE", 0, "None", ""},
- {PART_AVE_VELOCITY, "VELOCITY", 0, "Velocity", ""},
- {PART_AVE_HORIZONTAL, "HORIZONTAL", 0, "Horizontal", ""},
- {PART_AVE_VERTICAL, "VERTICAL", 0, "Vertical", ""},
- {PART_AVE_GLOBAL_X, "GLOBAL_X", 0, "Global X", ""},
- {PART_AVE_GLOBAL_Y, "GLOBAL_Y", 0, "Global Y", ""},
- {PART_AVE_GLOBAL_Z, "GLOBAL_Z", 0, "Global Z", ""},
- {PART_AVE_RAND, "RAND", 0, "Random", ""},
- {0, NULL, 0, NULL, NULL}
- };
-
- static EnumPropertyItem react_event_items[] = {
- {PART_EVENT_DEATH, "DEATH", 0, "Death", ""},
- {PART_EVENT_COLLIDE, "COLLIDE", 0, "Collision", ""},
- {PART_EVENT_NEAR, "NEAR", 0, "Near", ""},
- {0, NULL, 0, NULL, NULL}
- };
-
- static EnumPropertyItem child_type_items[] = {
- {0, "NONE", 0, "None", ""},
- {PART_CHILD_PARTICLES, "SIMPLE", 0, "Simple", ""},
- {PART_CHILD_FACES, "INTERPOLATED", 0, "Interpolated", ""},
- {0, NULL, 0, NULL, NULL}
- };
-
- /*TODO: names, tooltips */
- static EnumPropertyItem integrator_type_items[] = {
- {PART_INT_EULER, "EULER", 0, "Euler", ""},
- {PART_INT_VERLET, "VERLET", 0, "Verlet", ""},
- {PART_INT_MIDPOINT, "MIDPOINT", 0, "Midpoint", ""},
- {PART_INT_RK4, "RK4", 0, "RK4", ""},
- {0, NULL, 0, NULL, NULL}
- };
-
- static EnumPropertyItem kink_type_items[] = {
- {PART_KINK_NO, "NO", 0, "Nothing", ""},
- {PART_KINK_CURL, "CURL", 0, "Curl", ""},
- {PART_KINK_RADIAL, "RADIAL", 0, "Radial", ""},
- {PART_KINK_WAVE, "WAVE", 0, "Wave", ""},
- {PART_KINK_BRAID, "BRAID", 0, "Braid", ""},
- {PART_KINK_SPIRAL, "SPIRAL", 0, "Spiral", ""},
- {0, NULL, 0, NULL, NULL}
- };
-
- static EnumPropertyItem bb_align_items[] = {
- {PART_BB_X, "X", 0, "X", ""},
- {PART_BB_Y, "Y", 0, "Y", ""},
- {PART_BB_Z, "Z", 0, "Z", ""},
- {PART_BB_VIEW, "VIEW", 0, "View", ""},
- {PART_BB_VEL, "VEL", 0, "Velocity", ""},
- {0, NULL, 0, NULL, NULL}
- };
-
- static EnumPropertyItem bb_anim_items[] = {
- {PART_BB_ANIM_NONE, "NONE", 0, "None", ""},
- {PART_BB_ANIM_AGE, "AGE", 0, "Age", ""},
- {PART_BB_ANIM_FRAME, "FRAME", 0, "Frame", ""},
- {PART_BB_ANIM_ANGLE, "ANGLE", 0, "Angle", ""},
- {0, NULL, 0, NULL, NULL}
- };
-
- static EnumPropertyItem bb_split_offset_items[] = {
- {PART_BB_OFF_NONE, "NONE", 0, "None", ""},
- {PART_BB_OFF_LINEAR, "LINEAR", 0, "Linear", ""},
- {PART_BB_OFF_RANDOM, "RANDOM", 0, "Random", ""},
- {0, NULL, 0, NULL, NULL}
- };
-
- static EnumPropertyItem draw_col_items[] = {
- {PART_DRAW_COL_NONE, "NONE", 0, "None", ""},
- {PART_DRAW_COL_MAT, "MATERIAL", 0, "Material", ""},
- {PART_DRAW_COL_VEL, "VELOCITY", 0, "Velocity", ""},
- {PART_DRAW_COL_ACC, "ACCELERATION", 0, "Acceleration", ""},
- {0, NULL, 0, NULL, NULL}
- };
-
- static EnumPropertyItem part_mat_items[] = {
- {0, "DUMMY", 0, "Dummy", ""},
- {0, NULL, 0, NULL, NULL}
- };
-
- srna = RNA_def_struct(brna, "ParticleSettings", "ID");
- RNA_def_struct_ui_text(srna, "Particle Settings", "Particle settings, reusable by multiple particle systems");
- RNA_def_struct_ui_icon(srna, ICON_PARTICLE_DATA);
-
- rna_def_mtex_common(brna, srna, "rna_ParticleSettings_mtex_begin", "rna_ParticleSettings_active_texture_get",
- "rna_ParticleSettings_active_texture_set", NULL, "ParticleSettingsTextureSlot",
- "ParticleSettingsTextureSlots", "rna_Particle_reset", NULL);
-
- /* fluid particle type can't be checked from the type value in rna as it's not shown in the menu */
- prop = RNA_def_property(srna, "is_fluid", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_boolean_funcs(prop, "rna_PartSettings_is_fluid_get", NULL);
- RNA_def_property_ui_text(prop, "Fluid", "Particles were created by a fluid simulation");
-
- /* flag */
- prop = RNA_def_property(srna, "use_react_start_end", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", PART_REACT_STA_END);
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_ui_text(prop, "Start/End", "Give birth to unreacted particles eventually");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "use_react_multiple", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", PART_REACT_MULTIPLE);
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_ui_text(prop, "Multi React", "React multiple times");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "regrow_hair", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", PART_HAIR_REGROW);
- RNA_def_property_ui_text(prop, "Regrow", "Regrow hair for each frame");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- prop = RNA_def_property(srna, "show_unborn", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", PART_UNBORN);
- RNA_def_property_ui_text(prop, "Unborn", "Show particles before they are emitted");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- prop = RNA_def_property(srna, "use_dead", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", PART_DIED);
- RNA_def_property_ui_text(prop, "Died", "Show particles after they have died");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- prop = RNA_def_property(srna, "use_emit_random", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", PART_TRAND);
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_ui_text(prop, "Random", "Emit in random order of elements");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "use_even_distribution", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", PART_EDISTR);
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_ui_text(prop, "Even Distribution",
- "Use even distribution from faces based on face areas or edge lengths");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "use_die_on_collision", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", PART_DIE_ON_COL);
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_ui_text(prop, "Die on hit", "Particles die when they collide with a deflector object");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "use_size_deflect", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", PART_SIZE_DEFL);
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_ui_text(prop, "Size Deflect", "Use particle's size in deflection");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "use_rotations", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", PART_ROTATIONS);
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_ui_text(prop, "Rotations", "Calculate particle rotations");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "use_dynamic_rotation", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", PART_ROT_DYN);
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_ui_text(prop, "Dynamic", "Particle rotations are affected by collisions and effectors");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "use_multiply_size_mass", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", PART_SIZEMASS);
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_ui_text(prop, "Mass from Size", "Multiply mass by particle size");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "use_advanced_hair", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", PART_HIDE_ADVANCED_HAIR);
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_ui_text(prop, "Advanced", "Use full physics calculations for growing hair");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "lock_boids_to_surface", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", PART_BOIDS_2D);
- RNA_def_property_ui_text(prop, "Boids 2D", "Constrain boids to a surface");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "use_hair_bspline", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", PART_HAIR_BSPLINE);
- RNA_def_property_ui_text(prop, "B-Spline", "Interpolate hair using B-Splines");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- prop = RNA_def_property(srna, "invert_grid", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", PART_GRID_INVERT);
- RNA_def_property_ui_text(prop, "Invert Grid", "Invert what is considered object and what is not");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "hexagonal_grid", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", PART_GRID_HEXAGONAL);
- RNA_def_property_ui_text(prop, "Hexagonal Grid", "Create the grid in a hexagonal pattern");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "apply_effector_to_children", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", PART_CHILD_EFFECT);
- RNA_def_property_ui_text(prop, "Effect Children", "Apply effectors to children");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- prop = RNA_def_property(srna, "create_long_hair_children", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", PART_CHILD_LONG_HAIR);
- RNA_def_property_ui_text(prop, "Long Hair", "Calculate children that suit long hair well");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
-
- prop = RNA_def_property(srna, "apply_guide_to_children", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", PART_CHILD_GUIDE);
- RNA_def_property_ui_text(prop, "apply_guide_to_children", "");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- prop = RNA_def_property(srna, "use_self_effect", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", PART_SELF_EFFECT);
- RNA_def_property_ui_text(prop, "Self Effect", "Particle effectors affect themselves");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
-
- prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_items(prop, type_items);
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_ui_text(prop, "Type", "Particle Type");
- RNA_def_property_update(prop, 0, "rna_Particle_change_type");
-
- prop = RNA_def_property(srna, "emit_from", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "from");
- RNA_def_property_enum_items(prop, part_reactor_from_items);
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_Particle_from_itemf");
- RNA_def_property_ui_text(prop, "Emit From", "Where to emit particles from");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "distribution", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "distr");
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_enum_items(prop, part_dist_items);
- RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_Particle_dist_itemf");
- RNA_def_property_ui_text(prop, "Distribution", "How to distribute particles on selected element");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- /* physics modes */
- prop = RNA_def_property(srna, "physics_type", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "phystype");
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_enum_items(prop, phys_type_items);
- RNA_def_property_ui_text(prop, "Physics Type", "Particle physics type");
- RNA_def_property_update(prop, 0, "rna_Particle_change_physics");
-
- prop = RNA_def_property(srna, "rotation_mode", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "rotmode");
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_enum_items(prop, rot_mode_items);
- RNA_def_property_ui_text(prop, "Orientation axis",
- "Particle orientation axis (does not affect Explode modifier's results)");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "angular_velocity_mode", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "avemode");
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_enum_items(prop, ave_mode_items);
- RNA_def_property_ui_text(prop, "Angular Velocity Axis", "What axis is used to change particle rotation with time");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "react_event", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "reactevent");
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_enum_items(prop, react_event_items);
- RNA_def_property_ui_text(prop, "React On", "The event of target particles to react on");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- /*draw flag*/
- prop = RNA_def_property(srna, "show_guide_hairs", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "draw", PART_DRAW_GUIDE_HAIRS);
- RNA_def_property_ui_text(prop, "Guide Hairs", "Show guide hairs");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- prop = RNA_def_property(srna, "show_hair_grid", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "draw", PART_DRAW_HAIR_GRID);
- RNA_def_property_ui_text(prop, "Guide Hairs", "Show hair simulation grid");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- prop = RNA_def_property(srna, "show_velocity", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "draw", PART_DRAW_VEL);
- RNA_def_property_ui_text(prop, "Velocity", "Show particle velocity");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- prop = RNA_def_property(srna, "show_size", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "draw", PART_DRAW_SIZE);
- RNA_def_property_ui_text(prop, "Size", "Show particle size");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- prop = RNA_def_property(srna, "use_render_emitter", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "draw", PART_DRAW_EMITTER);
- RNA_def_property_ui_text(prop, "Emitter", "Render emitter Object also");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- prop = RNA_def_property(srna, "show_health", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "draw", PART_DRAW_HEALTH);
- RNA_def_property_ui_text(prop, "Health", "Draw boid health");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- prop = RNA_def_property(srna, "use_absolute_path_time", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "draw", PART_ABS_PATH_TIME);
- RNA_def_property_ui_text(prop, "Absolute Path Time", "Path timing is in absolute frames");
- RNA_def_property_update(prop, 0, "rna_Particle_abspathtime_update");
-
- prop = RNA_def_property(srna, "use_parent_particles", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "draw", PART_DRAW_PARENT);
- RNA_def_property_ui_text(prop, "Parents", "Render parent particles");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- prop = RNA_def_property(srna, "show_number", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "draw", PART_DRAW_NUM);
- RNA_def_property_ui_text(prop, "Number", "Show particle number");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- prop = RNA_def_property(srna, "use_group_pick_random", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "draw", PART_DRAW_RAND_GR);
- RNA_def_property_ui_text(prop, "Pick Random", "Pick objects from group randomly");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- prop = RNA_def_property(srna, "use_group_count", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "draw", PART_DRAW_COUNT_GR);
- RNA_def_property_ui_text(prop, "Use Count", "Use object multiple times in the same group");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- prop = RNA_def_property(srna, "use_global_dupli", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "draw", PART_DRAW_GLOBAL_OB);
- RNA_def_property_ui_text(prop, "Global", "Use object's global coordinates for duplication");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- prop = RNA_def_property(srna, "use_rotation_dupli", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "draw", PART_DRAW_ROTATE_OB);
- RNA_def_property_ui_text(prop, "Rotation",
- "Use object's rotation for duplication (global x-axis is aligned "
- "particle rotation axis)");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- prop = RNA_def_property(srna, "use_scale_dupli", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_negative_sdna(prop, NULL, "draw", PART_DRAW_NO_SCALE_OB);
- RNA_def_property_ui_text(prop, "Scale", "Use object's scale for duplication");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- prop = RNA_def_property(srna, "use_render_adaptive", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "draw", PART_DRAW_REN_ADAPT);
- RNA_def_property_ui_text(prop, "Adaptive render", "Draw steps of the particle path");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- prop = RNA_def_property(srna, "use_velocity_length", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "draw", PART_DRAW_VEL_LENGTH);
- RNA_def_property_ui_text(prop, "Speed", "Multiply line length by particle speed");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- prop = RNA_def_property(srna, "use_whole_group", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "draw", PART_DRAW_WHOLE_GR);
- RNA_def_property_ui_text(prop, "Whole Group", "Use whole group at once");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- prop = RNA_def_property(srna, "use_strand_primitive", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "draw", PART_DRAW_REN_STRAND);
- RNA_def_property_ui_text(prop, "Strand render", "Use the strand primitive for rendering");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- prop = RNA_def_property(srna, "draw_method", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "draw_as");
- RNA_def_property_enum_items(prop, part_draw_as_items);
- RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_Particle_draw_as_itemf");
- RNA_def_property_ui_text(prop, "Particle Drawing", "How particles are drawn in viewport");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- prop = RNA_def_property(srna, "render_type", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "ren_as");
- RNA_def_property_enum_items(prop, part_ren_as_items);
- RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_Particle_ren_as_itemf");
- RNA_def_property_ui_text(prop, "Particle Rendering", "How particles are rendered");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- prop = RNA_def_property(srna, "draw_color", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "draw_col");
- RNA_def_property_enum_items(prop, draw_col_items);
- RNA_def_property_ui_text(prop, "Draw Color", "Draw additional particle data as a color");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- prop = RNA_def_property(srna, "draw_size", PROP_INT, PROP_PIXEL);
- RNA_def_property_range(prop, 0, 1000);
- RNA_def_property_ui_range(prop, 0, 100, 1, -1);
- RNA_def_property_ui_text(prop, "Draw Size", "Size of particles on viewport in pixels (0=default)");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- prop = RNA_def_property(srna, "child_type", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "childtype");
- RNA_def_property_enum_items(prop, child_type_items);
- RNA_def_property_ui_text(prop, "Children From", "Create child particles");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
-
- prop = RNA_def_property(srna, "draw_step", PROP_INT, PROP_NONE);
- RNA_def_property_range(prop, 0, 10);
- RNA_def_property_ui_range(prop, 0, 7, 1, -1);
- RNA_def_property_ui_text(prop, "Steps", "How many steps paths are drawn with (power of 2)");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- prop = RNA_def_property(srna, "render_step", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "ren_step");
- RNA_def_property_range(prop, 0, 20);
- RNA_def_property_ui_range(prop, 0, 9, 1, -1);
- RNA_def_property_ui_text(prop, "Render", "How many steps paths are rendered with (power of 2)");
-
- prop = RNA_def_property(srna, "hair_step", PROP_INT, PROP_NONE);
- RNA_def_property_range(prop, 2, 50);
- RNA_def_property_ui_text(prop, "Segments", "Number of hair segments");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "bending_random", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "bending_random");
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Random Bending Stiffness", "Random stiffness of hairs");
- RNA_def_property_update(prop, 0, "rna_Particle_cloth_update");
-
- /*TODO: not found in UI, readonly? */
- prop = RNA_def_property(srna, "keys_step", PROP_INT, PROP_NONE);
- RNA_def_property_range(prop, 0, SHRT_MAX); /*TODO:min,max */
- RNA_def_property_ui_text(prop, "Keys Step", "");
-
- /* adaptive path rendering */
- prop = RNA_def_property(srna, "adaptive_angle", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "adapt_angle");
- RNA_def_property_range(prop, 0, 45);
- RNA_def_property_ui_text(prop, "Degrees", "How many degrees path has to curve to make another render segment");
-
- prop = RNA_def_property(srna, "adaptive_pixel", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "adapt_pix");
- RNA_def_property_range(prop, 0, 50);
- RNA_def_property_ui_text(prop, "Pixel", "How many pixels path has to cover to make another render segment");
-
- prop = RNA_def_property(srna, "draw_percentage", PROP_INT, PROP_PERCENTAGE);
- RNA_def_property_int_sdna(prop, NULL, "disp");
- RNA_def_property_range(prop, 0, 100);
- RNA_def_property_ui_text(prop, "Display", "Percentage of particles to display in 3D view");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "material", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "omat");
- RNA_def_property_range(prop, 1, 32767);
- RNA_def_property_ui_text(prop, "Material Index", "Index of material slot used for rendering particles");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- prop = RNA_def_property(srna, "material_slot", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "omat");
- RNA_def_property_enum_items(prop, part_mat_items);
- RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_Particle_Material_itemf");
- RNA_def_property_ui_text(prop, "Material Slot", "Material slot used for rendering particles");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- prop = RNA_def_property(srna, "integrator", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_items(prop, integrator_type_items);
- RNA_def_property_ui_text(prop, "Integration",
- "Algorithm used to calculate physics, from the fastest to the "
- "most stable/accurate: Midpoint, Euler, Verlet, RK4 (Old)");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "kink", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_items(prop, kink_type_items);
- RNA_def_property_ui_text(prop, "Kink", "Type of periodic offset on the path");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
-
- prop = RNA_def_property(srna, "kink_axis", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_items(prop, rna_enum_axis_xyz_items);
- RNA_def_property_ui_text(prop, "Axis", "Which axis to use for offset");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
-
- /* billboards */
- prop = RNA_def_property(srna, "lock_billboard", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "draw", PART_DRAW_BB_LOCK);
- RNA_def_property_ui_text(prop, "Lock Billboard", "Lock the billboards align axis");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- prop = RNA_def_property(srna, "billboard_align", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "bb_align");
- RNA_def_property_enum_items(prop, bb_align_items);
- RNA_def_property_ui_text(prop, "Align to", "In respect to what the billboards are aligned");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- prop = RNA_def_property(srna, "billboard_uv_split", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "bb_uv_split");
- RNA_def_property_range(prop, 1, 100);
- RNA_def_property_ui_range(prop, 1, 10, 1, -1);
- RNA_def_property_ui_text(prop, "UV Split", "Number of rows/columns to split UV coordinates for billboards");
-
- prop = RNA_def_property(srna, "billboard_animation", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "bb_anim");
- RNA_def_property_enum_items(prop, bb_anim_items);
- RNA_def_property_ui_text(prop, "Animate", "How to animate billboard textures");
-
- prop = RNA_def_property(srna, "billboard_offset_split", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "bb_split_offset");
- RNA_def_property_enum_items(prop, bb_split_offset_items);
- RNA_def_property_ui_text(prop, "Offset", "How to offset billboard textures");
-
- prop = RNA_def_property(srna, "billboard_tilt", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "bb_tilt");
- RNA_def_property_range(prop, -1.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Tilt", "Tilt of the billboards");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- prop = RNA_def_property(srna, "color_maximum", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "color_vec_max");
- RNA_def_property_range(prop, 0.01f, 100.0f);
- RNA_def_property_ui_text(prop, "Color Maximum", "Maximum length of the particle color vector");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- prop = RNA_def_property(srna, "billboard_tilt_random", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "bb_rand_tilt");
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Random Tilt", "Random tilt of the billboards");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- prop = RNA_def_property(srna, "billboard_offset", PROP_FLOAT, PROP_TRANSLATION);
- RNA_def_property_float_sdna(prop, NULL, "bb_offset");
- RNA_def_property_array(prop, 2);
- RNA_def_property_range(prop, -100.0f, 100.0f);
- RNA_def_property_ui_range(prop, -1.0, 1.0, 0.1, 3);
- RNA_def_property_ui_text(prop, "Billboard Offset", "");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- prop = RNA_def_property(srna, "billboard_size", PROP_FLOAT, PROP_FACTOR);
- RNA_def_property_float_sdna(prop, NULL, "bb_size");
- RNA_def_property_array(prop, 2);
- RNA_def_property_range(prop, 0.001f, 10.0f);
- RNA_def_property_ui_text(prop, "Billboard Scale", "Scale billboards relative to particle size");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- prop = RNA_def_property(srna, "billboard_velocity_head", PROP_FLOAT, PROP_FACTOR);
- RNA_def_property_float_sdna(prop, NULL, "bb_vel_head");
- RNA_def_property_range(prop, 0.0f, 10.0f);
- RNA_def_property_ui_text(prop, "Billboard Velocity Head", "Scale billboards by velocity");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- prop = RNA_def_property(srna, "billboard_velocity_tail", PROP_FLOAT, PROP_FACTOR);
- RNA_def_property_float_sdna(prop, NULL, "bb_vel_tail");
- RNA_def_property_range(prop, 0.0f, 10.0f);
- RNA_def_property_ui_text(prop, "Billboard Velocity Tail", "Scale billboards by velocity");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- /* simplification */
- prop = RNA_def_property(srna, "use_simplify", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "simplify_flag", PART_SIMPLIFY_ENABLE);
- RNA_def_property_ui_text(prop, "Child Simplification",
- "Remove child strands as the object becomes smaller on the screen");
-
- prop = RNA_def_property(srna, "use_simplify_viewport", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "simplify_flag", PART_SIMPLIFY_VIEWPORT);
- RNA_def_property_ui_text(prop, "Viewport", "");
-
- prop = RNA_def_property(srna, "simplify_refsize", PROP_INT, PROP_PIXEL);
- RNA_def_property_int_sdna(prop, NULL, "simplify_refsize");
- RNA_def_property_range(prop, 1, SHRT_MAX);
- RNA_def_property_ui_text(prop, "Reference Size", "Reference size in pixels, after which simplification begins");
-
- prop = RNA_def_property(srna, "simplify_rate", PROP_FLOAT, PROP_NONE);
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Rate", "Speed of simplification");
-
- prop = RNA_def_property(srna, "simplify_transition", PROP_FLOAT, PROP_NONE);
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Transition", "Transition period for fading out strands");
-
- prop = RNA_def_property(srna, "simplify_viewport", PROP_FLOAT, PROP_NONE);
- RNA_def_property_range(prop, 0.0f, 0.999f);
- RNA_def_property_ui_text(prop, "Rate", "Speed of Simplification");
-
- /* general values */
- prop = RNA_def_property(srna, "frame_start", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "sta"); /*optional if prop names are the same */
- RNA_def_property_range(prop, MINAFRAMEF, MAXFRAMEF);
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_float_funcs(prop, NULL, "rna_PartSettings_start_set", NULL);
- RNA_def_property_ui_text(prop, "Start", "Frame number to start emitting particles");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "frame_end", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "end");
- RNA_def_property_range(prop, MINAFRAMEF, MAXFRAMEF);
-
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_float_funcs(prop, NULL, "rna_PartSettings_end_set", NULL);
- RNA_def_property_ui_text(prop, "End", "Frame number to stop emitting particles");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "lifetime", PROP_FLOAT, PROP_TIME);
- RNA_def_property_range(prop, 1.0f, MAXFRAMEF);
- RNA_def_property_ui_text(prop, "Lifetime", "Life span of the particles");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "lifetime_random", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "randlife");
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Random", "Give the particle life a random variation");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "time_tweak", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "timetweak");
- RNA_def_property_range(prop, 0.0f, 100.0f);
- RNA_def_property_ui_range(prop, 0, 10, 1, 3);
- RNA_def_property_ui_text(prop, "Tweak", "A multiplier for physics timestep (1.0 means one frame = 1/25 seconds)");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "timestep", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_funcs(prop, "rna_PartSettings_timestep_get", "rna_PartSetings_timestep_set", NULL);
- RNA_def_property_range(prop, 0.0001, 100.0);
- RNA_def_property_ui_range(prop, 0.01, 10, 1, 3);
- RNA_def_property_ui_text(prop, "Timestep", "The simulation timestep per frame (seconds per frame)");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "use_adaptive_subframes", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "time_flag", PART_TIME_AUTOSF);
- RNA_def_property_ui_text(prop, "Automatic Subframes", "Automatically set the number of subframes");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "subframes", PROP_INT, PROP_NONE);
- RNA_def_property_range(prop, 0, 1000);
- RNA_def_property_ui_text(prop, "Subframes",
- "Subframes to simulate for improved stability and finer granularity simulations "
- "(dt = timestep / (subframes + 1))");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "courant_target", PROP_FLOAT, PROP_NONE);
- RNA_def_property_range(prop, 0.0001, 10);
- RNA_def_property_float_default(prop, 0.1);
- RNA_def_property_ui_text(prop, "Adaptive Subframe Threshold",
- "The relative distance a particle can move before requiring more subframes "
- "(target Courant number); 0.01-0.3 is the recommended range");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "jitter_factor", PROP_FLOAT, PROP_NONE);
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_float_sdna(prop, NULL, "jitfac");
- RNA_def_property_range(prop, 0.0f, 2.0f);
- RNA_def_property_ui_text(prop, "Amount", "Amount of jitter applied to the sampling");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "effect_hair", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "eff_hair");
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Stiffness", "Hair stiffness for effectors");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- prop = RNA_def_property(srna, "count", PROP_INT, PROP_UNSIGNED);
- RNA_def_property_int_sdna(prop, NULL, "totpart");
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- /* This limit is for those freaks who have the machine power to handle it. */
- /* 10M particles take around 2.2 Gb of memory / disk space in saved file and */
- /* each cached frame takes around 0.5 Gb of memory / disk space depending on cache mode. */
- RNA_def_property_range(prop, 0, 10000000);
- RNA_def_property_ui_range(prop, 0, 100000, 1, -1);
- RNA_def_property_ui_text(prop, "Number", "Total number of particles");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "userjit", PROP_INT, PROP_UNSIGNED); /*TODO: can we get a better name for userjit? */
- RNA_def_property_int_sdna(prop, NULL, "userjit");
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_range(prop, 0, 1000);
- RNA_def_property_ui_text(prop, "P/F", "Emission locations / face (0 = automatic)");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "grid_resolution", PROP_INT, PROP_UNSIGNED);
- RNA_def_property_int_sdna(prop, NULL, "grid_res");
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_range(prop, 1, 250); /* ~15M particles in a cube (ouch!), but could be very usable in a plane */
- RNA_def_property_ui_range(prop, 1, 50, 1, -1); /* ~100k particles in a cube */
- RNA_def_property_ui_text(prop, "Resolution", "The resolution of the particle grid");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "grid_random", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "grid_rand");
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Grid Randomness", "Add random offset to the grid locations");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "effector_amount", PROP_INT, PROP_UNSIGNED);
- /* in theory PROP_ANIMATABLE perhaps should be cleared, but animating this can give some interesting results! */
- RNA_def_property_range(prop, 0, 10000); /* 10000 effectors will bel SLOW, but who knows */
- RNA_def_property_ui_range(prop, 0, 100, 1, -1);
- RNA_def_property_ui_text(prop, "Effector Number", "How many particles are effectors (0 is all particles)");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- /* initial velocity factors */
- prop = RNA_def_property(srna, "normal_factor", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "normfac"); /*optional if prop names are the same */
- RNA_def_property_range(prop, -1000.0f, 1000.0f);
- RNA_def_property_ui_range(prop, 0, 100, 1, 3);
- RNA_def_property_ui_text(prop, "Normal", "Let the surface normal give the particle a starting velocity");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "object_factor", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "obfac");
- RNA_def_property_range(prop, -200.0f, 200.0f);
- RNA_def_property_ui_range(prop, -1.0f, 1.0f, 0.1, 3);
- RNA_def_property_ui_text(prop, "Object", "Let the object give the particle a starting velocity");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "factor_random", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "randfac"); /*optional if prop names are the same */
- RNA_def_property_range(prop, 0.0f, 200.0f);
- RNA_def_property_ui_range(prop, 0, 100, 1, 3);
- RNA_def_property_ui_text(prop, "Random", "Give the starting velocity a random variation");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "particle_factor", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "partfac");
- RNA_def_property_range(prop, -200.0f, 200.0f);
- RNA_def_property_ui_range(prop, -1.0f, 1.0f, 0.1, 3);
- RNA_def_property_ui_text(prop, "Particle", "Let the target particle give the particle a starting velocity");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "tangent_factor", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "tanfac");
- RNA_def_property_range(prop, -1000.0f, 1000.0f);
- RNA_def_property_ui_range(prop, -100, 100, 1, 2);
- RNA_def_property_ui_text(prop, "Tangent", "Let the surface tangent give the particle a starting velocity");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "tangent_phase", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "tanphase");
- RNA_def_property_range(prop, -1.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Rot", "Rotate the surface tangent");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "reactor_factor", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "reactfac");
- RNA_def_property_range(prop, -10.0f, 10.0f);
- RNA_def_property_ui_text(prop, "Reactor",
- "Let the vector away from the target particle's location give the particle "
- "a starting velocity");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "object_align_factor", PROP_FLOAT, PROP_VELOCITY);
- RNA_def_property_float_sdna(prop, NULL, "ob_vel");
- RNA_def_property_array(prop, 3);
- RNA_def_property_range(prop, -200.0f, 200.0f);
- RNA_def_property_ui_range(prop, -100, 100, 1, 3);
- RNA_def_property_ui_text(prop, "Object Aligned",
- "Let the emitter object orientation give the particle a starting velocity");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "angular_velocity_factor", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "avefac");
- RNA_def_property_range(prop, -200.0f, 200.0f);
- RNA_def_property_ui_range(prop, -100, 100, 10, 3);
- RNA_def_property_ui_text(prop, "Angular Velocity", "Angular velocity amount (in radians per second)");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "phase_factor", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "phasefac");
- RNA_def_property_range(prop, -1.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Phase", "Rotation around the chosen orientation axis");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "rotation_factor_random", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "randrotfac");
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Random Orientation", "Randomize particle orientation");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "phase_factor_random", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "randphasefac");
- RNA_def_property_range(prop, 0.0f, 2.0f);
- RNA_def_property_ui_text(prop, "Random Phase", "Randomize rotation around the chosen orientation axis");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "hair_length", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_funcs(prop, "rna_PartSetting_hairlength_get", "rna_PartSetting_hairlength_set", NULL);
- RNA_def_property_range(prop, 0.0f, 1000.0f);
- RNA_def_property_ui_range(prop, 0.0f, 10.0f, 1, 3);
- RNA_def_property_ui_text(prop, "Hair Length", "Length of the hair");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- /* physical properties */
- prop = RNA_def_property(srna, "mass", PROP_FLOAT, PROP_NONE);
- RNA_def_property_range(prop, 0.00000001f, 100000.0f);
- RNA_def_property_ui_range(prop, 0.01, 100, 1, 3);
- RNA_def_property_ui_text(prop, "Mass", "Mass of the particles");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "particle_size", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "size");
- RNA_def_property_range(prop, 0.001f, 100000.0f);
- RNA_def_property_ui_range(prop, 0.01, 100, 1, 3);
- RNA_def_property_ui_text(prop, "Size", "The size of the particles");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "size_random", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "randsize");
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Random Size", "Give the particle size a random variation");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "collision_group", PROP_POINTER, PROP_NONE);
- RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Collision Group", "Limit colliders to this Group");
- RNA_def_property_update(prop, 0, "rna_Particle_reset_dependency");
-
- /* global physical properties */
- prop = RNA_def_property(srna, "drag_factor", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "dragfac");
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Drag", "Amount of air-drag");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "brownian_factor", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "brownfac");
- RNA_def_property_range(prop, 0.0f, 200.0f);
- RNA_def_property_ui_range(prop, 0, 20, 1, 3);
- RNA_def_property_ui_text(prop, "Brownian", "Amount of random, erratic particle movement");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "damping", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "dampfac");
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Damp", "Amount of damping");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- /* random length */
- prop = RNA_def_property(srna, "length_random", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "randlength");
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Random Length", "Give path length a random variation");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- /* children */
- prop = RNA_def_property(srna, "child_nbr", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "child_nbr"); /*optional if prop names are the same */
- RNA_def_property_range(prop, 0, 100000);
- RNA_def_property_ui_range(prop, 0, 1000, 1, -1);
- RNA_def_property_ui_text(prop, "Children Per Parent", "Number of children/parent");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
-
- prop = RNA_def_property(srna, "rendered_child_count", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "ren_child_nbr");
- RNA_def_property_range(prop, 0, 100000);
- RNA_def_property_ui_range(prop, 0, 10000, 1, -1);
- RNA_def_property_ui_text(prop, "Rendered Children", "Number of children/parent for rendering");
-
- prop = RNA_def_property(srna, "virtual_parents", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "parents");
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Virtual Parents", "Relative amount of virtual parents");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
-
- prop = RNA_def_property(srna, "child_size", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "childsize");
- RNA_def_property_range(prop, 0.001f, 100000.0f);
- RNA_def_property_ui_range(prop, 0.01f, 100.0f, 0.1, 3);
- RNA_def_property_ui_text(prop, "Child Size", "A multiplier for the child particle size");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
-
- prop = RNA_def_property(srna, "child_size_random", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "childrandsize");
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Random Child Size", "Random variation to the size of the child particles");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
-
- prop = RNA_def_property(srna, "child_radius", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "childrad");
- RNA_def_property_range(prop, 0.0f, 10.0f);
- RNA_def_property_ui_text(prop, "Child Radius", "Radius of children around parent");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
-
- prop = RNA_def_property(srna, "child_roundness", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "childflat");
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Child Roundness", "Roundness of children around parent");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
-
- /* clumping */
- prop = RNA_def_property(srna, "clump_factor", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "clumpfac");
- RNA_def_property_range(prop, -1.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Clump", "Amount of clumping");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
-
- prop = RNA_def_property(srna, "clump_shape", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "clumppow");
- RNA_def_property_range(prop, -0.999f, 0.999f);
- RNA_def_property_ui_text(prop, "Shape", "Shape of clumping");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
-
- prop = RNA_def_property(srna, "use_clump_curve", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "child_flag", PART_CHILD_USE_CLUMP_CURVE);
- RNA_def_property_ui_text(prop, "Use Clump Curve", "Use a curve to define clump tapering");
- RNA_def_property_update(prop, 0, "rna_ParticleSettings_use_clump_curve_update");
-
- prop = RNA_def_property(srna, "clump_curve", PROP_POINTER, PROP_NONE);
- RNA_def_property_pointer_sdna(prop, NULL, "clumpcurve");
- RNA_def_property_struct_type(prop, "CurveMapping");
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Clump Curve", "Curve defining clump tapering");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
-
- prop = RNA_def_property(srna, "use_clump_noise", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "child_flag", PART_CHILD_USE_CLUMP_NOISE);
- RNA_def_property_ui_text(prop, "Use Clump Noise", "Create random clumps around the parent");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
-
- prop = RNA_def_property(srna, "clump_noise_size", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "clump_noise_size");
- RNA_def_property_range(prop, 0.00001f, 100000.0f);
- RNA_def_property_ui_range(prop, 0.01f, 10.0f, 0.1f, 3);
- RNA_def_property_ui_text(prop, "Clump Noise Size", "Size of clump noise");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
-
- /* kink */
- prop = RNA_def_property(srna, "kink_amplitude", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "kink_amp");
- RNA_def_property_range(prop, -100000.0f, 100000.0f);
- RNA_def_property_ui_range(prop, -10.0f, 10.0f, 0.1, 3);
- RNA_def_property_ui_text(prop, "Amplitude", "The amplitude of the offset");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
-
- prop = RNA_def_property(srna, "kink_amplitude_clump", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "kink_amp_clump");
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Amplitude Clump", "How much clump affects kink amplitude");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
-
- prop = RNA_def_property(srna, "kink_amplitude_random", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "kink_amp_random");
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Amplitude Random", "Random variation of the amplitude");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
-
- prop = RNA_def_property(srna, "kink_frequency", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "kink_freq");
- RNA_def_property_range(prop, -100000.0f, 100000.0f);
- RNA_def_property_ui_range(prop, -10.0f, 10.0f, 0.1, 3);
- RNA_def_property_ui_text(prop, "Frequency", "The frequency of the offset (1/total length)");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
-
- prop = RNA_def_property(srna, "kink_shape", PROP_FLOAT, PROP_NONE);
- RNA_def_property_range(prop, -0.999f, 0.999f);
- RNA_def_property_ui_text(prop, "Shape", "Adjust the offset to the beginning/end");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
-
- prop = RNA_def_property(srna, "kink_flat", PROP_FLOAT, PROP_NONE);
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Flatness", "How flat the hairs are");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
-
- prop = RNA_def_property(srna, "kink_extra_steps", PROP_INT, PROP_NONE);
- RNA_def_property_range(prop, 1, INT_MAX);
- RNA_def_property_ui_range(prop, 1, 100, 1, -1);
- RNA_def_property_ui_text(prop, "Extra Steps", "Extra steps for resolution of special kink features");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
-
- prop = RNA_def_property(srna, "kink_axis_random", PROP_FLOAT, PROP_NONE);
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Axis Random", "Random variation of the orientation");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
-
- /* rough */
- prop = RNA_def_property(srna, "roughness_1", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "rough1");
- RNA_def_property_range(prop, 0.0f, 100000.0f);
- RNA_def_property_ui_range(prop, 0.0f, 10.0f, 0.1, 3);
- RNA_def_property_ui_text(prop, "Rough1", "Amount of location dependent rough");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
-
- prop = RNA_def_property(srna, "roughness_1_size", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "rough1_size");
- RNA_def_property_range(prop, 0.01f, 100000.0f);
- RNA_def_property_ui_range(prop, 0.01f, 10.0f, 0.1, 3);
- RNA_def_property_ui_text(prop, "Size1", "Size of location dependent rough");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
-
- prop = RNA_def_property(srna, "roughness_2", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "rough2");
- RNA_def_property_range(prop, 0.0f, 100000.0f);
- RNA_def_property_ui_range(prop, 0.0f, 10.0f, 0.1, 3);
- RNA_def_property_ui_text(prop, "Rough2", "Amount of random rough");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
-
- prop = RNA_def_property(srna, "roughness_2_size", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "rough2_size");
- RNA_def_property_range(prop, 0.01f, 100000.0f);
- RNA_def_property_ui_range(prop, 0.01f, 10.0f, 0.1, 3);
- RNA_def_property_ui_text(prop, "Size2", "Size of random rough");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
-
- prop = RNA_def_property(srna, "roughness_2_threshold", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "rough2_thres");
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Threshold", "Amount of particles left untouched by random rough");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
-
- prop = RNA_def_property(srna, "roughness_endpoint", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "rough_end");
- RNA_def_property_range(prop, 0.0f, 100000.0f);
- RNA_def_property_ui_range(prop, 0.0f, 10.0f, 0.1, 3);
- RNA_def_property_ui_text(prop, "Rough Endpoint", "Amount of end point rough");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
-
- prop = RNA_def_property(srna, "roughness_end_shape", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "rough_end_shape");
- RNA_def_property_range(prop, 0.0f, 10.0f);
- RNA_def_property_ui_text(prop, "Shape", "Shape of end point rough");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
-
- prop = RNA_def_property(srna, "use_roughness_curve", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "child_flag", PART_CHILD_USE_ROUGH_CURVE);
- RNA_def_property_ui_text(prop, "Use Roughness Curve", "Use a curve to define roughness");
- RNA_def_property_update(prop, 0, "rna_ParticleSettings_use_roughness_curve_update");
-
- prop = RNA_def_property(srna, "roughness_curve", PROP_POINTER, PROP_NONE);
- RNA_def_property_pointer_sdna(prop, NULL, "roughcurve");
- RNA_def_property_struct_type(prop, "CurveMapping");
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Roughness Curve", "Curve defining roughness");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
-
- prop = RNA_def_property(srna, "child_length", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "clength");
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Length", "Length of child paths");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
-
- prop = RNA_def_property(srna, "child_length_threshold", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "clength_thres");
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Threshold", "Amount of particles left untouched by child path length");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
-
- /* parting */
- prop = RNA_def_property(srna, "child_parting_factor", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "parting_fac");
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Parting Factor", "Create parting in the children based on parent strands");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
-
- prop = RNA_def_property(srna, "child_parting_min", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "parting_min");
- RNA_def_property_range(prop, 0.0f, 180.0f);
- RNA_def_property_ui_text(prop, "Parting Minimum",
- "Minimum root to tip angle (tip distance/root distance for long hair)");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
-
- prop = RNA_def_property(srna, "child_parting_max", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "parting_max");
- RNA_def_property_range(prop, 0.0f, 180.0f);
- RNA_def_property_ui_text(prop, "Parting Maximum",
- "Maximum root to tip angle (tip distance/root distance for long hair)");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
-
- /* branching */
- prop = RNA_def_property(srna, "branch_threshold", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "branch_thres");
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Threshold", "Threshold of branching");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
-
- /* drawing stuff */
- prop = RNA_def_property(srna, "line_length_tail", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_funcs(prop, "rna_PartSetting_linelentail_get", "rna_PartSetting_linelentail_set", NULL);
- RNA_def_property_range(prop, 0.0f, 100000.0f);
- RNA_def_property_ui_range(prop, 0.0f, 10.0f, 0.1, 3);
- RNA_def_property_ui_text(prop, "Tail", "Length of the line's tail");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- prop = RNA_def_property(srna, "line_length_head", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_funcs(prop, "rna_PartSetting_linelenhead_get", "rna_PartSetting_linelenhead_set", NULL);
- RNA_def_property_range(prop, 0.0f, 100000.0f);
- RNA_def_property_ui_range(prop, 0.0f, 10.0f, 0.1, 3);
- RNA_def_property_ui_text(prop, "Head", "Length of the line's head");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- prop = RNA_def_property(srna, "path_start", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "path_start");
- RNA_def_property_float_funcs(prop, NULL, NULL, "rna_PartSetting_pathstartend_range");
- RNA_def_property_ui_text(prop, "Path Start", "Starting time of drawn path");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- prop = RNA_def_property(srna, "path_end", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "path_end");
- RNA_def_property_float_funcs(prop, NULL, NULL, "rna_PartSetting_pathstartend_range");
- RNA_def_property_ui_text(prop, "Path End", "End time of drawn path");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- prop = RNA_def_property(srna, "trail_count", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "trail_count");
- RNA_def_property_range(prop, 1, 100000);
- RNA_def_property_ui_range(prop, 1, 100, 1, -1);
- RNA_def_property_ui_text(prop, "Trail Count", "Number of trail particles");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- /* keyed particles */
- prop = RNA_def_property(srna, "keyed_loops", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "keyed_loops");
- RNA_def_property_range(prop, 1.0f, 10000.0f);
- RNA_def_property_ui_range(prop, 1.0f, 100.0f, 0.1, 3);
- RNA_def_property_ui_text(prop, "Loop count", "Number of times the keys are looped");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- /* modified dm support */
- prop = RNA_def_property(srna, "use_modifier_stack", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "use_modifier_stack", 0);
- RNA_def_property_ui_text(prop, "Use Modifier Stack", "Emit particles from mesh with modifiers applied "
- "(must use same subsurf level for viewport and render for correct results)");
- RNA_def_property_update(prop, 0, "rna_Particle_change_type");
-
- /* draw objects & groups */
- prop = RNA_def_property(srna, "dupli_group", PROP_POINTER, PROP_NONE);
- RNA_def_property_pointer_sdna(prop, NULL, "dup_group");
- RNA_def_property_struct_type(prop, "Group");
- RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Dupli Group", "Show Objects in this Group in place of particles");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- prop = RNA_def_property(srna, "dupli_weights", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_collection_sdna(prop, NULL, "dupliweights", NULL);
- RNA_def_property_struct_type(prop, "ParticleDupliWeight");
- RNA_def_property_ui_text(prop, "Dupli Group Weights", "Weights for all of the objects in the dupli group");
-
- prop = RNA_def_property(srna, "active_dupliweight", PROP_POINTER, PROP_NONE);
- RNA_def_property_struct_type(prop, "ParticleDupliWeight");
- RNA_def_property_pointer_funcs(prop, "rna_ParticleDupliWeight_active_get", NULL, NULL, NULL);
- RNA_def_property_ui_text(prop, "Active Dupli Object", "");
-
- prop = RNA_def_property(srna, "active_dupliweight_index", PROP_INT, PROP_UNSIGNED);
- RNA_def_property_int_funcs(prop, "rna_ParticleDupliWeight_active_index_get",
- "rna_ParticleDupliWeight_active_index_set",
- "rna_ParticleDupliWeight_active_index_range");
- RNA_def_property_ui_text(prop, "Active Dupli Object Index", "");
-
- prop = RNA_def_property(srna, "dupli_object", PROP_POINTER, PROP_NONE);
- RNA_def_property_pointer_sdna(prop, NULL, "dup_ob");
- RNA_def_property_struct_type(prop, "Object");
- RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Dupli Object", "Show this Object in place of particles");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_dependency");
-
- prop = RNA_def_property(srna, "billboard_object", PROP_POINTER, PROP_NONE);
- RNA_def_property_pointer_sdna(prop, NULL, "bb_ob");
- RNA_def_property_struct_type(prop, "Object");
- RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Billboard Object", "Billboards face this object (default is active camera)");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- /* boids */
- prop = RNA_def_property(srna, "boids", PROP_POINTER, PROP_NONE);
- RNA_def_property_struct_type(prop, "BoidSettings");
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Boid Settings", "");
-
- /* Fluid particles */
- prop = RNA_def_property(srna, "fluid", PROP_POINTER, PROP_NONE);
- RNA_def_property_struct_type(prop, "SPHFluidSettings");
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "SPH Fluid Settings", "");
-
- /* Effector weights */
- prop = RNA_def_property(srna, "effector_weights", PROP_POINTER, PROP_NONE);
- RNA_def_property_struct_type(prop, "EffectorWeights");
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Effector Weights", "");
-
- /* animation here? */
- rna_def_animdata_common(srna);
-
- prop = RNA_def_property(srna, "force_field_1", PROP_POINTER, PROP_NONE);
- RNA_def_property_pointer_sdna(prop, NULL, "pd");
- RNA_def_property_struct_type(prop, "FieldSettings");
- RNA_def_property_pointer_funcs(prop, "rna_Particle_field1_get", NULL, NULL, NULL);
- RNA_def_property_ui_text(prop, "Force Field 1", "");
-
- prop = RNA_def_property(srna, "force_field_2", PROP_POINTER, PROP_NONE);
- RNA_def_property_pointer_sdna(prop, NULL, "pd2");
- RNA_def_property_struct_type(prop, "FieldSettings");
- RNA_def_property_pointer_funcs(prop, "rna_Particle_field2_get", NULL, NULL, NULL);
- RNA_def_property_ui_text(prop, "Force Field 2", "");
-}
-
-static void rna_def_particle_target(BlenderRNA *brna)
-{
- StructRNA *srna;
- PropertyRNA *prop;
-
- static EnumPropertyItem mode_items[] = {
- {PTARGET_MODE_FRIEND, "FRIEND", 0, "Friend", ""},
- {PTARGET_MODE_NEUTRAL, "NEUTRAL", 0, "Neutral", ""},
- {PTARGET_MODE_ENEMY, "ENEMY", 0, "Enemy", ""},
- {0, NULL, 0, NULL, NULL}
- };
-
-
- srna = RNA_def_struct(brna, "ParticleTarget", NULL);
- RNA_def_struct_ui_text(srna, "Particle Target", "Target particle system");
-
- prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
- RNA_def_property_string_funcs(prop, "rna_ParticleTarget_name_get", "rna_ParticleTarget_name_length", NULL);
- RNA_def_property_ui_text(prop, "Name", "Particle target name");
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_struct_name_property(srna, prop);
-
- prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
- RNA_def_property_pointer_sdna(prop, NULL, "ob");
- RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Target Object",
- "The object that has the target particle system (empty if same object)");
- RNA_def_property_update(prop, 0, "rna_Particle_target_reset");
-
- prop = RNA_def_property(srna, "system", PROP_INT, PROP_UNSIGNED);
- RNA_def_property_int_sdna(prop, NULL, "psys");
- RNA_def_property_range(prop, 1, INT_MAX);
- RNA_def_property_ui_text(prop, "Target Particle System", "The index of particle system on the target object");
- RNA_def_property_update(prop, 0, "rna_Particle_target_reset");
-
- prop = RNA_def_property(srna, "time", PROP_FLOAT, PROP_TIME);
- RNA_def_property_float_sdna(prop, NULL, "time");
- RNA_def_property_range(prop, 0.0, 30000.0f); /*TODO: replace 30000 with MAXFRAMEF when available in 2.5 */
- RNA_def_property_ui_text(prop, "Time", "");
- RNA_def_property_update(prop, 0, "rna_Particle_target_redo");
-
- prop = RNA_def_property(srna, "duration", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "duration");
- RNA_def_property_range(prop, 0.0, 30000.0f); /*TODO: replace 30000 with MAXFRAMEF when available in 2.5 */
- RNA_def_property_ui_text(prop, "Duration", "");
- RNA_def_property_update(prop, 0, "rna_Particle_target_redo");
-
- prop = RNA_def_property(srna, "is_valid", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", PTARGET_VALID);
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_ui_text(prop, "Valid", "Keyed particles target is valid");
-
- prop = RNA_def_property(srna, "alliance", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "mode");
- RNA_def_property_enum_items(prop, mode_items);
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_ui_text(prop, "Mode", "");
- RNA_def_property_update(prop, 0, "rna_Particle_target_reset");
-
-}
-static void rna_def_particle_system(BlenderRNA *brna)
-{
- StructRNA *srna;
- PropertyRNA *prop;
- FunctionRNA *func;
-
- static EnumPropertyItem resolution_items[] = {
- {eModifierMode_Realtime, "PREVIEW", 0, "Preview", "Apply modifier preview settings"},
- {eModifierMode_Render, "RENDER", 0, "Render", "Apply modifier render settings"},
- {0, NULL, 0, NULL, NULL}
- };
-
- srna = RNA_def_struct(brna, "ParticleSystem", NULL);
- RNA_def_struct_ui_text(srna, "Particle System", "Particle system in an object");
- RNA_def_struct_ui_icon(srna, ICON_PARTICLE_DATA);
-
- prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
- RNA_def_property_ui_text(prop, "Name", "Particle system name");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER | NA_RENAME, NULL);
- RNA_def_property_string_funcs(prop, NULL, NULL, "rna_ParticleSystem_name_set");
- RNA_def_struct_name_property(srna, prop);
-
- /* access to particle settings is redirected through functions */
- /* to allow proper id-buttons functionality */
- prop = RNA_def_property(srna, "settings", PROP_POINTER, PROP_NONE);
- /*RNA_def_property_pointer_sdna(prop, NULL, "part"); */
- RNA_def_property_struct_type(prop, "ParticleSettings");
- RNA_def_property_flag(prop, PROP_EDITABLE | PROP_NEVER_NULL);
- RNA_def_property_pointer_funcs(prop, "rna_particle_settings_get", "rna_particle_settings_set", NULL, NULL);
- RNA_def_property_ui_text(prop, "Settings", "Particle system settings");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "particles", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_collection_sdna(prop, NULL, "particles", "totpart");
- RNA_def_property_struct_type(prop, "Particle");
- RNA_def_property_ui_text(prop, "Particles", "Particles generated by the particle system");
-
- prop = RNA_def_property(srna, "child_particles", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_collection_sdna(prop, NULL, "child", "totchild");
- RNA_def_property_struct_type(prop, "ChildParticle");
- RNA_def_property_ui_text(prop, "Child Particles", "Child particles generated by the particle system");
-
- prop = RNA_def_property(srna, "seed", PROP_INT, PROP_UNSIGNED);
- RNA_def_property_ui_text(prop, "Seed", "Offset in the random number table, to get a different randomized result");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "child_seed", PROP_INT, PROP_UNSIGNED);
- RNA_def_property_ui_text(prop, "Child Seed",
- "Offset in the random number table for child particles, to get a different "
- "randomized result");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
-
- /* hair */
- prop = RNA_def_property(srna, "is_global_hair", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", PSYS_GLOBAL_HAIR);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Global Hair", "Hair keys are in global coordinate space");
-
- prop = RNA_def_property(srna, "use_hair_dynamics", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", PSYS_HAIR_DYNAMICS);
- RNA_def_property_ui_text(prop, "Hair Dynamics", "Enable hair dynamics using cloth simulation");
- RNA_def_property_update(prop, 0, "rna_Particle_hair_dynamics");
-
- prop = RNA_def_property(srna, "cloth", PROP_POINTER, PROP_NONE);
- RNA_def_property_pointer_sdna(prop, NULL, "clmd");
- RNA_def_property_struct_type(prop, "ClothModifier");
- RNA_def_property_flag(prop, PROP_NEVER_NULL);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Cloth", "Cloth dynamics for hair");
-
- /* reactor */
- prop = RNA_def_property(srna, "reactor_target_object", PROP_POINTER, PROP_NONE);
- RNA_def_property_pointer_sdna(prop, NULL, "target_ob");
- RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Reactor Target Object",
- "For reactor systems, the object that has the target particle system "
- "(empty if same object)");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "reactor_target_particle_system", PROP_INT, PROP_UNSIGNED);
- RNA_def_property_int_sdna(prop, NULL, "target_psys");
- RNA_def_property_range(prop, 1, SHRT_MAX);
- RNA_def_property_ui_text(prop, "Reactor Target Particle System",
- "For reactor systems, index of particle system on the target object");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- /* keyed */
- prop = RNA_def_property(srna, "use_keyed_timing", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", PSYS_KEYED_TIMING);
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_ui_text(prop, "Keyed timing", "Use key times");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- prop = RNA_def_property(srna, "targets", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_struct_type(prop, "ParticleTarget");
- RNA_def_property_ui_text(prop, "Targets", "Target particle systems");
-
- prop = RNA_def_property(srna, "active_particle_target", PROP_POINTER, PROP_NONE);
- RNA_def_property_struct_type(prop, "ParticleTarget");
- RNA_def_property_pointer_funcs(prop, "rna_ParticleSystem_active_particle_target_get", NULL, NULL, NULL);
- RNA_def_property_ui_text(prop, "Active Particle Target", "");
-
- prop = RNA_def_property(srna, "active_particle_target_index", PROP_INT, PROP_UNSIGNED);
- RNA_def_property_int_funcs(prop, "rna_ParticleSystem_active_particle_target_index_get",
- "rna_ParticleSystem_active_particle_target_index_set",
- "rna_ParticleSystem_active_particle_target_index_range");
- RNA_def_property_ui_text(prop, "Active Particle Target Index", "");
-
- /* billboard */
- prop = RNA_def_property(srna, "billboard_normal_uv", PROP_STRING, PROP_NONE);
- RNA_def_property_string_sdna(prop, NULL, "bb_uvname[0]");
- RNA_def_property_string_maxlength(prop, 32);
- RNA_def_property_ui_text(prop, "Billboard Normal UV", "UV map to control billboard normals");
-
- prop = RNA_def_property(srna, "billboard_time_index_uv", PROP_STRING, PROP_NONE);
- RNA_def_property_string_sdna(prop, NULL, "bb_uvname[1]");
- RNA_def_property_string_maxlength(prop, 32);
- RNA_def_property_ui_text(prop, "Billboard Time Index UV", "UV map to control billboard time index (X-Y)");
-
- prop = RNA_def_property(srna, "billboard_split_uv", PROP_STRING, PROP_NONE);
- RNA_def_property_string_sdna(prop, NULL, "bb_uvname[2]");
- RNA_def_property_string_maxlength(prop, 32);
- RNA_def_property_ui_text(prop, "Billboard Split UV", "UV map to control billboard splitting");
-
- /* vertex groups */
-
- /* note, internally store as ints, access as strings */
-#if 0 /* int access. works ok but isn't useful for the UI */
- prop = RNA_def_property(srna, "vertex_group_density", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "vgroup[0]");
- RNA_def_property_ui_text(prop, "Vertex Group Density", "Vertex group to control density");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-#endif
-
- prop = RNA_def_property(srna, "vertex_group_density", PROP_STRING, PROP_NONE);
- RNA_def_property_string_funcs(prop, "rna_ParticleVGroup_name_get_0", "rna_ParticleVGroup_name_len_0",
- "rna_ParticleVGroup_name_set_0");
- RNA_def_property_ui_text(prop, "Vertex Group Density", "Vertex group to control density");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "invert_vertex_group_density", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "vg_neg", (1 << PSYS_VG_DENSITY));
- RNA_def_property_ui_text(prop, "Vertex Group Density Negate", "Negate the effect of the density vertex group");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "vertex_group_velocity", PROP_STRING, PROP_NONE);
- RNA_def_property_string_funcs(prop, "rna_ParticleVGroup_name_get_1", "rna_ParticleVGroup_name_len_1",
- "rna_ParticleVGroup_name_set_1");
- RNA_def_property_ui_text(prop, "Vertex Group Velocity", "Vertex group to control velocity");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "invert_vertex_group_velocity", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "vg_neg", (1 << PSYS_VG_VEL));
- RNA_def_property_ui_text(prop, "Vertex Group Velocity Negate", "Negate the effect of the velocity vertex group");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "vertex_group_length", PROP_STRING, PROP_NONE);
- RNA_def_property_string_funcs(prop, "rna_ParticleVGroup_name_get_2", "rna_ParticleVGroup_name_len_2",
- "rna_ParticleVGroup_name_set_2");
- RNA_def_property_ui_text(prop, "Vertex Group Length", "Vertex group to control length");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- prop = RNA_def_property(srna, "invert_vertex_group_length", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "vg_neg", (1 << PSYS_VG_LENGTH));
- RNA_def_property_ui_text(prop, "Vertex Group Length Negate", "Negate the effect of the length vertex group");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- prop = RNA_def_property(srna, "vertex_group_clump", PROP_STRING, PROP_NONE);
- RNA_def_property_string_funcs(prop, "rna_ParticleVGroup_name_get_3", "rna_ParticleVGroup_name_len_3",
- "rna_ParticleVGroup_name_set_3");
- RNA_def_property_ui_text(prop, "Vertex Group Clump", "Vertex group to control clump");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
-
- prop = RNA_def_property(srna, "invert_vertex_group_clump", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "vg_neg", (1 << PSYS_VG_CLUMP));
- RNA_def_property_ui_text(prop, "Vertex Group Clump Negate", "Negate the effect of the clump vertex group");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
-
- prop = RNA_def_property(srna, "vertex_group_kink", PROP_STRING, PROP_NONE);
- RNA_def_property_string_funcs(prop, "rna_ParticleVGroup_name_get_4", "rna_ParticleVGroup_name_len_4",
- "rna_ParticleVGroup_name_set_4");
- RNA_def_property_ui_text(prop, "Vertex Group Kink", "Vertex group to control kink");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
-
- prop = RNA_def_property(srna, "invert_vertex_group_kink", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "vg_neg", (1 << PSYS_VG_KINK));
- RNA_def_property_ui_text(prop, "Vertex Group Kink Negate", "Negate the effect of the kink vertex group");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
-
- prop = RNA_def_property(srna, "vertex_group_roughness_1", PROP_STRING, PROP_NONE);
- RNA_def_property_string_funcs(prop, "rna_ParticleVGroup_name_get_5", "rna_ParticleVGroup_name_len_5",
- "rna_ParticleVGroup_name_set_5");
- RNA_def_property_ui_text(prop, "Vertex Group Roughness 1", "Vertex group to control roughness 1");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
-
- prop = RNA_def_property(srna, "invert_vertex_group_roughness_1", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "vg_neg", (1 << PSYS_VG_ROUGH1));
- RNA_def_property_ui_text(prop, "Vertex Group Roughness 1 Negate",
- "Negate the effect of the roughness 1 vertex group");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
-
- prop = RNA_def_property(srna, "vertex_group_roughness_2", PROP_STRING, PROP_NONE);
- RNA_def_property_string_funcs(prop, "rna_ParticleVGroup_name_get_6", "rna_ParticleVGroup_name_len_6",
- "rna_ParticleVGroup_name_set_6");
- RNA_def_property_ui_text(prop, "Vertex Group Roughness 2", "Vertex group to control roughness 2");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
-
- prop = RNA_def_property(srna, "invert_vertex_group_roughness_2", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "vg_neg", (1 << PSYS_VG_ROUGH2));
- RNA_def_property_ui_text(prop, "Vertex Group Roughness 2 Negate",
- "Negate the effect of the roughness 2 vertex group");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
-
- prop = RNA_def_property(srna, "vertex_group_roughness_end", PROP_STRING, PROP_NONE);
- RNA_def_property_string_funcs(prop, "rna_ParticleVGroup_name_get_7", "rna_ParticleVGroup_name_len_7",
- "rna_ParticleVGroup_name_set_7");
- RNA_def_property_ui_text(prop, "Vertex Group Roughness End", "Vertex group to control roughness end");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
-
- prop = RNA_def_property(srna, "invert_vertex_group_roughness_end", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "vg_neg", (1 << PSYS_VG_ROUGHE));
- RNA_def_property_ui_text(prop, "Vertex Group Roughness End Negate",
- "Negate the effect of the roughness end vertex group");
- RNA_def_property_update(prop, 0, "rna_Particle_redo_child");
-
- prop = RNA_def_property(srna, "vertex_group_size", PROP_STRING, PROP_NONE);
- RNA_def_property_string_funcs(prop, "rna_ParticleVGroup_name_get_8", "rna_ParticleVGroup_name_len_8",
- "rna_ParticleVGroup_name_set_8");
- RNA_def_property_ui_text(prop, "Vertex Group Size", "Vertex group to control size");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "invert_vertex_group_size", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "vg_neg", (1 << PSYS_VG_SIZE));
- RNA_def_property_ui_text(prop, "Vertex Group Size Negate", "Negate the effect of the size vertex group");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "vertex_group_tangent", PROP_STRING, PROP_NONE);
- RNA_def_property_string_funcs(prop, "rna_ParticleVGroup_name_get_9", "rna_ParticleVGroup_name_len_9",
- "rna_ParticleVGroup_name_set_9");
- RNA_def_property_ui_text(prop, "Vertex Group Tangent", "Vertex group to control tangent");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "invert_vertex_group_tangent", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "vg_neg", (1 << PSYS_VG_TAN));
- RNA_def_property_ui_text(prop, "Vertex Group Tangent Negate", "Negate the effect of the tangent vertex group");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "vertex_group_rotation", PROP_STRING, PROP_NONE);
- RNA_def_property_string_funcs(prop, "rna_ParticleVGroup_name_get_10", "rna_ParticleVGroup_name_len_10",
- "rna_ParticleVGroup_name_set_10");
- RNA_def_property_ui_text(prop, "Vertex Group Rotation", "Vertex group to control rotation");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "invert_vertex_group_rotation", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "vg_neg", (1 << PSYS_VG_ROT));
- RNA_def_property_ui_text(prop, "Vertex Group Rotation Negate", "Negate the effect of the rotation vertex group");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "vertex_group_field", PROP_STRING, PROP_NONE);
- RNA_def_property_string_funcs(prop, "rna_ParticleVGroup_name_get_11", "rna_ParticleVGroup_name_len_11",
- "rna_ParticleVGroup_name_set_11");
- RNA_def_property_ui_text(prop, "Vertex Group Field", "Vertex group to control field");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- prop = RNA_def_property(srna, "invert_vertex_group_field", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "vg_neg", (1 << PSYS_VG_EFFECTOR));
- RNA_def_property_ui_text(prop, "Vertex Group Field Negate", "Negate the effect of the field vertex group");
- RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
- /* pointcache */
- prop = RNA_def_property(srna, "point_cache", PROP_POINTER, PROP_NONE);
- RNA_def_property_flag(prop, PROP_NEVER_NULL);
- RNA_def_property_pointer_sdna(prop, NULL, "pointcache");
- RNA_def_property_struct_type(prop, "PointCache");
- RNA_def_property_ui_text(prop, "Point Cache", "");
-
- prop = RNA_def_property(srna, "has_multiple_caches", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_funcs(prop, "rna_ParticleSystem_multiple_caches_get", NULL);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Multiple Caches", "Particle system has multiple point caches");
-
- /* offset ob */
- prop = RNA_def_property(srna, "parent", PROP_POINTER, PROP_NONE);
- RNA_def_property_pointer_sdna(prop, NULL, "parent");
- RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Parent",
- "Use this object's coordinate system instead of global coordinate system");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
- /* hair or cache editing */
- prop = RNA_def_property(srna, "is_editable", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_funcs(prop, "rna_ParticleSystem_editable_get", NULL);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Editable", "Particle system can be edited in particle mode");
-
- prop = RNA_def_property(srna, "is_edited", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_funcs(prop, "rna_ParticleSystem_edited_get", NULL);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Edited", "Particle system has been edited in particle mode");
-
- /* Read-only: this is calculated internally. Changing it would only affect
- * the next time-step. The user should change ParticlSettings.subframes or
- * ParticleSettings.courant_target instead. */
- prop = RNA_def_property(srna, "dt_frac", PROP_FLOAT, PROP_NONE);
- RNA_def_property_range(prop, 1.0f / 101.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Timestep", "The current simulation time step size, as a fraction of a frame");
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
-
- RNA_def_struct_path_func(srna, "rna_ParticleSystem_path");
-
- /* set viewport or render resolution */
- func = RNA_def_function(srna, "set_resolution", "rna_ParticleSystem_set_resolution");
- RNA_def_function_ui_description(func, "Set the resolution to use for the number of particles");
- prop = RNA_def_pointer(func, "scene", "Scene", "", "Scene");
- prop = RNA_def_pointer(func, "object", "Object", "", "Object");
- prop = RNA_def_enum(func, "resolution", resolution_items, 0, "", "Resolution settings to apply");
-
- /* extract cached hair location data */
- func = RNA_def_function(srna, "co_hair", "rna_ParticleSystem_co_hair");
- RNA_def_function_ui_description(func, "Obtain cache hair data");
-
- prop = RNA_def_pointer(func, "object", "Object", "", "Object");
- RNA_def_property_flag(prop, PROP_REQUIRED | PROP_NEVER_NULL);
- prop = RNA_def_int(func, "particle_no", 0, INT_MIN, INT_MAX, "Particle no", "", INT_MIN, INT_MAX);
- prop = RNA_def_int(func, "step", 0, INT_MIN, INT_MAX, "step no", "", INT_MIN, INT_MAX);
-
- prop = RNA_def_float_vector(func, "co", 3, NULL, -FLT_MAX, FLT_MAX, "Co",
- "Exported hairkey location", -1e4, 1e4);
- RNA_def_property_flag(prop, PROP_THICK_WRAP);
- RNA_def_function_output(func, prop);
-
- /* extract hair UVs */
- func = RNA_def_function(srna, "uv_on_emitter", "rna_ParticleSystem_uv_on_emitter");
- RNA_def_function_ui_description(func, "Obtain uv for all particles");
- RNA_def_function_flag(func, FUNC_USE_REPORTS);
- prop = RNA_def_pointer(func, "modifier", "ParticleSystemModifier", "", "Particle modifier");
- RNA_def_property_flag(prop, PROP_REQUIRED | PROP_NEVER_NULL);
- prop = RNA_def_pointer(func, "particle", "Particle", "", "Particle");
- RNA_def_property_flag(prop, PROP_REQUIRED | PROP_NEVER_NULL);
- prop = RNA_def_int(func, "particle_no", 0, INT_MIN, INT_MAX, "Particle no", "", INT_MIN, INT_MAX);
- prop = RNA_def_int(func, "uv_no", 0, INT_MIN, INT_MAX, "UV no", "", INT_MIN, INT_MAX);
- prop = RNA_def_property(func, "uv", PROP_FLOAT, PROP_COORDS);
- RNA_def_property_array(prop, 2);
- RNA_def_property_flag(prop, PROP_THICK_WRAP);
- RNA_def_function_output(func, prop);
-
- /* extract hair mcols */
- func = RNA_def_function(srna, "mcol_on_emitter", "rna_ParticleSystem_mcol_on_emitter");
- RNA_def_function_flag(func, FUNC_USE_REPORTS);
- RNA_def_function_ui_description(func, "Obtain mcol for all particles");
- prop = RNA_def_pointer(func, "modifier", "ParticleSystemModifier", "", "Particle modifier");
- RNA_def_property_flag(prop, PROP_REQUIRED | PROP_NEVER_NULL);
- prop = RNA_def_pointer(func, "particle", "Particle", "", "Particle");
- RNA_def_property_flag(prop, PROP_REQUIRED | PROP_NEVER_NULL);
- prop = RNA_def_int(func, "particle_no", 0, INT_MIN, INT_MAX, "Particle no", "", INT_MIN, INT_MAX);
- prop = RNA_def_int(func, "vcol_no", 0, INT_MIN, INT_MAX, "vcol no", "", INT_MIN, INT_MAX);
- prop = RNA_def_property(func, "mcol", PROP_FLOAT, PROP_COLOR);
- RNA_def_property_array(prop, 3);
- RNA_def_property_flag(prop, PROP_THICK_WRAP);
- RNA_def_function_output(func, prop);
-
-}
-
-void RNA_def_particle(BlenderRNA *brna)
-{
- rna_def_particle_target(brna);
- rna_def_fluid_settings(brna);
- rna_def_particle_hair_key(brna);
- rna_def_particle_key(brna);
-
- rna_def_child_particle(brna);
- rna_def_particle(brna);
- rna_def_particle_dupliweight(brna);
- rna_def_particle_system(brna);
- rna_def_particle_settings_mtex(brna);
- rna_def_particle_settings(brna);
-}
-
-#endif
diff --git a/source/blender/makesrna/intern/rna_rigidbody.c b/source/blender/makesrna/intern/rna_rigidbody.c
index bdf001ed0e1..074a24ad01f 100644
--- a/source/blender/makesrna/intern/rna_rigidbody.c
+++ b/source/blender/makesrna/intern/rna_rigidbody.c
@@ -109,8 +109,7 @@ static EnumPropertyItem rigidbody_mesh_source_items[] = {
static void rna_RigidBodyWorld_reset(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
RigidBodyWorld *rbw = (RigidBodyWorld *)ptr->data;
-
- BKE_rigidbody_cache_reset(rbw);
+ UNUSED_VARS(rbw);
}
static char *rna_RigidBodyWorld_path(PointerRNA *UNUSED(ptr))
@@ -149,10 +148,10 @@ static void rna_RigidBodyWorld_split_impulse_set(PointerRNA *ptr, int value)
static void rna_RigidBodyOb_reset(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr))
{
RigidBodyWorld *rbw = scene->rigidbody_world;
-
- BKE_rigidbody_cache_reset(rbw);
+ UNUSED_VARS(rbw);
}
+
static void rna_RigidBodyOb_shape_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
Object *ob = ptr->id.data;
@@ -162,12 +161,10 @@ static void rna_RigidBodyOb_shape_update(Main *bmain, Scene *scene, PointerRNA *
WM_main_add_notifier(NC_OBJECT | ND_DRAW, ob);
}
-static void rna_RigidBodyOb_shape_reset(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr)
+static void rna_RigidBodyOb_shape_reset(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- RigidBodyWorld *rbw = scene->rigidbody_world;
RigidBodyOb *rbo = (RigidBodyOb *)ptr->data;
- BKE_rigidbody_cache_reset(rbw);
if (rbo->physics_shape)
rbo->flag |= RBO_FLAG_NEEDS_RESHAPE;
}
@@ -721,12 +718,6 @@ static void rna_def_rigidbody_world(BlenderRNA *brna)
"stability a little so use only when necessary)");
RNA_def_property_update(prop, NC_SCENE, "rna_RigidBodyWorld_reset");
- /* cache */
- prop = RNA_def_property(srna, "point_cache", PROP_POINTER, PROP_NONE);
- RNA_def_property_flag(prop, PROP_NEVER_NULL);
- RNA_def_property_pointer_sdna(prop, NULL, "pointcache");
- RNA_def_property_ui_text(prop, "Point Cache", "");
-
/* effector weights */
prop = RNA_def_property(srna, "effector_weights", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "EffectorWeights");
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 90636bb0439..668286d3c67 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -29,7 +29,6 @@
#include "DNA_brush_types.h"
#include "DNA_group_types.h"
#include "DNA_modifier_types.h"
-#include "DNA_particle_types.h"
#include "DNA_rigidbody_types.h"
#include "DNA_scene_types.h"
#include "DNA_linestyle_types.h"
@@ -424,7 +423,6 @@ EnumPropertyItem rna_enum_bake_pass_filter_type_items[] = {
#include "BKE_image.h"
#include "BKE_main.h"
#include "BKE_node.h"
-#include "BKE_pointcache.h"
#include "BKE_scene.h"
#include "BKE_depsgraph.h"
#include "BKE_mesh.h"
@@ -1654,15 +1652,6 @@ static void rna_Scene_use_nodes_update(bContext *C, PointerRNA *ptr)
ED_node_composit_default(C, scene);
}
-static void rna_Physics_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
-{
- Scene *scene = (Scene *)ptr->id.data;
- Base *base;
-
- for (base = scene->base.first; base; base = base->next)
- BKE_ptcache_object_reset(scene, base->object, PTCACHE_RESET_DEPSGRAPH);
-}
-
static void rna_Scene_editmesh_select_mode_set(PointerRNA *ptr, const int *value)
{
Scene *scene = (Scene *)ptr->id.data;
@@ -1699,7 +1688,6 @@ static void rna_Scene_editmesh_select_mode_update(Main *UNUSED(bmain), Scene *sc
static void object_simplify_update(Object *ob)
{
ModifierData *md;
- ParticleSystem *psys;
if ((ob->id.tag & LIB_TAG_DOIT) == 0) {
return;
@@ -1708,14 +1696,11 @@ static void object_simplify_update(Object *ob)
ob->id.tag &= ~LIB_TAG_DOIT;
for (md = ob->modifiers.first; md; md = md->next) {
- if (ELEM(md->type, eModifierType_Subsurf, eModifierType_Multires, eModifierType_ParticleSystem)) {
+ if (ELEM(md->type, eModifierType_Subsurf, eModifierType_Multires)) {
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
}
- for (psys = ob->particlesystem.first; psys; psys = psys->next)
- psys->recalc |= PSYS_RECALC_CHILD;
-
if (ob->dup_group) {
GroupObject *gob;
@@ -2485,10 +2470,6 @@ static void rna_def_tool_settings(BlenderRNA *brna)
RNA_def_property_pointer_sdna(prop, NULL, "uvsculpt");
RNA_def_property_ui_text(prop, "UV Sculpt", "");
- prop = RNA_def_property(srna, "particle_edit", PROP_POINTER, PROP_NONE);
- RNA_def_property_pointer_sdna(prop, NULL, "particle");
- RNA_def_property_ui_text(prop, "Particle Edit", "");
-
prop = RNA_def_property(srna, "use_uv_sculpt", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "use_uv_sculpt", 1);
RNA_def_property_ui_text(prop, "UV Sculpt", "Enable brush for UV sculpting");
@@ -6550,22 +6531,12 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Simplify Subdivision", "Global maximum subdivision level");
RNA_def_property_update(prop, 0, "rna_Scene_simplify_update");
- prop = RNA_def_property(srna, "simplify_child_particles", PROP_FLOAT, PROP_FACTOR);
- RNA_def_property_float_sdna(prop, NULL, "simplify_particles");
- RNA_def_property_ui_text(prop, "Simplify Child Particles", "Global child particles percentage");
- RNA_def_property_update(prop, 0, "rna_Scene_simplify_update");
-
prop = RNA_def_property(srna, "simplify_subdivision_render", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_sdna(prop, NULL, "simplify_subsurf_render");
RNA_def_property_ui_range(prop, 0, 6, 1, -1);
RNA_def_property_ui_text(prop, "Simplify Subdivision", "Global maximum subdivision level during rendering");
RNA_def_property_update(prop, 0, "rna_Scene_simplify_update");
- prop = RNA_def_property(srna, "simplify_child_particles_render", PROP_FLOAT, PROP_FACTOR);
- RNA_def_property_float_sdna(prop, NULL, "simplify_particles_render");
- RNA_def_property_ui_text(prop, "Simplify Child Particles", "Global child particles percentage during rendering");
- RNA_def_property_update(prop, 0, "rna_Scene_simplify_update");
-
prop = RNA_def_property(srna, "simplify_shadow_samples", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_sdna(prop, NULL, "simplify_shadowsamples");
RNA_def_property_ui_range(prop, 1, 16, 1, -1);
@@ -7143,12 +7114,10 @@ void RNA_def_scene(BlenderRNA *brna)
RNA_def_property_array(prop, 3);
RNA_def_property_ui_range(prop, -200.0f, 200.0f, 1, 2);
RNA_def_property_ui_text(prop, "Gravity", "Constant acceleration in a given direction");
- RNA_def_property_update(prop, 0, "rna_Physics_update");
prop = RNA_def_property(srna, "use_gravity", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "physics_settings.flag", PHYS_GLOBAL_GRAVITY);
RNA_def_property_ui_text(prop, "Global Gravity", "Use global gravity for all dynamics");
- RNA_def_property_update(prop, 0, "rna_Physics_update");
/* Render Data */
prop = RNA_def_property(srna, "render", PROP_POINTER, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_sculpt_paint.c b/source/blender/makesrna/intern/rna_sculpt_paint.c
index 7e1d0164eb4..305b4aa1b6e 100644
--- a/source/blender/makesrna/intern/rna_sculpt_paint.c
+++ b/source/blender/makesrna/intern/rna_sculpt_paint.c
@@ -34,6 +34,7 @@
#include "DNA_ID.h"
#include "DNA_scene_types.h"
#include "DNA_brush_types.h"
+#include "DNA_object_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
@@ -48,18 +49,6 @@
#include "BLI_utildefines.h"
#include "bmesh.h"
-static EnumPropertyItem particle_edit_hair_brush_items[] = {
- {PE_BRUSH_NONE, "NONE", 0, "None", "Don't use any brush"},
- {PE_BRUSH_COMB, "COMB", 0, "Comb", "Comb hairs"},
- {PE_BRUSH_SMOOTH, "SMOOTH", 0, "Smooth", "Smooth hairs"},
- {PE_BRUSH_ADD, "ADD", 0, "Add", "Add hairs"},
- {PE_BRUSH_LENGTH, "LENGTH", 0, "Length", "Make hairs longer or shorter"},
- {PE_BRUSH_PUFF, "PUFF", 0, "Puff", "Make hairs stand up"},
- {PE_BRUSH_CUT, "CUT", 0, "Cut", "Cut hairs"},
- {PE_BRUSH_WEIGHT, "WEIGHT", 0, "Weight", "Weight hair particles"},
- {0, NULL, 0, NULL, NULL}
-};
-
EnumPropertyItem rna_enum_gpencil_sculpt_brush_items[] = {
{GP_EDITBRUSH_TYPE_SMOOTH, "SMOOTH", 0, "Smooth", "Smooth stroke points"},
{GP_EDITBRUSH_TYPE_THICKNESS, "THICKNESS", 0, "Thickness", "Adjust thickness of strokes"},
@@ -92,137 +81,16 @@ EnumPropertyItem rna_enum_symmetrize_direction_items[] = {
#include "BKE_context.h"
#include "BKE_DerivedMesh.h"
-#include "BKE_pointcache.h"
-#include "BKE_particle.h"
#include "BKE_depsgraph.h"
#include "BKE_pbvh.h"
#include "GPU_buffers.h"
-#include "ED_particle.h"
-
static void rna_GPencil_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
{
WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL);
}
-static EnumPropertyItem particle_edit_disconnected_hair_brush_items[] = {
- {PE_BRUSH_NONE, "NONE", 0, "None", "Don't use any brush"},
- {PE_BRUSH_COMB, "COMB", 0, "Comb", "Comb hairs"},
- {PE_BRUSH_SMOOTH, "SMOOTH", 0, "Smooth", "Smooth hairs"},
- {PE_BRUSH_LENGTH, "LENGTH", 0, "Length", "Make hairs longer or shorter"},
- {PE_BRUSH_CUT, "CUT", 0, "Cut", "Cut hairs"},
- {PE_BRUSH_WEIGHT, "WEIGHT", 0, "Weight", "Weight hair particles"},
- {0, NULL, 0, NULL, NULL}
-};
-
-static EnumPropertyItem particle_edit_cache_brush_items[] = {
- {PE_BRUSH_NONE, "NONE", 0, "None", "Don't use any brush"},
- {PE_BRUSH_COMB, "COMB", 0, "Comb", "Comb paths"},
- {PE_BRUSH_SMOOTH, "SMOOTH", 0, "Smooth", "Smooth paths"},
- {PE_BRUSH_LENGTH, "LENGTH", 0, "Length", "Make paths longer or shorter"},
- {0, NULL, 0, NULL, NULL}
-};
-
-static PointerRNA rna_ParticleEdit_brush_get(PointerRNA *ptr)
-{
- ParticleEditSettings *pset = (ParticleEditSettings *)ptr->data;
- ParticleBrushData *brush = NULL;
-
- if (pset->brushtype != PE_BRUSH_NONE)
- brush = &pset->brush[pset->brushtype];
-
- return rna_pointer_inherit_refine(ptr, &RNA_ParticleBrush, brush);
-}
-
-static PointerRNA rna_ParticleBrush_curve_get(PointerRNA *ptr)
-{
- return rna_pointer_inherit_refine(ptr, &RNA_CurveMapping, NULL);
-}
-
-static void rna_ParticleEdit_redo(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr))
-{
- Object *ob = (scene->basact) ? scene->basact->object : NULL;
- PTCacheEdit *edit = PE_get_current(scene, ob);
-
- if (!edit)
- return;
-
- psys_free_path_cache(edit->psys, edit);
-}
-
-static void rna_ParticleEdit_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr))
-{
- Object *ob = (scene->basact) ? scene->basact->object : NULL;
-
- if (ob) DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
-}
-static void rna_ParticleEdit_tool_set(PointerRNA *ptr, int value)
-{
- ParticleEditSettings *pset = (ParticleEditSettings *)ptr->data;
-
- /* redraw hair completely if weight brush is/was used */
- if ((pset->brushtype == PE_BRUSH_WEIGHT || value == PE_BRUSH_WEIGHT) && pset->scene) {
- Object *ob = (pset->scene->basact) ? pset->scene->basact->object : NULL;
- if (ob) {
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
- WM_main_add_notifier(NC_OBJECT | ND_PARTICLE | NA_EDITED, NULL);
- }
- }
-
- pset->brushtype = value;
-}
-static EnumPropertyItem *rna_ParticleEdit_tool_itemf(bContext *C, PointerRNA *UNUSED(ptr),
- PropertyRNA *UNUSED(prop), bool *UNUSED(r_free))
-{
- Scene *scene = CTX_data_scene(C);
- Object *ob = (scene->basact) ? scene->basact->object : NULL;
-#if 0
- PTCacheEdit *edit = PE_get_current(scene, ob);
- ParticleSystem *psys = edit ? edit->psys : NULL;
-#else
- /* use this rather than PE_get_current() - because the editing cache is
- * dependent on the cache being updated which can happen after this UI
- * draws causing a glitch [#28883] */
- ParticleSystem *psys = psys_get_current(ob);
-#endif
-
- if (psys) {
- if (psys->flag & PSYS_GLOBAL_HAIR) {
- return particle_edit_disconnected_hair_brush_items;
- }
- else {
- return particle_edit_hair_brush_items;
- }
- }
-
- return particle_edit_cache_brush_items;
-}
-
-static int rna_ParticleEdit_editable_get(PointerRNA *ptr)
-{
- ParticleEditSettings *pset = (ParticleEditSettings *)ptr->data;
-
- return (pset->object && pset->scene && PE_get_current(pset->scene, pset->object));
-}
-static int rna_ParticleEdit_hair_get(PointerRNA *ptr)
-{
- ParticleEditSettings *pset = (ParticleEditSettings *)ptr->data;
-
- if (pset->scene) {
- PTCacheEdit *edit = PE_get_current(pset->scene, pset->object);
-
- return (edit && edit->psys);
- }
-
- return 0;
-}
-
-static char *rna_ParticleEdit_path(PointerRNA *UNUSED(ptr))
-{
- return BLI_strdup("tool_settings.particle_edit");
-}
-
static int rna_Brush_mode_poll(PointerRNA *ptr, PointerRNA value)
{
Scene *scene = (Scene *)ptr->id.data;
@@ -302,11 +170,6 @@ static char *rna_UvSculpt_path(PointerRNA *UNUSED(ptr))
return BLI_strdup("tool_settings.uv_sculpt");
}
-static char *rna_ParticleBrush_path(PointerRNA *UNUSED(ptr))
-{
- return BLI_strdup("tool_settings.particle_edit.brush");
-}
-
static void rna_Paint_brush_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
Paint *paint = ptr->data;
@@ -807,188 +670,6 @@ static void rna_def_image_paint(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
}
-static void rna_def_particle_edit(BlenderRNA *brna)
-{
- StructRNA *srna;
- PropertyRNA *prop;
-
- static EnumPropertyItem select_mode_items[] = {
- {SCE_SELECT_PATH, "PATH", ICON_PARTICLE_PATH, "Path", "Path edit mode"},
- {SCE_SELECT_POINT, "POINT", ICON_PARTICLE_POINT, "Point", "Point select mode"},
- {SCE_SELECT_END, "TIP", ICON_PARTICLE_TIP, "Tip", "Tip select mode"},
- {0, NULL, 0, NULL, NULL}
- };
-
- static EnumPropertyItem puff_mode[] = {
- {0, "ADD", 0, "Add", "Make hairs more puffy"},
- {1, "SUB", 0, "Sub", "Make hairs less puffy"},
- {0, NULL, 0, NULL, NULL}
- };
-
- static EnumPropertyItem length_mode[] = {
- {0, "GROW", 0, "Grow", "Make hairs longer"},
- {1, "SHRINK", 0, "Shrink", "Make hairs shorter"},
- {0, NULL, 0, NULL, NULL}
- };
-
- static EnumPropertyItem edit_type_items[] = {
- {PE_TYPE_PARTICLES, "PARTICLES", 0, "Particles", ""},
- {PE_TYPE_SOFTBODY, "SOFT_BODY", 0, "Soft body", ""},
- {PE_TYPE_CLOTH, "CLOTH", 0, "Cloth", ""},
- {0, NULL, 0, NULL, NULL}
- };
-
-
- /* edit */
-
- srna = RNA_def_struct(brna, "ParticleEdit", NULL);
- RNA_def_struct_sdna(srna, "ParticleEditSettings");
- RNA_def_struct_path_func(srna, "rna_ParticleEdit_path");
- RNA_def_struct_ui_text(srna, "Particle Edit", "Properties of particle editing mode");
-
- prop = RNA_def_property(srna, "tool", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "brushtype");
- RNA_def_property_enum_items(prop, particle_edit_hair_brush_items);
- RNA_def_property_enum_funcs(prop, NULL, "rna_ParticleEdit_tool_set", "rna_ParticleEdit_tool_itemf");
- RNA_def_property_ui_text(prop, "Tool", "");
-
- prop = RNA_def_property(srna, "select_mode", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_bitflag_sdna(prop, NULL, "selectmode");
- RNA_def_property_enum_items(prop, select_mode_items);
- RNA_def_property_ui_text(prop, "Selection Mode", "Particle select and display mode");
- RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_ParticleEdit_update");
-
- prop = RNA_def_property(srna, "use_preserve_length", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", PE_KEEP_LENGTHS);
- RNA_def_property_ui_text(prop, "Keep Lengths", "Keep path lengths constant");
-
- prop = RNA_def_property(srna, "use_preserve_root", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", PE_LOCK_FIRST);
- RNA_def_property_ui_text(prop, "Keep Root", "Keep root keys unmodified");
-
- prop = RNA_def_property(srna, "use_emitter_deflect", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", PE_DEFLECT_EMITTER);
- RNA_def_property_ui_text(prop, "Deflect Emitter", "Keep paths from intersecting the emitter");
-
- prop = RNA_def_property(srna, "emitter_distance", PROP_FLOAT, PROP_UNSIGNED);
- RNA_def_property_float_sdna(prop, NULL, "emitterdist");
- RNA_def_property_ui_range(prop, 0.0f, 10.0f, 10, 3);
- RNA_def_property_ui_text(prop, "Emitter Distance", "Distance to keep particles away from the emitter");
-
- prop = RNA_def_property(srna, "use_fade_time", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", PE_FADE_TIME);
- RNA_def_property_ui_text(prop, "Fade Time", "Fade paths and keys further away from current frame");
- RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_ParticleEdit_update");
-
- prop = RNA_def_property(srna, "use_auto_velocity", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", PE_AUTO_VELOCITY);
- RNA_def_property_ui_text(prop, "Auto Velocity", "Calculate point velocities automatically");
-
- prop = RNA_def_property(srna, "show_particles", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", PE_DRAW_PART);
- RNA_def_property_ui_text(prop, "Draw Particles", "Draw actual particles");
- RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_ParticleEdit_redo");
-
- prop = RNA_def_property(srna, "use_default_interpolate", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", PE_INTERPOLATE_ADDED);
- RNA_def_property_ui_text(prop, "Interpolate", "Interpolate new particles from the existing ones");
-
- prop = RNA_def_property(srna, "default_key_count", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "totaddkey");
- RNA_def_property_range(prop, 2, SHRT_MAX);
- RNA_def_property_ui_range(prop, 2, 20, 10, 3);
- RNA_def_property_ui_text(prop, "Keys", "How many keys to make new particles with");
-
- prop = RNA_def_property(srna, "brush", PROP_POINTER, PROP_NONE);
- RNA_def_property_struct_type(prop, "ParticleBrush");
- RNA_def_property_pointer_funcs(prop, "rna_ParticleEdit_brush_get", NULL, NULL, NULL);
- RNA_def_property_ui_text(prop, "Brush", "");
-
- prop = RNA_def_property(srna, "draw_step", PROP_INT, PROP_NONE);
- RNA_def_property_range(prop, 1, 10);
- RNA_def_property_ui_text(prop, "Steps", "How many steps to draw the path with");
- RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_ParticleEdit_redo");
-
- prop = RNA_def_property(srna, "fade_frames", PROP_INT, PROP_NONE);
- RNA_def_property_range(prop, 1, 100);
- RNA_def_property_ui_text(prop, "Frames", "How many frames to fade");
- RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_ParticleEdit_update");
-
- prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "edittype");
- RNA_def_property_enum_items(prop, edit_type_items);
- RNA_def_property_ui_text(prop, "Type", "");
- RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_ParticleEdit_redo");
-
- prop = RNA_def_property(srna, "is_editable", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_funcs(prop, "rna_ParticleEdit_editable_get", NULL);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Editable", "A valid edit mode exists");
-
- prop = RNA_def_property(srna, "is_hair", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_funcs(prop, "rna_ParticleEdit_hair_get", NULL);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Hair", "Editing hair");
-
- prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Object", "The edited object");
-
- prop = RNA_def_property(srna, "shape_object", PROP_POINTER, PROP_NONE);
- RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Shape Object", "Outer shape to use for tools");
- RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_Mesh_object_poll");
- RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_ParticleEdit_redo");
-
- /* brush */
-
- srna = RNA_def_struct(brna, "ParticleBrush", NULL);
- RNA_def_struct_sdna(srna, "ParticleBrushData");
- RNA_def_struct_path_func(srna, "rna_ParticleBrush_path");
- RNA_def_struct_ui_text(srna, "Particle Brush", "Particle editing brush");
-
- prop = RNA_def_property(srna, "size", PROP_INT, PROP_PIXEL);
- RNA_def_property_range(prop, 1, SHRT_MAX);
- RNA_def_property_ui_range(prop, 1, MAX_BRUSH_PIXEL_RADIUS, 10, 3);
- RNA_def_property_ui_text(prop, "Radius", "Radius of the brush in pixels");
-
- prop = RNA_def_property(srna, "strength", PROP_FLOAT, PROP_FACTOR);
- RNA_def_property_range(prop, 0.001, 1.0);
- RNA_def_property_ui_text(prop, "Strength", "Brush strength");
-
- prop = RNA_def_property(srna, "count", PROP_INT, PROP_NONE);
- RNA_def_property_range(prop, 1, 1000);
- RNA_def_property_ui_range(prop, 1, 100, 10, 3);
- RNA_def_property_ui_text(prop, "Count", "Particle count");
-
- prop = RNA_def_property(srna, "steps", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "step");
- RNA_def_property_range(prop, 1, SHRT_MAX);
- RNA_def_property_ui_range(prop, 1, 50, 10, 3);
- RNA_def_property_ui_text(prop, "Steps", "Brush steps");
-
- prop = RNA_def_property(srna, "puff_mode", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "invert");
- RNA_def_property_enum_items(prop, puff_mode);
- RNA_def_property_ui_text(prop, "Puff Mode", "");
-
- prop = RNA_def_property(srna, "use_puff_volume", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", PE_BRUSH_DATA_PUFF_VOLUME);
- RNA_def_property_ui_text(prop, "Puff Volume",
- "Apply puff to unselected end-points (helps maintain hair volume when puffing root)");
-
- prop = RNA_def_property(srna, "length_mode", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "invert");
- RNA_def_property_enum_items(prop, length_mode);
- RNA_def_property_ui_text(prop, "Length Mode", "");
-
- /* dummy */
- prop = RNA_def_property(srna, "curve", PROP_POINTER, PROP_NONE);
- RNA_def_property_struct_type(prop, "CurveMapping");
- RNA_def_property_pointer_funcs(prop, "rna_ParticleBrush_curve_get", NULL, NULL, NULL);
- RNA_def_property_ui_text(prop, "Curve", "");
-}
-
static void rna_def_gpencil_sculpt(BlenderRNA *brna)
{
static EnumPropertyItem prop_direction_items[] = {
@@ -1103,7 +784,6 @@ void RNA_def_sculpt_paint(BlenderRNA *brna)
rna_def_uv_sculpt(brna);
rna_def_vertex_paint(brna);
rna_def_image_paint(brna);
- rna_def_particle_edit(brna);
rna_def_gpencil_sculpt(brna);
RNA_define_animate_sdna(true);
}
diff --git a/source/blender/makesrna/intern/rna_smoke.c b/source/blender/makesrna/intern/rna_smoke.c
index b4ba306df3f..6baf2f3631d 100644
--- a/source/blender/makesrna/intern/rna_smoke.c
+++ b/source/blender/makesrna/intern/rna_smoke.c
@@ -35,7 +35,6 @@
#include "BKE_modifier.h"
#include "BKE_smoke.h"
-#include "BKE_pointcache.h"
#include "BLI_threads.h"
@@ -52,7 +51,6 @@
#include "BKE_context.h"
#include "BKE_depsgraph.h"
-#include "BKE_particle.h"
#include "smoke_API.h"
@@ -68,35 +66,11 @@ static void rna_Smoke_dependency_update(Main *bmain, Scene *scene, PointerRNA *p
DAG_relations_tag_update(bmain);
}
-static void rna_Smoke_resetCache(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
-{
- SmokeDomainSettings *settings = (SmokeDomainSettings *)ptr->data;
- if (settings->smd && settings->smd->domain)
- settings->point_cache[0]->flag |= PTCACHE_OUTDATED;
- DAG_id_tag_update(ptr->id.data, OB_RECALC_DATA);
-}
-
-static void rna_Smoke_cachetype_set(struct PointerRNA *ptr, int value)
-{
- SmokeDomainSettings *settings = (SmokeDomainSettings *)ptr->data;
- Object *ob = (Object *)ptr->id.data;
-
- if (value != settings->cache_file_format) {
- /* Clear old caches. */
- PTCacheID id;
- BKE_ptcache_id_from_smoke(&id, ob, settings->smd);
- BKE_ptcache_id_clear(&id, PTCACHE_CLEAR_ALL, 0);
-
- settings->cache_file_format = value;
- }
-}
-
static void rna_Smoke_reset(Main *bmain, Scene *scene, PointerRNA *ptr)
{
SmokeDomainSettings *settings = (SmokeDomainSettings *)ptr->data;
smokeModifier_reset(settings->smd);
- rna_Smoke_resetCache(bmain, scene, ptr);
rna_Smoke_update(bmain, scene, ptr);
}
@@ -107,9 +81,6 @@ static void rna_Smoke_reset_dependency(Main *bmain, Scene *scene, PointerRNA *pt
smokeModifier_reset(settings->smd);
- if (settings->smd && settings->smd->domain)
- settings->smd->domain->point_cache[0]->flag |= PTCACHE_OUTDATED;
-
rna_Smoke_dependency_update(bmain, scene, ptr);
}
@@ -408,12 +379,6 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna)
{ 0, NULL, 0, NULL, NULL }
};
- static EnumPropertyItem smoke_cache_comp_items[] = {
- {SM_CACHE_LIGHT, "CACHELIGHT", 0, "Light", "Fast but not so effective compression"},
- {SM_CACHE_HEAVY, "CACHEHEAVY", 0, "Heavy", "Effective but slow compression"},
- {0, NULL, 0, NULL, NULL}
- };
-
static EnumPropertyItem smoke_highres_sampling_items[] = {
{SM_HRES_FULLSAMPLE, "FULLSAMPLE", 0, "Full Sample", ""},
{SM_HRES_LINEAR, "LINEAR", 0, "Linear", ""},
@@ -435,14 +400,6 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
- static EnumPropertyItem cache_file_type_items[] = {
- {PTCACHE_FILE_PTCACHE, "POINTCACHE", 0, "Point Cache", "Blender specific point cache file format"},
-#ifdef WITH_OPENVDB
- {PTCACHE_FILE_OPENVDB, "OPENVDB", 0, "OpenVDB", "OpenVDB file format"},
-#endif
- {0, NULL, 0, NULL, NULL}
- };
-
static EnumPropertyItem smoke_view_items[] = {
{MOD_SMOKE_SLICE_VIEW_ALIGNED, "VIEW_ALIGNED", 0, "View", "Slice volume parallel to the view plane"},
{MOD_SMOKE_SLICE_AXIS_ALIGNED, "AXIS_ALIGNED", 0, "Axis", "Slice volume parallel to the major axis"},
@@ -514,7 +471,7 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna)
RNA_def_property_ui_range(prop, -5.0, 5.0, 0.02, 5);
RNA_def_property_ui_text(prop, "Density",
"How much density affects smoke motion (higher value results in faster rising smoke)");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_update");
prop = RNA_def_property(srna, "beta", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "beta");
@@ -522,7 +479,7 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna)
RNA_def_property_ui_range(prop, -5.0, 5.0, 0.02, 5);
RNA_def_property_ui_text(prop, "Heat",
"How much heat affects smoke motion (higher value results in faster rising smoke)");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_update");
prop = RNA_def_property(srna, "collision_group", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "coll_group");
@@ -550,34 +507,24 @@ static void rna_def_smoke_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_Smoke_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_update");
prop = RNA_def_property(srna, "dissolve_speed", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "diss_speed");
RNA_def_property_range(prop, 1.0, 10000.0);
RNA_def_property_ui_range(prop, 1.0, 10000.0, 1, -1);
RNA_def_property_ui_text(prop, "Dissolve Speed", "Dissolve Speed");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_update");
prop = RNA_def_property(srna, "use_dissolve_smoke", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_SMOKE_DISSOLVE);
RNA_def_property_ui_text(prop, "Dissolve Smoke", "Enable smoke to disappear over time");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_update");
prop = RNA_def_property(srna, "use_dissolve_smoke_log", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_SMOKE_DISSOLVE_LOG);
RNA_def_property_ui_text(prop, "Logarithmic dissolve", "Using 1/x ");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache");
-
- prop = RNA_def_property(srna, "point_cache", PROP_POINTER, PROP_NONE);
- RNA_def_property_flag(prop, PROP_NEVER_NULL);
- RNA_def_property_pointer_sdna(prop, NULL, "point_cache[0]");
- RNA_def_property_ui_text(prop, "Point Cache", "");
-
- prop = RNA_def_property(srna, "point_cache_compress_type", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "cache_comp");
- RNA_def_property_enum_items(prop, smoke_cache_comp_items);
- RNA_def_property_ui_text(prop, "Cache Compression", "Compression method to be used");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_update");
prop = RNA_def_property(srna, "openvdb_cache_compress_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "openvdb_comp");
@@ -607,21 +554,21 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna)
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_Smoke_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_update");
prop = RNA_def_property(srna, "time_scale", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "time_scale");
RNA_def_property_range(prop, 0.2, 1.5);
RNA_def_property_ui_range(prop, 0.2, 1.5, 0.02, 5);
RNA_def_property_ui_text(prop, "Time Scale", "Adjust simulation speed");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_update");
prop = RNA_def_property(srna, "vorticity", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "vorticity");
RNA_def_property_range(prop, 0.01, 4.0);
RNA_def_property_ui_range(prop, 0.01, 4.0, 0.02, 5);
RNA_def_property_ui_text(prop, "Vorticity", "Amount of turbulence/rotation in fluid");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_update");
prop = RNA_def_property(srna, "density_grid", PROP_FLOAT, PROP_NONE);
RNA_def_property_array(prop, 32);
@@ -681,36 +628,36 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna)
RNA_def_property_range(prop, 0.01, 4.0);
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 (use larger values for smaller flame)");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_update");
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_Smoke_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_update");
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_Smoke_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_update");
prop = RNA_def_property(srna, "flame_ignition", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.5, 5.0);
RNA_def_property_ui_range(prop, 0.5, 2.5, 1.0, 5);
RNA_def_property_ui_text(prop, "Ignition", "Minimum temperature of flames");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_update");
prop = RNA_def_property(srna, "flame_max_temp", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 1.0, 10.0);
RNA_def_property_ui_range(prop, 1.0, 5.0, 1.0, 5);
RNA_def_property_ui_text(prop, "Maximum", "Maximum temperature of flames");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_update");
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_Smoke_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_update");
prop = RNA_def_property(srna, "use_adaptive_domain", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_SMOKE_ADAPTIVE_DOMAIN);
@@ -723,28 +670,20 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna)
RNA_def_property_range(prop, 0, 512);
RNA_def_property_ui_range(prop, 0, 512, 2, -1);
RNA_def_property_ui_text(prop, "Additional", "Maximum number of additional cells");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_update");
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_range(prop, 2, 24, 2, -1);
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_Smoke_resetCache");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_update");
prop = RNA_def_property(srna, "adapt_threshold", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.01, 0.5);
RNA_def_property_ui_range(prop, 0.01, 0.5, 1.0, 5);
RNA_def_property_ui_text(prop, "Threshold",
"Maximum amount of fluid cell can contain before it is considered empty");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache");
-
- prop = RNA_def_property(srna, "cache_file_format", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "cache_file_format");
- RNA_def_property_enum_items(prop, cache_file_type_items);
- RNA_def_property_enum_funcs(prop, NULL, "rna_Smoke_cachetype_set", NULL);
- RNA_def_property_ui_text(prop, "File Format", "Select the file format to be used for caching");
- RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache");
/* display settings */
@@ -863,13 +802,6 @@ static void rna_def_smoke_flow_settings(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Temp. Diff.", "Temperature difference to ambient temperature");
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset");
- prop = RNA_def_property(srna, "particle_system", PROP_POINTER, PROP_NONE);
- RNA_def_property_pointer_sdna(prop, NULL, "psys");
- RNA_def_property_struct_type(prop, "ParticleSystem");
- RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Particle Systems", "Particle systems emitted from the object");
- RNA_def_property_update(prop, 0, "rna_Smoke_reset_dependency");
-
prop = RNA_def_property(srna, "smoke_flow_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "type");
RNA_def_property_enum_items(prop, smoke_flow_types);
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index b9fbec6f12e..eb4d51657b9 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -208,7 +208,6 @@ static EnumPropertyItem buttons_context_items[] = {
{BCONTEXT_BONE_CONSTRAINT, "BONE_CONSTRAINT", ICON_CONSTRAINT_BONE, "Bone Constraints", "Bone constraints"},
{BCONTEXT_MATERIAL, "MATERIAL", ICON_MATERIAL, "Material", "Material"},
{BCONTEXT_TEXTURE, "TEXTURE", ICON_TEXTURE, "Texture", "Texture"},
- {BCONTEXT_PARTICLE, "PARTICLES", ICON_PARTICLES, "Particles", "Particle"},
{BCONTEXT_PHYSICS, "PHYSICS", ICON_PHYSICS, "Physics", "Physics"},
{0, NULL, 0, NULL, NULL}
};
@@ -218,7 +217,6 @@ static EnumPropertyItem buttons_texture_context_items[] = {
{SB_TEXC_MATERIAL, "MATERIAL", ICON_MATERIAL, "", "Show material textures"},
{SB_TEXC_WORLD, "WORLD", ICON_WORLD, "", "Show world textures"},
{SB_TEXC_LAMP, "LAMP", ICON_LAMP, "", "Show lamp textures"},
- {SB_TEXC_PARTICLES, "PARTICLES", ICON_PARTICLES, "", "Show particles textures"},
{SB_TEXC_LINESTYLE, "LINESTYLE", ICON_LINE_DATA, "", "Show linestyle textures"},
{SB_TEXC_OTHER, "OTHER", ICON_TEXTURE, "", "Show other data textures"},
{0, NULL, 0, NULL, NULL}
@@ -1141,10 +1139,6 @@ static EnumPropertyItem *rna_SpaceProperties_context_itemf(bContext *UNUSED(C),
RNA_enum_items_add_value(&item, &totitem, buttons_context_items, BCONTEXT_TEXTURE);
}
- if (sbuts->pathflag & (1 << BCONTEXT_PARTICLE)) {
- RNA_enum_items_add_value(&item, &totitem, buttons_context_items, BCONTEXT_PARTICLE);
- }
-
if (sbuts->pathflag & (1 << BCONTEXT_PHYSICS)) {
RNA_enum_items_add_value(&item, &totitem, buttons_context_items, BCONTEXT_PHYSICS);
}
@@ -1188,10 +1182,6 @@ static EnumPropertyItem *rna_SpaceProperties_texture_context_itemf(bContext *C,
RNA_enum_items_add_value(&item, &totitem, buttons_texture_context_items, SB_TEXC_MATERIAL);
}
- if (ED_texture_context_check_particles(C)) {
- RNA_enum_items_add_value(&item, &totitem, buttons_texture_context_items, SB_TEXC_PARTICLES);
- }
-
if (ED_texture_context_check_linestyle(C)) {
RNA_enum_items_add_value(&item, &totitem, buttons_texture_context_items, SB_TEXC_LINESTYLE);
}
@@ -2920,6 +2910,12 @@ static void rna_def_space_view3d(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Volume Alpha", "Opacity (alpha) of the cameras' frustum volume");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+ /* *** Blender 2.8 Viewport temporary *** */
+ prop = RNA_def_property(srna, "use_modern_viewport", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "tmp_compat_flag", V3D_NEW_VIEWPORT);
+ RNA_def_property_ui_text(prop, "Modern Viewport", "Use modern viewport");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
/* *** Animated *** */
RNA_define_animate_sdna(true);
/* region */
@@ -3847,11 +3843,6 @@ static void rna_def_space_time(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Softbody", "Show the active object's softbody point cache");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_TIME, NULL);
- prop = RNA_def_property(srna, "cache_particles", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "cache_display", TIME_CACHE_PARTICLES);
- RNA_def_property_ui_text(prop, "Particles", "Show the active object's particle point cache");
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_TIME, NULL);
-
prop = RNA_def_property(srna, "cache_cloth", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "cache_display", TIME_CACHE_CLOTH);
RNA_def_property_ui_text(prop, "Cloth", "Show the active object's cloth point cache");
@@ -3990,8 +3981,6 @@ static void rna_def_fileselect_params(BlenderRNA *brna)
{FILTER_ID_MSK, "MASK", ICON_MOD_MASK, "Masks", "Show/hide Mask data-blocks"},
{FILTER_ID_NT, "NODE_TREE", ICON_NODETREE, "Node Trees", "Show/hide Node Tree data-blocks"},
{FILTER_ID_OB, "OBJECT", ICON_OBJECT_DATA, "Objects", "Show/hide Object data-blocks"},
- {FILTER_ID_PA, "PARTICLE_SETTINGS", ICON_PARTICLE_DATA,
- "Particles Settings", "Show/hide Particle Settings data-blocks"},
{FILTER_ID_PAL, "PALETTE", ICON_COLOR, "Palettes", "Show/hide Palette data-blocks"},
{FILTER_ID_PC, "PAINT_CURVE", ICON_CURVE_BEZCURVE, "Paint Curves", "Show/hide Paint Curve data-blocks"},
{FILTER_ID_SCE, "SCENE", ICON_SCENE_DATA, "Scenes", "Show/hide Scene data-blocks"},
@@ -4020,7 +4009,7 @@ static void rna_def_fileselect_params(BlenderRNA *brna)
"IMAGE", ICON_IMAGE_DATA, "Images & Sounds", "Show/hide images, movie clips, sounds and masks"},
{FILTER_ID_CA | FILTER_ID_LA | FILTER_ID_SPK | FILTER_ID_WO,
"ENVIRONMENT", ICON_WORLD_DATA, "Environment", "Show/hide worlds, lamps, cameras and speakers"},
- {FILTER_ID_BR | FILTER_ID_GD | FILTER_ID_PA | FILTER_ID_PAL | FILTER_ID_PC | FILTER_ID_TXT | FILTER_ID_VF | FILTER_ID_CF,
+ {FILTER_ID_BR | FILTER_ID_GD | FILTER_ID_PAL | FILTER_ID_PC | FILTER_ID_TXT | FILTER_ID_VF | FILTER_ID_CF,
"MISC", ICON_GREASEPENCIL, "Miscellaneous", "Show/hide other data types"},
{0, NULL, 0, NULL, NULL}
};
diff --git a/source/blender/makesrna/intern/rna_texture.c b/source/blender/makesrna/intern/rna_texture.c
index 1e88585a286..959f30170f5 100644
--- a/source/blender/makesrna/intern/rna_texture.c
+++ b/source/blender/makesrna/intern/rna_texture.c
@@ -35,7 +35,6 @@
#include "DNA_texture_types.h"
#include "DNA_world_types.h"
#include "DNA_node_types.h"
-#include "DNA_particle_types.h"
#include "DNA_scene_types.h" /* MAXFRAME only */
#include "BLI_utildefines.h"
@@ -253,20 +252,6 @@ void rna_TextureSlot_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr)
case ID_LS:
WM_main_add_notifier(NC_LINESTYLE, id);
break;
- case ID_PA:
- {
- MTex *mtex = ptr->data;
- int recalc = OB_RECALC_DATA;
-
- if (mtex->mapto & PAMAP_INIT)
- recalc |= PSYS_RECALC_RESET;
- if (mtex->mapto & PAMAP_CHILD)
- recalc |= PSYS_RECALC_CHILD;
-
- DAG_id_tag_update(id, recalc);
- WM_main_add_notifier(NC_OBJECT | ND_PARTICLE | NA_EDITED, NULL);
- break;
- }
}
}
@@ -436,29 +421,6 @@ static void rna_Envmap_update_generic(Main *bmain, Scene *scene, PointerRNA *ptr
rna_Texture_update(bmain, scene, ptr);
}
-static PointerRNA rna_PointDensity_psys_get(PointerRNA *ptr)
-{
- PointDensity *pd = ptr->data;
- Object *ob = pd->object;
- ParticleSystem *psys = NULL;
- PointerRNA value;
-
- if (ob && pd->psys)
- psys = BLI_findlink(&ob->particlesystem, pd->psys - 1);
-
- RNA_pointer_create(&ob->id, &RNA_ParticleSystem, psys, &value);
- return value;
-}
-
-static void rna_PointDensity_psys_set(PointerRNA *ptr, PointerRNA value)
-{
- PointDensity *pd = ptr->data;
- Object *ob = pd->object;
-
- if (ob && value.id.data == ob)
- pd->psys = BLI_findindex(&ob->particlesystem, value.data) + 1;
-}
-
static char *rna_PointDensity_path(PointerRNA *UNUSED(ptr))
{
return BLI_sprintfN("point_density");
@@ -1699,13 +1661,6 @@ static void rna_def_texture_pointdensity(BlenderRNA *brna)
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_update(prop, 0, "rna_Texture_update");
- prop = RNA_def_property(srna, "particle_system", PROP_POINTER, PROP_NONE);
- RNA_def_property_ui_text(prop, "Particle System", "Particle System to render as points");
- RNA_def_property_struct_type(prop, "ParticleSystem");
- RNA_def_property_pointer_funcs(prop, "rna_PointDensity_psys_get", "rna_PointDensity_psys_set", NULL, NULL);
- RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_update(prop, 0, "rna_Texture_update");
-
prop = RNA_def_property(srna, "particle_cache_space", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "psys_cache_space");
RNA_def_property_enum_items(prop, particle_cache_items);
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index 8ad016007f4..fd5a9d9ecc5 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -3862,10 +3862,6 @@ static void rna_def_userdef_edit(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_duplicate_action", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "dupflag", USER_DUP_ACT);
RNA_def_property_ui_text(prop, "Duplicate Action", "Causes actions to be duplicated with the object");
-
- prop = RNA_def_property(srna, "use_duplicate_particle", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "dupflag", USER_DUP_PSYS);
- RNA_def_property_ui_text(prop, "Duplicate Particle", "Causes particle systems to be duplicated with the object");
/* currently only used for insert offset (aka auto-offset), maybe also be useful for later stuff though */
prop = RNA_def_property(srna, "node_margin", PROP_INT, PROP_NONE);
diff --git a/source/blender/modifiers/CMakeLists.txt b/source/blender/modifiers/CMakeLists.txt
index b8ebb375a48..d5b9303249a 100644
--- a/source/blender/modifiers/CMakeLists.txt
+++ b/source/blender/modifiers/CMakeLists.txt
@@ -79,8 +79,6 @@ set(SRC
intern/MOD_none.c
intern/MOD_normal_edit.c
intern/MOD_ocean.c
- intern/MOD_particleinstance.c
- intern/MOD_particlesystem.c
intern/MOD_remesh.c
intern/MOD_screw.c
intern/MOD_shapekey.c
diff --git a/source/blender/modifiers/MOD_modifiertypes.h b/source/blender/modifiers/MOD_modifiertypes.h
index 4c881445893..93176cb012a 100644
--- a/source/blender/modifiers/MOD_modifiertypes.h
+++ b/source/blender/modifiers/MOD_modifiertypes.h
@@ -50,8 +50,6 @@ extern ModifierTypeInfo modifierType_UVProject;
extern ModifierTypeInfo modifierType_Smooth;
extern ModifierTypeInfo modifierType_Cast;
extern ModifierTypeInfo modifierType_MeshDeform;
-extern ModifierTypeInfo modifierType_ParticleSystem;
-extern ModifierTypeInfo modifierType_ParticleInstance;
extern ModifierTypeInfo modifierType_Explode;
extern ModifierTypeInfo modifierType_Cloth;
extern ModifierTypeInfo modifierType_Collision;
diff --git a/source/blender/modifiers/intern/MOD_build.c b/source/blender/modifiers/intern/MOD_build.c
index a364eef2974..8f3e1c24141 100644
--- a/source/blender/modifiers/intern/MOD_build.c
+++ b/source/blender/modifiers/intern/MOD_build.c
@@ -41,10 +41,10 @@
#include "BLI_ghash.h"
#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_modifier.h"
-#include "BKE_particle.h"
#include "BKE_scene.h"
#ifdef _OPENMP
diff --git a/source/blender/modifiers/intern/MOD_cloth.c b/source/blender/modifiers/intern/MOD_cloth.c
index d15a6fcb1c8..0b99aa55c8d 100644
--- a/source/blender/modifiers/intern/MOD_cloth.c
+++ b/source/blender/modifiers/intern/MOD_cloth.c
@@ -37,6 +37,7 @@
#include "DNA_cloth_types.h"
#include "DNA_key_types.h"
#include "DNA_scene_types.h"
+#include "DNA_object_force.h"
#include "DNA_object_types.h"
#include "MEM_guardedalloc.h"
@@ -51,7 +52,6 @@
#include "BKE_key.h"
#include "BKE_library_query.h"
#include "BKE_modifier.h"
-#include "BKE_pointcache.h"
#include "depsgraph_private.h"
@@ -63,10 +63,9 @@ static void initData(ModifierData *md)
clmd->sim_parms = MEM_callocN(sizeof(ClothSimSettings), "cloth sim parms");
clmd->coll_parms = MEM_callocN(sizeof(ClothCollSettings), "cloth coll parms");
- clmd->point_cache = BKE_ptcache_add(&clmd->ptcaches);
/* check for alloc failing */
- if (!clmd->sim_parms || !clmd->coll_parms || !clmd->point_cache)
+ if (!clmd->sim_parms || !clmd->coll_parms)
return;
cloth_init(clmd);
@@ -174,15 +173,10 @@ static void copyData(ModifierData *md, ModifierData *target)
if (tclmd->coll_parms)
MEM_freeN(tclmd->coll_parms);
- BKE_ptcache_free_list(&tclmd->ptcaches);
- tclmd->point_cache = NULL;
-
tclmd->sim_parms = MEM_dupallocN(clmd->sim_parms);
if (clmd->sim_parms->effector_weights)
tclmd->sim_parms->effector_weights = MEM_dupallocN(clmd->sim_parms->effector_weights);
tclmd->coll_parms = MEM_dupallocN(clmd->coll_parms);
- tclmd->point_cache = BKE_ptcache_add(&tclmd->ptcaches);
- tclmd->point_cache->step = 1;
tclmd->clothObject = NULL;
tclmd->hairdata = NULL;
tclmd->solver_result = NULL;
@@ -211,9 +205,6 @@ static void freeData(ModifierData *md)
if (clmd->coll_parms)
MEM_freeN(clmd->coll_parms);
- BKE_ptcache_free_list(&clmd->ptcaches);
- clmd->point_cache = NULL;
-
if (clmd->hairdata)
MEM_freeN(clmd->hairdata);
diff --git a/source/blender/modifiers/intern/MOD_collision.c b/source/blender/modifiers/intern/MOD_collision.c
index e7ff0a90fbc..8790d8083a6 100644
--- a/source/blender/modifiers/intern/MOD_collision.c
+++ b/source/blender/modifiers/intern/MOD_collision.c
@@ -34,6 +34,7 @@
#include "DNA_object_types.h"
#include "DNA_meshdata_types.h"
+#include "DNA_object_force.h"
#include "MEM_guardedalloc.h"
@@ -45,7 +46,6 @@
#include "BKE_cdderivedmesh.h"
#include "BKE_global.h"
#include "BKE_modifier.h"
-#include "BKE_pointcache.h"
#include "BKE_scene.h"
static void initData(ModifierData *md)
diff --git a/source/blender/modifiers/intern/MOD_explode.c b/source/blender/modifiers/intern/MOD_explode.c
index 38ffdaa709b..97f4423b798 100644
--- a/source/blender/modifiers/intern/MOD_explode.c
+++ b/source/blender/modifiers/intern/MOD_explode.c
@@ -48,7 +48,6 @@
#include "BKE_lattice.h"
#include "BKE_mesh.h"
#include "BKE_modifier.h"
-#include "BKE_particle.h"
#include "BKE_scene.h"
@@ -94,950 +93,10 @@ static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
return dataMask;
}
-static void createFacepa(ExplodeModifierData *emd,
- ParticleSystemModifierData *psmd,
- DerivedMesh *dm)
-{
- ParticleSystem *psys = psmd->psys;
- MFace *fa = NULL, *mface = NULL;
- MVert *mvert = NULL;
- ParticleData *pa;
- KDTree *tree;
- RNG *rng;
- float center[3], co[3];
- int *facepa = NULL, *vertpa = NULL, totvert = 0, totface = 0, totpart = 0;
- int i, p, v1, v2, v3, v4 = 0;
-
- mvert = dm->getVertArray(dm);
- mface = dm->getTessFaceArray(dm);
- totface = dm->getNumTessFaces(dm);
- totvert = dm->getNumVerts(dm);
- totpart = psmd->psys->totpart;
-
- rng = BLI_rng_new_srandom(psys->seed);
-
- if (emd->facepa)
- MEM_freeN(emd->facepa);
-
- facepa = emd->facepa = MEM_callocN(sizeof(int) * totface, "explode_facepa");
-
- vertpa = MEM_callocN(sizeof(int) * totvert, "explode_vertpa");
-
- /* initialize all faces & verts to no particle */
- for (i = 0; i < totface; i++)
- facepa[i] = totpart;
-
- for (i = 0; i < totvert; i++)
- vertpa[i] = totpart;
-
- /* set protected verts */
- if (emd->vgroup) {
- MDeformVert *dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
- if (dvert) {
- const int defgrp_index = emd->vgroup - 1;
- for (i = 0; i < totvert; i++, dvert++) {
- float val = BLI_rng_get_float(rng);
- val = (1.0f - emd->protect) * val + emd->protect * 0.5f;
- if (val < defvert_find_weight(dvert, defgrp_index))
- vertpa[i] = -1;
- }
- }
- }
-
- /* make tree of emitter locations */
- tree = BLI_kdtree_new(totpart);
- for (p = 0, pa = psys->particles; p < totpart; p++, pa++) {
- psys_particle_on_emitter(psmd, psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, co, NULL, NULL, NULL, NULL, NULL);
- BLI_kdtree_insert(tree, p, co);
- }
- BLI_kdtree_balance(tree);
-
- /* set face-particle-indexes to nearest particle to face center */
- for (i = 0, fa = mface; i < totface; i++, fa++) {
- add_v3_v3v3(center, mvert[fa->v1].co, mvert[fa->v2].co);
- add_v3_v3(center, mvert[fa->v3].co);
- if (fa->v4) {
- add_v3_v3(center, mvert[fa->v4].co);
- mul_v3_fl(center, 0.25);
- }
- else
- mul_v3_fl(center, 1.0f / 3.0f);
-
- p = BLI_kdtree_find_nearest(tree, center, NULL);
-
- v1 = vertpa[fa->v1];
- v2 = vertpa[fa->v2];
- v3 = vertpa[fa->v3];
- if (fa->v4)
- v4 = vertpa[fa->v4];
-
- if (v1 >= 0 && v2 >= 0 && v3 >= 0 && (fa->v4 == 0 || v4 >= 0))
- facepa[i] = p;
-
- if (v1 >= 0) vertpa[fa->v1] = p;
- if (v2 >= 0) vertpa[fa->v2] = p;
- if (v3 >= 0) vertpa[fa->v3] = p;
- if (fa->v4 && v4 >= 0) vertpa[fa->v4] = p;
- }
-
- if (vertpa) MEM_freeN(vertpa);
- BLI_kdtree_free(tree);
-
- BLI_rng_free(rng);
-}
-
-static int edgecut_get(EdgeHash *edgehash, unsigned int v1, unsigned int v2)
-{
- return GET_INT_FROM_POINTER(BLI_edgehash_lookup(edgehash, v1, v2));
-}
-
-
-static const short add_faces[24] = {
- 0,
- 0, 0, 2, 0, 1, 2, 2, 0, 2, 1,
- 2, 2, 2, 2, 3, 0, 0, 0, 1, 0,
- 1, 1, 2
-};
-
-static MFace *get_dface(DerivedMesh *dm, DerivedMesh *split, int cur, int i, MFace *mf)
-{
- MFace *df = CDDM_get_tessface(split, cur);
- DM_copy_tessface_data(dm, split, i, cur, 1);
- *df = *mf;
- return df;
-}
-
-#define SET_VERTS(a, b, c, d) \
- { \
- v[0] = mf->v##a; uv[0] = a - 1; \
- v[1] = mf->v##b; uv[1] = b - 1; \
- v[2] = mf->v##c; uv[2] = c - 1; \
- v[3] = mf->v##d; uv[3] = d - 1; \
- } (void)0
-
-#define GET_ES(v1, v2) edgecut_get(eh, v1, v2)
-#define INT_UV(uvf, c0, c1) mid_v2_v2v2(uvf, mf->uv[c0], mf->uv[c1])
-
-static void remap_faces_3_6_9_12(DerivedMesh *dm, DerivedMesh *split, MFace *mf, int *facepa, int *vertpa, int i, EdgeHash *eh, int cur, int v1, int v2, int v3, int v4)
-{
- MFace *df1 = get_dface(dm, split, cur, i, mf);
- MFace *df2 = get_dface(dm, split, cur + 1, i, mf);
- MFace *df3 = get_dface(dm, split, cur + 2, i, mf);
-
- facepa[cur] = vertpa[v1];
- df1->v1 = v1;
- df1->v2 = GET_ES(v1, v2);
- df1->v3 = GET_ES(v2, v3);
- df1->v4 = v3;
- df1->flag |= ME_FACE_SEL;
-
- facepa[cur + 1] = vertpa[v2];
- df2->v1 = GET_ES(v1, v2);
- df2->v2 = v2;
- df2->v3 = GET_ES(v2, v3);
- df2->v4 = 0;
- df2->flag &= ~ME_FACE_SEL;
-
- facepa[cur + 2] = vertpa[v1];
- df3->v1 = v1;
- df3->v2 = v3;
- df3->v3 = v4;
- df3->v4 = 0;
- df3->flag &= ~ME_FACE_SEL;
-}
-
-static void remap_uvs_3_6_9_12(DerivedMesh *dm, DerivedMesh *split, int numlayer, int i, int cur, int c0, int c1, int c2, int c3)
-{
- MTFace *mf, *df1, *df2, *df3;
- int l;
-
- for (l = 0; l < numlayer; l++) {
- mf = CustomData_get_layer_n(&split->faceData, CD_MTFACE, l);
- df1 = mf + cur;
- df2 = df1 + 1;
- df3 = df1 + 2;
- mf = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, l);
- mf += i;
-
- copy_v2_v2(df1->uv[0], mf->uv[c0]);
- INT_UV(df1->uv[1], c0, c1);
- INT_UV(df1->uv[2], c1, c2);
- copy_v2_v2(df1->uv[3], mf->uv[c2]);
-
- INT_UV(df2->uv[0], c0, c1);
- copy_v2_v2(df2->uv[1], mf->uv[c1]);
- INT_UV(df2->uv[2], c1, c2);
-
- copy_v2_v2(df3->uv[0], mf->uv[c0]);
- copy_v2_v2(df3->uv[1], mf->uv[c2]);
- copy_v2_v2(df3->uv[2], mf->uv[c3]);
- }
-}
-
-static void remap_faces_5_10(DerivedMesh *dm, DerivedMesh *split, MFace *mf, int *facepa, int *vertpa, int i, EdgeHash *eh, int cur, int v1, int v2, int v3, int v4)
-{
- MFace *df1 = get_dface(dm, split, cur, i, mf);
- MFace *df2 = get_dface(dm, split, cur + 1, i, mf);
-
- facepa[cur] = vertpa[v1];
- df1->v1 = v1;
- df1->v2 = v2;
- df1->v3 = GET_ES(v2, v3);
- df1->v4 = GET_ES(v1, v4);
- df1->flag |= ME_FACE_SEL;
-
- facepa[cur + 1] = vertpa[v3];
- df2->v1 = GET_ES(v1, v4);
- df2->v2 = GET_ES(v2, v3);
- df2->v3 = v3;
- df2->v4 = v4;
- df2->flag |= ME_FACE_SEL;
-}
-
-static void remap_uvs_5_10(DerivedMesh *dm, DerivedMesh *split, int numlayer, int i, int cur, int c0, int c1, int c2, int c3)
-{
- MTFace *mf, *df1, *df2;
- int l;
-
- for (l = 0; l < numlayer; l++) {
- mf = CustomData_get_layer_n(&split->faceData, CD_MTFACE, l);
- df1 = mf + cur;
- df2 = df1 + 1;
- mf = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, l);
- mf += i;
-
- copy_v2_v2(df1->uv[0], mf->uv[c0]);
- copy_v2_v2(df1->uv[1], mf->uv[c1]);
- INT_UV(df1->uv[2], c1, c2);
- INT_UV(df1->uv[3], c0, c3);
-
- INT_UV(df2->uv[0], c0, c3);
- INT_UV(df2->uv[1], c1, c2);
- copy_v2_v2(df2->uv[2], mf->uv[c2]);
- copy_v2_v2(df2->uv[3], mf->uv[c3]);
-
- }
-}
-
-static void remap_faces_15(DerivedMesh *dm, DerivedMesh *split, MFace *mf, int *facepa, int *vertpa, int i, EdgeHash *eh, int cur, int v1, int v2, int v3, int v4)
-{
- MFace *df1 = get_dface(dm, split, cur, i, mf);
- MFace *df2 = get_dface(dm, split, cur + 1, i, mf);
- MFace *df3 = get_dface(dm, split, cur + 2, i, mf);
- MFace *df4 = get_dface(dm, split, cur + 3, i, mf);
-
- facepa[cur] = vertpa[v1];
- df1->v1 = v1;
- df1->v2 = GET_ES(v1, v2);
- df1->v3 = GET_ES(v1, v3);
- df1->v4 = GET_ES(v1, v4);
- df1->flag |= ME_FACE_SEL;
-
- facepa[cur + 1] = vertpa[v2];
- df2->v1 = GET_ES(v1, v2);
- df2->v2 = v2;
- df2->v3 = GET_ES(v2, v3);
- df2->v4 = GET_ES(v1, v3);
- df2->flag |= ME_FACE_SEL;
-
- facepa[cur + 2] = vertpa[v3];
- df3->v1 = GET_ES(v1, v3);
- df3->v2 = GET_ES(v2, v3);
- df3->v3 = v3;
- df3->v4 = GET_ES(v3, v4);
- df3->flag |= ME_FACE_SEL;
-
- facepa[cur + 3] = vertpa[v4];
- df4->v1 = GET_ES(v1, v4);
- df4->v2 = GET_ES(v1, v3);
- df4->v3 = GET_ES(v3, v4);
- df4->v4 = v4;
- df4->flag |= ME_FACE_SEL;
-}
-
-static void remap_uvs_15(DerivedMesh *dm, DerivedMesh *split, int numlayer, int i, int cur, int c0, int c1, int c2, int c3)
-{
- MTFace *mf, *df1, *df2, *df3, *df4;
- int l;
-
- for (l = 0; l < numlayer; l++) {
- mf = CustomData_get_layer_n(&split->faceData, CD_MTFACE, l);
- df1 = mf + cur;
- df2 = df1 + 1;
- df3 = df1 + 2;
- df4 = df1 + 3;
- mf = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, l);
- mf += i;
-
- copy_v2_v2(df1->uv[0], mf->uv[c0]);
- INT_UV(df1->uv[1], c0, c1);
- INT_UV(df1->uv[2], c0, c2);
- INT_UV(df1->uv[3], c0, c3);
-
- INT_UV(df2->uv[0], c0, c1);
- copy_v2_v2(df2->uv[1], mf->uv[c1]);
- INT_UV(df2->uv[2], c1, c2);
- INT_UV(df2->uv[3], c0, c2);
-
- INT_UV(df3->uv[0], c0, c2);
- INT_UV(df3->uv[1], c1, c2);
- copy_v2_v2(df3->uv[2], mf->uv[c2]);
- INT_UV(df3->uv[3], c2, c3);
-
- INT_UV(df4->uv[0], c0, c3);
- INT_UV(df4->uv[1], c0, c2);
- INT_UV(df4->uv[2], c2, c3);
- copy_v2_v2(df4->uv[3], mf->uv[c3]);
- }
-}
-
-static void remap_faces_7_11_13_14(DerivedMesh *dm, DerivedMesh *split, MFace *mf, int *facepa, int *vertpa, int i, EdgeHash *eh, int cur, int v1, int v2, int v3, int v4)
-{
- MFace *df1 = get_dface(dm, split, cur, i, mf);
- MFace *df2 = get_dface(dm, split, cur + 1, i, mf);
- MFace *df3 = get_dface(dm, split, cur + 2, i, mf);
-
- facepa[cur] = vertpa[v1];
- df1->v1 = v1;
- df1->v2 = GET_ES(v1, v2);
- df1->v3 = GET_ES(v2, v3);
- df1->v4 = GET_ES(v1, v4);
- df1->flag |= ME_FACE_SEL;
-
- facepa[cur + 1] = vertpa[v2];
- df2->v1 = GET_ES(v1, v2);
- df2->v2 = v2;
- df2->v3 = GET_ES(v2, v3);
- df2->v4 = 0;
- df2->flag &= ~ME_FACE_SEL;
-
- facepa[cur + 2] = vertpa[v4];
- df3->v1 = GET_ES(v1, v4);
- df3->v2 = GET_ES(v2, v3);
- df3->v3 = v3;
- df3->v4 = v4;
- df3->flag |= ME_FACE_SEL;
-}
-
-static void remap_uvs_7_11_13_14(DerivedMesh *dm, DerivedMesh *split, int numlayer, int i, int cur, int c0, int c1, int c2, int c3)
-{
- MTFace *mf, *df1, *df2, *df3;
- int l;
-
- for (l = 0; l < numlayer; l++) {
- mf = CustomData_get_layer_n(&split->faceData, CD_MTFACE, l);
- df1 = mf + cur;
- df2 = df1 + 1;
- df3 = df1 + 2;
- mf = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, l);
- mf += i;
-
- copy_v2_v2(df1->uv[0], mf->uv[c0]);
- INT_UV(df1->uv[1], c0, c1);
- INT_UV(df1->uv[2], c1, c2);
- INT_UV(df1->uv[3], c0, c3);
-
- INT_UV(df2->uv[0], c0, c1);
- copy_v2_v2(df2->uv[1], mf->uv[c1]);
- INT_UV(df2->uv[2], c1, c2);
-
- INT_UV(df3->uv[0], c0, c3);
- INT_UV(df3->uv[1], c1, c2);
- copy_v2_v2(df3->uv[2], mf->uv[c2]);
- copy_v2_v2(df3->uv[3], mf->uv[c3]);
- }
-}
-
-static void remap_faces_19_21_22(DerivedMesh *dm, DerivedMesh *split, MFace *mf, int *facepa, int *vertpa, int i, EdgeHash *eh, int cur, int v1, int v2, int v3)
-{
- MFace *df1 = get_dface(dm, split, cur, i, mf);
- MFace *df2 = get_dface(dm, split, cur + 1, i, mf);
-
- facepa[cur] = vertpa[v1];
- df1->v1 = v1;
- df1->v2 = GET_ES(v1, v2);
- df1->v3 = GET_ES(v1, v3);
- df1->v4 = 0;
- df1->flag &= ~ME_FACE_SEL;
-
- facepa[cur + 1] = vertpa[v2];
- df2->v1 = GET_ES(v1, v2);
- df2->v2 = v2;
- df2->v3 = v3;
- df2->v4 = GET_ES(v1, v3);
- df2->flag |= ME_FACE_SEL;
-}
-
-static void remap_uvs_19_21_22(DerivedMesh *dm, DerivedMesh *split, int numlayer, int i, int cur, int c0, int c1, int c2)
-{
- MTFace *mf, *df1, *df2;
- int l;
-
- for (l = 0; l < numlayer; l++) {
- mf = CustomData_get_layer_n(&split->faceData, CD_MTFACE, l);
- df1 = mf + cur;
- df2 = df1 + 1;
- mf = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, l);
- mf += i;
-
- copy_v2_v2(df1->uv[0], mf->uv[c0]);
- INT_UV(df1->uv[1], c0, c1);
- INT_UV(df1->uv[2], c0, c2);
-
- INT_UV(df2->uv[0], c0, c1);
- copy_v2_v2(df2->uv[1], mf->uv[c1]);
- copy_v2_v2(df2->uv[2], mf->uv[c2]);
- INT_UV(df2->uv[3], c0, c2);
- }
-}
-
-static void remap_faces_23(DerivedMesh *dm, DerivedMesh *split, MFace *mf, int *facepa, int *vertpa, int i, EdgeHash *eh, int cur, int v1, int v2, int v3)
-{
- MFace *df1 = get_dface(dm, split, cur, i, mf);
- MFace *df2 = get_dface(dm, split, cur + 1, i, mf);
- MFace *df3 = get_dface(dm, split, cur + 2, i, mf);
-
- facepa[cur] = vertpa[v1];
- df1->v1 = v1;
- df1->v2 = GET_ES(v1, v2);
- df1->v3 = GET_ES(v2, v3);
- df1->v4 = GET_ES(v1, v3);
- df1->flag |= ME_FACE_SEL;
-
- facepa[cur + 1] = vertpa[v2];
- df2->v1 = GET_ES(v1, v2);
- df2->v2 = v2;
- df2->v3 = GET_ES(v2, v3);
- df2->v4 = 0;
- df2->flag &= ~ME_FACE_SEL;
-
- facepa[cur + 2] = vertpa[v3];
- df3->v1 = GET_ES(v1, v3);
- df3->v2 = GET_ES(v2, v3);
- df3->v3 = v3;
- df3->v4 = 0;
- df3->flag &= ~ME_FACE_SEL;
-}
-
-static void remap_uvs_23(DerivedMesh *dm, DerivedMesh *split, int numlayer, int i, int cur, int c0, int c1, int c2)
-{
- MTFace *mf, *df1, *df2;
- int l;
-
- for (l = 0; l < numlayer; l++) {
- mf = CustomData_get_layer_n(&split->faceData, CD_MTFACE, l);
- df1 = mf + cur;
- df2 = df1 + 1;
- mf = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, l);
- mf += i;
-
- copy_v2_v2(df1->uv[0], mf->uv[c0]);
- INT_UV(df1->uv[1], c0, c1);
- INT_UV(df1->uv[2], c1, c2);
- INT_UV(df1->uv[3], c0, c2);
-
- INT_UV(df2->uv[0], c0, c1);
- copy_v2_v2(df2->uv[1], mf->uv[c1]);
- INT_UV(df2->uv[2], c1, c2);
-
- INT_UV(df2->uv[0], c0, c2);
- INT_UV(df2->uv[1], c1, c2);
- copy_v2_v2(df2->uv[2], mf->uv[c2]);
- }
-}
-
-static DerivedMesh *cutEdges(ExplodeModifierData *emd, DerivedMesh *dm)
-{
- DerivedMesh *splitdm;
- MFace *mf = NULL, *df1 = NULL;
- MFace *mface = dm->getTessFaceArray(dm);
- MVert *dupve, *mv;
- EdgeHash *edgehash;
- EdgeHashIterator *ehi;
- int totvert = dm->getNumVerts(dm);
- int totface = dm->getNumTessFaces(dm);
-
- int *facesplit = MEM_callocN(sizeof(int) * totface, "explode_facesplit");
- int *vertpa = MEM_callocN(sizeof(int) * totvert, "explode_vertpa2");
- int *facepa = emd->facepa;
- int *fs, totesplit = 0, totfsplit = 0, curdupface = 0;
- int i, v1, v2, v3, v4, esplit,
- v[4] = {0, 0, 0, 0}, /* To quite gcc barking... */
- uv[4] = {0, 0, 0, 0}; /* To quite gcc barking... */
- int numlayer;
- unsigned int ed_v1, ed_v2;
-
- edgehash = BLI_edgehash_new(__func__);
-
- /* recreate vertpa from facepa calculation */
- for (i = 0, mf = mface; i < totface; i++, mf++) {
- vertpa[mf->v1] = facepa[i];
- vertpa[mf->v2] = facepa[i];
- vertpa[mf->v3] = facepa[i];
- if (mf->v4)
- vertpa[mf->v4] = facepa[i];
- }
-
- /* mark edges for splitting and how to split faces */
- for (i = 0, mf = mface, fs = facesplit; i < totface; i++, mf++, fs++) {
- v1 = vertpa[mf->v1];
- v2 = vertpa[mf->v2];
- v3 = vertpa[mf->v3];
-
- if (v1 != v2) {
- BLI_edgehash_reinsert(edgehash, mf->v1, mf->v2, NULL);
- (*fs) |= 1;
- }
-
- if (v2 != v3) {
- BLI_edgehash_reinsert(edgehash, mf->v2, mf->v3, NULL);
- (*fs) |= 2;
- }
-
- if (mf->v4) {
- v4 = vertpa[mf->v4];
-
- if (v3 != v4) {
- BLI_edgehash_reinsert(edgehash, mf->v3, mf->v4, NULL);
- (*fs) |= 4;
- }
-
- if (v1 != v4) {
- BLI_edgehash_reinsert(edgehash, mf->v1, mf->v4, NULL);
- (*fs) |= 8;
- }
-
- /* mark center vertex as a fake edge split */
- if (*fs == 15)
- BLI_edgehash_reinsert(edgehash, mf->v1, mf->v3, NULL);
- }
- else {
- (*fs) |= 16; /* mark face as tri */
-
- if (v1 != v3) {
- BLI_edgehash_reinsert(edgehash, mf->v1, mf->v3, NULL);
- (*fs) |= 4;
- }
- }
- }
-
- /* count splits & create indexes for new verts */
- ehi = BLI_edgehashIterator_new(edgehash);
- totesplit = totvert;
- for (; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) {
- BLI_edgehashIterator_setValue(ehi, SET_INT_IN_POINTER(totesplit));
- totesplit++;
- }
- BLI_edgehashIterator_free(ehi);
-
- /* count new faces due to splitting */
- for (i = 0, fs = facesplit; i < totface; i++, fs++)
- totfsplit += add_faces[*fs];
-
- splitdm = CDDM_from_template_ex(
- dm, totesplit, 0, totface + totfsplit, 0, 0,
- CD_MASK_DERIVEDMESH | CD_MASK_FACECORNERS);
- numlayer = CustomData_number_of_layers(&splitdm->faceData, CD_MTFACE);
-
- /* copy new faces & verts (is it really this painful with custom data??) */
- for (i = 0; i < totvert; i++) {
- MVert source;
- MVert *dest;
- dm->getVert(dm, i, &source);
- dest = CDDM_get_vert(splitdm, i);
-
- DM_copy_vert_data(dm, splitdm, i, i, 1);
- *dest = source;
- }
-
- /* override original facepa (original pointer is saved in caller function) */
-
- /* BMESH_TODO, (totfsplit * 2) over allocation is used since the quads are
- * later interpreted as tri's, for this to work right I think we probably
- * have to stop using tessface - campbell */
-
- facepa = MEM_callocN(sizeof(int) * (totface + (totfsplit * 2)), "explode_facepa");
- //memcpy(facepa, emd->facepa, totface*sizeof(int));
- emd->facepa = facepa;
-
- /* create new verts */
- ehi = BLI_edgehashIterator_new(edgehash);
- for (; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) {
- BLI_edgehashIterator_getKey(ehi, &ed_v1, &ed_v2);
- esplit = GET_INT_FROM_POINTER(BLI_edgehashIterator_getValue(ehi));
- mv = CDDM_get_vert(splitdm, ed_v2);
- dupve = CDDM_get_vert(splitdm, esplit);
-
- DM_copy_vert_data(splitdm, splitdm, ed_v2, esplit, 1);
-
- *dupve = *mv;
-
- mv = CDDM_get_vert(splitdm, ed_v1);
-
- mid_v3_v3v3(dupve->co, dupve->co, mv->co);
- }
- BLI_edgehashIterator_free(ehi);
-
- /* create new faces */
- curdupface = 0; //=totface;
- //curdupin=totesplit;
- for (i = 0, fs = facesplit; i < totface; i++, fs++) {
- mf = dm->getTessFaceData(dm, i, CD_MFACE);
-
- switch (*fs) {
- case 3:
- case 10:
- case 11:
- case 15:
- SET_VERTS(1, 2, 3, 4);
- break;
- case 5:
- case 6:
- case 7:
- SET_VERTS(2, 3, 4, 1);
- break;
- case 9:
- case 13:
- SET_VERTS(4, 1, 2, 3);
- break;
- case 12:
- case 14:
- SET_VERTS(3, 4, 1, 2);
- break;
- case 21:
- case 23:
- SET_VERTS(1, 2, 3, 4);
- break;
- case 19:
- SET_VERTS(2, 3, 1, 4);
- break;
- case 22:
- SET_VERTS(3, 1, 2, 4);
- break;
- }
-
- switch (*fs) {
- case 3:
- case 6:
- case 9:
- case 12:
- remap_faces_3_6_9_12(dm, splitdm, mf, facepa, vertpa, i, edgehash, curdupface, v[0], v[1], v[2], v[3]);
- if (numlayer)
- remap_uvs_3_6_9_12(dm, splitdm, numlayer, i, curdupface, uv[0], uv[1], uv[2], uv[3]);
- break;
- case 5:
- case 10:
- remap_faces_5_10(dm, splitdm, mf, facepa, vertpa, i, edgehash, curdupface, v[0], v[1], v[2], v[3]);
- if (numlayer)
- remap_uvs_5_10(dm, splitdm, numlayer, i, curdupface, uv[0], uv[1], uv[2], uv[3]);
- break;
- case 15:
- remap_faces_15(dm, splitdm, mf, facepa, vertpa, i, edgehash, curdupface, v[0], v[1], v[2], v[3]);
- if (numlayer)
- remap_uvs_15(dm, splitdm, numlayer, i, curdupface, uv[0], uv[1], uv[2], uv[3]);
- break;
- case 7:
- case 11:
- case 13:
- case 14:
- remap_faces_7_11_13_14(dm, splitdm, mf, facepa, vertpa, i, edgehash, curdupface, v[0], v[1], v[2], v[3]);
- if (numlayer)
- remap_uvs_7_11_13_14(dm, splitdm, numlayer, i, curdupface, uv[0], uv[1], uv[2], uv[3]);
- break;
- case 19:
- case 21:
- case 22:
- remap_faces_19_21_22(dm, splitdm, mf, facepa, vertpa, i, edgehash, curdupface, v[0], v[1], v[2]);
- if (numlayer)
- remap_uvs_19_21_22(dm, splitdm, numlayer, i, curdupface, uv[0], uv[1], uv[2]);
- break;
- case 23:
- remap_faces_23(dm, splitdm, mf, facepa, vertpa, i, edgehash, curdupface, v[0], v[1], v[2]);
- if (numlayer)
- remap_uvs_23(dm, splitdm, numlayer, i, curdupface, uv[0], uv[1], uv[2]);
- break;
- case 0:
- case 16:
- df1 = get_dface(dm, splitdm, curdupface, i, mf);
- facepa[curdupface] = vertpa[mf->v1];
-
- if (df1->v4)
- df1->flag |= ME_FACE_SEL;
- else
- df1->flag &= ~ME_FACE_SEL;
- break;
- }
-
- curdupface += add_faces[*fs] + 1;
- }
-
- for (i = 0; i < curdupface; i++) {
- mf = CDDM_get_tessface(splitdm, i);
- test_index_face(mf, &splitdm->faceData, i, ((mf->flag & ME_FACE_SEL) ? 4 : 3));
- }
-
- BLI_edgehash_free(edgehash, NULL);
- MEM_freeN(facesplit);
- MEM_freeN(vertpa);
-
- CDDM_calc_edges_tessface(splitdm);
- CDDM_tessfaces_to_faces(splitdm); /*builds ngon faces from tess (mface) faces*/
-
- return splitdm;
-}
-static DerivedMesh *explodeMesh(ExplodeModifierData *emd,
- ParticleSystemModifierData *psmd, Scene *scene, Object *ob,
- DerivedMesh *to_explode)
-{
- DerivedMesh *explode, *dm = to_explode;
- MFace *mf = NULL, *mface;
- /* ParticleSettings *part=psmd->psys->part; */ /* UNUSED */
- ParticleSimulationData sim = {NULL};
- ParticleData *pa = NULL, *pars = psmd->psys->particles;
- ParticleKey state, birth;
- EdgeHash *vertpahash;
- EdgeHashIterator *ehi;
- float *vertco = NULL, imat[4][4];
- float rot[4];
- float cfra;
- /* float timestep; */
- const int *facepa = emd->facepa;
- int totdup = 0, totvert = 0, totface = 0, totpart = 0, delface = 0;
- int i, v, u;
- unsigned int ed_v1, ed_v2, mindex = 0;
- MTFace *mtface = NULL, *mtf;
-
- totface = dm->getNumTessFaces(dm);
- totvert = dm->getNumVerts(dm);
- mface = dm->getTessFaceArray(dm);
- totpart = psmd->psys->totpart;
-
- sim.scene = scene;
- sim.ob = ob;
- sim.psys = psmd->psys;
- sim.psmd = psmd;
-
- /* timestep = psys_get_timestep(&sim); */
-
- cfra = BKE_scene_frame_get(scene);
-
- /* hash table for vertice <-> particle relations */
- vertpahash = BLI_edgehash_new(__func__);
-
- for (i = 0; i < totface; i++) {
- if (facepa[i] != totpart) {
- pa = pars + facepa[i];
-
- if ((pa->alive == PARS_UNBORN && (emd->flag & eExplodeFlag_Unborn) == 0) ||
- (pa->alive == PARS_ALIVE && (emd->flag & eExplodeFlag_Alive) == 0) ||
- (pa->alive == PARS_DEAD && (emd->flag & eExplodeFlag_Dead) == 0))
- {
- delface++;
- continue;
- }
- }
-
- /* do mindex + totvert to ensure the vertex index to be the first
- * with BLI_edgehashIterator_getKey */
- if (facepa[i] == totpart || cfra < (pars + facepa[i])->time)
- mindex = totvert + totpart;
- else
- mindex = totvert + facepa[i];
-
- mf = &mface[i];
-
- /* set face vertices to exist in particle group */
- BLI_edgehash_reinsert(vertpahash, mf->v1, mindex, NULL);
- BLI_edgehash_reinsert(vertpahash, mf->v2, mindex, NULL);
- BLI_edgehash_reinsert(vertpahash, mf->v3, mindex, NULL);
- if (mf->v4)
- BLI_edgehash_reinsert(vertpahash, mf->v4, mindex, NULL);
- }
-
- /* make new vertice indexes & count total vertices after duplication */
- ehi = BLI_edgehashIterator_new(vertpahash);
- for (; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) {
- BLI_edgehashIterator_setValue(ehi, SET_INT_IN_POINTER(totdup));
- totdup++;
- }
- BLI_edgehashIterator_free(ehi);
-
- /* the final duplicated vertices */
- explode = CDDM_from_template_ex(dm, totdup, 0, totface - delface, 0, 0, CD_MASK_DERIVEDMESH | CD_MASK_FACECORNERS);
- mtface = CustomData_get_layer_named(&explode->faceData, CD_MTFACE, emd->uvname);
- /*dupvert = CDDM_get_verts(explode);*/
-
- /* getting back to object space */
- invert_m4_m4(imat, ob->obmat);
-
- psmd->psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
-
- /* duplicate & displace vertices */
- ehi = BLI_edgehashIterator_new(vertpahash);
- for (; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) {
- MVert source;
- MVert *dest;
-
- /* get particle + vertex from hash */
- BLI_edgehashIterator_getKey(ehi, &ed_v1, &ed_v2);
- ed_v2 -= totvert;
- v = GET_INT_FROM_POINTER(BLI_edgehashIterator_getValue(ehi));
-
- dm->getVert(dm, ed_v1, &source);
- dest = CDDM_get_vert(explode, v);
-
- DM_copy_vert_data(dm, explode, ed_v1, v, 1);
- *dest = source;
-
- if (ed_v2 != totpart) {
- /* get particle */
- pa = pars + ed_v2;
-
- psys_get_birth_coords(&sim, pa, &birth, 0, 0);
-
- state.time = cfra;
- psys_get_particle_state(&sim, ed_v2, &state, 1);
-
- vertco = CDDM_get_vert(explode, v)->co;
- mul_m4_v3(ob->obmat, vertco);
-
- sub_v3_v3(vertco, birth.co);
-
- /* apply rotation, size & location */
- sub_qt_qtqt(rot, state.rot, birth.rot);
- mul_qt_v3(rot, vertco);
-
- if (emd->flag & eExplodeFlag_PaSize)
- mul_v3_fl(vertco, pa->size);
-
- add_v3_v3(vertco, state.co);
-
- mul_m4_v3(imat, vertco);
- }
- }
- BLI_edgehashIterator_free(ehi);
-
- /*map new vertices to faces*/
- for (i = 0, u = 0; i < totface; i++) {
- MFace source;
- int orig_v4;
-
- if (facepa[i] != totpart) {
- pa = pars + facepa[i];
-
- if (pa->alive == PARS_UNBORN && (emd->flag & eExplodeFlag_Unborn) == 0) continue;
- if (pa->alive == PARS_ALIVE && (emd->flag & eExplodeFlag_Alive) == 0) continue;
- if (pa->alive == PARS_DEAD && (emd->flag & eExplodeFlag_Dead) == 0) continue;
- }
-
- dm->getTessFace(dm, i, &source);
- mf = CDDM_get_tessface(explode, u);
-
- orig_v4 = source.v4;
-
- if (facepa[i] != totpart && cfra < pa->time)
- mindex = totvert + totpart;
- else
- mindex = totvert + facepa[i];
-
- source.v1 = edgecut_get(vertpahash, source.v1, mindex);
- source.v2 = edgecut_get(vertpahash, source.v2, mindex);
- source.v3 = edgecut_get(vertpahash, source.v3, mindex);
- if (source.v4)
- source.v4 = edgecut_get(vertpahash, source.v4, mindex);
-
- DM_copy_tessface_data(dm, explode, i, u, 1);
-
- *mf = source;
-
- /* override uv channel for particle age */
- if (mtface) {
- float age = (cfra - pa->time) / pa->lifetime;
- /* Clamp to this range to avoid flipping to the other side of the coordinates. */
- CLAMP(age, 0.001f, 0.999f);
-
- mtf = mtface + u;
-
- mtf->uv[0][0] = mtf->uv[1][0] = mtf->uv[2][0] = mtf->uv[3][0] = age;
- mtf->uv[0][1] = mtf->uv[1][1] = mtf->uv[2][1] = mtf->uv[3][1] = 0.5f;
- }
-
- test_index_face(mf, &explode->faceData, u, (orig_v4 ? 4 : 3));
- u++;
- }
-
- /* cleanup */
- BLI_edgehash_free(vertpahash, NULL);
-
- /* finalization */
- CDDM_calc_edges_tessface(explode);
- CDDM_tessfaces_to_faces(explode);
- explode->dirty |= DM_DIRTY_NORMALS;
-
- if (psmd->psys->lattice_deform_data) {
- end_latt_deform(psmd->psys->lattice_deform_data);
- psmd->psys->lattice_deform_data = NULL;
- }
-
- return explode;
-}
-
-static ParticleSystemModifierData *findPrecedingParticlesystem(Object *ob, ModifierData *emd)
-{
- ModifierData *md;
- ParticleSystemModifierData *psmd = NULL;
-
- for (md = ob->modifiers.first; emd != md; md = md->next) {
- if (md->type == eModifierType_ParticleSystem)
- psmd = (ParticleSystemModifierData *) md;
- }
- return psmd;
-}
-static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
+static DerivedMesh *applyModifier(ModifierData *UNUSED(md), Object *UNUSED(ob),
DerivedMesh *derivedData,
ModifierApplyFlag UNUSED(flag))
{
- DerivedMesh *dm = derivedData;
- ExplodeModifierData *emd = (ExplodeModifierData *) md;
- ParticleSystemModifierData *psmd = findPrecedingParticlesystem(ob, md);
-
- DM_ensure_tessface(dm); /* BMESH - UNTIL MODIFIER IS UPDATED FOR MPoly */
-
- if (psmd) {
- ParticleSystem *psys = psmd->psys;
-
- if (psys == NULL || psys->totpart == 0) return derivedData;
- if (psys->part == NULL || psys->particles == NULL) return derivedData;
- if (psmd->dm_final == NULL) return derivedData;
-
- /* 1. find faces to be exploded if needed */
- if (emd->facepa == NULL ||
- psmd->flag & eParticleSystemFlag_Pars ||
- emd->flag & eExplodeFlag_CalcFaces ||
- MEM_allocN_len(emd->facepa) / sizeof(int) != dm->getNumTessFaces(dm))
- {
- if (psmd->flag & eParticleSystemFlag_Pars)
- psmd->flag &= ~eParticleSystemFlag_Pars;
-
- if (emd->flag & eExplodeFlag_CalcFaces)
- emd->flag &= ~eExplodeFlag_CalcFaces;
-
- createFacepa(emd, psmd, derivedData);
- }
- /* 2. create new mesh */
- if (emd->flag & eExplodeFlag_EdgeCut) {
- int *facepa = emd->facepa;
- DerivedMesh *splitdm = cutEdges(emd, dm);
- DerivedMesh *explode = explodeMesh(emd, psmd, md->scene, ob, splitdm);
-
- MEM_freeN(emd->facepa);
- emd->facepa = facepa;
- splitdm->release(splitdm);
- return explode;
- }
- else
- return explodeMesh(emd, psmd, md->scene, ob, derivedData);
- }
return derivedData;
}
diff --git a/source/blender/modifiers/intern/MOD_laplaciandeform.c b/source/blender/modifiers/intern/MOD_laplaciandeform.c
index ce3fdc4bbe8..5439f77aede 100644
--- a/source/blender/modifiers/intern/MOD_laplaciandeform.c
+++ b/source/blender/modifiers/intern/MOD_laplaciandeform.c
@@ -33,11 +33,12 @@
#include "BLI_math.h"
#include "BLI_string.h"
+#include "DNA_object_types.h"
+
#include "MEM_guardedalloc.h"
#include "BKE_mesh_mapping.h"
#include "BKE_cdderivedmesh.h"
-#include "BKE_particle.h"
#include "BKE_deform.h"
#include "MOD_util.h"
diff --git a/source/blender/modifiers/intern/MOD_particleinstance.c b/source/blender/modifiers/intern/MOD_particleinstance.c
deleted file mode 100644
index 4e78e758dc3..00000000000
--- a/source/blender/modifiers/intern/MOD_particleinstance.c
+++ /dev/null
@@ -1,470 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2005 by the Blender Foundation.
- * All rights reserved.
- *
- * Contributor(s): Daniel Dunbar
- * Ton Roosendaal,
- * Ben Batt,
- * Brecht Van Lommel,
- * Campbell Barton
- *
- * ***** END GPL LICENSE BLOCK *****
- *
- */
-
-/** \file blender/modifiers/intern/MOD_particleinstance.c
- * \ingroup modifiers
- */
-
-
-#include "DNA_meshdata_types.h"
-
-#include "MEM_guardedalloc.h"
-
-#include "BLI_math.h"
-#include "BLI_listbase.h"
-#include "BLI_rand.h"
-#include "BLI_utildefines.h"
-
-#include "BKE_cdderivedmesh.h"
-#include "BKE_effect.h"
-#include "BKE_global.h"
-#include "BKE_lattice.h"
-#include "BKE_library_query.h"
-#include "BKE_modifier.h"
-#include "BKE_particle.h"
-#include "BKE_pointcache.h"
-
-#include "depsgraph_private.h"
-#include "DEG_depsgraph_build.h"
-
-static void initData(ModifierData *md)
-{
- ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *) md;
-
- pimd->flag = eParticleInstanceFlag_Parents | eParticleInstanceFlag_Unborn |
- eParticleInstanceFlag_Alive | eParticleInstanceFlag_Dead;
- pimd->psys = 1;
- pimd->position = 1.0f;
- pimd->axis = 2;
-
-}
-static void copyData(ModifierData *md, ModifierData *target)
-{
-#if 0
- ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *) md;
- ParticleInstanceModifierData *tpimd = (ParticleInstanceModifierData *) target;
-#endif
- modifier_copyData_generic(md, target);
-}
-
-static bool isDisabled(ModifierData *md, int useRenderParams)
-{
- ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *)md;
- ParticleSystem *psys;
- ModifierData *ob_md;
-
- if (!pimd->ob)
- return true;
-
- psys = BLI_findlink(&pimd->ob->particlesystem, pimd->psys - 1);
- if (psys == NULL)
- return true;
-
- /* If the psys modifier is disabled we cannot use its data.
- * First look up the psys modifier from the object, then check if it is enabled.
- */
- for (ob_md = pimd->ob->modifiers.first; ob_md; ob_md = ob_md->next) {
- if (ob_md->type == eModifierType_ParticleSystem) {
- ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)ob_md;
- if (psmd->psys == psys) {
- int required_mode;
-
- if (useRenderParams) required_mode = eModifierMode_Render;
- else required_mode = eModifierMode_Realtime;
-
- if (!modifier_isEnabled(md->scene, ob_md, required_mode))
- return true;
-
- break;
- }
- }
- }
-
- return false;
-}
-
-
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob),
- DagNode *obNode)
-{
- ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *) md;
-
- if (pimd->ob) {
- DagNode *curNode = dag_get_node(forest, pimd->ob);
-
- dag_add_relation(forest, curNode, obNode,
- DAG_RL_DATA_DATA | DAG_RL_OB_DATA,
- "Particle Instance Modifier");
- }
-}
-
-static void updateDepsgraph(ModifierData *md,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob),
- struct DepsNodeHandle *node)
-{
- ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *) md;
- if (pimd->ob != NULL) {
- DEG_add_object_relation(node, pimd->ob, DEG_OB_COMP_TRANSFORM, "Particle Instance Modifier");
- }
-}
-
-static void foreachObjectLink(ModifierData *md, Object *ob,
- ObjectWalkFunc walk, void *userData)
-{
- ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *) md;
-
- walk(userData, ob, &pimd->ob, IDWALK_NOP);
-}
-
-static int particle_skip(ParticleInstanceModifierData *pimd, ParticleSystem *psys, int p)
-{
- ParticleData *pa;
-
- if (pimd->flag & eParticleInstanceFlag_Parents) {
- if (p >= psys->totpart) {
- if (psys->part->childtype == PART_CHILD_PARTICLES) {
- pa = psys->particles + (psys->child + p - psys->totpart)->parent;
- }
- else {
- pa = NULL;
- }
- }
- else {
- pa = psys->particles + p;
- }
- }
- else {
- if (psys->part->childtype == PART_CHILD_PARTICLES) {
- pa = psys->particles + (psys->child + p)->parent;
- }
- else {
- pa = NULL;
- }
- }
-
- if (pa) {
- if (pa->alive == PARS_UNBORN && (pimd->flag & eParticleInstanceFlag_Unborn) == 0) return 1;
- if (pa->alive == PARS_ALIVE && (pimd->flag & eParticleInstanceFlag_Alive) == 0) return 1;
- if (pa->alive == PARS_DEAD && (pimd->flag & eParticleInstanceFlag_Dead) == 0) return 1;
- }
-
- return 0;
-}
-
-static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
- DerivedMesh *derivedData,
- ModifierApplyFlag UNUSED(flag))
-{
- DerivedMesh *dm = derivedData, *result;
- ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *) md;
- ParticleSimulationData sim;
- ParticleSystem *psys = NULL;
- ParticleData *pa = NULL;
- MPoly *mpoly, *orig_mpoly;
- MLoop *mloop, *orig_mloop;
- MVert *mvert, *orig_mvert;
- int totvert, totpoly, totloop /* , totedge */;
- int maxvert, maxpoly, maxloop, totpart = 0, first_particle = 0;
- int k, p, p_skip;
- short track = ob->trackflag % 3, trackneg, axis = pimd->axis;
- float max_co = 0.0, min_co = 0.0, temp_co[3];
- float *size = NULL;
-
- trackneg = ((ob->trackflag > 2) ? 1 : 0);
-
- if (pimd->ob == ob) {
- pimd->ob = NULL;
- return derivedData;
- }
-
- if (pimd->ob) {
- psys = BLI_findlink(&pimd->ob->particlesystem, pimd->psys - 1);
- if (psys == NULL || psys->totpart == 0)
- return derivedData;
- }
- else {
- return derivedData;
- }
-
- if (pimd->flag & eParticleInstanceFlag_Parents)
- totpart += psys->totpart;
- if (pimd->flag & eParticleInstanceFlag_Children) {
- if (totpart == 0)
- first_particle = psys->totpart;
- totpart += psys->totchild;
- }
-
- if (totpart == 0)
- return derivedData;
-
- sim.scene = md->scene;
- sim.ob = pimd->ob;
- sim.psys = psys;
- sim.psmd = psys_get_modifier(pimd->ob, psys);
-
- if (pimd->flag & eParticleInstanceFlag_UseSize) {
- float *si;
- si = size = MEM_callocN(totpart * sizeof(float), "particle size array");
-
- if (pimd->flag & eParticleInstanceFlag_Parents) {
- for (p = 0, pa = psys->particles; p < psys->totpart; p++, pa++, si++)
- *si = pa->size;
- }
-
- if (pimd->flag & eParticleInstanceFlag_Children) {
- ChildParticle *cpa = psys->child;
-
- for (p = 0; p < psys->totchild; p++, cpa++, si++) {
- *si = psys_get_child_size(psys, cpa, 0.0f, NULL);
- }
- }
- }
-
- totvert = dm->getNumVerts(dm);
- totpoly = dm->getNumPolys(dm);
- totloop = dm->getNumLoops(dm);
- /* totedge = dm->getNumEdges(dm); */ /* UNUSED */
-
- /* count particles */
- maxvert = 0;
- maxpoly = 0;
- maxloop = 0;
-
- for (p = 0; p < totpart; p++) {
- if (particle_skip(pimd, psys, p))
- continue;
-
- maxvert += totvert;
- maxpoly += totpoly;
- maxloop += totloop;
- }
-
- psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
-
- if (psys->flag & (PSYS_HAIR_DONE | PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED) {
- float min[3], max[3];
- INIT_MINMAX(min, max);
- dm->getMinMax(dm, min, max);
- min_co = min[track];
- max_co = max[track];
- }
-
- result = CDDM_from_template(dm, maxvert, 0, 0, maxloop, maxpoly);
-
- mvert = result->getVertArray(result);
- orig_mvert = dm->getVertArray(dm);
-
- mpoly = result->getPolyArray(result);
- orig_mpoly = dm->getPolyArray(dm);
- mloop = result->getLoopArray(result);
- orig_mloop = dm->getLoopArray(dm);
-
- for (p = 0, p_skip = 0; p < totpart; p++) {
- float prev_dir[3];
- float frame[4]; /* frame orientation quaternion */
-
- /* skip particle? */
- if (particle_skip(pimd, psys, p))
- continue;
-
- /* set vertices coordinates */
- for (k = 0; k < totvert; k++) {
- ParticleKey state;
- MVert *inMV;
- MVert *mv = mvert + p_skip * totvert + k;
-
- inMV = orig_mvert + k;
- DM_copy_vert_data(dm, result, k, p_skip * totvert + k, 1);
- *mv = *inMV;
-
- /*change orientation based on object trackflag*/
- copy_v3_v3(temp_co, mv->co);
- mv->co[axis] = temp_co[track];
- mv->co[(axis + 1) % 3] = temp_co[(track + 1) % 3];
- mv->co[(axis + 2) % 3] = temp_co[(track + 2) % 3];
-
- /* get particle state */
- if ((psys->flag & (PSYS_HAIR_DONE | PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED) &&
- (pimd->flag & eParticleInstanceFlag_Path))
- {
- float ran = 0.0f;
- if (pimd->random_position != 0.0f) {
- ran = pimd->random_position * BLI_hash_frand(psys->seed + p);
- }
-
- if (pimd->flag & eParticleInstanceFlag_KeepShape) {
- state.time = pimd->position * (1.0f - ran);
- }
- else {
- state.time = (mv->co[axis] - min_co) / (max_co - min_co) * pimd->position * (1.0f - ran);
-
- if (trackneg)
- state.time = 1.0f - state.time;
-
- mv->co[axis] = 0.0;
- }
-
- psys_get_particle_on_path(&sim, first_particle + p, &state, 1);
-
- normalize_v3(state.vel);
-
- /* Incrementally Rotating Frame (Bishop Frame) */
- if (k == 0) {
- float hairmat[4][4];
- float mat[3][3];
-
- if (first_particle + p < psys->totpart)
- pa = psys->particles + first_particle + p;
- else {
- ChildParticle *cpa = psys->child + (p - psys->totpart);
- pa = psys->particles + cpa->parent;
- }
- psys_mat_hair_to_global(sim.ob, sim.psmd->dm_final, sim.psys->part->from, pa, hairmat);
- copy_m3_m4(mat, hairmat);
- /* to quaternion */
- mat3_to_quat(frame, mat);
-
- /* note: direction is same as normal vector currently,
- * but best to keep this separate so the frame can be
- * rotated later if necessary
- */
- copy_v3_v3(prev_dir, state.vel);
- }
- else {
- float rot[4];
-
- /* incrementally rotate along bend direction */
- rotation_between_vecs_to_quat(rot, prev_dir, state.vel);
- mul_qt_qtqt(frame, rot, frame);
-
- copy_v3_v3(prev_dir, state.vel);
- }
-
- copy_qt_qt(state.rot, frame);
-#if 0
- /* Absolute Frame (Frenet Frame) */
- if (state.vel[axis] < -0.9999f || state.vel[axis] > 0.9999f) {
- unit_qt(state.rot);
- }
- else {
- float cross[3];
- float temp[3] = {0.0f, 0.0f, 0.0f};
- temp[axis] = 1.0f;
-
- cross_v3_v3v3(cross, temp, state.vel);
-
- /* state.vel[axis] is the only component surviving from a dot product with the axis */
- axis_angle_to_quat(state.rot, cross, saacos(state.vel[axis]));
- }
-#endif
- }
- else {
- state.time = -1.0;
- psys_get_particle_state(&sim, first_particle + p, &state, 1);
- }
-
- mul_qt_v3(state.rot, mv->co);
- if (pimd->flag & eParticleInstanceFlag_UseSize)
- mul_v3_fl(mv->co, size[p]);
- add_v3_v3(mv->co, state.co);
- }
-
- /* create polys and loops */
- for (k = 0; k < totpoly; k++) {
- MPoly *inMP = orig_mpoly + k;
- MPoly *mp = mpoly + p_skip * totpoly + k;
-
- DM_copy_poly_data(dm, result, k, p_skip * totpoly + k, 1);
- *mp = *inMP;
- mp->loopstart += p_skip * totloop;
-
- {
- MLoop *inML = orig_mloop + inMP->loopstart;
- MLoop *ml = mloop + mp->loopstart;
- int j = mp->totloop;
-
- DM_copy_loop_data(dm, result, inMP->loopstart, mp->loopstart, j);
- for (; j; j--, ml++, inML++) {
- ml->v = inML->v + (p_skip * totvert);
- }
- }
- }
-
- p_skip++;
- }
-
- CDDM_calc_edges(result);
-
- if (psys->lattice_deform_data) {
- end_latt_deform(psys->lattice_deform_data);
- psys->lattice_deform_data = NULL;
- }
-
- if (size)
- MEM_freeN(size);
-
- result->dirty |= DM_DIRTY_NORMALS;
-
- return result;
-}
-ModifierTypeInfo modifierType_ParticleInstance = {
- /* name */ "ParticleInstance",
- /* structName */ "ParticleInstanceModifierData",
- /* structSize */ sizeof(ParticleInstanceModifierData),
- /* type */ eModifierTypeType_Constructive,
- /* flags */ eModifierTypeFlag_AcceptsMesh |
- eModifierTypeFlag_SupportsMapping |
- eModifierTypeFlag_SupportsEditmode |
- eModifierTypeFlag_EnableInEditmode,
-
- /* copyData */ copyData,
- /* deformVerts */ NULL,
- /* deformMatrices */ NULL,
- /* deformVertsEM */ NULL,
- /* deformMatricesEM */ NULL,
- /* applyModifier */ applyModifier,
- /* applyModifierEM */ NULL,
- /* initData */ initData,
- /* requiredDataMask */ NULL,
- /* freeData */ NULL,
- /* isDisabled */ isDisabled,
- /* updateDepgraph */ updateDepgraph,
- /* updateDepsgraph */ updateDepsgraph,
- /* dependsOnTime */ NULL,
- /* dependsOnNormals */ NULL,
- /* foreachObjectLink */ foreachObjectLink,
- /* foreachIDLink */ NULL,
- /* foreachTexLink */ NULL,
-};
diff --git a/source/blender/modifiers/intern/MOD_particlesystem.c b/source/blender/modifiers/intern/MOD_particlesystem.c
deleted file mode 100644
index d8cccca415c..00000000000
--- a/source/blender/modifiers/intern/MOD_particlesystem.c
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2005 by the Blender Foundation.
- * All rights reserved.
- *
- * Contributor(s): Daniel Dunbar
- * Ton Roosendaal,
- * Ben Batt,
- * Brecht Van Lommel,
- * Campbell Barton
- *
- * ***** END GPL LICENSE BLOCK *****
- *
- */
-
-/** \file blender/modifiers/intern/MOD_particlesystem.c
- * \ingroup modifiers
- */
-
-
-#include <stddef.h>
-
-#include "DNA_material_types.h"
-#include "DNA_mesh_types.h"
-
-#include "BLI_utildefines.h"
-
-
-#include "BKE_cdderivedmesh.h"
-#include "BKE_modifier.h"
-#include "BKE_particle.h"
-
-#include "MOD_util.h"
-
-
-static void initData(ModifierData *md)
-{
- ParticleSystemModifierData *psmd = (ParticleSystemModifierData *) md;
- psmd->psys = NULL;
- psmd->dm_final = NULL;
- psmd->dm_deformed = NULL;
- psmd->totdmvert = psmd->totdmedge = psmd->totdmface = 0;
-}
-static void freeData(ModifierData *md)
-{
- ParticleSystemModifierData *psmd = (ParticleSystemModifierData *) md;
-
- if (psmd->dm_final) {
- psmd->dm_final->needsFree = true;
- psmd->dm_final->release(psmd->dm_final);
- psmd->dm_final = NULL;
- if (psmd->dm_deformed) {
- psmd->dm_deformed->needsFree = true;
- psmd->dm_deformed->release(psmd->dm_deformed);
- psmd->dm_deformed = NULL;
- }
- }
-
- /* ED_object_modifier_remove may have freed this first before calling
- * modifier_free (which calls this function) */
- if (psmd->psys)
- psmd->psys->flag |= PSYS_DELETE;
-}
-static void copyData(ModifierData *md, ModifierData *target)
-{
-#if 0
- ParticleSystemModifierData *psmd = (ParticleSystemModifierData *) md;
-#endif
- ParticleSystemModifierData *tpsmd = (ParticleSystemModifierData *) target;
-
- modifier_copyData_generic(md, target);
-
- tpsmd->dm_final = NULL;
- tpsmd->dm_deformed = NULL;
- tpsmd->totdmvert = tpsmd->totdmedge = tpsmd->totdmface = 0;
-}
-
-static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
-{
- ParticleSystemModifierData *psmd = (ParticleSystemModifierData *) md;
- return psys_emitter_customdata_mask(psmd->psys);
-}
-
-/* saves the current emitter state for a particle system and calculates particles */
-static void deformVerts(ModifierData *md, Object *ob,
- DerivedMesh *derivedData,
- float (*vertexCos)[3],
- int UNUSED(numVerts),
- ModifierApplyFlag flag)
-{
- DerivedMesh *dm = derivedData;
- ParticleSystemModifierData *psmd = (ParticleSystemModifierData *) md;
- ParticleSystem *psys = NULL;
- bool needsFree = false;
- /* float cfra = BKE_scene_frame_get(md->scene); */ /* UNUSED */
-
- if (ob->particlesystem.first)
- psys = psmd->psys;
- else
- return;
-
- if (!psys_check_enabled(ob, psys, (flag & MOD_APPLY_RENDER) != 0))
- return;
-
- if (dm == NULL) {
- dm = get_dm(ob, NULL, NULL, vertexCos, false, true);
-
- if (!dm)
- return;
-
- needsFree = true;
- }
-
- /* clear old dm */
- if (psmd->dm_final) {
- psmd->dm_final->needsFree = true;
- psmd->dm_final->release(psmd->dm_final);
- if (psmd->dm_deformed) {
- psmd->dm_deformed->needsFree = 1;
- psmd->dm_deformed->release(psmd->dm_deformed);
- psmd->dm_deformed = NULL;
- }
- }
- else if (psmd->flag & eParticleSystemFlag_file_loaded) {
- /* in file read dm just wasn't saved in file so no need to reset everything */
- psmd->flag &= ~eParticleSystemFlag_file_loaded;
- }
- else {
- /* no dm before, so recalc particles fully */
- psys->recalc |= PSYS_RECALC_RESET;
- }
-
- /* make new dm */
- psmd->dm_final = CDDM_copy(dm);
- CDDM_apply_vert_coords(psmd->dm_final, vertexCos);
- CDDM_calc_normals(psmd->dm_final);
-
- if (needsFree) {
- dm->needsFree = true;
- dm->release(dm);
- }
-
- /* protect dm */
- psmd->dm_final->needsFree = false;
-
- DM_ensure_tessface(psmd->dm_final);
-
- if (!psmd->dm_final->deformedOnly) {
- /* XXX Think we can assume here that if current DM is not only-deformed, ob->deformedOnly has been set.
- * This is awfully weak though. :| */
- if (ob->derivedDeform) {
- psmd->dm_deformed = CDDM_copy(ob->derivedDeform);
- }
- else { /* Can happen in some cases, e.g. when rendering from Edit mode... */
- psmd->dm_deformed = CDDM_from_mesh((Mesh *)ob->data);
- }
- DM_ensure_tessface(psmd->dm_deformed);
- }
-
- /* report change in mesh structure */
- if (psmd->dm_final->getNumVerts(psmd->dm_final) != psmd->totdmvert ||
- psmd->dm_final->getNumEdges(psmd->dm_final) != psmd->totdmedge ||
- psmd->dm_final->getNumTessFaces(psmd->dm_final) != psmd->totdmface)
- {
- psys->recalc |= PSYS_RECALC_RESET;
-
- psmd->totdmvert = psmd->dm_final->getNumVerts(psmd->dm_final);
- psmd->totdmedge = psmd->dm_final->getNumEdges(psmd->dm_final);
- psmd->totdmface = psmd->dm_final->getNumTessFaces(psmd->dm_final);
- }
-
- if (!(ob->transflag & OB_NO_PSYS_UPDATE)) {
- psmd->flag &= ~eParticleSystemFlag_psys_updated;
- particle_system_update(md->scene, ob, psys, (flag & MOD_APPLY_RENDER) != 0);
- psmd->flag |= eParticleSystemFlag_psys_updated;
- }
-}
-
-/* disabled particles in editmode for now, until support for proper derivedmesh
- * updates is coded */
-#if 0
-static void deformVertsEM(
- ModifierData *md, Object *ob, EditMesh *editData,
- DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
-{
- DerivedMesh *dm = derivedData;
-
- if (!derivedData) dm = CDDM_from_editmesh(editData, ob->data);
-
- deformVerts(md, ob, dm, vertexCos, numVerts);
-
- if (!derivedData) dm->release(dm);
-}
-#endif
-
-
-ModifierTypeInfo modifierType_ParticleSystem = {
- /* name */ "ParticleSystem",
- /* structName */ "ParticleSystemModifierData",
- /* structSize */ sizeof(ParticleSystemModifierData),
- /* type */ eModifierTypeType_OnlyDeform,
- /* flags */ eModifierTypeFlag_AcceptsMesh |
- eModifierTypeFlag_SupportsMapping |
- eModifierTypeFlag_UsesPointCache /* |
- eModifierTypeFlag_SupportsEditmode |
- eModifierTypeFlag_EnableInEditmode */,
-
- /* copyData */ copyData,
- /* deformVerts */ deformVerts,
- /* deformVertsEM */ NULL,
- /* deformMatrices */ NULL,
- /* deformMatricesEM */ NULL,
- /* applyModifier */ NULL,
- /* applyModifierEM */ NULL,
- /* initData */ initData,
- /* requiredDataMask */ requiredDataMask,
- /* freeData */ freeData,
- /* isDisabled */ NULL,
- /* updateDepgraph */ NULL,
- /* updateDepsgraph */ NULL,
- /* dependsOnTime */ NULL,
- /* dependsOnNormals */ NULL,
- /* foreachObjectLink */ NULL,
- /* foreachIDLink */ NULL,
- /* foreachTexLink */ NULL,
-};
diff --git a/source/blender/modifiers/intern/MOD_shapekey.c b/source/blender/modifiers/intern/MOD_shapekey.c
index 97aae733532..4ccf9fabf0c 100644
--- a/source/blender/modifiers/intern/MOD_shapekey.c
+++ b/source/blender/modifiers/intern/MOD_shapekey.c
@@ -35,12 +35,12 @@
#include "BLI_math.h"
#include "DNA_key_types.h"
+#include "DNA_object_types.h"
#include "BLI_utildefines.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_key.h"
-#include "BKE_particle.h"
#include "MOD_modifiertypes.h"
diff --git a/source/blender/modifiers/intern/MOD_smooth.c b/source/blender/modifiers/intern/MOD_smooth.c
index d45c8528510..66c9f613447 100644
--- a/source/blender/modifiers/intern/MOD_smooth.c
+++ b/source/blender/modifiers/intern/MOD_smooth.c
@@ -34,6 +34,7 @@
#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
@@ -41,7 +42,6 @@
#include "MEM_guardedalloc.h"
#include "BKE_cdderivedmesh.h"
-#include "BKE_particle.h"
#include "BKE_deform.h"
#include "MOD_modifiertypes.h"
diff --git a/source/blender/modifiers/intern/MOD_softbody.c b/source/blender/modifiers/intern/MOD_softbody.c
index 17adc7f1520..101f5a4f619 100644
--- a/source/blender/modifiers/intern/MOD_softbody.c
+++ b/source/blender/modifiers/intern/MOD_softbody.c
@@ -34,13 +34,13 @@
#include <stdio.h>
+#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_object_force.h"
#include "BLI_utildefines.h"
#include "BKE_cdderivedmesh.h"
-#include "BKE_particle.h"
#include "BKE_softbody.h"
#include "depsgraph_private.h"
diff --git a/source/blender/modifiers/intern/MOD_solidify.c b/source/blender/modifiers/intern/MOD_solidify.c
index 911b6997058..9eb7e4e83b6 100644
--- a/source/blender/modifiers/intern/MOD_solidify.c
+++ b/source/blender/modifiers/intern/MOD_solidify.c
@@ -32,6 +32,7 @@
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
#include "MEM_guardedalloc.h"
@@ -42,7 +43,6 @@
#include "BKE_cdderivedmesh.h"
#include "BKE_mesh.h"
-#include "BKE_particle.h"
#include "BKE_deform.h"
#include "MOD_modifiertypes.h"
diff --git a/source/blender/modifiers/intern/MOD_util.c b/source/blender/modifiers/intern/MOD_util.c
index 93414562ccf..a59ace130e7 100644
--- a/source/blender/modifiers/intern/MOD_util.c
+++ b/source/blender/modifiers/intern/MOD_util.c
@@ -257,8 +257,6 @@ void modifier_type_init(ModifierTypeInfo *types[])
INIT_TYPE(Boolean);
INIT_TYPE(MeshDeform);
INIT_TYPE(Ocean);
- INIT_TYPE(ParticleSystem);
- INIT_TYPE(ParticleInstance);
INIT_TYPE(Explode);
INIT_TYPE(Shrinkwrap);
INIT_TYPE(Fluidsim);
diff --git a/source/blender/nodes/shader/nodes/node_shader_particle_info.c b/source/blender/nodes/shader/nodes/node_shader_particle_info.c
index 5f0d81e98c9..dc19416d688 100644
--- a/source/blender/nodes/shader/nodes/node_shader_particle_info.c
+++ b/source/blender/nodes/shader/nodes/node_shader_particle_info.c
@@ -50,12 +50,7 @@ static void node_shader_exec_particle_info(void *data, int UNUSED(thread), bNode
static int gpu_shader_particle_info(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
-
- return GPU_stack_link(mat, "particle_info", in, out,
- GPU_builtin(GPU_PARTICLE_SCALAR_PROPS),
- GPU_builtin(GPU_PARTICLE_LOCATION),
- GPU_builtin(GPU_PARTICLE_VELOCITY),
- GPU_builtin(GPU_PARTICLE_ANG_VELOCITY));
+ return GPU_stack_link(mat, "particle_info", in, out);
}
/* node type definition */
diff --git a/source/blender/python/generic/blf_py_api.c b/source/blender/python/generic/blf_py_api.c
index 69f1e297b43..02bd1fdbe39 100644
--- a/source/blender/python/generic/blf_py_api.c
+++ b/source/blender/python/generic/blf_py_api.c
@@ -114,6 +114,7 @@ static PyObject *py_blf_aspect(PyObject *UNUSED(self), PyObject *args)
}
+#if BLF_BLUR_ENABLE
PyDoc_STRVAR(py_blf_blur_doc,
".. function:: blur(fontid, radius)\n"
"\n"
@@ -135,6 +136,7 @@ static PyObject *py_blf_blur(PyObject *UNUSED(self), PyObject *args)
Py_RETURN_NONE;
}
+#endif
PyDoc_STRVAR(py_blf_draw_doc,
@@ -418,7 +420,9 @@ static PyObject *py_blf_unload(PyObject *UNUSED(self), PyObject *args)
/*----------------------------MODULE INIT-------------------------*/
static PyMethodDef BLF_methods[] = {
{"aspect", (PyCFunction) py_blf_aspect, METH_VARARGS, py_blf_aspect_doc},
+#if BLF_BLUR_ENABLE
{"blur", (PyCFunction) py_blf_blur, METH_VARARGS, py_blf_blur_doc},
+#endif
{"clipping", (PyCFunction) py_blf_clipping, METH_VARARGS, py_blf_clipping_doc},
{"word_wrap", (PyCFunction) py_blf_word_wrap, METH_VARARGS, py_blf_word_wrap_doc},
{"disable", (PyCFunction) py_blf_disable, METH_VARARGS, py_blf_disable_doc},
diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c
index 86961cdd169..5f87f9b03d6 100644
--- a/source/blender/render/intern/source/convertblender.c
+++ b/source/blender/render/intern/source/convertblender.c
@@ -57,7 +57,6 @@
#include "DNA_node_types.h"
#include "DNA_object_types.h"
#include "DNA_object_fluidsim.h"
-#include "DNA_particle_types.h"
#include "DNA_scene_types.h"
#include "DNA_texture_types.h"
@@ -79,7 +78,6 @@
#include "BKE_modifier.h"
#include "BKE_node.h"
#include "BKE_object.h"
-#include "BKE_particle.h"
#include "BKE_scene.h"
#include "PIL_time.h"
@@ -749,1148 +747,6 @@ static Material *give_render_material(Render *re, Object *ob, short nr)
}
/* ------------------------------------------------------------------------- */
-/* Particles */
-/* ------------------------------------------------------------------------- */
-typedef struct ParticleStrandData {
- struct MCol *mcol;
- float *orco, *uvco, *surfnor;
- float time, adapt_angle, adapt_pix, size;
- int totuv, totcol;
- int first, line, adapt, override_uv;
-}
-ParticleStrandData;
-/* future thread problem... */
-static void static_particle_strand(Render *re, ObjectRen *obr, Material *ma, ParticleStrandData *sd, const float vec[3], const float vec1[3])
-{
- static VertRen *v1= NULL, *v2= NULL;
- VlakRen *vlr= NULL;
- float nor[3], cross[3], crosslen, w, dx, dy, width;
- static float anor[3], avec[3];
- int flag, i;
- static int second=0;
-
- sub_v3_v3v3(nor, vec, vec1);
- normalize_v3(nor); /* nor needed as tangent */
- cross_v3_v3v3(cross, vec, nor);
-
- /* turn cross in pixelsize */
- w= vec[2]*re->winmat[2][3] + re->winmat[3][3];
- dx= re->winx*cross[0]*re->winmat[0][0];
- dy= re->winy*cross[1]*re->winmat[1][1];
- w = sqrtf(dx * dx + dy * dy) / w;
-
- if (w!=0.0f) {
- float fac;
- if (ma->strand_ease!=0.0f) {
- if (ma->strand_ease<0.0f)
- fac= pow(sd->time, 1.0f+ma->strand_ease);
- else
- fac= pow(sd->time, 1.0f/(1.0f-ma->strand_ease));
- }
- else fac= sd->time;
-
- width= ((1.0f-fac)*ma->strand_sta + (fac)*ma->strand_end);
-
- /* use actual Blender units for strand width and fall back to minimum width */
- if (ma->mode & MA_STR_B_UNITS) {
- crosslen= len_v3(cross);
- w= 2.0f*crosslen*ma->strand_min/w;
-
- if (width < w)
- width= w;
-
- /*cross is the radius of the strand so we want it to be half of full width */
- mul_v3_fl(cross, 0.5f/crosslen);
- }
- else
- width/=w;
-
- mul_v3_fl(cross, width);
- }
-
- if (ma->mode & MA_TANGENT_STR)
- flag= R_SMOOTH|R_TANGENT;
- else
- flag= R_SMOOTH;
-
- /* only 1 pixel wide strands filled in as quads now, otherwise zbuf errors */
- if (ma->strand_sta==1.0f)
- flag |= R_STRAND;
-
- /* single face line */
- if (sd->line) {
- vlr= RE_findOrAddVlak(obr, obr->totvlak++);
- vlr->flag= flag;
- vlr->v1= RE_findOrAddVert(obr, obr->totvert++);
- vlr->v2= RE_findOrAddVert(obr, obr->totvert++);
- vlr->v3= RE_findOrAddVert(obr, obr->totvert++);
- vlr->v4= RE_findOrAddVert(obr, obr->totvert++);
-
- copy_v3_v3(vlr->v1->co, vec);
- add_v3_v3(vlr->v1->co, cross);
- copy_v3_v3(vlr->v1->n, nor);
- vlr->v1->orco= sd->orco;
- vlr->v1->accum = -1.0f; /* accum abuse for strand texco */
-
- copy_v3_v3(vlr->v2->co, vec);
- sub_v3_v3v3(vlr->v2->co, vlr->v2->co, cross);
- copy_v3_v3(vlr->v2->n, nor);
- vlr->v2->orco= sd->orco;
- vlr->v2->accum= vlr->v1->accum;
-
- copy_v3_v3(vlr->v4->co, vec1);
- add_v3_v3(vlr->v4->co, cross);
- copy_v3_v3(vlr->v4->n, nor);
- vlr->v4->orco= sd->orco;
- vlr->v4->accum = 1.0f; /* accum abuse for strand texco */
-
- copy_v3_v3(vlr->v3->co, vec1);
- sub_v3_v3v3(vlr->v3->co, vlr->v3->co, cross);
- copy_v3_v3(vlr->v3->n, nor);
- vlr->v3->orco= sd->orco;
- vlr->v3->accum= vlr->v4->accum;
-
- normal_quad_v3(vlr->n, vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co);
-
- vlr->mat= ma;
- vlr->ec= ME_V2V3;
-
- if (sd->surfnor) {
- float *snor= RE_vlakren_get_surfnor(obr, vlr, 1);
- copy_v3_v3(snor, sd->surfnor);
- }
-
- if (sd->uvco) {
- for (i=0; i<sd->totuv; i++) {
- MTFace *mtf;
- mtf=RE_vlakren_get_tface(obr, vlr, i, NULL, 1);
- mtf->uv[0][0]=mtf->uv[1][0]=
- mtf->uv[2][0]=mtf->uv[3][0]=(sd->uvco+2*i)[0];
- mtf->uv[0][1]=mtf->uv[1][1]=
- mtf->uv[2][1]=mtf->uv[3][1]=(sd->uvco+2*i)[1];
- }
- if (sd->override_uv>=0) {
- MTFace *mtf;
- mtf=RE_vlakren_get_tface(obr, vlr, sd->override_uv, NULL, 0);
-
- mtf->uv[0][0]=mtf->uv[3][0]=0.0f;
- mtf->uv[1][0]=mtf->uv[2][0]=1.0f;
-
- mtf->uv[0][1]=mtf->uv[1][1]=0.0f;
- mtf->uv[2][1]=mtf->uv[3][1]=1.0f;
- }
- }
- if (sd->mcol) {
- for (i=0; i<sd->totcol; i++) {
- MCol *mc;
- mc=RE_vlakren_get_mcol(obr, vlr, i, NULL, 1);
- mc[0]=mc[1]=mc[2]=mc[3]=sd->mcol[i];
- mc[0]=mc[1]=mc[2]=mc[3]=sd->mcol[i];
- }
- }
- }
- /* first two vertices of a strand */
- else if (sd->first) {
- if (sd->adapt) {
- copy_v3_v3(anor, nor);
- copy_v3_v3(avec, vec);
- second=1;
- }
-
- v1= RE_findOrAddVert(obr, obr->totvert++);
- v2= RE_findOrAddVert(obr, obr->totvert++);
-
- copy_v3_v3(v1->co, vec);
- add_v3_v3(v1->co, cross);
- copy_v3_v3(v1->n, nor);
- v1->orco= sd->orco;
- v1->accum = -1.0f; /* accum abuse for strand texco */
-
- copy_v3_v3(v2->co, vec);
- sub_v3_v3v3(v2->co, v2->co, cross);
- copy_v3_v3(v2->n, nor);
- v2->orco= sd->orco;
- v2->accum= v1->accum;
- }
- /* more vertices & faces to strand */
- else {
- if (sd->adapt==0 || second) {
- vlr= RE_findOrAddVlak(obr, obr->totvlak++);
- vlr->flag= flag;
- vlr->v1= v1;
- vlr->v2= v2;
- vlr->v3= RE_findOrAddVert(obr, obr->totvert++);
- vlr->v4= RE_findOrAddVert(obr, obr->totvert++);
-
- v1= vlr->v4; /* cycle */
- v2= vlr->v3; /* cycle */
-
-
- if (sd->adapt) {
- second=0;
- copy_v3_v3(anor, nor);
- copy_v3_v3(avec, vec);
- }
-
- }
- else if (sd->adapt) {
- float dvec[3], pvec[3];
- sub_v3_v3v3(dvec, avec, vec);
- project_v3_v3v3(pvec, dvec, vec);
- sub_v3_v3v3(dvec, dvec, pvec);
-
- w= vec[2]*re->winmat[2][3] + re->winmat[3][3];
- dx= re->winx*dvec[0]*re->winmat[0][0]/w;
- dy= re->winy*dvec[1]*re->winmat[1][1]/w;
- w = sqrtf(dx * dx + dy * dy);
- if (dot_v3v3(anor, nor)<sd->adapt_angle && w>sd->adapt_pix) {
- vlr= RE_findOrAddVlak(obr, obr->totvlak++);
- vlr->flag= flag;
- vlr->v1= v1;
- vlr->v2= v2;
- vlr->v3= RE_findOrAddVert(obr, obr->totvert++);
- vlr->v4= RE_findOrAddVert(obr, obr->totvert++);
-
- v1= vlr->v4; /* cycle */
- v2= vlr->v3; /* cycle */
-
- copy_v3_v3(anor, nor);
- copy_v3_v3(avec, vec);
- }
- else {
- vlr= RE_findOrAddVlak(obr, obr->totvlak-1);
- }
- }
-
- copy_v3_v3(vlr->v4->co, vec);
- add_v3_v3(vlr->v4->co, cross);
- copy_v3_v3(vlr->v4->n, nor);
- vlr->v4->orco= sd->orco;
- vlr->v4->accum= -1.0f + 2.0f * sd->time; /* accum abuse for strand texco */
-
- copy_v3_v3(vlr->v3->co, vec);
- sub_v3_v3v3(vlr->v3->co, vlr->v3->co, cross);
- copy_v3_v3(vlr->v3->n, nor);
- vlr->v3->orco= sd->orco;
- vlr->v3->accum= vlr->v4->accum;
-
- normal_quad_v3(vlr->n, vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co);
-
- vlr->mat= ma;
- vlr->ec= ME_V2V3;
-
- if (sd->surfnor) {
- float *snor= RE_vlakren_get_surfnor(obr, vlr, 1);
- copy_v3_v3(snor, sd->surfnor);
- }
-
- if (sd->uvco) {
- for (i=0; i<sd->totuv; i++) {
- MTFace *mtf;
- mtf=RE_vlakren_get_tface(obr, vlr, i, NULL, 1);
- mtf->uv[0][0]=mtf->uv[1][0]=
- mtf->uv[2][0]=mtf->uv[3][0]=(sd->uvco+2*i)[0];
- mtf->uv[0][1]=mtf->uv[1][1]=
- mtf->uv[2][1]=mtf->uv[3][1]=(sd->uvco+2*i)[1];
- }
- if (sd->override_uv>=0) {
- MTFace *mtf;
- mtf=RE_vlakren_get_tface(obr, vlr, sd->override_uv, NULL, 0);
-
- mtf->uv[0][0]=mtf->uv[3][0]=0.0f;
- mtf->uv[1][0]=mtf->uv[2][0]=1.0f;
-
- mtf->uv[0][1]=mtf->uv[1][1]=(vlr->v1->accum+1.0f)/2.0f;
- mtf->uv[2][1]=mtf->uv[3][1]=(vlr->v3->accum+1.0f)/2.0f;
- }
- }
- if (sd->mcol) {
- for (i=0; i<sd->totcol; i++) {
- MCol *mc;
- mc=RE_vlakren_get_mcol(obr, vlr, i, NULL, 1);
- mc[0]=mc[1]=mc[2]=mc[3]=sd->mcol[i];
- mc[0]=mc[1]=mc[2]=mc[3]=sd->mcol[i];
- }
- }
- }
-}
-
-static void static_particle_wire(ObjectRen *obr, Material *ma, const float vec[3], const float vec1[3], int first, int line)
-{
- VlakRen *vlr;
- static VertRen *v1;
-
- if (line) {
- vlr= RE_findOrAddVlak(obr, obr->totvlak++);
- vlr->v1= RE_findOrAddVert(obr, obr->totvert++);
- vlr->v2= RE_findOrAddVert(obr, obr->totvert++);
- vlr->v3= vlr->v2;
- vlr->v4= NULL;
-
- copy_v3_v3(vlr->v1->co, vec);
- copy_v3_v3(vlr->v2->co, vec1);
-
- sub_v3_v3v3(vlr->n, vec, vec1);
- normalize_v3(vlr->n);
- copy_v3_v3(vlr->v1->n, vlr->n);
- copy_v3_v3(vlr->v2->n, vlr->n);
-
- vlr->mat= ma;
- vlr->ec= ME_V1V2;
-
- }
- else if (first) {
- v1= RE_findOrAddVert(obr, obr->totvert++);
- copy_v3_v3(v1->co, vec);
- }
- else {
- vlr= RE_findOrAddVlak(obr, obr->totvlak++);
- vlr->v1= v1;
- vlr->v2= RE_findOrAddVert(obr, obr->totvert++);
- vlr->v3= vlr->v2;
- vlr->v4= NULL;
-
- v1= vlr->v2; /* cycle */
- copy_v3_v3(v1->co, vec);
-
- sub_v3_v3v3(vlr->n, vec, vec1);
- normalize_v3(vlr->n);
- copy_v3_v3(v1->n, vlr->n);
-
- vlr->mat= ma;
- vlr->ec= ME_V1V2;
- }
-
-}
-
-static void particle_curve(Render *re, ObjectRen *obr, DerivedMesh *dm, Material *ma, ParticleStrandData *sd,
- const float loc[3], const float loc1[3], int seed, float *pa_co)
-{
- HaloRen *har = NULL;
-
- if (ma->material_type == MA_TYPE_WIRE)
- static_particle_wire(obr, ma, loc, loc1, sd->first, sd->line);
- else if (ma->material_type == MA_TYPE_HALO) {
- har= RE_inithalo_particle(re, obr, dm, ma, loc, loc1, sd->orco, sd->uvco, sd->size, 1.0, seed, pa_co);
- if (har) har->lay= obr->ob->lay;
- }
- else
- static_particle_strand(re, obr, ma, sd, loc, loc1);
-}
-static void particle_billboard(Render *re, ObjectRen *obr, Material *ma, ParticleBillboardData *bb)
-{
- VlakRen *vlr;
- MTFace *mtf;
- float xvec[3], yvec[3], zvec[3], bb_center[3];
- /* Number of tiles */
- int totsplit = bb->uv_split * bb->uv_split;
- int tile, x, y;
- /* Tile offsets */
- float uvx = 0.0f, uvy = 0.0f, uvdx = 1.0f, uvdy = 1.0f, time = 0.0f;
-
- vlr= RE_findOrAddVlak(obr, obr->totvlak++);
- vlr->v1= RE_findOrAddVert(obr, obr->totvert++);
- vlr->v2= RE_findOrAddVert(obr, obr->totvert++);
- vlr->v3= RE_findOrAddVert(obr, obr->totvert++);
- vlr->v4= RE_findOrAddVert(obr, obr->totvert++);
-
- psys_make_billboard(bb, xvec, yvec, zvec, bb_center);
-
- add_v3_v3v3(vlr->v1->co, bb_center, xvec);
- add_v3_v3(vlr->v1->co, yvec);
- mul_m4_v3(re->viewmat, vlr->v1->co);
-
- sub_v3_v3v3(vlr->v2->co, bb_center, xvec);
- add_v3_v3(vlr->v2->co, yvec);
- mul_m4_v3(re->viewmat, vlr->v2->co);
-
- sub_v3_v3v3(vlr->v3->co, bb_center, xvec);
- sub_v3_v3v3(vlr->v3->co, vlr->v3->co, yvec);
- mul_m4_v3(re->viewmat, vlr->v3->co);
-
- add_v3_v3v3(vlr->v4->co, bb_center, xvec);
- sub_v3_v3(vlr->v4->co, yvec);
- mul_m4_v3(re->viewmat, vlr->v4->co);
-
- normal_quad_v3(vlr->n, vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co);
- copy_v3_v3(vlr->v1->n, vlr->n);
- copy_v3_v3(vlr->v2->n, vlr->n);
- copy_v3_v3(vlr->v3->n, vlr->n);
- copy_v3_v3(vlr->v4->n, vlr->n);
-
- vlr->mat= ma;
- vlr->ec= ME_V2V3;
-
- if (bb->uv_split > 1) {
- uvdx = uvdy = 1.0f / (float)bb->uv_split;
-
- if (ELEM(bb->anim, PART_BB_ANIM_AGE, PART_BB_ANIM_FRAME)) {
- if (bb->anim == PART_BB_ANIM_FRAME)
- time = ((int)(bb->time * bb->lifetime) % totsplit)/(float)totsplit;
- else
- time = bb->time;
- }
- else if (bb->anim == PART_BB_ANIM_ANGLE) {
- if (bb->align == PART_BB_VIEW) {
- time = (float)fmod((bb->tilt + 1.0f) / 2.0f, 1.0);
- }
- else {
- float axis1[3] = {0.0f, 0.0f, 0.0f};
- float axis2[3] = {0.0f, 0.0f, 0.0f};
-
- axis1[(bb->align + 1) % 3] = 1.0f;
- axis2[(bb->align + 2) % 3] = 1.0f;
-
- if (bb->lock == 0) {
- zvec[bb->align] = 0.0f;
- normalize_v3(zvec);
- }
-
- time = saacos(dot_v3v3(zvec, axis1)) / (float)M_PI;
-
- if (dot_v3v3(zvec, axis2) < 0.0f)
- time = 1.0f - time / 2.0f;
- else
- time /= 2.0f;
- }
- }
-
- if (bb->split_offset == PART_BB_OFF_LINEAR)
- time = (float)fmod(time + (float)bb->num / (float)totsplit, 1.0f);
- else if (bb->split_offset==PART_BB_OFF_RANDOM)
- time = (float)fmod(time + bb->random, 1.0f);
-
- /* Find the coordinates in tile space (integer), then convert to UV
- * space (float). Note that Y is flipped. */
- tile = (int)((time + FLT_EPSILON10) * totsplit);
- x = tile % bb->uv_split;
- y = tile / bb->uv_split;
- y = (bb->uv_split - 1) - y;
- uvx = uvdx * x;
- uvy = uvdy * y;
- }
-
- /* normal UVs */
- if (bb->uv[0] >= 0) {
- mtf = RE_vlakren_get_tface(obr, vlr, bb->uv[0], NULL, 1);
- mtf->uv[0][0] = 1.0f;
- mtf->uv[0][1] = 1.0f;
- mtf->uv[1][0] = 0.0f;
- mtf->uv[1][1] = 1.0f;
- mtf->uv[2][0] = 0.0f;
- mtf->uv[2][1] = 0.0f;
- mtf->uv[3][0] = 1.0f;
- mtf->uv[3][1] = 0.0f;
- }
-
- /* time-index UVs */
- if (bb->uv[1] >= 0) {
- mtf = RE_vlakren_get_tface(obr, vlr, bb->uv[1], NULL, 1);
- mtf->uv[0][0] = mtf->uv[1][0] = mtf->uv[2][0] = mtf->uv[3][0] = bb->time;
- mtf->uv[0][1] = mtf->uv[1][1] = mtf->uv[2][1] = mtf->uv[3][1] = (float)bb->num/(float)bb->totnum;
- }
-
- /* split UVs */
- if (bb->uv_split > 1 && bb->uv[2] >= 0) {
- mtf = RE_vlakren_get_tface(obr, vlr, bb->uv[2], NULL, 1);
- mtf->uv[0][0] = uvx + uvdx;
- mtf->uv[0][1] = uvy + uvdy;
- mtf->uv[1][0] = uvx;
- mtf->uv[1][1] = uvy + uvdy;
- mtf->uv[2][0] = uvx;
- mtf->uv[2][1] = uvy;
- mtf->uv[3][0] = uvx + uvdx;
- mtf->uv[3][1] = uvy;
- }
-}
-static void particle_normal_ren(short ren_as, ParticleSettings *part, Render *re, ObjectRen *obr, DerivedMesh *dm, Material *ma, ParticleStrandData *sd, ParticleBillboardData *bb, ParticleKey *state, int seed, float hasize, float *pa_co)
-{
- float loc[3], loc0[3], loc1[3], vel[3];
-
- copy_v3_v3(loc, state->co);
-
- if (ren_as != PART_DRAW_BB)
- mul_m4_v3(re->viewmat, loc);
-
- switch (ren_as) {
- case PART_DRAW_LINE:
- sd->line = 1;
- sd->time = 0.0f;
- sd->size = hasize;
-
- mul_v3_mat3_m4v3(vel, re->viewmat, state->vel);
- normalize_v3(vel);
-
- if (part->draw & PART_DRAW_VEL_LENGTH)
- mul_v3_fl(vel, len_v3(state->vel));
-
- madd_v3_v3v3fl(loc0, loc, vel, -part->draw_line[0]);
- madd_v3_v3v3fl(loc1, loc, vel, part->draw_line[1]);
-
- particle_curve(re, obr, dm, ma, sd, loc0, loc1, seed, pa_co);
-
- break;
-
- case PART_DRAW_BB:
-
- copy_v3_v3(bb->vec, loc);
- copy_v3_v3(bb->vel, state->vel);
-
- particle_billboard(re, obr, ma, bb);
-
- break;
-
- default:
- {
- HaloRen *har = NULL;
-
- har = RE_inithalo_particle(re, obr, dm, ma, loc, NULL, sd->orco, sd->uvco, hasize, 0.0, seed, pa_co);
-
- if (har) har->lay= obr->ob->lay;
-
- break;
- }
- }
-}
-static void get_particle_uvco_mcol(short from, DerivedMesh *dm, float *fuv, int num, ParticleStrandData *sd)
-{
- int i;
-
- /* get uvco */
- if (sd->uvco && ELEM(from, PART_FROM_FACE, PART_FROM_VOLUME)) {
- for (i=0; i<sd->totuv; i++) {
- if (!ELEM(num, DMCACHE_NOTFOUND, DMCACHE_ISCHILD)) {
- MFace *mface = dm->getTessFaceData(dm, num, CD_MFACE);
- MTFace *mtface = (MTFace*)CustomData_get_layer_n(&dm->faceData, CD_MTFACE, i);
- mtface += num;
-
- psys_interpolate_uvs(mtface, mface->v4, fuv, sd->uvco + 2 * i);
- }
- else {
- sd->uvco[2*i] = 0.0f;
- sd->uvco[2*i + 1] = 0.0f;
- }
- }
- }
-
- /* get mcol */
- if (sd->mcol && ELEM(from, PART_FROM_FACE, PART_FROM_VOLUME)) {
- for (i=0; i<sd->totcol; i++) {
- if (!ELEM(num, DMCACHE_NOTFOUND, DMCACHE_ISCHILD)) {
- MFace *mface = dm->getTessFaceData(dm, num, CD_MFACE);
- MCol *mc = (MCol*)CustomData_get_layer_n(&dm->faceData, CD_MCOL, i);
- mc += num * 4;
-
- psys_interpolate_mcol(mc, mface->v4, fuv, sd->mcol + i);
- }
- else
- memset(&sd->mcol[i], 0, sizeof(MCol));
- }
- }
-}
-static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem *psys, int timeoffset)
-{
- Object *ob= obr->ob;
-// Object *tob=0;
- Material *ma = NULL;
- ParticleSystemModifierData *psmd;
- ParticleSystem *tpsys = NULL;
- ParticleSettings *part, *tpart = NULL;
- ParticleData *pars, *pa = NULL, *tpa = NULL;
- ParticleKey *states = NULL;
- ParticleKey state;
- ParticleCacheKey *cache = NULL;
- ParticleBillboardData bb;
- ParticleSimulationData sim = {NULL};
- ParticleStrandData sd;
- StrandBuffer *strandbuf = NULL;
- StrandVert *svert = NULL;
- StrandBound *sbound = NULL;
- StrandRen *strand = NULL;
- RNG *rng = NULL;
- float loc[3], loc1[3], loc0[3], mat[4][4], nmat[3][3], co[3], nor[3], duplimat[4][4];
- float strandlen=0.0f, curlen=0.0f;
- float hasize, pa_size, r_tilt, r_length;
- float pa_time, pa_birthtime, pa_dietime;
- float random, simplify[2], pa_co[3];
- const float cfra= BKE_scene_frame_get(re->scene);
- int i, a, k, max_k=0, totpart;
- bool do_simplify = false, do_surfacecache = false, use_duplimat = false;
- int totchild=0, step_nbr;
- int seed, path_nbr=0, orco1=0, num;
- int totface;
-
- const int *index_mf_to_mpoly = NULL;
- const int *index_mp_to_orig = NULL;
-
-/* 1. check that everything is ok & updated */
- if (psys==NULL)
- return 0;
-
- part=psys->part;
- pars=psys->particles;
-
- if (part==NULL || pars==NULL || !psys_check_enabled(ob, psys, G.is_rendering))
- return 0;
-
- if (part->ren_as==PART_DRAW_OB || part->ren_as==PART_DRAW_GR || part->ren_as==PART_DRAW_NOT)
- return 1;
-
- if ((re->r.scemode & R_VIEWPORT_PREVIEW) && (ob->mode & OB_MODE_PARTICLE_EDIT))
- return 0;
-
- if (part->ren_as == PART_DRAW_BB && part->bb_ob == NULL && RE_GetCamera(re) == NULL)
- return 0;
-
-/* 2. start initializing things */
-
- /* last possibility to bail out! */
- psmd = psys_get_modifier(ob, psys);
- if (!(psmd->modifier.mode & eModifierMode_Render))
- return 0;
-
- sim.scene= re->scene;
- sim.ob= ob;
- sim.psys= psys;
- sim.psmd= psmd;
-
- if (part->phystype==PART_PHYS_KEYED)
- psys_count_keyed_targets(&sim);
-
- totchild=psys->totchild;
-
- /* can happen for disconnected/global hair */
- if (part->type==PART_HAIR && !psys->childcache)
- totchild= 0;
-
- if (re->r.scemode & R_VIEWPORT_PREVIEW) { /* preview render */
- totchild = (int)((float)totchild * (float)part->disp / 100.0f);
- step_nbr = 1 << part->draw_step;
- }
- else {
- step_nbr = 1 << part->ren_step;
- }
- if (ELEM(part->kink, PART_KINK_SPIRAL))
- step_nbr += part->kink_extra_steps;
-
- psys->flag |= PSYS_DRAWING;
-
- rng= BLI_rng_new(psys->seed);
-
- totpart=psys->totpart;
-
- memset(&sd, 0, sizeof(ParticleStrandData));
- sd.override_uv = -1;
-
-/* 2.1 setup material stff */
- ma= give_render_material(re, ob, part->omat);
-
-#if 0 /* XXX old animation system */
- if (ma->ipo) {
- calc_ipo(ma->ipo, cfra);
- execute_ipo((ID *)ma, ma->ipo);
- }
-#endif /* XXX old animation system */
-
- hasize = ma->hasize;
- seed = ma->seed1;
-
- re->flag |= R_HALO;
-
- RE_set_customdata_names(obr, &psmd->dm_final->faceData);
- sd.totuv = CustomData_number_of_layers(&psmd->dm_final->faceData, CD_MTFACE);
- sd.totcol = CustomData_number_of_layers(&psmd->dm_final->faceData, CD_MCOL);
-
- if (ma->texco & TEXCO_UV && sd.totuv) {
- sd.uvco = MEM_callocN(sd.totuv * 2 * sizeof(float), "particle_uvs");
-
- if (ma->strand_uvname[0]) {
- sd.override_uv = CustomData_get_named_layer_index(&psmd->dm_final->faceData, CD_MTFACE, ma->strand_uvname);
- sd.override_uv -= CustomData_get_layer_index(&psmd->dm_final->faceData, CD_MTFACE);
- }
- }
- else
- sd.uvco = NULL;
-
- if (sd.totcol)
- sd.mcol = MEM_callocN(sd.totcol * sizeof(MCol), "particle_mcols");
-
-/* 2.2 setup billboards */
- if (part->ren_as == PART_DRAW_BB) {
- int first_uv = CustomData_get_layer_index(&psmd->dm_final->faceData, CD_MTFACE);
-
- bb.uv[0] = CustomData_get_named_layer_index(&psmd->dm_final->faceData, CD_MTFACE, psys->bb_uvname[0]);
- if (bb.uv[0] < 0)
- bb.uv[0] = CustomData_get_active_layer_index(&psmd->dm_final->faceData, CD_MTFACE);
-
- bb.uv[1] = CustomData_get_named_layer_index(&psmd->dm_final->faceData, CD_MTFACE, psys->bb_uvname[1]);
-
- bb.uv[2] = CustomData_get_named_layer_index(&psmd->dm_final->faceData, CD_MTFACE, psys->bb_uvname[2]);
-
- if (first_uv >= 0) {
- bb.uv[0] -= first_uv;
- bb.uv[1] -= first_uv;
- bb.uv[2] -= first_uv;
- }
-
- bb.align = part->bb_align;
- bb.anim = part->bb_anim;
- bb.lock = part->draw & PART_DRAW_BB_LOCK;
- bb.ob = (part->bb_ob ? part->bb_ob : RE_GetCamera(re));
- bb.split_offset = part->bb_split_offset;
- bb.totnum = totpart+totchild;
- bb.uv_split = part->bb_uv_split;
- }
-
-/* 2.5 setup matrices */
- mul_m4_m4m4(mat, re->viewmat, ob->obmat);
- invert_m4_m4(ob->imat, mat); /* need to be that way, for imat texture */
- transpose_m3_m4(nmat, ob->imat);
-
- if (psys->flag & PSYS_USE_IMAT) {
- /* psys->imat is the original emitter's inverse matrix, ob->obmat is the duplicated object's matrix */
- mul_m4_m4m4(duplimat, ob->obmat, psys->imat);
- use_duplimat = true;
- }
-
-/* 2.6 setup strand rendering */
- if (part->ren_as == PART_DRAW_PATH && psys->pathcache) {
- path_nbr = step_nbr;
-
- if (path_nbr) {
- if (!ELEM(ma->material_type, MA_TYPE_HALO, MA_TYPE_WIRE)) {
- sd.orco = get_object_orco(re, psys);
- if (!sd.orco) {
- sd.orco = MEM_mallocN(3*sizeof(float)*(totpart+totchild), "particle orcos");
- set_object_orco(re, psys, sd.orco);
- }
- }
- }
-
- if (part->draw & PART_DRAW_REN_ADAPT) {
- sd.adapt = 1;
- sd.adapt_pix = (float)part->adapt_pix;
- sd.adapt_angle = cosf(DEG2RADF((float)part->adapt_angle));
- }
-
- if (part->draw & PART_DRAW_REN_STRAND) {
- strandbuf= RE_addStrandBuffer(obr, (totpart+totchild)*(path_nbr+1));
- strandbuf->ma= ma;
- strandbuf->lay= ob->lay;
- copy_m4_m4(strandbuf->winmat, re->winmat);
- strandbuf->winx= re->winx;
- strandbuf->winy= re->winy;
- strandbuf->maxdepth= 2;
- strandbuf->adaptcos= cosf(DEG2RADF((float)part->adapt_angle));
- strandbuf->overrideuv= sd.override_uv;
- strandbuf->minwidth= ma->strand_min;
-
- if (ma->strand_widthfade == 0.0f)
- strandbuf->widthfade= -1.0f;
- else if (ma->strand_widthfade >= 1.0f)
- strandbuf->widthfade= 2.0f - ma->strand_widthfade;
- else
- strandbuf->widthfade= 1.0f/MAX2(ma->strand_widthfade, 1e-5f);
-
- if (part->flag & PART_HAIR_BSPLINE)
- strandbuf->flag |= R_STRAND_BSPLINE;
- if (ma->mode & MA_STR_B_UNITS)
- strandbuf->flag |= R_STRAND_B_UNITS;
-
- svert= strandbuf->vert;
-
- if (re->r.mode & R_SPEED)
- do_surfacecache = true;
- else if ((re->wrld.mode & (WO_AMB_OCC|WO_ENV_LIGHT|WO_INDIRECT_LIGHT)) && (re->wrld.ao_gather_method == WO_AOGATHER_APPROX))
- if (ma->amb != 0.0f)
- do_surfacecache = true;
-
- totface= psmd->dm_final->getNumTessFaces(psmd->dm_final);
- index_mf_to_mpoly = psmd->dm_final->getTessFaceDataArray(psmd->dm_final, CD_ORIGINDEX);
- index_mp_to_orig = psmd->dm_final->getPolyDataArray(psmd->dm_final, CD_ORIGINDEX);
- if (index_mf_to_mpoly == NULL) {
- index_mp_to_orig = NULL;
- }
- for (a=0; a<totface; a++)
- strandbuf->totbound = max_ii(strandbuf->totbound, (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, a): a);
-
- strandbuf->totbound++;
- strandbuf->bound= MEM_callocN(sizeof(StrandBound)*strandbuf->totbound, "StrandBound");
- sbound= strandbuf->bound;
- sbound->start= sbound->end= 0;
- }
- }
-
- if (sd.orco == NULL) {
- sd.orco = MEM_mallocN(3 * sizeof(float), "particle orco");
- orco1 = 1;
- }
-
- if (path_nbr == 0)
- psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
-
-/* 3. start creating renderable things */
- for (a=0, pa=pars; a<totpart+totchild; a++, pa++, seed++) {
- random = BLI_rng_get_float(rng);
- /* setup per particle individual stuff */
- if (a<totpart) {
- if (pa->flag & PARS_UNEXIST) continue;
-
- pa_time=(cfra-pa->time)/pa->lifetime;
- pa_birthtime = pa->time;
- pa_dietime = pa->dietime;
-
- hasize = ma->hasize;
-
- /* XXX 'tpsys' is alwyas NULL, this code won't run! */
- /* get orco */
- if (tpsys && part->phystype == PART_PHYS_NO) {
- tpa = tpsys->particles + pa->num;
- psys_particle_on_emitter(
- psmd,
- tpart->from, tpa->num, pa->num_dmcache, tpa->fuv,
- tpa->foffset, co, nor, NULL, NULL, sd.orco, NULL);
- }
- else {
- psys_particle_on_emitter(
- psmd,
- part->from, pa->num, pa->num_dmcache,
- pa->fuv, pa->foffset, co, nor, NULL, NULL, sd.orco, NULL);
- }
-
- /* get uvco & mcol */
- num= pa->num_dmcache;
-
- if (num == DMCACHE_NOTFOUND)
- if (pa->num < psmd->dm_final->getNumTessFaces(psmd->dm_final))
- num= pa->num;
-
- get_particle_uvco_mcol(part->from, psmd->dm_final, pa->fuv, num, &sd);
-
- pa_size = pa->size;
-
- r_tilt = 2.0f*(psys_frand(psys, a) - 0.5f);
- r_length = psys_frand(psys, a+1);
-
- if (path_nbr) {
- cache = psys->pathcache[a];
- max_k = (int)cache->segments;
- }
-
- if (totchild && (part->draw&PART_DRAW_PARENT)==0) continue;
- }
- else {
- ChildParticle *cpa= psys->child+a-totpart;
-
- if (path_nbr) {
- cache = psys->childcache[a-totpart];
-
- if (cache->segments < 0)
- continue;
-
- max_k = (int)cache->segments;
- }
-
- pa_time = psys_get_child_time(psys, cpa, cfra, &pa_birthtime, &pa_dietime);
- pa_size = psys_get_child_size(psys, cpa, cfra, &pa_time);
-
- r_tilt = 2.0f*(psys_frand(psys, a + 21) - 0.5f);
- r_length = psys_frand(psys, a + 22);
-
- num = cpa->num;
-
- /* get orco */
- if (part->childtype == PART_CHILD_FACES) {
- psys_particle_on_emitter(
- psmd,
- PART_FROM_FACE, cpa->num, DMCACHE_ISCHILD,
- cpa->fuv, cpa->foffset, co, nor, NULL, NULL, sd.orco, NULL);
- }
- else {
- ParticleData *par = psys->particles + cpa->parent;
- psys_particle_on_emitter(
- psmd,
- part->from, par->num, DMCACHE_ISCHILD, par->fuv,
- par->foffset, co, nor, NULL, NULL, sd.orco, NULL);
- }
-
- /* get uvco & mcol */
- if (part->childtype==PART_CHILD_FACES) {
- get_particle_uvco_mcol(PART_FROM_FACE, psmd->dm_final, cpa->fuv, cpa->num, &sd);
- }
- else {
- ParticleData *parent = psys->particles + cpa->parent;
- num = parent->num_dmcache;
-
- if (num == DMCACHE_NOTFOUND)
- if (parent->num < psmd->dm_final->getNumTessFaces(psmd->dm_final))
- num = parent->num;
-
- get_particle_uvco_mcol(part->from, psmd->dm_final, parent->fuv, num, &sd);
- }
-
- do_simplify = psys_render_simplify_params(psys, cpa, simplify);
-
- if (strandbuf) {
- int orignum = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, cpa->num) : cpa->num;
-
- if ((orignum > sbound - strandbuf->bound) &&
- (orignum < strandbuf->totbound))
- {
- sbound = &strandbuf->bound[orignum];
- sbound->start = sbound->end = obr->totstrand;
- }
- }
- }
-
- /* TEXCO_PARTICLE */
- pa_co[0] = pa_time;
- pa_co[1] = 0.f;
- pa_co[2] = 0.f;
-
- /* surface normal shading setup */
- if (ma->mode_l & MA_STR_SURFDIFF) {
- mul_m3_v3(nmat, nor);
- sd.surfnor= nor;
- }
- else
- sd.surfnor= NULL;
-
- /* strand render setup */
- if (strandbuf) {
- strand= RE_findOrAddStrand(obr, obr->totstrand++);
- strand->buffer= strandbuf;
- strand->vert= svert;
- copy_v3_v3(strand->orco, sd.orco);
-
- if (do_simplify) {
- float *ssimplify= RE_strandren_get_simplify(obr, strand, 1);
- ssimplify[0]= simplify[0];
- ssimplify[1]= simplify[1];
- }
-
- if (sd.surfnor) {
- float *snor= RE_strandren_get_surfnor(obr, strand, 1);
- copy_v3_v3(snor, sd.surfnor);
- }
-
- if (do_surfacecache && num >= 0) {
- int *facenum= RE_strandren_get_face(obr, strand, 1);
- *facenum= num;
- }
-
- if (sd.uvco) {
- for (i=0; i<sd.totuv; i++) {
- if (i != sd.override_uv) {
- float *uv= RE_strandren_get_uv(obr, strand, i, NULL, 1);
-
- uv[0]= sd.uvco[2*i];
- uv[1]= sd.uvco[2*i+1];
- }
- }
- }
- if (sd.mcol) {
- for (i=0; i<sd.totcol; i++) {
- MCol *mc= RE_strandren_get_mcol(obr, strand, i, NULL, 1);
- *mc = sd.mcol[i];
- }
- }
-
- sbound->end++;
- }
-
- /* strandco computation setup */
- if (path_nbr) {
- strandlen= 0.0f;
- curlen= 0.0f;
- for (k=1; k<=path_nbr; k++)
- if (k<=max_k)
- strandlen += len_v3v3((cache+k-1)->co, (cache+k)->co);
- }
-
- if (path_nbr) {
- /* render strands */
- for (k=0; k<=path_nbr; k++) {
- float time;
-
- if (k<=max_k) {
- copy_v3_v3(state.co, (cache+k)->co);
- copy_v3_v3(state.vel, (cache+k)->vel);
- }
- else
- continue;
-
- if (k > 0)
- curlen += len_v3v3((cache+k-1)->co, (cache+k)->co);
- time= curlen/strandlen;
-
- copy_v3_v3(loc, state.co);
- mul_m4_v3(re->viewmat, loc);
-
- if (strandbuf) {
- copy_v3_v3(svert->co, loc);
- svert->strandco= -1.0f + 2.0f*time;
- svert++;
- strand->totvert++;
- }
- else {
- sd.size = hasize;
-
- if (k==1) {
- sd.first = 1;
- sd.time = 0.0f;
- sub_v3_v3v3(loc0, loc1, loc);
- add_v3_v3v3(loc0, loc1, loc0);
-
- particle_curve(re, obr, psmd->dm_final, ma, &sd, loc1, loc0, seed, pa_co);
- }
-
- sd.first = 0;
- sd.time = time;
-
- if (k)
- particle_curve(re, obr, psmd->dm_final, ma, &sd, loc, loc1, seed, pa_co);
-
- copy_v3_v3(loc1, loc);
- }
- }
-
- }
- else {
- /* render normal particles */
- if (part->trail_count > 1) {
- float length = part->path_end * (1.0f - part->randlength * r_length);
- int trail_count = part->trail_count * (1.0f - part->randlength * r_length);
- float ct = (part->draw & PART_ABS_PATH_TIME) ? cfra : pa_time;
- float dt = length / (trail_count ? (float)trail_count : 1.0f);
-
- /* make sure we have pointcache in memory before getting particle on path */
- psys_make_temp_pointcache(ob, psys);
-
- for (i=0; i < trail_count; i++, ct -= dt) {
- if (part->draw & PART_ABS_PATH_TIME) {
- if (ct < pa_birthtime || ct > pa_dietime)
- continue;
- }
- else if (ct < 0.0f || ct > 1.0f)
- continue;
-
- state.time = (part->draw & PART_ABS_PATH_TIME) ? -ct : ct;
- psys_get_particle_on_path(&sim, a, &state, 1);
-
- if (psys->parent)
- mul_m4_v3(psys->parent->obmat, state.co);
-
- if (use_duplimat)
- mul_m4_v4(duplimat, state.co);
-
- if (part->ren_as == PART_DRAW_BB) {
- bb.random = random;
- bb.offset[0] = part->bb_offset[0];
- bb.offset[1] = part->bb_offset[1];
- bb.size[0] = part->bb_size[0] * pa_size;
- if (part->bb_align==PART_BB_VEL) {
- float pa_vel = len_v3(state.vel);
- float head = part->bb_vel_head*pa_vel;
- float tail = part->bb_vel_tail*pa_vel;
- bb.size[1] = part->bb_size[1]*pa_size + head + tail;
- /* use offset to adjust the particle center. this is relative to size, so need to divide! */
- if (bb.size[1] > 0.0f)
- bb.offset[1] += (head-tail) / bb.size[1];
- }
- else
- bb.size[1] = part->bb_size[1] * pa_size;
- bb.tilt = part->bb_tilt * (1.0f - part->bb_rand_tilt * r_tilt);
- bb.time = ct;
- bb.num = a;
- }
-
- pa_co[0] = (part->draw & PART_ABS_PATH_TIME) ? (ct-pa_birthtime)/(pa_dietime-pa_birthtime) : ct;
- pa_co[1] = (float)i/(float)(trail_count-1);
-
- particle_normal_ren(part->ren_as, part, re, obr, psmd->dm_final, ma, &sd, &bb, &state, seed, hasize, pa_co);
- }
- }
- else {
- state.time=cfra;
- if (psys_get_particle_state(&sim, a, &state, 0)==0)
- continue;
-
- if (psys->parent)
- mul_m4_v3(psys->parent->obmat, state.co);
-
- if (use_duplimat)
- mul_m4_v3(duplimat, state.co);
-
- if (part->ren_as == PART_DRAW_BB) {
- bb.random = random;
- bb.offset[0] = part->bb_offset[0];
- bb.offset[1] = part->bb_offset[1];
- bb.size[0] = part->bb_size[0] * pa_size;
- if (part->bb_align==PART_BB_VEL) {
- float pa_vel = len_v3(state.vel);
- float head = part->bb_vel_head*pa_vel;
- float tail = part->bb_vel_tail*pa_vel;
- bb.size[1] = part->bb_size[1]*pa_size + head + tail;
- /* use offset to adjust the particle center. this is relative to size, so need to divide! */
- if (bb.size[1] > 0.0f)
- bb.offset[1] += (head-tail) / bb.size[1];
- }
- else
- bb.size[1] = part->bb_size[1] * pa_size;
- bb.tilt = part->bb_tilt * (1.0f - part->bb_rand_tilt * r_tilt);
- bb.time = pa_time;
- bb.num = a;
- bb.lifetime = pa_dietime-pa_birthtime;
- }
-
- particle_normal_ren(part->ren_as, part, re, obr, psmd->dm_final, ma, &sd, &bb, &state, seed, hasize, pa_co);
- }
- }
-
- if (orco1==0)
- sd.orco+=3;
-
- if (re->test_break(re->tbh))
- break;
- }
-
- if (do_surfacecache)
- strandbuf->surface= cache_strand_surface(re, obr, psmd->dm_final, mat, timeoffset);
-
-/* 4. clean up */
-#if 0 /* XXX old animation system */
- if (ma) do_mat_ipo(re->scene, ma);
-#endif /* XXX old animation system */
-
- if (orco1)
- MEM_freeN(sd.orco);
-
- if (sd.uvco)
- MEM_freeN(sd.uvco);
-
- if (sd.mcol)
- MEM_freeN(sd.mcol);
-
- if (states)
- MEM_freeN(states);
-
- BLI_rng_free(rng);
-
- psys->flag &= ~PSYS_DRAWING;
-
- if (psys->lattice_deform_data) {
- end_latt_deform(psys->lattice_deform_data);
- psys->lattice_deform_data = NULL;
- }
-
- if (path_nbr && (ma->mode_l & MA_TANGENT_STR)==0)
- calc_vertexnormals(re, obr, 1, 0, 0);
-
- return 1;
-}
-
-/* ------------------------------------------------------------------------- */
/* Halo's */
/* ------------------------------------------------------------------------- */
@@ -4608,38 +3464,15 @@ static void set_dupli_tex_mat(Render *re, ObjectInstanceRen *obi, DupliObject *d
static void init_render_object_data(Render *re, ObjectRen *obr, int timeoffset)
{
Object *ob= obr->ob;
- ParticleSystem *psys;
- int i;
-
- if (obr->psysindex) {
- if ((!obr->prev || obr->prev->ob != ob || (obr->prev->flag & R_INSTANCEABLE)==0) && ob->type==OB_MESH) {
- /* the emitter mesh wasn't rendered so the modifier stack wasn't
- * evaluated with render settings */
- DerivedMesh *dm;
- const CustomDataMask mask = CD_MASK_RENDER_INTERNAL;
- if (re->r.scemode & R_VIEWPORT_PREVIEW)
- dm = mesh_create_derived_view(re->scene, ob, mask);
- else
- dm = mesh_create_derived_render(re->scene, ob, mask);
- dm->release(dm);
- }
-
- for (psys=ob->particlesystem.first, i=0; i<obr->psysindex-1; i++)
- psys= psys->next;
-
- render_new_particle_system(re, obr, psys, timeoffset);
- }
- else {
- if (ELEM(ob->type, OB_FONT, OB_CURVE))
- init_render_curve(re, obr, timeoffset);
- else if (ob->type==OB_SURF)
- init_render_surf(re, obr, timeoffset);
- else if (ob->type==OB_MESH)
- init_render_mesh(re, obr, timeoffset);
- else if (ob->type==OB_MBALL)
- init_render_mball(re, obr);
- }
+ if (ELEM(ob->type, OB_FONT, OB_CURVE))
+ init_render_curve(re, obr, timeoffset);
+ else if (ob->type==OB_SURF)
+ init_render_surf(re, obr, timeoffset);
+ else if (ob->type==OB_MESH)
+ init_render_mesh(re, obr, timeoffset);
+ else if (ob->type==OB_MBALL)
+ init_render_mball(re, obr);
finalize_render_object(re, obr, timeoffset);
@@ -4653,26 +3486,10 @@ static void add_render_object(Render *re, Object *ob, Object *par, DupliObject *
{
ObjectRen *obr;
ObjectInstanceRen *obi;
- ParticleSystem *psys;
- int show_emitter, allow_render= 1, index, psysindex, i;
+ int allow_render= 1, index, i;
index= (dob)? dob->persistent_id[0]: 0;
- /* the emitter has to be processed first (render levels of modifiers) */
- /* so here we only check if the emitter should be rendered */
- if (ob->particlesystem.first) {
- show_emitter= 0;
- for (psys=ob->particlesystem.first; psys; psys=psys->next) {
- show_emitter += psys->part->draw & PART_DRAW_EMITTER;
- if (!(re->r.scemode & R_VIEWPORT_PREVIEW))
- psys_render_set(ob, psys, re->viewmat, re->winmat, re->winx, re->winy, timeoffset);
- }
-
- /* if no psys has "show emitter" selected don't render emitter */
- if (show_emitter == 0)
- allow_render= 0;
- }
-
/* one render object for the data itself */
if (allow_render) {
obr= RE_addRenderObject(re, ob, par, index, 0, ob->lay);
@@ -4696,35 +3513,6 @@ static void add_render_object(Render *re, Object *ob, Object *par, DupliObject *
add_volume(re, obr, ma);
}
}
-
- /* and one render object per particle system */
- if (ob->particlesystem.first) {
- psysindex= 1;
- for (psys=ob->particlesystem.first; psys; psys=psys->next, psysindex++) {
- if (!psys_check_enabled(ob, psys, G.is_rendering))
- continue;
-
- obr= RE_addRenderObject(re, ob, par, index, psysindex, ob->lay);
- if ((dob && !dob->animated) || (ob->transflag & OB_RENDER_DUPLI)) {
- obr->flag |= R_INSTANCEABLE;
- copy_m4_m4(obr->obmat, ob->obmat);
- }
- if (dob)
- psys->flag |= PSYS_USE_IMAT;
- init_render_object_data(re, obr, timeoffset);
- if (!(re->r.scemode & R_VIEWPORT_PREVIEW))
- psys_render_restore(ob, psys);
- psys->flag &= ~PSYS_USE_IMAT;
-
- /* only add instance for objects that have not been used for dupli */
- if (!(ob->transflag & OB_RENDER_DUPLI)) {
- obi = RE_addRenderInstance(re, obr, ob, par, index, psysindex, NULL, ob->lay, dob);
- if (dob) set_dupli_tex_mat(re, obi, dob, omat);
- }
- else
- find_dupli_instances(re, obr, dob);
- }
- }
}
/* par = pointer to duplicator parent, needed for object lookup table */
@@ -4845,11 +3633,8 @@ static int allow_render_object(Render *re, Object *ob, int nolamps, int onlysele
if (is_object_hidden(re, ob))
return 0;
- /* Only handle dupli-hiding here if there is no particle systems. Else, let those handle show/noshow. */
- if (!ob->particlesystem.first) {
- if ((ob->transflag & OB_DUPLI) && !(ob->transflag & OB_DUPLIFRAMES)) {
- return 0;
- }
+ if ((ob->transflag & OB_DUPLI) && !(ob->transflag & OB_DUPLIFRAMES)) {
+ return 0;
}
/* don't add non-basic meta objects, ends up having renderobjects with no geometry */
@@ -4867,7 +3652,6 @@ static int allow_render_object(Render *re, Object *ob, int nolamps, int onlysele
static int allow_render_dupli_instance(Render *UNUSED(re), DupliObject *dob, Object *obd)
{
- ParticleSystem *psys;
Material *ma;
short a, *totmaterial;
@@ -4883,10 +3667,6 @@ static int allow_render_dupli_instance(Render *UNUSED(re), DupliObject *dob, Obj
}
}
- for (psys=obd->particlesystem.first; psys; psys=psys->next)
- if (!ELEM(psys->part->ren_as, PART_DRAW_BB, PART_DRAW_LINE, PART_DRAW_PATH, PART_DRAW_OB, PART_DRAW_GR))
- return 0;
-
/* don't allow lamp, animated duplis, or radio render */
return (render_object_type(obd->type) &&
(!(dob->type == OB_DUPLIGROUP) || !dob->animated));
@@ -4898,36 +3678,12 @@ static void dupli_render_particle_set(Render *re, Object *ob, int timeoffset, in
* settings before calling object_duplilist, to get render level duplis */
Group *group;
GroupObject *go;
- ParticleSystem *psys;
- DerivedMesh *dm;
if (re->r.scemode & R_VIEWPORT_PREVIEW)
return;
if (level >= MAX_DUPLI_RECUR)
return;
-
- if (ob->transflag & OB_DUPLIPARTS) {
- for (psys=ob->particlesystem.first; psys; psys=psys->next) {
- if (ELEM(psys->part->ren_as, PART_DRAW_OB, PART_DRAW_GR)) {
- if (enable)
- psys_render_set(ob, psys, re->viewmat, re->winmat, re->winx, re->winy, timeoffset);
- else
- psys_render_restore(ob, psys);
- }
- }
-
- if (enable) {
- /* this is to make sure we get render level duplis in groups:
- * the derivedmesh must be created before init_render_mesh,
- * since object_duplilist does dupliparticles before that */
- dm = mesh_create_derived_render(re->scene, ob, CD_MASK_RENDER_INTERNAL);
- dm->release(dm);
-
- for (psys=ob->particlesystem.first; psys; psys=psys->next)
- psys_get_modifier(ob, psys)->flag &= ~eParticleSystemFlag_psys_updated;
- }
- }
if (ob->dup_group==NULL) return;
group= ob->dup_group;
@@ -5066,9 +3822,7 @@ static void database_init_objects(Render *re, unsigned int renderlay, int nolamp
continue;
if (allow_render_dupli_instance(re, dob, obd)) {
- ParticleSystem *psys;
ObjectRen *obr = NULL;
- int psysindex;
float mat[4][4];
obi=NULL;
@@ -5099,29 +3853,6 @@ static void database_init_objects(Render *re, unsigned int renderlay, int nolamp
}
}
- /* same logic for particles, each particle system has it's own object, so
- * need to go over them separately */
- psysindex= 1;
- for (psys=obd->particlesystem.first; psys; psys=psys->next) {
- if (dob->type != OB_DUPLIGROUP || (obr=find_dupligroup_dupli(re, obd, psysindex))) {
- if (obi == NULL)
- mul_m4_m4m4(mat, re->viewmat, dob->mat);
- obi = RE_addRenderInstance(re, NULL, obd, ob, dob->persistent_id[0], psysindex++, mat, obd->lay, dob);
-
- set_dupli_tex_mat(re, obi, dob, dob_extra->obmat);
- if (dob->type != OB_DUPLIGROUP) {
- copy_v3_v3(obi->dupliorco, dob->orco);
- obi->dupliuv[0]= dob->uv[0];
- obi->dupliuv[1]= dob->uv[1];
- }
- else {
- assign_dupligroup_dupli(re, obi, obr, dob);
- if (obd->transflag & OB_RENDER_DUPLI)
- find_dupli_instances(re, obr, dob);
- }
- }
- }
-
if (obi==NULL)
/* can't instance, just create the object */
init_render_object(re, obd, ob, dob, dob_extra->obmat, timeoffset);
diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c
index 9f1ae4a96e0..badc438b826 100644
--- a/source/blender/render/intern/source/pipeline.c
+++ b/source/blender/render/intern/source/pipeline.c
@@ -70,7 +70,6 @@
#include "BKE_main.h"
#include "BKE_modifier.h"
#include "BKE_node.h"
-#include "BKE_pointcache.h"
#include "BKE_report.h"
#include "BKE_scene.h"
#include "BKE_sequencer.h"
@@ -3090,21 +3089,6 @@ static void validate_render_settings(Render *re)
}
}
-static void update_physics_cache(Render *re, Scene *scene, int UNUSED(anim_init))
-{
- PTCacheBaker baker;
-
- memset(&baker, 0, sizeof(baker));
- baker.main = re->main;
- baker.scene = scene;
- baker.bake = 0;
- baker.render = 1;
- baker.anim_init = 1;
- baker.quick_step = 1;
-
- BKE_ptcache_bake(&baker);
-}
-
void RE_SetActiveRenderView(Render *re, const char *viewname)
{
BLI_strncpy(re->viewname, viewname, sizeof(re->viewname));
@@ -3117,7 +3101,7 @@ const char *RE_GetActiveRenderView(Render *re)
/* evaluating scene options for general Blender render */
static int render_initialize_from_main(Render *re, RenderData *rd, Main *bmain, Scene *scene, SceneRenderLayer *srl,
- Object *camera_override, unsigned int lay_override, int anim, int anim_init)
+ Object *camera_override, unsigned int lay_override, int anim, int UNUSED(anim_init))
{
int winx, winy;
rcti disprect;
@@ -3161,16 +3145,6 @@ static int render_initialize_from_main(Render *re, RenderData *rd, Main *bmain,
/* check all scenes involved */
tag_scenes_for_render(re);
-
- /*
- * Disabled completely for now,
- * can be later set as render profile option
- * and default for background render.
- */
- if (0) {
- /* make sure dynamics are up to date */
- update_physics_cache(re, scene, anim_init);
- }
if (srl || scene->r.scemode & R_SINGLE_LAYER) {
BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
diff --git a/source/blender/render/intern/source/pointdensity.c b/source/blender/render/intern/source/pointdensity.c
index a03ea9cb896..ffb44cf6826 100644
--- a/source/blender/render/intern/source/pointdensity.c
+++ b/source/blender/render/intern/source/pointdensity.c
@@ -45,7 +45,6 @@
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
-#include "DNA_particle_types.h"
#include "DNA_texture_types.h"
#include "BKE_deform.h"
@@ -53,7 +52,6 @@
#include "BKE_lattice.h"
#include "BKE_main.h"
#include "BKE_object.h"
-#include "BKE_particle.h"
#include "BKE_scene.h"
#include "BKE_texture.h"
#include "BKE_colortools.h"
@@ -167,149 +165,6 @@ static void alloc_point_data(PointDensity *pd)
}
}
-static void pointdensity_cache_psys(Scene *scene,
- PointDensity *pd,
- Object *ob,
- ParticleSystem *psys,
- float viewmat[4][4],
- float winmat[4][4],
- int winx, int winy,
- const bool use_render_params)
-{
- DerivedMesh *dm;
- ParticleKey state;
- ParticleCacheKey *cache;
- ParticleSimulationData sim = {NULL};
- ParticleData *pa = NULL;
- float cfra = BKE_scene_frame_get(scene);
- int i /*, childexists*/ /* UNUSED */;
- int total_particles;
- int data_used;
- float *data_vel, *data_life;
- float partco[3];
-
- /* init everything */
- if (!psys || !ob || !pd) {
- return;
- }
-
- data_used = point_data_used(pd);
-
- /* Just to create a valid rendering context for particles */
- if (use_render_params) {
- psys_render_set(ob, psys, viewmat, winmat, winx, winy, 0);
- }
-
- if (use_render_params) {
- dm = mesh_create_derived_render(scene,
- ob,
- CD_MASK_BAREMESH | CD_MASK_MTFACE | CD_MASK_MCOL);
- }
- else {
- dm = mesh_get_derived_final(scene,
- ob,
- CD_MASK_BAREMESH | CD_MASK_MTFACE | CD_MASK_MCOL);
- }
-
- if (!psys_check_enabled(ob, psys, use_render_params)) {
- psys_render_restore(ob, psys);
- return;
- }
-
- sim.scene = scene;
- sim.ob = ob;
- sim.psys = psys;
- sim.psmd = psys_get_modifier(ob, psys);
-
- /* in case ob->imat isn't up-to-date */
- invert_m4_m4(ob->imat, ob->obmat);
-
- total_particles = psys->totpart + psys->totchild;
- psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
-
- pd->point_tree = BLI_bvhtree_new(total_particles, 0.0, 4, 6);
- pd->totpoints = total_particles;
- alloc_point_data(pd);
- point_data_pointers(pd, &data_vel, &data_life, NULL);
-
-#if 0 /* UNUSED */
- if (psys->totchild > 0 && !(psys->part->draw & PART_DRAW_PARENT))
- childexists = 1;
-#endif
-
- for (i = 0, pa = psys->particles; i < total_particles; i++, pa++) {
-
- if (psys->part->type == PART_HAIR) {
- /* hair particles */
- if (i < psys->totpart && psys->pathcache)
- cache = psys->pathcache[i];
- else if (i >= psys->totpart && psys->childcache)
- cache = psys->childcache[i - psys->totpart];
- else
- continue;
-
- cache += cache->segments; /* use endpoint */
-
- copy_v3_v3(state.co, cache->co);
- zero_v3(state.vel);
- state.time = 0.0f;
- }
- else {
- /* emitter particles */
- state.time = cfra;
-
- if (!psys_get_particle_state(&sim, i, &state, 0))
- continue;
-
- if (data_used & POINT_DATA_LIFE) {
- if (i < psys->totpart) {
- state.time = (cfra - pa->time) / pa->lifetime;
- }
- else {
- ChildParticle *cpa = (psys->child + i) - psys->totpart;
- float pa_birthtime, pa_dietime;
-
- state.time = psys_get_child_time(psys, cpa, cfra, &pa_birthtime, &pa_dietime);
- }
- }
- }
-
- copy_v3_v3(partco, state.co);
-
- if (pd->psys_cache_space == TEX_PD_OBJECTSPACE)
- mul_m4_v3(ob->imat, partco);
- else if (pd->psys_cache_space == TEX_PD_OBJECTLOC) {
- sub_v3_v3(partco, ob->loc);
- }
- else {
- /* TEX_PD_WORLDSPACE */
- }
-
- BLI_bvhtree_insert(pd->point_tree, i, partco, 1);
-
- if (data_vel) {
- data_vel[i*3 + 0] = state.vel[0];
- data_vel[i*3 + 1] = state.vel[1];
- data_vel[i*3 + 2] = state.vel[2];
- }
- if (data_life) {
- data_life[i] = state.time;
- }
- }
-
- BLI_bvhtree_balance(pd->point_tree);
- dm->release(dm);
-
- if (psys->lattice_deform_data) {
- end_latt_deform(psys->lattice_deform_data);
- psys->lattice_deform_data = NULL;
- }
-
- if (use_render_params) {
- psys_render_restore(ob, psys);
- }
-}
-
static void pointdensity_cache_vertex_color(PointDensity *pd, Object *UNUSED(ob), DerivedMesh *dm, float *data_color)
{
@@ -477,9 +332,6 @@ static void pointdensity_cache_object(Scene *scene,
static void cache_pointdensity_ex(Scene *scene,
PointDensity *pd,
- float viewmat[4][4],
- float winmat[4][4],
- int winx, int winy,
const bool use_render_params)
{
if (pd == NULL) {
@@ -491,28 +343,7 @@ static void cache_pointdensity_ex(Scene *scene,
pd->point_tree = NULL;
}
- if (pd->source == TEX_PD_PSYS) {
- Object *ob = pd->object;
- ParticleSystem *psys;
-
- if (!ob || !pd->psys) {
- return;
- }
-
- psys = BLI_findlink(&ob->particlesystem, pd->psys - 1);
- if (!psys) {
- return;
- }
-
- pointdensity_cache_psys(scene,
- pd,
- ob,
- psys,
- viewmat, winmat,
- winx, winy,
- use_render_params);
- }
- else if (pd->source == TEX_PD_OBJECT) {
+ if (pd->source == TEX_PD_OBJECT) {
Object *ob = pd->object;
if (ob && ob->type == OB_MESH)
pointdensity_cache_object(scene, pd, ob, use_render_params);
@@ -521,11 +352,7 @@ static void cache_pointdensity_ex(Scene *scene,
void cache_pointdensity(Render *re, PointDensity *pd)
{
- cache_pointdensity_ex(re->scene,
- pd,
- re->viewmat, re->winmat,
- re->winx, re->winy,
- true);
+ cache_pointdensity_ex(re->scene, pd, true);
}
void free_pointdensity(PointDensity *pd)
@@ -876,83 +703,20 @@ static void sample_dummy_point_density(int resolution, float *values)
memset(values, 0, sizeof(float) * 4 * resolution * resolution * resolution);
}
-static void particle_system_minmax(Scene *scene,
- Object *object,
- ParticleSystem *psys,
- float radius,
- const bool use_render_params,
- float min[3], float max[3])
-{
- const float size[3] = {radius, radius, radius};
- const float cfra = BKE_scene_frame_get(scene);
- ParticleSettings *part = psys->part;
- ParticleSimulationData sim = {NULL};
- ParticleData *pa = NULL;
- int i;
- int total_particles;
- float mat[4][4], imat[4][4];
-
- INIT_MINMAX(min, max);
- if (part->type == PART_HAIR) {
- /* TOOD(sergey): Not supported currently. */
- return;
- }
-
- unit_m4(mat);
- if (use_render_params) {
- psys_render_set(object, psys, mat, mat, 1, 1, 0);
- }
-
- sim.scene = scene;
- sim.ob = object;
- sim.psys = psys;
- sim.psmd = psys_get_modifier(object, psys);
-
- invert_m4_m4(imat, object->obmat);
- total_particles = psys->totpart + psys->totchild;
- psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
-
- for (i = 0, pa = psys->particles; i < total_particles; i++, pa++) {
- float co_object[3], co_min[3], co_max[3];
- ParticleKey state;
- state.time = cfra;
- if (!psys_get_particle_state(&sim, i, &state, 0)) {
- continue;
- }
- mul_v3_m4v3(co_object, imat, state.co);
- sub_v3_v3v3(co_min, co_object, size);
- add_v3_v3v3(co_max, co_object, size);
- minmax_v3v3_v3(min, max, co_min);
- minmax_v3v3_v3(min, max, co_max);
- }
-
- if (psys->lattice_deform_data) {
- end_latt_deform(psys->lattice_deform_data);
- psys->lattice_deform_data = NULL;
- }
-
- if (use_render_params) {
- psys_render_restore(object, psys);
- }
-}
-
void RE_point_density_cache(
Scene *scene,
PointDensity *pd,
const bool use_render_params)
{
- float mat[4][4];
- /* Same matricies/resolution as dupli_render_particle_set(). */
- unit_m4(mat);
BLI_mutex_lock(&sample_mutex);
- cache_pointdensity_ex(scene, pd, mat, mat, 1, 1, use_render_params);
+ cache_pointdensity_ex(scene, pd, use_render_params);
BLI_mutex_unlock(&sample_mutex);
}
void RE_point_density_minmax(
- struct Scene *scene,
+ struct Scene *UNUSED(scene),
struct PointDensity *pd,
- const bool use_render_params,
+ const bool UNUSED(use_render_params),
float r_min[3], float r_max[3])
{
Object *object = pd->object;
@@ -961,27 +725,7 @@ void RE_point_density_minmax(
zero_v3(r_max);
return;
}
- if (pd->source == TEX_PD_PSYS) {
- ParticleSystem *psys;
- if (pd->psys == 0) {
- zero_v3(r_min);
- zero_v3(r_max);
- return;
- }
- psys = BLI_findlink(&object->particlesystem, pd->psys - 1);
- if (psys == NULL) {
- zero_v3(r_min);
- zero_v3(r_max);
- return;
- }
- particle_system_minmax(scene,
- object,
- psys,
- pd->radius,
- use_render_params,
- r_min, r_max);
- }
- else {
+ if (pd->source == TEX_PD_OBJECT) {
float radius[3] = {pd->radius, pd->radius, pd->radius};
float *loc, *size;
diff --git a/source/blender/render/intern/source/renderdatabase.c b/source/blender/render/intern/source/renderdatabase.c
index 76e6ca8d467..2d6d7244a5f 100644
--- a/source/blender/render/intern/source/renderdatabase.c
+++ b/source/blender/render/intern/source/renderdatabase.c
@@ -71,7 +71,6 @@
#include "DNA_meshdata_types.h"
#include "DNA_texture_types.h"
#include "DNA_listBase.h"
-#include "DNA_particle_types.h"
#include "BKE_customdata.h"
#include "BKE_DerivedMesh.h"
@@ -1416,7 +1415,7 @@ void RE_updateRenderInstances(Render *re, int flag)
ObjectInstanceRen *RE_addRenderInstance(
Render *re, ObjectRen *obr, Object *ob, Object *par,
- int index, int psysindex, float mat[4][4], int lay, const DupliObject *dob)
+ int index, int psysindex, float mat[4][4], int lay, const DupliObject *UNUSED(dob))
{
ObjectInstanceRen *obi;
float mat3[3][3];
@@ -1429,35 +1428,6 @@ ObjectInstanceRen *RE_addRenderInstance(
obi->psysindex= psysindex;
obi->lay= lay;
- /* Fill particle info */
- if (par && dob) {
- const ParticleSystem *psys = dob->particle_system;
- if (psys) {
- int part_index;
- if (obi->index < psys->totpart) {
- part_index = obi->index;
- }
- else if (psys->child) {
- part_index = psys->child[obi->index - psys->totpart].parent;
- }
- else {
- part_index = -1;
- }
-
- if (part_index >= 0) {
- const ParticleData *p = &psys->particles[part_index];
- obi->part_index = part_index;
- obi->part_size = p->size;
- obi->part_age = RE_GetStats(re)->cfra - p->time;
- obi->part_lifetime = p->lifetime;
-
- copy_v3_v3(obi->part_co, p->state.co);
- copy_v3_v3(obi->part_vel, p->state.vel);
- copy_v3_v3(obi->part_avel, p->state.ave);
- }
- }
- }
-
RE_updateRenderInstance(re, obi, RE_OBJECT_INSTANCES_UPDATE_OBMAT | RE_OBJECT_INSTANCES_UPDATE_VIEW);
if (mat) {
diff --git a/source/blender/render/intern/source/shadeinput.c b/source/blender/render/intern/source/shadeinput.c
index 20602314526..5fce2930ab1 100644
--- a/source/blender/render/intern/source/shadeinput.c
+++ b/source/blender/render/intern/source/shadeinput.c
@@ -39,7 +39,6 @@
#include "DNA_lamp_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_material_types.h"
-#include "DNA_particle_types.h"
#include "BKE_scene.h"
diff --git a/source/blender/render/intern/source/voxeldata.c b/source/blender/render/intern/source/voxeldata.c
index 1022aeeec66..f21ce7795f6 100644
--- a/source/blender/render/intern/source/voxeldata.c
+++ b/source/blender/render/intern/source/voxeldata.c
@@ -63,7 +63,6 @@
#include "DNA_texture_types.h"
#include "DNA_object_force.h"
#include "DNA_object_types.h"
-#include "DNA_particle_types.h"
#include "DNA_modifier_types.h"
#include "DNA_smoke_types.h"
@@ -226,7 +225,7 @@ static int read_voxeldata_header(FILE *fp, struct VoxelData *vd)
return 1;
}
-static void init_frame_smoke(VoxelData *vd, int cfra)
+static void init_frame_smoke(VoxelData *vd, int UNUSED(cfra))
{
#ifdef WITH_SMOKE
Object *ob;
@@ -249,9 +248,7 @@ static void init_frame_smoke(VoxelData *vd, int cfra)
return;
}
- if (cfra < sds->point_cache[0]->startframe)
- ; /* don't show smoke before simulation starts, this could be made an option in the future */
- else if (vd->smoked_type == TEX_VD_SMOKEHEAT) {
+ if (vd->smoked_type == TEX_VD_SMOKEHEAT) {
size_t totRes;
size_t i;
float *heat;
@@ -361,7 +358,6 @@ static void init_frame_smoke(VoxelData *vd, int cfra)
#else // WITH_SMOKE
(void)vd;
- (void)cfra;
vd->dataset = NULL;
#endif
@@ -369,20 +365,8 @@ static void init_frame_smoke(VoxelData *vd, int cfra)
static void init_frame_hair(VoxelData *vd, int UNUSED(cfra))
{
- Object *ob;
- ModifierData *md;
-
vd->dataset = NULL;
if (vd->object == NULL) return;
- ob = vd->object;
-
- if ((md = (ModifierData *)modifiers_findByType(ob, eModifierType_ParticleSystem))) {
- ParticleSystemModifierData *pmd = (ParticleSystemModifierData *)md;
-
- if (pmd->psys && pmd->psys->clmd) {
- vd->ok |= BPH_cloth_solver_get_texture_data(ob, pmd->psys->clmd, vd);
- }
- }
}
void cache_voxeldata(Tex *tex, int scene_frame)
diff --git a/source/blender/windowmanager/CMakeLists.txt b/source/blender/windowmanager/CMakeLists.txt
index b6245a8c0d1..b5c19534b15 100644
--- a/source/blender/windowmanager/CMakeLists.txt
+++ b/source/blender/windowmanager/CMakeLists.txt
@@ -25,6 +25,8 @@
set(INC
.
+ manipulators
+ manipulators/intern
../blenfont
../blenkernel
../blenlib
@@ -68,6 +70,10 @@ set(SRC
intern/wm_subwindow.c
intern/wm_window.c
intern/wm_stereo.c
+ manipulators/intern/wm_manipulator.c
+ manipulators/intern/wm_manipulatorgroup.c
+ manipulators/intern/wm_manipulatormap.c
+ manipulators/intern/manipulator_library/manipulator_library_utils.c
WM_api.h
WM_keymap.h
@@ -80,6 +86,11 @@ set(SRC
wm_files.h
wm_subwindow.h
wm_window.h
+ manipulators/WM_manipulator_api.h
+ manipulators/WM_manipulator_types.h
+ manipulators/wm_manipulator_wmapi.h
+ manipulators/intern/wm_manipulator_intern.h
+ manipulators/intern/manipulator_library/manipulator_library_intern.h
)
if(WITH_AUDASPACE)
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index 2b82f1becb3..2809795268d 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -42,6 +42,9 @@
#include "WM_keymap.h"
#include "BLI_compiler_attrs.h"
+/* Include external manipulator API's */
+#include "manipulators/WM_manipulator_api.h"
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -64,12 +67,16 @@ struct wmDrag;
struct ImBuf;
struct ImageFormatData;
struct ARegion;
+struct ScrArea;
#ifdef WITH_INPUT_NDOF
struct wmNDOFMotionData;
#endif
typedef struct wmJob wmJob;
+typedef struct wmManipulator wmManipulator;
+typedef struct wmManipulatorMap wmManipulatorMap;
+typedef struct wmManipulatorMapType wmManipulatorMapType;
/* general API */
void WM_init_state_size_set (int stax, int stay, int sizx, int sizy);
@@ -171,6 +178,9 @@ void WM_event_free_ui_handler_all(
wmUIHandlerFunc ui_handle, wmUIHandlerRemoveFunc ui_remove);
struct wmEventHandler *WM_event_add_modal_handler(struct bContext *C, struct wmOperator *op);
+void WM_event_modal_handler_area_replace(wmWindow *win, const struct ScrArea *old_area, struct ScrArea *new_area);
+void WM_event_modal_handler_region_replace(wmWindow *win, const struct ARegion *old_region, struct ARegion *new_region);
+
void WM_event_remove_handlers(struct bContext *C, ListBase *handlers);
/* handler flag */
diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h
index 0fe3e8a0fcf..547968e2906 100644
--- a/source/blender/windowmanager/WM_types.h
+++ b/source/blender/windowmanager/WM_types.h
@@ -119,6 +119,7 @@ struct ImBuf;
/* exported types for WM */
#include "wm_cursors.h"
#include "wm_event_types.h"
+#include "manipulators/WM_manipulator_types.h"
/* ************** wmOperatorType ************************ */
@@ -298,7 +299,7 @@ typedef struct wmNotifier {
#define ND_MODIFIER (24<<16)
#define ND_KEYS (25<<16)
#define ND_CONSTRAINT (26<<16)
-#define ND_PARTICLE (27<<16)
+/*#define ND_PARTICLE (27<<16)*/ /* DEPRECATED */
#define ND_POINTCACHE (28<<16)
#define ND_PARENT (29<<16)
#define ND_LOD (30<<16)
@@ -566,6 +567,9 @@ typedef struct wmOperatorType {
/* pointer to modal keymap, do not free! */
struct wmKeyMap *modalkeymap;
+ /* manipulator-group that is accessible while operator runs */
+ wmManipulatorGroupType *mgrouptype;
+
/* python needs the operator type as well */
int (*pyop_poll)(struct bContext *, struct wmOperatorType *ot) ATTR_WARN_UNUSED_RESULT;
diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c
index 3825db14e93..f38f1eee7ec 100644
--- a/source/blender/windowmanager/intern/wm_draw.c
+++ b/source/blender/windowmanager/intern/wm_draw.c
@@ -59,6 +59,7 @@
#include "GPU_extensions.h"
#include "GPU_glew.h"
#include "GPU_basic_shader.h"
+#include "GPU_immediate.h"
#include "RE_engine.h"
@@ -376,7 +377,7 @@ static void wm_draw_triple_fail(bContext *C, wmWindow *win)
wm_method_draw_overlap_all(C, win, 0);
}
-static int wm_triple_gen_textures(wmWindow *win, wmDrawTriple *triple)
+static bool wm_triple_gen_textures(wmWindow *win, wmDrawTriple *triple)
{
const int winsize_x = WM_window_pixels_x(win);
const int winsize_y = WM_window_pixels_y(win);
@@ -400,7 +401,7 @@ static int wm_triple_gen_textures(wmWindow *win, wmDrawTriple *triple)
if (!triple->bind) {
/* not the typical failure case but we handle it anyway */
printf("WM: failed to allocate texture for triple buffer drawing (glGenTextures).\n");
- return 0;
+ return false;
}
/* proxy texture is only guaranteed to test for the cases that
@@ -411,7 +412,7 @@ static int wm_triple_gen_textures(wmWindow *win, wmDrawTriple *triple)
glBindTexture(triple->target, 0);
printf("WM: failed to allocate texture for triple buffer drawing "
"(texture too large for graphics card).\n");
- return 0;
+ return false;
}
/* setup actual texture */
@@ -421,13 +422,7 @@ static int wm_triple_gen_textures(wmWindow *win, wmDrawTriple *triple)
glTexParameteri(triple->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glBindTexture(triple->target, 0);
- /* not sure if this works everywhere .. */
- if (glGetError() == GL_OUT_OF_MEMORY) {
- printf("WM: failed to allocate texture for triple buffer drawing (out of memory).\n");
- return 0;
- }
-
- return 1;
+ return true;
}
void wm_triple_draw_textures(wmWindow *win, wmDrawTriple *triple, float alpha)
@@ -451,28 +446,36 @@ void wm_triple_draw_textures(wmWindow *win, wmDrawTriple *triple, float alpha)
halfy /= triple->y;
}
- GPU_basic_shader_bind((triple->target == GL_TEXTURE_2D) ? GPU_SHADER_TEXTURE_2D : GPU_SHADER_TEXTURE_RECT);
+ VertexFormat *format = immVertexFormat();
+ unsigned texcoord = add_attrib(format, "texCoord", GL_FLOAT, 2, KEEP_FLOAT);
+ unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ const int activeTex = GL_TEXTURE0;
+ glActiveTexture(activeTex);
glBindTexture(triple->target, triple->bind);
- glColor4f(1.0f, 1.0f, 1.0f, alpha);
- glBegin(GL_QUADS);
- glTexCoord2f(halfx, halfy);
- glVertex2f(0, 0);
+ immBindBuiltinProgram((triple->target == GL_TEXTURE_2D) ? GPU_SHADER_3D_IMAGE_MODULATE_ALPHA : GPU_SHADER_3D_IMAGE_RECT_MODULATE_ALPHA);
+ immUniform1f("alpha", alpha);
+ immUniform1i("image", activeTex);
- glTexCoord2f(ratiox + halfx, halfy);
- glVertex2f(sizex, 0);
+ immBegin(GL_QUADS, 4);
- glTexCoord2f(ratiox + halfx, ratioy + halfy);
- glVertex2f(sizex, sizey);
+ immAttrib2f(texcoord, halfx, halfy);
+ immVertex2f(pos, 0.0f, 0.0f);
- glTexCoord2f(halfx, ratioy + halfy);
- glVertex2f(0, sizey);
- glEnd();
+ immAttrib2f(texcoord, ratiox + halfx, halfy);
+ immVertex2f(pos, sizex, 0.0f);
- glBindTexture(triple->target, 0);
+ immAttrib2f(texcoord, ratiox + halfx, ratioy + halfy);
+ immVertex2f(pos, sizex, sizey);
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
+ immAttrib2f(texcoord, halfx, ratioy + halfy);
+ immVertex2f(pos, 0.0f, sizey);
+
+ immEnd();
+ immUnbindProgram();
+
+ glBindTexture(triple->target, 0);
}
static void wm_triple_copy_textures(wmWindow *win, wmDrawTriple *triple)
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index dc34e8015c9..b15b47c8edc 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -68,8 +68,6 @@
#include "RNA_access.h"
-#include "GPU_debug.h"
-
#include "UI_interface.h"
#include "PIL_time.h"
@@ -1674,7 +1672,12 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand
wm_handler_op_context(C, handler, event);
wm_region_mouse_co(C, event);
wm_event_modalkeymap(C, op, event, &dbl_click_disabled);
-
+
+ /* attach manipulator-map to handler if not there yet */
+ if (ot->mgrouptype && !handler->manipulator_map) {
+ wm_manipulatorgroup_attach_to_modal_handler(C, handler, ot->mgrouptype, op);
+ }
+
if (ot->flag & OPTYPE_UNDO)
wm->op_undo_depth++;
@@ -1723,6 +1726,9 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand
CTX_wm_region_set(C, NULL);
}
+ /* update manipulators during modal handlers */
+ wm_manipulatormaps_handled_modal_update(C, event, handler, ot);
+
/* remove modal handler, operator itself should have been canceled and freed */
if (retval & (OPERATOR_CANCELLED | OPERATOR_FINISHED)) {
WM_cursor_grab_disable(CTX_wm_window(C), NULL);
@@ -2092,6 +2098,71 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers
}
}
}
+ else if (handler->manipulator_map) {
+ ScrArea *area = CTX_wm_area(C);
+ ARegion *region = CTX_wm_region(C);
+ wmManipulatorMap *mmap = handler->manipulator_map;
+ wmManipulator *manipulator = wm_manipulatormap_get_highlighted_manipulator(mmap);
+ unsigned char part;
+
+ wm_manipulatormap_handler_context(C, handler);
+ wm_region_mouse_co(C, event);
+
+ /* handle manipulator highlighting */
+ if (event->type == MOUSEMOVE && !wm_manipulatormap_get_active_manipulator(mmap)) {
+ manipulator = wm_manipulatormap_find_highlighted_manipulator(mmap, C, event, &part);
+ wm_manipulatormap_set_highlighted_manipulator(mmap, C, manipulator, part);
+ }
+ /* handle user configurable manipulator-map keymap */
+ else if (manipulator) {
+ /* get user customized keymap from default one */
+ const wmManipulatorGroup *highlightgroup = wm_manipulator_get_parent_group(manipulator);
+ const wmKeyMap *keymap = WM_keymap_active(wm, highlightgroup->type->keymap);
+ wmKeyMapItem *kmi;
+
+ PRINT("%s: checking '%s' ...", __func__, keymap->idname);
+
+ if (!keymap->poll || keymap->poll(C)) {
+ PRINT("pass\n");
+ for (kmi = keymap->items.first; kmi; kmi = kmi->next) {
+ if (wm_eventmatch(event, kmi)) {
+ wmOperator *op = handler->op;
+
+ PRINT("%s: item matched '%s'\n", __func__, kmi->idname);
+
+ /* weak, but allows interactive callback to not use rawkey */
+ event->keymap_idname = kmi->idname;
+
+ /* handler->op is called later, we want keymap op to be triggered here */
+ handler->op = NULL;
+ action |= wm_handler_operator_call(C, handlers, handler, event, kmi->ptr);
+ handler->op = op;
+
+ if (action & WM_HANDLER_BREAK) {
+ if (action & WM_HANDLER_HANDLED) {
+ if (G.debug & (G_DEBUG_EVENTS | G_DEBUG_HANDLERS))
+ printf("%s: handled - and pass on! '%s'\n", __func__, kmi->idname);
+ }
+ else {
+ PRINT("%s: un-handled '%s'\n", __func__, kmi->idname);
+ }
+ }
+ }
+ }
+ }
+ else {
+ PRINT("fail\n");
+ }
+ }
+
+ /* restore the area */
+ CTX_wm_area_set(C, area);
+ CTX_wm_region_set(C, region);
+
+ if (handler->op) {
+ action |= wm_handler_operator_call(C, handlers, handler, event, NULL);
+ }
+ }
else {
/* modal, swallows all */
action |= wm_handler_operator_call(C, handlers, handler, event, NULL);
@@ -2534,8 +2605,6 @@ void wm_event_do_handlers(bContext *C)
/* update key configuration after handling events */
WM_keyconfig_update(wm);
-
- GPU_ASSERT_NO_GL_ERRORS("wm_event_do_handlers");
}
/* ********** filesector handling ************ */
@@ -2648,6 +2717,33 @@ wmEventHandler *WM_event_add_modal_handler(bContext *C, wmOperator *op)
return handler;
}
+/**
+ * Modal handlers store a pointer to an area which might be freed while the handler runs.
+ * Use this function to NULL all handler pointers to \a old_area.
+ */
+void WM_event_modal_handler_area_replace(wmWindow *win, const ScrArea *old_area, ScrArea *new_area)
+{
+ for (wmEventHandler *handler = win->modalhandlers.first; handler; handler = handler->next) {
+ if (handler->op_area == old_area) {
+ handler->op_area = new_area;
+ }
+ }
+}
+
+/**
+ * Modal handlers store a pointer to a region which might be freed while the handler runs.
+ * Use this function to NULL all handler pointers to \a old_region.
+ */
+void WM_event_modal_handler_region_replace(wmWindow *win, const ARegion *old_region, ARegion *new_region)
+{
+ for (wmEventHandler *handler = win->modalhandlers.first; handler; handler = handler->next) {
+ if (handler->op_region == old_region) {
+ handler->op_region = new_region;
+ handler->op_region_type = new_region ? new_region->regiontype : RGN_TYPE_WINDOW;
+ }
+ }
+}
+
wmEventHandler *WM_event_add_keymap_handler(ListBase *handlers, wmKeyMap *keymap)
{
wmEventHandler *handler;
diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c
index c11c398c616..fbbde2a6d28 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -169,6 +169,7 @@ void WM_init(bContext *C, int argc, const char **argv)
BKE_library_callback_free_window_manager_set(wm_close_and_free); /* library.c */
BKE_library_callback_free_notifier_reference_set(WM_main_remove_notifier_reference); /* library.c */
+ BKE_region_callback_free_manipulatormap_set(wm_manipulatormap_delete); /* screen.c */
BKE_library_callback_remap_editor_id_reference_set(WM_main_remap_editor_id_reference); /* library.c */
BKE_blender_callback_test_break_set(wm_window_testbreak); /* blender.c */
BKE_spacedata_callback_id_remap_set(ED_spacedata_id_remap); /* screen.c */
@@ -529,6 +530,9 @@ void WM_exit_ext(bContext *C, const bool do_python)
ED_gpencil_strokes_copybuf_free();
BKE_node_clipboard_clear();
+ /* free manipulator-maps after freeing blender, so no deleted data get accessed during cleaning up of areas */
+ wm_manipulatormaptypes_free();
+
BLF_exit();
#ifdef WITH_INTERNATIONAL
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index b9fd4d2e762..a132d323a8c 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -491,6 +491,9 @@ void WM_operatortype_remove_ptr(wmOperatorType *ot)
BLI_ghash_remove(global_ops_hash, ot->idname, NULL, NULL);
WM_keyconfig_update_operatortype();
+ if (ot->mgrouptype) {
+ WM_manipulatorgrouptype_unregister(NULL, G.main, ot->mgrouptype);
+ }
MEM_freeN(ot);
}
@@ -4170,6 +4173,10 @@ void wm_operatortype_init(void)
WM_operatortype_append(WM_OT_previews_ensure);
WM_operatortype_append(WM_OT_previews_clear);
WM_operatortype_append(WM_OT_doc_view_manual_ui_context);
+
+ /* manipulators */
+ WM_operatortype_append(MANIPULATORGROUP_OT_manipulator_select);
+ WM_operatortype_append(MANIPULATORGROUP_OT_manipulator_tweak);
}
/* circleselect-like modal operators */
@@ -4475,6 +4482,7 @@ void wm_window_keymap(wmKeyConfig *keyconf)
RNA_float_set(kmi->ptr, "value", 1.0f / 1.5f);
#endif /* WITH_INPUT_NDOF */
+ wm_manipulators_keymap(keyconf);
gesture_circle_modal_keymap(keyconf);
gesture_border_modal_keymap(keyconf);
gesture_zoom_border_modal_keymap(keyconf);
diff --git a/source/blender/windowmanager/intern/wm_stereo.c b/source/blender/windowmanager/intern/wm_stereo.c
index 1c1c2ad35af..c72bd676364 100644
--- a/source/blender/windowmanager/intern/wm_stereo.c
+++ b/source/blender/windowmanager/intern/wm_stereo.c
@@ -54,6 +54,7 @@
#include "GPU_glew.h"
#include "GPU_basic_shader.h"
+#include "GPU_immediate.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -172,6 +173,13 @@ static void wm_method_draw_stereo3d_sidebyside(wmWindow *win)
int soffx;
bool cross_eyed = (win->stereo3d_format->flag & S3D_SIDEBYSIDE_CROSSEYED) != 0;
+ const int activeTex = GL_TEXTURE0;
+ glActiveTexture(activeTex);
+
+ VertexFormat *format = immVertexFormat();
+ unsigned texcoord = add_attrib(format, "texCoord", GL_FLOAT, 2, KEEP_FLOAT);
+ unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+
for (view = 0; view < 2; view ++) {
drawdata = BLI_findlink(&win->drawdata, (view * 2) + 1);
triple = drawdata->triple;
@@ -203,26 +211,32 @@ static void wm_method_draw_stereo3d_sidebyside(wmWindow *win)
halfy /= triple->y;
}
- glEnable(triple->target);
+ /* TODO: if target is always same for both eyes, bind program & set uniform before loop */
+ immBindBuiltinProgram((triple->target == GL_TEXTURE_2D) ? GPU_SHADER_3D_IMAGE_MODULATE_ALPHA : GPU_SHADER_3D_IMAGE_RECT_MODULATE_ALPHA);
+
glBindTexture(triple->target, triple->bind);
- glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
- glBegin(GL_QUADS);
- glTexCoord2f(halfx, halfy);
- glVertex2f(soffx, 0);
+ immUniform1i("image", activeTex);
+
+ immBegin(GL_QUADS, 4);
+
+ immAttrib2f(texcoord, halfx, halfy);
+ immVertex2f(pos, soffx, 0.0f);
+
+ immAttrib2f(texcoord, ratiox + halfx, halfy);
+ immVertex2f(pos, soffx + (sizex * 0.5f), 0.0f);
- glTexCoord2f(ratiox + halfx, halfy);
- glVertex2f(soffx + (sizex * 0.5f), 0);
+ immAttrib2f(texcoord, ratiox + halfx, ratioy + halfy);
+ immVertex2f(pos, soffx + (sizex * 0.5f), sizey);
- glTexCoord2f(ratiox + halfx, ratioy + halfy);
- glVertex2f(soffx + (sizex * 0.5f), sizey);
+ immAttrib2f(texcoord, halfx, ratioy + halfy);
+ immVertex2f(pos, soffx, sizey);
- glTexCoord2f(halfx, ratioy + halfy);
- glVertex2f(soffx, sizey);
- glEnd();
+ immEnd();
+ /* TODO: if target is always same for both eyes, unbind program & texture target after loop */
glBindTexture(triple->target, 0);
- glDisable(triple->target);
+ immUnbindProgram();
}
}
@@ -234,6 +248,13 @@ static void wm_method_draw_stereo3d_topbottom(wmWindow *win)
int view;
int soffy;
+ const int activeTex = GL_TEXTURE0;
+ glActiveTexture(activeTex);
+
+ VertexFormat *format = immVertexFormat();
+ unsigned texcoord = add_attrib(format, "texCoord", GL_FLOAT, 2, KEEP_FLOAT);
+ unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+
for (view = 0; view < 2; view ++) {
drawdata = BLI_findlink(&win->drawdata, (view * 2) + 1);
triple = drawdata->triple;
@@ -262,26 +283,33 @@ static void wm_method_draw_stereo3d_topbottom(wmWindow *win)
halfy /= triple->y;
}
- glEnable(triple->target);
+ /* TODO: if target is always same for both eyes, bind program & set uniforms before loop */
+ immBindBuiltinProgram((triple->target == GL_TEXTURE_2D) ? GPU_SHADER_3D_IMAGE_MODULATE_ALPHA : GPU_SHADER_3D_IMAGE_RECT_MODULATE_ALPHA);
+
glBindTexture(triple->target, triple->bind);
- glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
- glBegin(GL_QUADS);
- glTexCoord2f(halfx, halfy);
- glVertex2f(0, soffy);
+ immUniform1f("alpha", 1.0f);
+ immUniform1i("image", activeTex);
+
+ immBegin(GL_QUADS, 4);
+
+ immAttrib2f(texcoord, halfx, halfy);
+ immVertex2f(pos, 0.0f, soffy);
+
+ immAttrib2f(texcoord, ratiox + halfx, halfy);
+ immVertex2f(pos, sizex, soffy);
- glTexCoord2f(ratiox + halfx, halfy);
- glVertex2f(sizex, soffy);
+ immAttrib2f(texcoord, ratiox + halfx, ratioy + halfy);
+ immVertex2f(pos, sizex, soffy + (sizey * 0.5f));
- glTexCoord2f(ratiox + halfx, ratioy + halfy);
- glVertex2f(sizex, soffy + (sizey * 0.5f));
+ immAttrib2f(texcoord, halfx, ratioy + halfy);
+ immVertex2f(pos, 0.0f, soffy + (sizey * 0.5f));
- glTexCoord2f(halfx, ratioy + halfy);
- glVertex2f(0, soffy + (sizey * 0.5f));
- glEnd();
+ immEnd();
+ /* TODO: if target is always same for both eyes, unbind program & texture target after loop */
+ immUnbindProgram();
glBindTexture(triple->target, 0);
- glDisable(triple->target);
}
}
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c
index 2d43c47679d..718a9afea1f 100644
--- a/source/blender/windowmanager/intern/wm_window.c
+++ b/source/blender/windowmanager/intern/wm_window.c
@@ -76,7 +76,7 @@
#include "GPU_draw.h"
#include "GPU_extensions.h"
#include "GPU_init_exit.h"
-#include "GPU_glew.h"
+#include "GPU_immediate.h"
/* for assert */
#ifndef NDEBUG
@@ -827,13 +827,16 @@ void wm_window_make_drawable(wmWindowManager *wm, wmWindow *win)
{
if (win != wm->windrawable && win->ghostwin) {
// win->lmbut = 0; /* keeps hanging when mousepressed while other window opened */
-
+
wm->windrawable = win;
if (G.debug & G_DEBUG_EVENTS) {
printf("%s: set drawable %d\n", __func__, win->winid);
}
+
+ immDeactivate();
GHOST_ActivateWindowDrawingContext(win->ghostwin);
-
+ immActivate();
+
/* this can change per window */
U.pixelsize = wm_window_pixelsize(win);
BKE_blender_userdef_refresh();
diff --git a/source/blender/windowmanager/manipulators/WM_manipulator_api.h b/source/blender/windowmanager/manipulators/WM_manipulator_api.h
new file mode 100644
index 00000000000..099ad7fd851
--- /dev/null
+++ b/source/blender/windowmanager/manipulators/WM_manipulator_api.h
@@ -0,0 +1,110 @@
+/*
+ * ***** 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) 2016 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/windowmanager/manipulators/WM_manipulator_api.h
+ * \ingroup wm
+ *
+ * \name Manipulator API
+ * \brief API for external use of wmManipulator types.
+ *
+ * Only included in WM_api.h
+ */
+
+
+#ifndef __WM_MANIPULATOR_API_H__
+#define __WM_MANIPULATOR_API_H__
+
+struct ARegion;
+struct Main;
+struct wmKeyConfig;
+struct wmManipulatorGroupType;
+struct wmManipulatorMap;
+struct wmManipulatorMapType;
+struct wmManipulatorMapType_Params;
+
+/* -------------------------------------------------------------------- */
+/* wmManipulator */
+
+struct wmManipulator *WM_manipulator_new(
+ void (*draw)(const struct bContext *, struct wmManipulator *),
+ void (*render_3d_intersection)(const struct bContext *, struct wmManipulator *, int),
+ int (*intersect)(struct bContext *, const struct wmEvent *, struct wmManipulator *),
+ int (*handler)(struct bContext *, const struct wmEvent *, struct wmManipulator *, const int));
+void WM_manipulator_delete(
+ ListBase *manipulatorlist, struct wmManipulatorMap *mmap, struct wmManipulator *manipulator,
+ struct bContext *C);
+
+void WM_manipulator_set_property(struct wmManipulator *, int slot, struct PointerRNA *ptr, const char *propname);
+struct PointerRNA *WM_manipulator_set_operator(struct wmManipulator *, const char *opname);
+void WM_manipulator_set_func_select(
+ struct wmManipulator *manipulator,
+ void (*select)(struct bContext *, struct wmManipulator *, const int action)); /* wmManipulatorSelectFunc */
+void WM_manipulator_set_origin(struct wmManipulator *manipulator, const float origin[3]);
+void WM_manipulator_set_offset(struct wmManipulator *manipulator, const float offset[3]);
+void WM_manipulator_set_flag(struct wmManipulator *manipulator, const int flag, const bool enable);
+void WM_manipulator_set_scale(struct wmManipulator *manipulator, float scale);
+void WM_manipulator_set_line_width(struct wmManipulator *manipulator, const float line_width);
+void WM_manipulator_set_colors(struct wmManipulator *manipulator, const float col[4], const float col_hi[4]);
+
+
+/* -------------------------------------------------------------------- */
+/* wmManipulatorGroup */
+
+struct wmManipulatorGroupType *WM_manipulatorgrouptype_append(
+ struct wmManipulatorMapType *mmaptype,
+ void (*mgrouptype_func)(struct wmManipulatorGroupType *));
+struct wmManipulatorGroupType *WM_manipulatorgrouptype_append_runtime(
+ const struct Main *main, struct wmManipulatorMapType *mmaptype,
+ void (*mgrouptype_func)(struct wmManipulatorGroupType *));
+void WM_manipulatorgrouptype_init_runtime(
+ const struct Main *bmain, struct wmManipulatorMapType *mmaptype,
+ struct wmManipulatorGroupType *mgrouptype);
+void WM_manipulatorgrouptype_unregister(
+ struct bContext *C, struct Main *bmain, struct wmManipulatorGroupType *mgroup);
+
+struct wmKeyMap *WM_manipulatorgroup_keymap_common(
+ const struct wmManipulatorGroupType *mgrouptype, struct wmKeyConfig *config);
+struct wmKeyMap *WM_manipulatorgroup_keymap_common_sel(
+ const struct wmManipulatorGroupType *mgrouptype, struct wmKeyConfig *config);
+
+
+/* -------------------------------------------------------------------- */
+/* wmManipulatorMap */
+
+struct wmManipulatorMapType *WM_manipulatormaptype_find(
+ const struct wmManipulatorMapType_Params *mmap_params);
+struct wmManipulatorMapType *WM_manipulatormaptype_ensure(
+ const struct wmManipulatorMapType_Params *mmap_params);
+
+struct wmManipulatorMap *WM_manipulatormap_new_from_type(
+ const struct wmManipulatorMapType_Params *mmap_params);
+void WM_manipulatormap_tag_refresh(struct wmManipulatorMap *mmap);
+void WM_manipulatormap_draw(struct wmManipulatorMap *mmap, const struct bContext *C, const int drawstep);
+void WM_manipulatormap_add_handlers(struct ARegion *ar, struct wmManipulatorMap *mmap);
+bool WM_manipulatormap_select_all(struct bContext *C, struct wmManipulatorMap *mmap, const int action);
+bool WM_manipulatormap_cursor_set(const struct wmManipulatorMap *mmap, struct wmWindow *win);
+
+#endif /* __WM_MANIPULATOR_API_H__ */
+
diff --git a/source/blender/windowmanager/manipulators/WM_manipulator_types.h b/source/blender/windowmanager/manipulators/WM_manipulator_types.h
new file mode 100644
index 00000000000..284a3e9bd22
--- /dev/null
+++ b/source/blender/windowmanager/manipulators/WM_manipulator_types.h
@@ -0,0 +1,167 @@
+/*
+ * ***** 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) 2016 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/windowmanager/manipulators/WM_manipulator_types.h
+ * \ingroup wm
+ *
+ * \name Manipulator Types
+ * \brief Manipulator defines for external use.
+ *
+ * Only included in WM_types.h and lower level files.
+ */
+
+
+#ifndef __WM_MANIPULATOR_TYPES_H__
+#define __WM_MANIPULATOR_TYPES_H__
+
+#include "BLI_compiler_attrs.h"
+
+struct wmManipulatorGroupType;
+struct wmManipulatorGroup;
+struct wmKeyConfig;
+
+typedef bool (*wmManipulatorGroupPollFunc)(const struct bContext *, struct wmManipulatorGroupType *) ATTR_WARN_UNUSED_RESULT;
+typedef void (*wmManipulatorGroupInitFunc)(const struct bContext *, struct wmManipulatorGroup *);
+typedef void (*wmManipulatorGroupRefreshFunc)(const struct bContext *, struct wmManipulatorGroup *);
+typedef void (*wmManipulatorGroupDrawPrepareFunc)(const struct bContext *, struct wmManipulatorGroup *);
+
+
+/* -------------------------------------------------------------------- */
+/* wmManipulator */
+
+/**
+ * Simple utility wrapper for storing a single manipulator as wmManipulatorGroup.customdata (which gets freed).
+ */
+typedef struct wmManipulatorWrapper {
+ struct wmManipulator *manipulator;
+} wmManipulatorWrapper;
+
+/* wmManipulator.flag
+ * Flags for individual manipulators. */
+enum {
+ WM_MANIPULATOR_DRAW_HOVER = (1 << 0), /* draw *only* while hovering */
+ WM_MANIPULATOR_DRAW_ACTIVE = (1 << 1), /* draw while dragging */
+ WM_MANIPULATOR_DRAW_VALUE = (1 << 2), /* draw an indicator for the current value while dragging */
+ WM_MANIPULATOR_HIDDEN = (1 << 3),
+};
+
+
+/* -------------------------------------------------------------------- */
+/* wmManipulatorGroup */
+
+typedef struct wmManipulatorGroup {
+ struct wmManipulatorGroup *next, *prev;
+
+ struct wmManipulatorGroupType *type;
+ ListBase manipulators;
+
+ void *py_instance; /* python stores the class instance here */
+ struct ReportList *reports; /* errors and warnings storage */
+
+ void *customdata;
+ void (*customdata_free)(void *); /* for freeing customdata from above */
+ int flag; /* private */
+ int pad;
+} wmManipulatorGroup;
+
+/* factory class for a manipulator-group type, gets called every time a new area is spawned */
+typedef struct wmManipulatorGroupType {
+ struct wmManipulatorGroupType *next, *prev;
+
+ char idname[64]; /* MAX_NAME */
+ const char *name; /* manipulator-group name - displayed in UI (keymap editor) */
+
+ /* poll if manipulator-map should be visible */
+ wmManipulatorGroupPollFunc poll;
+ /* initially create manipulators and set permanent data - stuff you only need to do once */
+ wmManipulatorGroupInitFunc init;
+ /* refresh data, only called if recreate flag is set (WM_manipulatormap_tag_refresh) */
+ wmManipulatorGroupRefreshFunc refresh;
+ /* refresh data for drawing, called before each redraw */
+ wmManipulatorGroupDrawPrepareFunc draw_prepare;
+
+ /* keymap init callback for this manipulator-group */
+ struct wmKeyMap *(*keymap_init)(const struct wmManipulatorGroupType *, struct wmKeyConfig *);
+ /* keymap created with callback from above */
+ struct wmKeyMap *keymap;
+
+ /* rna for properties */
+ struct StructRNA *srna;
+
+ /* RNA integration */
+ ExtensionRNA ext;
+
+ int flag;
+
+ /* if type is spawned from operator this is set here */
+ void *op;
+
+ /* same as manipulator-maps, so registering/unregistering goes to the correct region */
+ short spaceid, regionid;
+ char mapidname[64];
+} wmManipulatorGroupType;
+
+/**
+ * wmManipulatorGroupType.flag
+ * Flags that influence the behavior of all manipulators in the group.
+ */
+enum {
+ /* Mark manipulator-group as being 3D */
+ WM_MANIPULATORGROUPTYPE_IS_3D = (1 << 0),
+ /* Scale manipulators as 3D object that respects zoom (otherwise zoom independent draw size) */
+ WM_MANIPULATORGROUPTYPE_SCALE_3D = (1 << 1),
+ /* Manipulators can be depth culled with scene objects (covered by other geometry - TODO) */
+ WM_MANIPULATORGROUPTYPE_SCENE_DEPTH = (1 << 2),
+ /* Manipulators can be selected */
+ WM_MANIPULATORGROUPTYPE_SELECTABLE = (1 << 3),
+ /* manipulator group is attached to operator, and is only accessible as long as this runs */
+ WM_MANIPULATORGROUPTYPE_OP = (1 << 4),
+};
+
+
+/* -------------------------------------------------------------------- */
+/* wmManipulatorMap */
+
+struct wmManipulatorMapType_Params {
+ const char *idname;
+ const int spaceid;
+ const int regionid;
+};
+
+/**
+ * Pass a value of this enum to #WM_manipulatormap_draw to tell it what to draw.
+ */
+enum {
+ /* Draw 2D manipulator-groups (ManipulatorGroupType.is_3d == false) */
+ WM_MANIPULATORMAP_DRAWSTEP_2D = 0,
+ /* Draw 3D manipulator-groups (ManipulatorGroupType.is_3d == true) */
+ WM_MANIPULATORMAP_DRAWSTEP_3D,
+ /* Draw only depth culled manipulators (WM_MANIPULATOR_SCENE_DEPTH flag).
+ * Note that these are expected to be 3D manipulators too. */
+ WM_MANIPULATORMAP_DRAWSTEP_IN_SCENE,
+};
+
+#endif /* __WM_MANIPULATOR_TYPES_H__ */
+
diff --git a/source/blender/windowmanager/manipulators/intern/manipulator_library/manipulator_library_intern.h b/source/blender/windowmanager/manipulators/intern/manipulator_library/manipulator_library_intern.h
new file mode 100644
index 00000000000..66598fa29d7
--- /dev/null
+++ b/source/blender/windowmanager/manipulators/intern/manipulator_library/manipulator_library_intern.h
@@ -0,0 +1,100 @@
+/*
+ * ***** 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) 2016 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/windowmanager/manipulators/intern/manipulator_library/manipulator_library_intern.h
+ * \ingroup wm
+ */
+
+
+#ifndef __MANIPULATOR_LIBRARY_INTERN_H__
+#define __MANIPULATOR_LIBRARY_INTERN_H__
+
+/* distance around which manipulators respond to input (and get highlighted) */
+#define MANIPULATOR_HOTSPOT 14.0f
+
+/**
+ * Data for common interactions. Used in manipulator_library_utils.c functions.
+ */
+typedef struct ManipulatorCommonData {
+ int flag;
+
+ float range_fac; /* factor for arrow min/max distance */
+ float offset;
+
+ /* property range for constrained manipulators */
+ float range;
+ /* min/max value for constrained manipulators */
+ float min, max;
+} ManipulatorCommonData;
+
+typedef struct ManipulatorInteraction {
+ float init_value; /* initial property value */
+ float init_origin[3];
+ float init_mval[2];
+ float init_offset;
+ float init_scale;
+
+ /* offset of last handling step */
+ float prev_offset;
+ /* Total offset added by precision tweaking.
+ * Needed to allow toggling precision on/off without causing jumps */
+ float precision_offset;
+} ManipulatorInteraction;
+
+/* ManipulatorCommonData->flag */
+enum {
+ MANIPULATOR_CUSTOM_RANGE_SET = (1 << 0),
+};
+
+
+float manipulator_offset_from_value(
+ ManipulatorCommonData *data, const float value,
+ const bool constrained, const bool inverted);
+float manipulator_value_from_offset(
+ ManipulatorCommonData *data, ManipulatorInteraction *inter, const float offset,
+ const bool constrained, const bool inverted, const bool use_precision);
+
+void manipulator_property_data_update(
+ wmManipulator *manipulator, ManipulatorCommonData *data, const int slot,
+ const bool constrained, const bool inverted);
+
+void manipulator_property_value_set(
+ bContext *C, const wmManipulator *manipulator,
+ const int slot, const float value);
+float manipulator_property_value_get(
+ const wmManipulator *manipulator, const int slot);
+void manipulator_property_value_reset(
+ bContext *C, const wmManipulator *manipulator, ManipulatorInteraction *inter,
+ const int slot);
+
+
+/* -------------------------------------------------------------------- */
+
+void manipulator_color_get(
+ const wmManipulator *manipulator, const bool highlight,
+ float r_col[]);
+
+#endif /* __MANIPULATOR_LIBRARY_INTERN_H__ */
+
diff --git a/source/blender/windowmanager/manipulators/intern/manipulator_library/manipulator_library_utils.c b/source/blender/windowmanager/manipulators/intern/manipulator_library/manipulator_library_utils.c
new file mode 100644
index 00000000000..0617e9e873b
--- /dev/null
+++ b/source/blender/windowmanager/manipulators/intern/manipulator_library/manipulator_library_utils.c
@@ -0,0 +1,171 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2015 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/windowmanager/manipulators/intern/manipulator_library/manipulator_library_utils.c
+ * \ingroup wm
+ *
+ * \name Manipulator Library Utilities
+ *
+ * \brief This file contains functions for common behaviors of manipulators.
+ */
+
+#include "BKE_context.h"
+
+#include "BLI_math.h"
+
+#include "RNA_access.h"
+
+#include "WM_api.h"
+
+/* own includes */
+#include "WM_manipulator_types.h"
+#include "wm_manipulator_wmapi.h"
+#include "wm_manipulator_intern.h"
+#include "manipulator_library_intern.h"
+
+/* factor for precision tweaking */
+#define MANIPULATOR_PRECISION_FAC 0.05f
+
+
+BLI_INLINE float manipulator_offset_from_value_constr(
+ const float range_fac, const float min, const float range, const float value,
+ const bool inverted)
+{
+ return inverted ? (range_fac * (min + range - value) / range) : (range_fac * (value / range));
+}
+
+BLI_INLINE float manipulator_value_from_offset_constr(
+ const float range_fac, const float min, const float range, const float value,
+ const bool inverted)
+{
+ return inverted ? (min + range - (value * range / range_fac)) : (value * range / range_fac);
+}
+
+float manipulator_offset_from_value(
+ ManipulatorCommonData *data, const float value, const bool constrained, const bool inverted)
+{
+ if (constrained)
+ return manipulator_offset_from_value_constr(data->range_fac, data->min, data->range, value, inverted);
+
+ return value;
+}
+
+float manipulator_value_from_offset(
+ ManipulatorCommonData *data, ManipulatorInteraction *inter, const float offset,
+ const bool constrained, const bool inverted, const bool use_precision)
+{
+ const float max = data->min + data->range;
+
+ if (use_precision) {
+ /* add delta offset of this step to total precision_offset */
+ inter->precision_offset += offset - inter->prev_offset;
+ }
+ inter->prev_offset = offset;
+
+ float ofs_new = inter->init_offset + offset - inter->precision_offset * (1.0f - MANIPULATOR_PRECISION_FAC);
+ float value;
+
+ if (constrained) {
+ value = manipulator_value_from_offset_constr(data->range_fac, data->min, data->range, ofs_new, inverted);
+ }
+ else {
+ value = ofs_new;
+ }
+
+ /* clamp to custom range */
+ if (data->flag & MANIPULATOR_CUSTOM_RANGE_SET) {
+ CLAMP(value, data->min, max);
+ }
+
+ return value;
+}
+
+void manipulator_property_data_update(
+ wmManipulator *manipulator, ManipulatorCommonData *data, const int slot,
+ const bool constrained, const bool inverted)
+{
+ if (!manipulator->props[slot]) {
+ data->offset = 0.0f;
+ return;
+ }
+
+ PointerRNA ptr = manipulator->ptr[slot];
+ PropertyRNA *prop = manipulator->props[slot];
+ float value = manipulator_property_value_get(manipulator, slot);
+
+ if (constrained) {
+ if ((data->flag & MANIPULATOR_CUSTOM_RANGE_SET) == 0) {
+ float step, precision;
+ float min, max;
+ RNA_property_float_ui_range(&ptr, prop, &min, &max, &step, &precision);
+ data->range = max - min;
+ data->min = min;
+ }
+ data->offset = manipulator_offset_from_value_constr(data->range_fac, data->min, data->range, value, inverted);
+ }
+ else {
+ data->offset = value;
+ }
+}
+
+void manipulator_property_value_set(
+ bContext *C, const wmManipulator *manipulator,
+ const int slot, const float value)
+{
+ PointerRNA ptr = manipulator->ptr[slot];
+ PropertyRNA *prop = manipulator->props[slot];
+
+ /* reset property */
+ RNA_property_float_set(&ptr, prop, value);
+ RNA_property_update(C, &ptr, prop);
+}
+
+float manipulator_property_value_get(const wmManipulator *manipulator, const int slot)
+{
+ BLI_assert(RNA_property_type(manipulator->props[slot]) == PROP_FLOAT);
+ return RNA_property_float_get(&manipulator->ptr[slot], manipulator->props[slot]);
+}
+
+void manipulator_property_value_reset(
+ bContext *C, const wmManipulator *manipulator, ManipulatorInteraction *inter,
+ const int slot)
+{
+ manipulator_property_value_set(C, manipulator, slot, inter->init_value);
+}
+
+
+/* -------------------------------------------------------------------- */
+
+void manipulator_color_get(
+ const wmManipulator *manipulator, const bool highlight,
+ float r_col[4])
+{
+ if (highlight && !(manipulator->flag & WM_MANIPULATOR_DRAW_HOVER)) {
+ copy_v4_v4(r_col, manipulator->col_hi);
+ }
+ else {
+ copy_v4_v4(r_col, manipulator->col);
+ }
+}
diff --git a/source/blender/windowmanager/manipulators/intern/wm_manipulator.c b/source/blender/windowmanager/manipulators/intern/wm_manipulator.c
new file mode 100644
index 00000000000..824141d1c40
--- /dev/null
+++ b/source/blender/windowmanager/manipulators/intern/wm_manipulator.c
@@ -0,0 +1,404 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/windowmanager/manipulators/intern/wm_manipulator.c
+ * \ingroup wm
+ */
+
+#include "BKE_context.h"
+
+#include "BLI_listbase.h"
+#include "BLI_math.h"
+#include "BLI_path_util.h"
+#include "BLI_string.h"
+
+#include "ED_screen.h"
+#include "ED_view3d.h"
+
+#include "GL/glew.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "RNA_access.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+/* own includes */
+#include "wm_manipulator_wmapi.h"
+#include "wm_manipulator_intern.h"
+
+
+/* Still unused */
+wmManipulator *WM_manipulator_new(
+ void (*draw)(const bContext *C, wmManipulator *customdata),
+ void (*render_3d_intersection)(const bContext *C, wmManipulator *customdata, int selectionbase),
+ int (*intersect)(bContext *C, const wmEvent *event, wmManipulator *manipulator),
+ int (*handler)(bContext *C, const wmEvent *event, wmManipulator *manipulator, const int flag))
+{
+ wmManipulator *manipulator = MEM_callocN(sizeof(wmManipulator), "manipulator");
+
+ manipulator->draw = draw;
+ manipulator->handler = handler;
+ manipulator->intersect = intersect;
+ manipulator->render_3d_intersection = render_3d_intersection;
+
+ /* XXX */
+// fix_linking_manipulator_arrow();
+// fix_linking_manipulator_arrow2d();
+// fix_linking_manipulator_cage();
+// fix_linking_manipulator_dial();
+// fix_linking_manipulator_facemap();
+// fix_linking_manipulator_primitive();
+
+ return manipulator;
+}
+
+/**
+ * Assign an idname that is unique in \a mgroup to \a manipulator.
+ *
+ * \param rawname: Name used as basis to define final unique idname.
+ */
+static void manipulator_unique_idname_set(wmManipulatorGroup *mgroup, wmManipulator *manipulator, const char *rawname)
+{
+ if (mgroup->type->idname[0]) {
+ BLI_snprintf(manipulator->idname, sizeof(manipulator->idname), "%s_%s", mgroup->type->idname, rawname);
+ }
+ else {
+ BLI_strncpy(manipulator->idname, rawname, sizeof(manipulator->idname));
+ }
+
+ /* ensure name is unique, append '.001', '.002', etc if not */
+ BLI_uniquename(&mgroup->manipulators, manipulator, "Manipulator", '.',
+ offsetof(wmManipulator, idname), sizeof(manipulator->idname));
+}
+
+/**
+ * Initialize default values and allocate needed memory for members.
+ */
+static void manipulator_init(wmManipulator *manipulator)
+{
+ const float col_default[4] = {1.0f, 1.0f, 1.0f, 1.0f};
+
+ manipulator->user_scale = 1.0f;
+ manipulator->line_width = 1.0f;
+
+ /* defaults */
+ copy_v4_v4(manipulator->col, col_default);
+ copy_v4_v4(manipulator->col_hi, col_default);
+
+ /* create at least one property for interaction */
+ if (manipulator->max_prop == 0) {
+ manipulator->max_prop = 1;
+ }
+
+ manipulator->props = MEM_callocN(sizeof(PropertyRNA *) * manipulator->max_prop, "manipulator->props");
+ manipulator->ptr = MEM_callocN(sizeof(PointerRNA) * manipulator->max_prop, "manipulator->ptr");
+}
+
+/**
+ * Register \a manipulator.
+ *
+ * \param name: name used to create a unique idname for \a manipulator in \a mgroup
+ */
+void wm_manipulator_register(wmManipulatorGroup *mgroup, wmManipulator *manipulator, const char *name)
+{
+ manipulator_init(manipulator);
+ manipulator_unique_idname_set(mgroup, manipulator, name);
+ wm_manipulatorgroup_manipulator_register(mgroup, manipulator);
+}
+
+/**
+ * Free \a manipulator and unlink from \a manipulatorlist.
+ * \a manipulatorlist is allowed to be NULL.
+ */
+void WM_manipulator_delete(ListBase *manipulatorlist, wmManipulatorMap *mmap, wmManipulator *manipulator, bContext *C)
+{
+ if (manipulator->state & WM_MANIPULATOR_HIGHLIGHT) {
+ wm_manipulatormap_set_highlighted_manipulator(mmap, C, NULL, 0);
+ }
+ if (manipulator->state & WM_MANIPULATOR_ACTIVE) {
+ wm_manipulatormap_set_active_manipulator(mmap, C, NULL, NULL);
+ }
+ if (manipulator->state & WM_MANIPULATOR_SELECTED) {
+ wm_manipulator_deselect(mmap, manipulator);
+ }
+
+ if (manipulator->opptr.data) {
+ WM_operator_properties_free(&manipulator->opptr);
+ }
+ MEM_freeN(manipulator->props);
+ MEM_freeN(manipulator->ptr);
+
+ if (manipulatorlist)
+ BLI_remlink(manipulatorlist, manipulator);
+ MEM_freeN(manipulator);
+}
+
+wmManipulatorGroup *wm_manipulator_get_parent_group(const wmManipulator *manipulator)
+{
+ return manipulator->mgroup;
+}
+
+
+/* -------------------------------------------------------------------- */
+/** \name Manipulator Creation API
+ *
+ * API for defining data on manipulator creation.
+ *
+ * \{ */
+
+void WM_manipulator_set_property(wmManipulator *manipulator, const int slot, PointerRNA *ptr, const char *propname)
+{
+ if (slot < 0 || slot >= manipulator->max_prop) {
+ fprintf(stderr, "invalid index %d when binding property for manipulator type %s\n", slot, manipulator->idname);
+ return;
+ }
+
+ /* if manipulator evokes an operator we cannot use it for property manipulation */
+ manipulator->opname = NULL;
+ manipulator->ptr[slot] = *ptr;
+ manipulator->props[slot] = RNA_struct_find_property(ptr, propname);
+
+ if (manipulator->prop_data_update)
+ manipulator->prop_data_update(manipulator, slot);
+}
+
+PointerRNA *WM_manipulator_set_operator(wmManipulator *manipulator, const char *opname)
+{
+ wmOperatorType *ot = WM_operatortype_find(opname, 0);
+
+ if (ot) {
+ manipulator->opname = opname;
+
+ if (manipulator->opptr.data) {
+ WM_operator_properties_free(&manipulator->opptr);
+ }
+ WM_operator_properties_create_ptr(&manipulator->opptr, ot);
+
+ return &manipulator->opptr;
+ }
+ else {
+ fprintf(stderr, "Error binding operator to manipulator: operator %s not found!\n", opname);
+ }
+
+ return NULL;
+}
+
+/**
+ * \brief Set manipulator select callback.
+ *
+ * Callback is called when manipulator gets selected/deselected.
+ */
+void WM_manipulator_set_func_select(wmManipulator *manipulator, wmManipulatorSelectFunc select)
+{
+ BLI_assert(manipulator->mgroup->type->flag & WM_MANIPULATORGROUPTYPE_SELECTABLE);
+ manipulator->select = select;
+}
+
+void WM_manipulator_set_origin(wmManipulator *manipulator, const float origin[3])
+{
+ copy_v3_v3(manipulator->origin, origin);
+}
+
+void WM_manipulator_set_offset(wmManipulator *manipulator, const float offset[3])
+{
+ copy_v3_v3(manipulator->offset, offset);
+}
+
+void WM_manipulator_set_flag(wmManipulator *manipulator, const int flag, const bool enable)
+{
+ if (enable) {
+ manipulator->flag |= flag;
+ }
+ else {
+ manipulator->flag &= ~flag;
+ }
+}
+
+void WM_manipulator_set_scale(wmManipulator *manipulator, const float scale)
+{
+ manipulator->user_scale = scale;
+}
+
+void WM_manipulator_set_line_width(wmManipulator *manipulator, const float line_width)
+{
+ manipulator->line_width = line_width;
+}
+
+/**
+ * Set manipulator rgba colors.
+ *
+ * \param col Normal state color.
+ * \param col_hi Highlighted state color.
+ */
+void WM_manipulator_set_colors(wmManipulator *manipulator, const float col[4], const float col_hi[4])
+{
+ copy_v4_v4(manipulator->col, col);
+ copy_v4_v4(manipulator->col_hi, col_hi);
+}
+
+/** \} */ // Manipulator Creation API
+
+
+/* -------------------------------------------------------------------- */
+
+/**
+ * Remove \a manipulator from selection.
+ * Reallocates memory for selected manipulators so better not call for selecting multiple ones.
+ *
+ * \return if the selection has changed.
+ */
+bool wm_manipulator_deselect(wmManipulatorMap *mmap, wmManipulator *manipulator)
+{
+ if (!mmap->mmap_context.selected_manipulator)
+ return false;
+
+ wmManipulator ***sel = &mmap->mmap_context.selected_manipulator;
+ int *tot_selected = &mmap->mmap_context.tot_selected;
+ bool changed = false;
+
+ /* caller should check! */
+ BLI_assert(manipulator->state & WM_MANIPULATOR_SELECTED);
+
+ /* remove manipulator from selected_manipulators array */
+ for (int i = 0; i < (*tot_selected); i++) {
+ if ((*sel)[i] == manipulator) {
+ for (int j = i; j < ((*tot_selected) - 1); j++) {
+ (*sel)[j] = (*sel)[j + 1];
+ }
+ changed = true;
+ break;
+ }
+ }
+
+ /* update array data */
+ if ((*tot_selected) <= 1) {
+ wm_manipulatormap_selected_delete(mmap);
+ }
+ else {
+ *sel = MEM_reallocN(*sel, sizeof(**sel) * (*tot_selected));
+ (*tot_selected)--;
+ }
+
+ manipulator->state &= ~WM_MANIPULATOR_SELECTED;
+ return changed;
+}
+
+/**
+ * Add \a manipulator to selection.
+ * Reallocates memory for selected manipulators so better not call for selecting multiple ones.
+ *
+ * \return if the selection has changed.
+ */
+bool wm_manipulator_select(bContext *C, wmManipulatorMap *mmap, wmManipulator *manipulator)
+{
+ wmManipulator ***sel = &mmap->mmap_context.selected_manipulator;
+ int *tot_selected = &mmap->mmap_context.tot_selected;
+
+ if (!manipulator || (manipulator->state & WM_MANIPULATOR_SELECTED))
+ return false;
+
+ (*tot_selected)++;
+
+ *sel = MEM_reallocN(*sel, sizeof(wmManipulator *) * (*tot_selected));
+ (*sel)[(*tot_selected) - 1] = manipulator;
+
+ manipulator->state |= WM_MANIPULATOR_SELECTED;
+ if (manipulator->select) {
+ manipulator->select(C, manipulator, SEL_SELECT);
+ }
+ wm_manipulatormap_set_highlighted_manipulator(mmap, C, manipulator, manipulator->highlighted_part);
+
+ return true;
+}
+
+void wm_manipulator_calculate_scale(wmManipulator *manipulator, const bContext *C)
+{
+ const RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ float scale = 1.0f;
+
+ if (manipulator->mgroup->type->flag & WM_MANIPULATORGROUPTYPE_SCALE_3D) {
+ if (rv3d /*&& (U.manipulator_flag & V3D_3D_MANIPULATORS) == 0*/) { /* UserPref flag might be useful for later */
+ if (manipulator->get_final_position) {
+ float position[3];
+
+ manipulator->get_final_position(manipulator, position);
+ scale = ED_view3d_pixel_size(rv3d, position) * (float)U.manipulator_scale;
+ }
+ else {
+ scale = ED_view3d_pixel_size(rv3d, manipulator->origin) * (float)U.manipulator_scale;
+ }
+ }
+ else {
+ scale = U.manipulator_scale * 0.02f;
+ }
+ }
+
+ manipulator->scale = scale * manipulator->user_scale;
+}
+
+static void manipulator_update_prop_data(wmManipulator *manipulator)
+{
+ /* manipulator property might have been changed, so update manipulator */
+ if (manipulator->props && manipulator->prop_data_update) {
+ for (int i = 0; i < manipulator->max_prop; i++) {
+ if (manipulator->props[i]) {
+ manipulator->prop_data_update(manipulator, i);
+ }
+ }
+ }
+}
+
+void wm_manipulator_update(wmManipulator *manipulator, const bContext *C, const bool refresh_map)
+{
+ if (refresh_map) {
+ manipulator_update_prop_data(manipulator);
+ }
+ wm_manipulator_calculate_scale(manipulator, C);
+}
+
+bool wm_manipulator_is_visible(wmManipulator *manipulator)
+{
+ if (manipulator->flag & WM_MANIPULATOR_HIDDEN) {
+ return false;
+ }
+ if ((manipulator->state & WM_MANIPULATOR_ACTIVE) &&
+ !(manipulator->flag & (WM_MANIPULATOR_DRAW_ACTIVE | WM_MANIPULATOR_DRAW_VALUE)))
+ {
+ /* don't draw while active (while dragging) */
+ return false;
+ }
+ if ((manipulator->flag & WM_MANIPULATOR_DRAW_HOVER) &&
+ !(manipulator->state & WM_MANIPULATOR_HIGHLIGHT) &&
+ !(manipulator->state & WM_MANIPULATOR_SELECTED)) /* still draw selected manipulators */
+ {
+ /* only draw on mouse hover */
+ return false;
+ }
+
+ return true;
+}
+
diff --git a/source/blender/windowmanager/manipulators/intern/wm_manipulator_intern.h b/source/blender/windowmanager/manipulators/intern/wm_manipulator_intern.h
new file mode 100644
index 00000000000..1a9693a472b
--- /dev/null
+++ b/source/blender/windowmanager/manipulators/intern/wm_manipulator_intern.h
@@ -0,0 +1,230 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/windowmanager/manipulators/intern/wm_manipulator_intern.h
+ * \ingroup wm
+ */
+
+
+#ifndef __WM_MANIPULATOR_INTERN_H__
+#define __WM_MANIPULATOR_INTERN_H__
+
+struct wmKeyConfig;
+struct wmManipulatorMap;
+
+/* -------------------------------------------------------------------- */
+/* wmManipulator */
+
+/* manipulators are set per region by registering them on manipulator-maps */
+typedef struct wmManipulator {
+ struct wmManipulator *next, *prev;
+
+ char idname[MAX_NAME + 4]; /* + 4 for unique '.001', '.002', etc suffix */
+ /* pointer back to group this manipulator is in (just for quick access) */
+ struct wmManipulatorGroup *mgroup;
+
+ /* could become wmManipulatorType */
+ /* draw manipulator */
+ void (*draw)(const struct bContext *, struct wmManipulator *);
+
+ /* determine if the mouse intersects with the manipulator. The calculation should be done in the callback itself */
+ int (*intersect)(struct bContext *, const struct wmEvent *, struct wmManipulator *);
+
+ /* determines 3d intersection by rendering the manipulator in a selection routine. */
+ void (*render_3d_intersection)(const struct bContext *, struct wmManipulator *, int);
+
+ /* handler used by the manipulator. Usually handles interaction tied to a manipulator type */
+ int (*handler)(struct bContext *, const struct wmEvent *, struct wmManipulator *, const int);
+
+ /* manipulator-specific handler to update manipulator attributes based on the property value */
+ void (*prop_data_update)(struct wmManipulator *, int);
+
+ /* returns the final position which may be different from the origin, depending on the manipulator.
+ * used in calculations of scale */
+ void (*get_final_position)(struct wmManipulator *, float[]);
+
+ /* activate a manipulator state when the user clicks on it */
+ int (*invoke)(struct bContext *, const struct wmEvent *, struct wmManipulator *);
+
+ /* called when manipulator tweaking is done - used to free data and reset property when cancelling */
+ void (*exit)(struct bContext *, struct wmManipulator *, const bool );
+
+ int (*get_cursor)(struct wmManipulator *);
+
+ /* called when manipulator selection state changes */
+ wmManipulatorSelectFunc select;
+
+ int flag; /* flags that influence the behavior or how the manipulators are drawn */
+ short state; /* state flags (active, highlighted, selected) */
+
+ unsigned char highlighted_part;
+
+ /* center of manipulator in space, 2d or 3d */
+ float origin[3];
+ /* custom offset from origin */
+ float offset[3];
+ /* runtime property, set the scale while drawing on the viewport */
+ float scale;
+ /* user defined scale, in addition to the original one */
+ float user_scale;
+ /* user defined width for line drawing */
+ float line_width;
+ /* manipulator colors (uses default fallbacks if not defined) */
+ float col[4], col_hi[4];
+
+ /* data used during interaction */
+ void *interaction_data;
+
+ /* name of operator to spawn when activating the manipulator */
+ const char *opname;
+ /* operator properties if manipulator spawns and controls an operator,
+ * or owner pointer if manipulator spawns and controls a property */
+ PointerRNA opptr;
+
+ /* maximum number of properties attached to the manipulator */
+ int max_prop;
+ /* arrays of properties attached to various manipulator parameters. As
+ * the manipulator is interacted with, those properties get updated */
+ PointerRNA *ptr;
+ PropertyRNA **props;
+} wmManipulator;
+
+/* wmManipulator.state */
+enum {
+ WM_MANIPULATOR_HIGHLIGHT = (1 << 0), /* while hovered */
+ WM_MANIPULATOR_ACTIVE = (1 << 1), /* while dragging */
+ WM_MANIPULATOR_SELECTED = (1 << 2),
+};
+
+/**
+ * \brief Manipulator tweak flag.
+ * Bitflag passed to manipulator while tweaking.
+ */
+enum {
+ /* drag with extra precision (shift)
+ * NOTE: Manipulators are responsible for handling this (manipulator->handler callback)! */
+ WM_MANIPULATOR_TWEAK_PRECISE = (1 << 0),
+};
+
+void wm_manipulator_register(struct wmManipulatorGroup *mgroup, struct wmManipulator *manipulator, const char *name);
+
+bool wm_manipulator_deselect(struct wmManipulatorMap *mmap, struct wmManipulator *manipulator);
+bool wm_manipulator_select(bContext *C, struct wmManipulatorMap *mmap, struct wmManipulator *manipulator);
+
+void wm_manipulator_calculate_scale(struct wmManipulator *manipulator, const bContext *C);
+void wm_manipulator_update(struct wmManipulator *manipulator, const bContext *C, const bool refresh_map);
+bool wm_manipulator_is_visible(struct wmManipulator *manipulator);
+
+void fix_linking_manipulator_arrow(void);
+void fix_linking_manipulator_arrow2d(void);
+void fix_linking_manipulator_cage(void);
+void fix_linking_manipulator_dial(void);
+void fix_linking_manipulator_facemap(void);
+void fix_linking_manipulator_primitive(void);
+
+
+/* -------------------------------------------------------------------- */
+/* wmManipulatorGroup */
+
+enum {
+ TWEAK_MODAL_CANCEL = 1,
+ TWEAK_MODAL_CONFIRM,
+ TWEAK_MODAL_PRECISION_ON,
+ TWEAK_MODAL_PRECISION_OFF,
+};
+
+struct wmManipulatorGroup *wm_manipulatorgroup_new_from_type(struct wmManipulatorGroupType *mgrouptype);
+void wm_manipulatorgroup_free(bContext *C, struct wmManipulatorMap *mmap, struct wmManipulatorGroup *mgroup);
+void wm_manipulatorgroup_manipulator_register(struct wmManipulatorGroup *mgroup, wmManipulator *manipulator);
+wmManipulator *wm_manipulatorgroup_find_intersected_mainpulator(
+ const struct wmManipulatorGroup *mgroup, struct bContext *C, const struct wmEvent *event,
+ unsigned char *part);
+void wm_manipulatorgroup_intersectable_manipulators_to_list(
+ const struct wmManipulatorGroup *mgroup, struct ListBase *listbase);
+void wm_manipulatorgroup_ensure_initialized(struct wmManipulatorGroup *mgroup, const struct bContext *C);
+bool wm_manipulatorgroup_is_visible(const struct wmManipulatorGroup *mgroup, const struct bContext *C);
+bool wm_manipulatorgroup_is_visible_in_drawstep(const struct wmManipulatorGroup *mgroup, const int drawstep);
+
+void wm_manipulatorgrouptype_keymap_init(struct wmManipulatorGroupType *mgrouptype, struct wmKeyConfig *keyconf);
+
+
+/* -------------------------------------------------------------------- */
+/* wmManipulatorMap */
+
+typedef struct wmManipulatorMap {
+ struct wmManipulatorMap *next, *prev;
+
+ struct wmManipulatorMapType *type;
+ ListBase manipulator_groups;
+
+ char update_flag; /* private, update tagging */
+
+ /**
+ * \brief Manipulator map runtime context
+ *
+ * Contains information about this manipulator-map. Currently
+ * highlighted manipulator, currently selected manipulators, ...
+ */
+ struct {
+ /* we redraw the manipulator-map when this changes */
+ struct wmManipulator *highlighted_manipulator;
+ /* user has clicked this manipulator and it gets all input */
+ struct wmManipulator *active_manipulator;
+ /* array for all selected manipulators
+ * TODO check on using BLI_array */
+ struct wmManipulator **selected_manipulator;
+ int tot_selected;
+ } mmap_context;
+} wmManipulatorMap;
+
+/**
+ * This is a container for all manipulator types that can be instantiated in a region.
+ * (similar to dropboxes).
+ *
+ * \note There is only ever one of these for every (area, region) combination.
+ */
+typedef struct wmManipulatorMapType {
+ struct wmManipulatorMapType *next, *prev;
+ char idname[64];
+ short spaceid, regionid;
+ /* types of manipulator-groups for this manipulator-map type */
+ ListBase manipulator_grouptypes;
+} wmManipulatorMapType;
+
+void wm_manipulatormap_selected_delete(wmManipulatorMap *mmap);
+bool wm_manipulatormap_deselect_all(struct wmManipulatorMap *mmap, wmManipulator ***sel);
+
+
+/* -------------------------------------------------------------------- */
+/* Manipulator drawing */
+
+typedef struct ManipulatorGeometryInfo {
+ int nverts;
+ int ntris;
+ float (*verts)[3];
+ float (*normals)[3];
+ unsigned short *indices;
+ bool init;
+} ManipulatorGeometryInfo;
+
+#endif /* __WM_MANIPULATOR_INTERN_H__ */
+
diff --git a/source/blender/windowmanager/manipulators/intern/wm_manipulatorgroup.c b/source/blender/windowmanager/manipulators/intern/wm_manipulatorgroup.c
new file mode 100644
index 00000000000..37a3ca8b55c
--- /dev/null
+++ b/source/blender/windowmanager/manipulators/intern/wm_manipulatorgroup.c
@@ -0,0 +1,586 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/windowmanager/manipulators/intern/wm_manipulatorgroup.c
+ * \ingroup wm
+ *
+ * \name Manipulator-Group
+ *
+ * Manipulator-groups store and manage groups of manipulators. They can be
+ * attached to modal handlers and have own keymaps.
+ */
+
+#include "BKE_context.h"
+#include "BKE_main.h"
+#include "BKE_report.h"
+
+#include "BLI_listbase.h"
+#include "BLI_string.h"
+
+#include "BPY_extern.h"
+
+#include "ED_screen.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "RNA_access.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+#include "wm_event_system.h"
+
+/* own includes */
+#include "wm_manipulator_wmapi.h"
+#include "wm_manipulator_intern.h"
+
+
+/* -------------------------------------------------------------------- */
+/** \name wmManipulatorGroup
+ *
+ * \{ */
+
+/* wmManipulatorGroup.flag */
+enum {
+ WM_MANIPULATORGROUP_INITIALIZED = (1 << 2), /* mgroup has been initialized */
+};
+
+/**
+ * Create a new manipulator-group from \a mgrouptype.
+ */
+wmManipulatorGroup *wm_manipulatorgroup_new_from_type(wmManipulatorGroupType *mgrouptype)
+{
+ wmManipulatorGroup *mgroup = MEM_callocN(sizeof(*mgroup), "manipulator-group");
+ mgroup->type = mgrouptype;
+
+ return mgroup;
+}
+
+void wm_manipulatorgroup_free(bContext *C, wmManipulatorMap *mmap, wmManipulatorGroup *mgroup)
+{
+ for (wmManipulator *manipulator = mgroup->manipulators.first; manipulator;) {
+ wmManipulator *manipulator_next = manipulator->next;
+ WM_manipulator_delete(&mgroup->manipulators, mmap, manipulator, C);
+ manipulator = manipulator_next;
+ }
+ BLI_assert(BLI_listbase_is_empty(&mgroup->manipulators));
+
+#ifdef WITH_PYTHON
+ if (mgroup->py_instance) {
+ /* do this first in case there are any __del__ functions or
+ * similar that use properties */
+ BPY_DECREF_RNA_INVALIDATE(mgroup->py_instance);
+ }
+#endif
+
+ if (mgroup->reports && (mgroup->reports->flag & RPT_FREE)) {
+ BKE_reports_clear(mgroup->reports);
+ MEM_freeN(mgroup->reports);
+ }
+
+ if (mgroup->customdata_free) {
+ mgroup->customdata_free(mgroup->customdata);
+ }
+ else {
+ MEM_SAFE_FREE(mgroup->customdata);
+ }
+
+ BLI_remlink(&mmap->manipulator_groups, mgroup);
+ MEM_freeN(mgroup);
+}
+
+/**
+ * Add \a manipulator to \a mgroup and make sure its name is unique within the group.
+ */
+void wm_manipulatorgroup_manipulator_register(wmManipulatorGroup *mgroup, wmManipulator *manipulator)
+{
+ BLI_assert(!BLI_findstring(&mgroup->manipulators, manipulator->idname, offsetof(wmManipulator, idname)));
+ BLI_addtail(&mgroup->manipulators, manipulator);
+ manipulator->mgroup = mgroup;
+}
+
+void wm_manipulatorgroup_attach_to_modal_handler(
+ bContext *C, wmEventHandler *handler,
+ wmManipulatorGroupType *mgrouptype, wmOperator *op)
+{
+ /* maybe overly careful, but manipulator-grouptype could come from a failed creation */
+ if (!mgrouptype) {
+ return;
+ }
+
+ /* now instantiate the manipulator-map */
+ mgrouptype->op = op;
+
+ /* try to find map in handler region that contains mgrouptype */
+ if (handler->op_region && handler->op_region->manipulator_map) {
+ handler->manipulator_map = handler->op_region->manipulator_map;
+ ED_region_tag_redraw(handler->op_region);
+ }
+
+ WM_event_add_mousemove(C);
+}
+
+wmManipulator *wm_manipulatorgroup_find_intersected_mainpulator(
+ const wmManipulatorGroup *mgroup, bContext *C, const wmEvent *event,
+ unsigned char *part)
+{
+ for (wmManipulator *manipulator = mgroup->manipulators.first; manipulator; manipulator = manipulator->next) {
+ if (manipulator->intersect && (manipulator->flag & WM_MANIPULATOR_HIDDEN) == 0) {
+ if ((*part = manipulator->intersect(C, event, manipulator))) {
+ return manipulator;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * Adds all manipulators of \a mgroup that can be selected to the head of \a listbase. Added items need freeing!
+ */
+void wm_manipulatorgroup_intersectable_manipulators_to_list(const wmManipulatorGroup *mgroup, ListBase *listbase)
+{
+ for (wmManipulator *manipulator = mgroup->manipulators.first; manipulator; manipulator = manipulator->next) {
+ if ((manipulator->flag & WM_MANIPULATOR_HIDDEN) == 0) {
+ if (((mgroup->type->flag & WM_MANIPULATORGROUPTYPE_IS_3D) && manipulator->render_3d_intersection) ||
+ ((mgroup->type->flag & WM_MANIPULATORGROUPTYPE_IS_3D) == 0 && manipulator->intersect))
+ {
+ BLI_addhead(listbase, BLI_genericNodeN(manipulator));
+ }
+ }
+ }
+}
+
+void wm_manipulatorgroup_ensure_initialized(wmManipulatorGroup *mgroup, const bContext *C)
+{
+ /* prepare for first draw */
+ if (UNLIKELY((mgroup->flag & WM_MANIPULATORGROUP_INITIALIZED) == 0)) {
+ mgroup->type->init(C, mgroup);
+ mgroup->flag |= WM_MANIPULATORGROUP_INITIALIZED;
+ }
+}
+
+bool wm_manipulatorgroup_is_visible(const wmManipulatorGroup *mgroup, const bContext *C)
+{
+ /* Check for poll function, if manipulator-group belongs to an operator, also check if the operator is running. */
+ return ((mgroup->type->flag & WM_MANIPULATORGROUPTYPE_OP) == 0 || mgroup->type->op) &&
+ (!mgroup->type->poll || mgroup->type->poll(C, mgroup->type));
+}
+
+bool wm_manipulatorgroup_is_visible_in_drawstep(const wmManipulatorGroup *mgroup, const int drawstep)
+{
+ switch (drawstep) {
+ case WM_MANIPULATORMAP_DRAWSTEP_2D:
+ return (mgroup->type->flag & WM_MANIPULATORGROUPTYPE_IS_3D) == 0;
+ case WM_MANIPULATORMAP_DRAWSTEP_3D:
+ return (mgroup->type->flag & WM_MANIPULATORGROUPTYPE_IS_3D);
+ case WM_MANIPULATORMAP_DRAWSTEP_IN_SCENE:
+ return (mgroup->type->flag & WM_MANIPULATORGROUPTYPE_SCENE_DEPTH);
+ default:
+ BLI_assert(0);
+ return false;
+ }
+}
+
+/** \name Manipulator operators
+ *
+ * Basic operators for manipulator interaction with user configurable keymaps.
+ *
+ * \{ */
+
+static int manipulator_select_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ ARegion *ar = CTX_wm_region(C);
+ wmManipulatorMap *mmap = ar->manipulator_map;
+ wmManipulator ***sel = &mmap->mmap_context.selected_manipulator;
+ wmManipulator *highlighted = mmap->mmap_context.highlighted_manipulator;
+
+ bool extend = RNA_boolean_get(op->ptr, "extend");
+ bool deselect = RNA_boolean_get(op->ptr, "deselect");
+ bool toggle = RNA_boolean_get(op->ptr, "toggle");
+
+ /* deselect all first */
+ if (extend == false && deselect == false && toggle == false) {
+ wm_manipulatormap_deselect_all(mmap, sel);
+ BLI_assert(*sel == NULL && mmap->mmap_context.tot_selected == 0);
+ }
+
+ if (highlighted) {
+ const bool is_selected = (highlighted->state & WM_MANIPULATOR_SELECTED);
+ bool redraw = false;
+
+ if (toggle) {
+ /* toggle: deselect if already selected, else select */
+ deselect = is_selected;
+ }
+
+ if (deselect) {
+ if (is_selected && wm_manipulator_deselect(mmap, highlighted)) {
+ redraw = true;
+ }
+ }
+ else if (wm_manipulator_select(C, mmap, highlighted)) {
+ redraw = true;
+ }
+
+ if (redraw) {
+ ED_region_tag_redraw(ar);
+ }
+
+ return OPERATOR_FINISHED;
+ }
+ else {
+ BLI_assert(0);
+ return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
+ }
+
+ return OPERATOR_PASS_THROUGH;
+}
+
+void MANIPULATORGROUP_OT_manipulator_select(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Manipulator Select";
+ ot->description = "Select the currently highlighted manipulator";
+ ot->idname = "MANIPULATORGROUP_OT_manipulator_select";
+
+ /* api callbacks */
+ ot->invoke = manipulator_select_invoke;
+
+ ot->flag = OPTYPE_UNDO;
+
+ WM_operator_properties_mouse_select(ot);
+}
+
+typedef struct ManipulatorTweakData {
+ wmManipulatorMap *mmap;
+ wmManipulator *active;
+
+ int init_event; /* initial event type */
+ int flag; /* tweak flags */
+} ManipulatorTweakData;
+
+static void manipulator_tweak_finish(bContext *C, wmOperator *op, const bool cancel)
+{
+ ManipulatorTweakData *mtweak = op->customdata;
+ if (mtweak->active->exit) {
+ mtweak->active->exit(C, mtweak->active, cancel);
+ }
+ wm_manipulatormap_set_active_manipulator(mtweak->mmap, C, NULL, NULL);
+ MEM_freeN(mtweak);
+}
+
+static int manipulator_tweak_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ ManipulatorTweakData *mtweak = op->customdata;
+ wmManipulator *manipulator = mtweak->active;
+
+ if (!manipulator) {
+ BLI_assert(0);
+ return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
+ }
+
+ if (event->type == mtweak->init_event && event->val == KM_RELEASE) {
+ manipulator_tweak_finish(C, op, false);
+ return OPERATOR_FINISHED;
+ }
+
+
+ if (event->type == EVT_MODAL_MAP) {
+ switch (event->val) {
+ case TWEAK_MODAL_CANCEL:
+ manipulator_tweak_finish(C, op, true);
+ return OPERATOR_CANCELLED;
+ case TWEAK_MODAL_CONFIRM:
+ manipulator_tweak_finish(C, op, false);
+ return OPERATOR_FINISHED;
+ case TWEAK_MODAL_PRECISION_ON:
+ mtweak->flag |= WM_MANIPULATOR_TWEAK_PRECISE;
+ break;
+ case TWEAK_MODAL_PRECISION_OFF:
+ mtweak->flag &= ~WM_MANIPULATOR_TWEAK_PRECISE;
+ break;
+ }
+ }
+
+ /* handle manipulator */
+ if (manipulator->handler) {
+ manipulator->handler(C, event, manipulator, mtweak->flag);
+ }
+
+ /* Ugly hack to send manipulator events */
+ ((wmEvent *)event)->type = EVT_MANIPULATOR_UPDATE;
+
+ /* always return PASS_THROUGH so modal handlers
+ * with manipulators attached can update */
+ return OPERATOR_PASS_THROUGH;
+}
+
+static int manipulator_tweak_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ ARegion *ar = CTX_wm_region(C);
+ wmManipulatorMap *mmap = ar->manipulator_map;
+ wmManipulator *manipulator = mmap->mmap_context.highlighted_manipulator;
+
+ if (!manipulator) {
+ /* wm_handlers_do_intern shouldn't let this happen */
+ BLI_assert(0);
+ return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
+ }
+
+
+ /* activate highlighted manipulator */
+ wm_manipulatormap_set_active_manipulator(mmap, C, event, manipulator);
+
+ /* XXX temporary workaround for modal manipulator operator
+ * conflicting with modal operator attached to manipulator */
+ if (manipulator->opname) {
+ wmOperatorType *ot = WM_operatortype_find(manipulator->opname, true);
+ if (ot->modal) {
+ return OPERATOR_FINISHED;
+ }
+ }
+
+
+ ManipulatorTweakData *mtweak = MEM_mallocN(sizeof(ManipulatorTweakData), __func__);
+
+ mtweak->init_event = event->type;
+ mtweak->active = mmap->mmap_context.highlighted_manipulator;
+ mtweak->mmap = mmap;
+ mtweak->flag = 0;
+
+ op->customdata = mtweak;
+
+ WM_event_add_modal_handler(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+void MANIPULATORGROUP_OT_manipulator_tweak(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Manipulator Tweak";
+ ot->description = "Tweak the active manipulator";
+ ot->idname = "MANIPULATORGROUP_OT_manipulator_tweak";
+
+ /* api callbacks */
+ ot->invoke = manipulator_tweak_invoke;
+ ot->modal = manipulator_tweak_modal;
+
+ ot->flag = OPTYPE_UNDO;
+}
+
+/** \} */ // Manipulator operators
+
+
+static wmKeyMap *manipulatorgroup_tweak_modal_keymap(wmKeyConfig *keyconf, const char *mgroupname)
+{
+ wmKeyMap *keymap;
+ char name[KMAP_MAX_NAME];
+
+ static EnumPropertyItem modal_items[] = {
+ {TWEAK_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""},
+ {TWEAK_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
+ {TWEAK_MODAL_PRECISION_ON, "PRECISION_ON", 0, "Enable Precision", ""},
+ {TWEAK_MODAL_PRECISION_OFF, "PRECISION_OFF", 0, "Disable Precision", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+
+ BLI_snprintf(name, sizeof(name), "%s Tweak Modal Map", mgroupname);
+ keymap = WM_modalkeymap_get(keyconf, name);
+
+ /* this function is called for each spacetype, only needs to add map once */
+ if (keymap && keymap->modal_items)
+ return NULL;
+
+ keymap = WM_modalkeymap_add(keyconf, name, modal_items);
+
+
+ /* items for modal map */
+ WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, TWEAK_MODAL_CANCEL);
+ WM_modalkeymap_add_item(keymap, RIGHTMOUSE, KM_PRESS, KM_ANY, 0, TWEAK_MODAL_CANCEL);
+
+ WM_modalkeymap_add_item(keymap, RETKEY, KM_PRESS, KM_ANY, 0, TWEAK_MODAL_CONFIRM);
+ WM_modalkeymap_add_item(keymap, PADENTER, KM_PRESS, KM_ANY, 0, TWEAK_MODAL_CONFIRM);
+
+ WM_modalkeymap_add_item(keymap, RIGHTSHIFTKEY, KM_PRESS, KM_ANY, 0, TWEAK_MODAL_PRECISION_ON);
+ WM_modalkeymap_add_item(keymap, RIGHTSHIFTKEY, KM_RELEASE, KM_ANY, 0, TWEAK_MODAL_PRECISION_OFF);
+ WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_PRESS, KM_ANY, 0, TWEAK_MODAL_PRECISION_ON);
+ WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_RELEASE, KM_ANY, 0, TWEAK_MODAL_PRECISION_OFF);
+
+
+ WM_modalkeymap_assign(keymap, "MANIPULATORGROUP_OT_manipulator_tweak");
+
+ return keymap;
+}
+
+/**
+ * Common default keymap for manipulator groups
+ */
+wmKeyMap *WM_manipulatorgroup_keymap_common(const struct wmManipulatorGroupType *mgrouptype, wmKeyConfig *config)
+{
+ /* Use area and region id since we might have multiple manipulators with the same name in different areas/regions */
+ wmKeyMap *km = WM_keymap_find(config, mgrouptype->name, mgrouptype->spaceid, mgrouptype->regionid);
+
+ WM_keymap_add_item(km, "MANIPULATORGROUP_OT_manipulator_tweak", ACTIONMOUSE, KM_PRESS, KM_ANY, 0);
+ manipulatorgroup_tweak_modal_keymap(config, mgrouptype->name);
+
+ return km;
+}
+
+/**
+ * Variation of #WM_manipulatorgroup_keymap_common but with keymap items for selection
+ */
+wmKeyMap *WM_manipulatorgroup_keymap_common_sel(const struct wmManipulatorGroupType *mgrouptype, wmKeyConfig *config)
+{
+ /* Use area and region id since we might have multiple manipulators with the same name in different areas/regions */
+ wmKeyMap *km = WM_keymap_find(config, mgrouptype->name, mgrouptype->spaceid, mgrouptype->regionid);
+
+ WM_keymap_add_item(km, "MANIPULATORGROUP_OT_manipulator_tweak", ACTIONMOUSE, KM_PRESS, KM_ANY, 0);
+ manipulatorgroup_tweak_modal_keymap(config, mgrouptype->name);
+
+ wmKeyMapItem *kmi = WM_keymap_add_item(km, "MANIPULATORGROUP_OT_manipulator_select", SELECTMOUSE, KM_PRESS, 0, 0);
+ RNA_boolean_set(kmi->ptr, "extend", false);
+ RNA_boolean_set(kmi->ptr, "deselect", false);
+ RNA_boolean_set(kmi->ptr, "toggle", false);
+ kmi = WM_keymap_add_item(km, "MANIPULATORGROUP_OT_manipulator_select", SELECTMOUSE, KM_PRESS, KM_SHIFT, 0);
+ RNA_boolean_set(kmi->ptr, "extend", false);
+ RNA_boolean_set(kmi->ptr, "deselect", false);
+ RNA_boolean_set(kmi->ptr, "toggle", true);
+
+ return km;
+}
+
+/** \} */ /* wmManipulatorGroup */
+
+/* -------------------------------------------------------------------- */
+/** \name wmManipulatorGroupType
+ *
+ * \{ */
+
+/**
+ * Use this for registering manipulators on startup. For runtime, use #WM_manipulatorgrouptype_append_runtime.
+ */
+wmManipulatorGroupType *WM_manipulatorgrouptype_append(
+ wmManipulatorMapType *mmaptype, void (*mgrouptype_func)(wmManipulatorGroupType *))
+{
+ wmManipulatorGroupType *mgrouptype = MEM_callocN(sizeof(wmManipulatorGroupType), "manipulator-group");
+
+ mgrouptype_func(mgrouptype);
+ mgrouptype->spaceid = mmaptype->spaceid;
+ mgrouptype->regionid = mmaptype->regionid;
+ BLI_strncpy(mgrouptype->mapidname, mmaptype->idname, MAX_NAME);
+ /* if not set, use default */
+ if (!mgrouptype->keymap_init) {
+ mgrouptype->keymap_init = WM_manipulatorgroup_keymap_common;
+ }
+
+ /* add the type for future created areas of the same type */
+ BLI_addtail(&mmaptype->manipulator_grouptypes, mgrouptype);
+ return mgrouptype;
+}
+
+/**
+ * Use this for registering manipulators on runtime.
+ */
+wmManipulatorGroupType *WM_manipulatorgrouptype_append_runtime(
+ const Main *main, wmManipulatorMapType *mmaptype,
+ void (*mgrouptype_func)(wmManipulatorGroupType *))
+{
+ wmManipulatorGroupType *mgrouptype = WM_manipulatorgrouptype_append(mmaptype, mgrouptype_func);
+
+ /* Main is missing on startup when we create new areas.
+ * So this is only called for manipulators initialized on runtime */
+ WM_manipulatorgrouptype_init_runtime(main, mmaptype, mgrouptype);
+
+ return mgrouptype;
+}
+
+void WM_manipulatorgrouptype_init_runtime(
+ const Main *bmain, wmManipulatorMapType *mmaptype,
+ wmManipulatorGroupType *mgrouptype)
+{
+ /* init keymap - on startup there's an extra call to init keymaps for 'permanent' manipulator-groups */
+ wm_manipulatorgrouptype_keymap_init(mgrouptype, ((wmWindowManager *)bmain->wm.first)->defaultconf);
+
+ /* now create a manipulator for all existing areas */
+ for (bScreen *sc = bmain->screen.first; sc; sc = sc->id.next) {
+ for (ScrArea *sa = sc->areabase.first; sa; sa = sa->next) {
+ for (SpaceLink *sl = sa->spacedata.first; sl; sl = sl->next) {
+ ListBase *lb = (sl == sa->spacedata.first) ? &sa->regionbase : &sl->regionbase;
+ for (ARegion *ar = lb->first; ar; ar = ar->next) {
+ wmManipulatorMap *mmap = ar->manipulator_map;
+ if (mmap->type == mmaptype) {
+ wmManipulatorGroup *mgroup = wm_manipulatorgroup_new_from_type(mgrouptype);
+
+ /* just add here, drawing will occur on next update */
+ BLI_addtail(&mmap->manipulator_groups, mgroup);
+ wm_manipulatormap_set_highlighted_manipulator(mmap, NULL, NULL, 0);
+ ED_region_tag_redraw(ar);
+ }
+ }
+ }
+ }
+ }
+}
+
+void WM_manipulatorgrouptype_unregister(bContext *C, Main *bmain, wmManipulatorGroupType *mgrouptype)
+{
+ for (bScreen *sc = bmain->screen.first; sc; sc = sc->id.next) {
+ for (ScrArea *sa = sc->areabase.first; sa; sa = sa->next) {
+ for (SpaceLink *sl = sa->spacedata.first; sl; sl = sl->next) {
+ ListBase *lb = (sl == sa->spacedata.first) ? &sa->regionbase : &sl->regionbase;
+ for (ARegion *ar = lb->first; ar; ar = ar->next) {
+ wmManipulatorMap *mmap = ar->manipulator_map;
+ wmManipulatorGroup *mgroup, *mgroup_next;
+
+ for (mgroup = mmap->manipulator_groups.first; mgroup; mgroup = mgroup_next) {
+ mgroup_next = mgroup->next;
+ if (mgroup->type == mgrouptype) {
+ wm_manipulatorgroup_free(C, mmap, mgroup);
+ ED_region_tag_redraw(ar);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ wmManipulatorMapType *mmaptype = WM_manipulatormaptype_find(&(const struct wmManipulatorMapType_Params) {
+ mgrouptype->mapidname, mgrouptype->spaceid,
+ mgrouptype->regionid});
+
+ BLI_remlink(&mmaptype->manipulator_grouptypes, mgrouptype);
+ mgrouptype->prev = mgrouptype->next = NULL;
+
+ MEM_freeN(mgrouptype);
+}
+
+void wm_manipulatorgrouptype_keymap_init(wmManipulatorGroupType *mgrouptype, wmKeyConfig *keyconf)
+{
+ mgrouptype->keymap = mgrouptype->keymap_init(mgrouptype, keyconf);
+}
+
+/** \} */ /* wmManipulatorGroupType */
diff --git a/source/blender/windowmanager/manipulators/intern/wm_manipulatormap.c b/source/blender/windowmanager/manipulators/intern/wm_manipulatormap.c
new file mode 100644
index 00000000000..500092f5f2d
--- /dev/null
+++ b/source/blender/windowmanager/manipulators/intern/wm_manipulatormap.c
@@ -0,0 +1,760 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/windowmanager/manipulators/intern/wm_manipulatormap.c
+ * \ingroup wm
+ */
+
+#include <string.h>
+
+#include "BKE_context.h"
+
+#include "BLI_listbase.h"
+#include "BLI_math.h"
+#include "BLI_string.h"
+#include "BLI_ghash.h"
+
+#include "ED_screen.h"
+#include "ED_view3d.h"
+
+#include "GPU_glew.h"
+#include "GPU_select.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+#include "wm_event_system.h"
+
+/* own includes */
+#include "wm_manipulator_wmapi.h"
+#include "wm_manipulator_intern.h"
+
+/**
+ * Store all manipulator-maps here. Anyone who wants to register a manipulator for a certain
+ * area type can query the manipulator-map to do so.
+ */
+static ListBase manipulatormaptypes = {NULL, NULL};
+
+/**
+ * Manipulator-map update tagging.
+ */
+enum eManipulatorMapUpdateFlags {
+ /* Tag manipulator-map for refresh. */
+ MANIPULATORMAP_REFRESH = (1 << 0),
+};
+
+
+/* -------------------------------------------------------------------- */
+/** \name wmManipulatorMap
+ *
+ * \{ */
+
+/**
+ * Creates a manipulator-map with all registered manipulators for that type
+ */
+wmManipulatorMap *WM_manipulatormap_new_from_type(const struct wmManipulatorMapType_Params *mmap_params)
+{
+ wmManipulatorMapType *mmaptype = WM_manipulatormaptype_ensure(mmap_params);
+ wmManipulatorMap *mmap;
+
+ mmap = MEM_callocN(sizeof(wmManipulatorMap), "ManipulatorMap");
+ mmap->type = mmaptype;
+ mmap->update_flag = MANIPULATORMAP_REFRESH;
+
+ /* create all manipulator-groups for this manipulator-map. We may create an empty one
+ * too in anticipation of manipulators from operators etc */
+ for (wmManipulatorGroupType *mgrouptype = mmaptype->manipulator_grouptypes.first;
+ mgrouptype;
+ mgrouptype = mgrouptype->next)
+ {
+ wmManipulatorGroup *mgroup = wm_manipulatorgroup_new_from_type(mgrouptype);
+ BLI_addtail(&mmap->manipulator_groups, mgroup);
+ }
+
+ return mmap;
+}
+
+void wm_manipulatormap_selected_delete(wmManipulatorMap *mmap)
+{
+ MEM_SAFE_FREE(mmap->mmap_context.selected_manipulator);
+ mmap->mmap_context.tot_selected = 0;
+}
+
+void wm_manipulatormap_delete(wmManipulatorMap *mmap)
+{
+ if (!mmap)
+ return;
+
+ for (wmManipulatorGroup *mgroup = mmap->manipulator_groups.first, *mgroup_next; mgroup; mgroup = mgroup_next) {
+ mgroup_next = mgroup->next;
+ wm_manipulatorgroup_free(NULL, mmap, mgroup);
+ }
+ BLI_assert(BLI_listbase_is_empty(&mmap->manipulator_groups));
+
+ wm_manipulatormap_selected_delete(mmap);
+
+ MEM_freeN(mmap);
+}
+
+/**
+ * Creates and returns idname hash table for (visible) manipulators in \a mmap
+ *
+ * \param poll Polling function for excluding manipulators.
+ * \param data Custom data passed to \a poll
+ */
+static GHash *WM_manipulatormap_manipulator_hash_new(
+ const bContext *C, wmManipulatorMap *mmap,
+ bool (*poll)(const wmManipulator *, void *),
+ void *data, const bool include_hidden)
+{
+ GHash *hash = BLI_ghash_str_new(__func__);
+
+ /* collect manipulators */
+ for (wmManipulatorGroup *mgroup = mmap->manipulator_groups.first; mgroup; mgroup = mgroup->next) {
+ if (!mgroup->type->poll || mgroup->type->poll(C, mgroup->type)) {
+ for (wmManipulator *manipulator = mgroup->manipulators.first;
+ manipulator;
+ manipulator = manipulator->next)
+ {
+ if ((include_hidden || (manipulator->flag & WM_MANIPULATOR_HIDDEN) == 0) &&
+ (!poll || poll(manipulator, data)))
+ {
+ BLI_ghash_insert(hash, manipulator->idname, manipulator);
+ }
+ }
+ }
+ }
+
+ return hash;
+}
+
+void WM_manipulatormap_tag_refresh(wmManipulatorMap *mmap)
+{
+ if (mmap) {
+ mmap->update_flag |= MANIPULATORMAP_REFRESH;
+ }
+}
+
+static void manipulatormap_tag_updated(wmManipulatorMap *mmap)
+{
+ mmap->update_flag = 0;
+}
+
+static bool manipulator_prepare_drawing(
+ wmManipulatorMap *mmap, wmManipulator *manipulator,
+ const bContext *C, ListBase *draw_manipulators)
+{
+ if (!wm_manipulator_is_visible(manipulator)) {
+ /* skip */
+ }
+ else {
+ wm_manipulator_update(manipulator, C, (mmap->update_flag & MANIPULATORMAP_REFRESH) != 0);
+ BLI_addhead(draw_manipulators, BLI_genericNodeN(manipulator));
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * Update manipulators of \a mmap to prepare for drawing. Adds all manipulators that
+ * should be drawn to list \a draw_manipulators, note that added items need freeing.
+ */
+static void manipulatormap_prepare_drawing(
+ wmManipulatorMap *mmap, const bContext *C, ListBase *draw_manipulators, const int drawstep)
+{
+ if (!mmap || BLI_listbase_is_empty(&mmap->manipulator_groups))
+ return;
+ wmManipulator *active_manipulator = mmap->mmap_context.active_manipulator;
+
+ /* only active manipulator needs updating */
+ if (active_manipulator) {
+ if (manipulator_prepare_drawing(mmap, active_manipulator, C, draw_manipulators)) {
+ manipulatormap_tag_updated(mmap);
+ }
+ /* don't draw any other manipulators */
+ return;
+ }
+
+ for (wmManipulatorGroup *mgroup = mmap->manipulator_groups.first; mgroup; mgroup = mgroup->next) {
+ /* check group visibility - drawstep first to avoid unnecessary call of group poll callback */
+ if (!wm_manipulatorgroup_is_visible_in_drawstep(mgroup, drawstep) ||
+ !wm_manipulatorgroup_is_visible(mgroup, C))
+ {
+ continue;
+ }
+
+ /* needs to be initialized on first draw */
+ wm_manipulatorgroup_ensure_initialized(mgroup, C);
+ /* update data if needed */
+ /* XXX weak: Manipulator-group may skip refreshing if it's invisible (map gets untagged nevertheless) */
+ if (mmap->update_flag & MANIPULATORMAP_REFRESH && mgroup->type->refresh) {
+ mgroup->type->refresh(C, mgroup);
+ }
+ /* prepare drawing */
+ if (mgroup->type->draw_prepare) {
+ mgroup->type->draw_prepare(C, mgroup);
+ }
+
+ for (wmManipulator *manipulator = mgroup->manipulators.first; manipulator; manipulator = manipulator->next) {
+ manipulator_prepare_drawing(mmap, manipulator, C, draw_manipulators);
+ }
+ }
+
+ manipulatormap_tag_updated(mmap);
+}
+
+/**
+ * Draw all visible manipulators in \a mmap.
+ * Uses global draw_manipulators listbase.
+ */
+static void manipulators_draw_list(const wmManipulatorMap *mmap, const bContext *C, ListBase *draw_manipulators)
+{
+ if (!mmap)
+ return;
+ BLI_assert(!BLI_listbase_is_empty(&mmap->manipulator_groups));
+
+ /* draw_manipulators contains all visible manipulators - draw them */
+ for (LinkData *link = draw_manipulators->first, *link_next; link; link = link_next) {
+ wmManipulator *manipulator = link->data;
+ link_next = link->next;
+
+ manipulator->draw(C, manipulator);
+ /* free/remove manipulator link after drawing */
+ BLI_freelinkN(draw_manipulators, link);
+ }
+}
+
+void WM_manipulatormap_draw(wmManipulatorMap *mmap, const bContext *C, const int drawstep)
+{
+ ListBase draw_manipulators = {NULL};
+
+ manipulatormap_prepare_drawing(mmap, C, &draw_manipulators, drawstep);
+ manipulators_draw_list(mmap, C, &draw_manipulators);
+ BLI_assert(BLI_listbase_is_empty(&draw_manipulators));
+}
+
+static void manipulator_find_active_3D_loop(const bContext *C, ListBase *visible_manipulators)
+{
+ int selectionbase = 0;
+ wmManipulator *manipulator;
+
+ for (LinkData *link = visible_manipulators->first; link; link = link->next) {
+ manipulator = link->data;
+ /* pass the selection id shifted by 8 bits. Last 8 bits are used for selected manipulator part id */
+ manipulator->render_3d_intersection(C, manipulator, selectionbase << 8);
+
+ selectionbase++;
+ }
+}
+
+static int manipulator_find_intersected_3D_intern(
+ ListBase *visible_manipulators, const bContext *C, const int co[2],
+ const float hotspot)
+{
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
+ View3D *v3d = sa->spacedata.first;
+ RegionView3D *rv3d = ar->regiondata;
+ rctf rect, selrect;
+ GLuint buffer[64]; // max 4 items per select, so large enuf
+ short hits;
+ const bool do_passes = GPU_select_query_check_active();
+
+ extern void view3d_winmatrix_set(ARegion *ar, View3D *v3d, rctf *rect);
+
+
+ rect.xmin = co[0] - hotspot;
+ rect.xmax = co[0] + hotspot;
+ rect.ymin = co[1] - hotspot;
+ rect.ymax = co[1] + hotspot;
+
+ selrect = rect;
+
+ view3d_winmatrix_set(ar, v3d, &rect);
+ mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat);
+
+ if (do_passes)
+ GPU_select_begin(buffer, ARRAY_SIZE(buffer), &selrect, GPU_SELECT_NEAREST_FIRST_PASS, 0);
+ else
+ GPU_select_begin(buffer, ARRAY_SIZE(buffer), &selrect, GPU_SELECT_ALL, 0);
+ /* do the drawing */
+ manipulator_find_active_3D_loop(C, visible_manipulators);
+
+ hits = GPU_select_end();
+
+ if (do_passes) {
+ GPU_select_begin(buffer, ARRAY_SIZE(buffer), &selrect, GPU_SELECT_NEAREST_SECOND_PASS, hits);
+ manipulator_find_active_3D_loop(C, visible_manipulators);
+ GPU_select_end();
+ }
+
+ view3d_winmatrix_set(ar, v3d, NULL);
+ mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat);
+
+ return hits > 0 ? buffer[3] : -1;
+}
+
+/**
+ * Try to find a 3D manipulator at screen-space coordinate \a co. Uses OpenGL picking.
+ */
+static wmManipulator *manipulator_find_intersected_3D(
+ bContext *C, const int co[2], ListBase *visible_manipulators,
+ unsigned char *part)
+{
+ wmManipulator *result = NULL;
+ const float hotspot = 14.0f;
+ int ret;
+
+ *part = 0;
+ /* set up view matrices */
+ view3d_operator_needs_opengl(C);
+
+ ret = manipulator_find_intersected_3D_intern(visible_manipulators, C, co, 0.5f * hotspot);
+
+ if (ret != -1) {
+ LinkData *link;
+ int retsec;
+ retsec = manipulator_find_intersected_3D_intern(visible_manipulators, C, co, 0.2f * hotspot);
+
+ if (retsec != -1)
+ ret = retsec;
+
+ link = BLI_findlink(visible_manipulators, ret >> 8);
+ *part = ret & 255;
+ result = link->data;
+ }
+
+ return result;
+}
+
+/**
+ * Try to find a manipulator under the mouse position. 2D intersections have priority over
+ * 3D ones (could check for smallest screen-space distance but not needed right now).
+ */
+wmManipulator *wm_manipulatormap_find_highlighted_manipulator(
+ wmManipulatorMap *mmap, bContext *C, const wmEvent *event,
+ unsigned char *part)
+{
+ wmManipulator *manipulator = NULL;
+ ListBase visible_3d_manipulators = {NULL};
+
+ for (wmManipulatorGroup *mgroup = mmap->manipulator_groups.first; mgroup; mgroup = mgroup->next) {
+ if (wm_manipulatorgroup_is_visible(mgroup, C)) {
+ if (mgroup->type->flag & WM_MANIPULATORGROUPTYPE_IS_3D) {
+ wm_manipulatorgroup_intersectable_manipulators_to_list(mgroup, &visible_3d_manipulators);
+ }
+ else if ((manipulator = wm_manipulatorgroup_find_intersected_mainpulator(mgroup, C, event, part))) {
+ break;
+ }
+ }
+ }
+
+ if (!BLI_listbase_is_empty(&visible_3d_manipulators)) {
+ manipulator = manipulator_find_intersected_3D(C, event->mval, &visible_3d_manipulators, part);
+ BLI_freelistN(&visible_3d_manipulators);
+ }
+
+ return manipulator;
+}
+
+void WM_manipulatormap_add_handlers(ARegion *ar, wmManipulatorMap *mmap)
+{
+ wmEventHandler *handler = MEM_callocN(sizeof(wmEventHandler), "manipulator handler");
+
+ BLI_assert(mmap == ar->manipulator_map);
+ handler->manipulator_map = mmap;
+ BLI_addtail(&ar->handlers, handler);
+}
+
+void wm_manipulatormaps_handled_modal_update(
+ bContext *C, wmEvent *event, wmEventHandler *handler,
+ const wmOperatorType *ot)
+{
+ const bool modal_running = (handler->op != NULL);
+
+ /* happens on render or when joining areas */
+ if (!handler->op_region || !handler->op_region->manipulator_map)
+ return;
+
+ /* hide operator manipulators */
+ if (!modal_running && ot->mgrouptype) {
+ ot->mgrouptype->op = NULL;
+ }
+
+ wmManipulatorMap *mmap = handler->op_region->manipulator_map;
+ wmManipulator *manipulator = wm_manipulatormap_get_active_manipulator(mmap);
+ ScrArea *area = CTX_wm_area(C);
+ ARegion *region = CTX_wm_region(C);
+
+ wm_manipulatormap_handler_context(C, handler);
+
+ /* regular update for running operator */
+ if (modal_running) {
+ if (manipulator && manipulator->handler && manipulator->opname &&
+ STREQ(manipulator->opname, handler->op->idname))
+ {
+ manipulator->handler(C, event, manipulator, 0);
+ }
+ }
+ /* operator not running anymore */
+ else {
+ wm_manipulatormap_set_highlighted_manipulator(mmap, C, NULL, 0);
+ wm_manipulatormap_set_active_manipulator(mmap, C, event, NULL);
+ }
+
+ /* restore the area */
+ CTX_wm_area_set(C, area);
+ CTX_wm_region_set(C, region);
+}
+
+/**
+ * Deselect all selected manipulators in \a mmap.
+ * \return if selection has changed.
+ */
+bool wm_manipulatormap_deselect_all(wmManipulatorMap *mmap, wmManipulator ***sel)
+{
+ if (*sel == NULL || mmap->mmap_context.tot_selected == 0)
+ return false;
+
+ for (int i = 0; i < mmap->mmap_context.tot_selected; i++) {
+ (*sel)[i]->state &= ~WM_MANIPULATOR_SELECTED;
+ (*sel)[i] = NULL;
+ }
+ wm_manipulatormap_selected_delete(mmap);
+
+ /* always return true, we already checked
+ * if there's anything to deselect */
+ return true;
+}
+
+BLI_INLINE bool manipulator_selectable_poll(const wmManipulator *manipulator, void *UNUSED(data))
+{
+ return (manipulator->mgroup->type->flag & WM_MANIPULATORGROUPTYPE_SELECTABLE);
+}
+
+/**
+ * Select all selectable manipulators in \a mmap.
+ * \return if selection has changed.
+ */
+static bool wm_manipulatormap_select_all_intern(
+ bContext *C, wmManipulatorMap *mmap, wmManipulator ***sel,
+ const int action)
+{
+ /* GHash is used here to avoid having to loop over all manipulators twice (once to
+ * get tot_sel for allocating, once for actually selecting). Instead we collect
+ * selectable manipulators in hash table and use this to get tot_sel and do selection */
+
+ GHash *hash = WM_manipulatormap_manipulator_hash_new(C, mmap, manipulator_selectable_poll, NULL, true);
+ GHashIterator gh_iter;
+ int i, *tot_sel = &mmap->mmap_context.tot_selected;
+ bool changed = false;
+
+ *tot_sel = BLI_ghash_size(hash);
+ *sel = MEM_reallocN(*sel, sizeof(**sel) * (*tot_sel));
+
+ GHASH_ITER_INDEX (gh_iter, hash, i) {
+ wmManipulator *manipulator_iter = BLI_ghashIterator_getValue(&gh_iter);
+
+ if ((manipulator_iter->state & WM_MANIPULATOR_SELECTED) == 0) {
+ changed = true;
+ }
+ manipulator_iter->state |= WM_MANIPULATOR_SELECTED;
+ if (manipulator_iter->select) {
+ manipulator_iter->select(C, manipulator_iter, action);
+ }
+ (*sel)[i] = manipulator_iter;
+ BLI_assert(i < (*tot_sel));
+ }
+ /* highlight first manipulator */
+ wm_manipulatormap_set_highlighted_manipulator(mmap, C, (*sel)[0], (*sel)[0]->highlighted_part);
+
+ BLI_ghash_free(hash, NULL, NULL);
+ return changed;
+}
+
+/**
+ * Select/Deselect all selectable manipulators in \a mmap.
+ * \return if selection has changed.
+ *
+ * TODO select all by type
+ */
+bool WM_manipulatormap_select_all(bContext *C, wmManipulatorMap *mmap, const int action)
+{
+ wmManipulator ***sel = &mmap->mmap_context.selected_manipulator;
+ bool changed = false;
+
+ switch (action) {
+ case SEL_SELECT:
+ changed = wm_manipulatormap_select_all_intern(C, mmap, sel, action);
+ break;
+ case SEL_DESELECT:
+ changed = wm_manipulatormap_deselect_all(mmap, sel);
+ break;
+ default:
+ BLI_assert(0);
+ break;
+ }
+
+ if (changed)
+ WM_event_add_mousemove(C);
+
+ return changed;
+}
+
+/**
+ * Prepare context for manipulator handling (but only if area/region is
+ * part of screen). Version of #wm_handler_op_context for manipulators.
+ */
+void wm_manipulatormap_handler_context(bContext *C, wmEventHandler *handler)
+{
+ bScreen *screen = CTX_wm_screen(C);
+
+ if (screen) {
+ if (handler->op_area == NULL) {
+ /* do nothing in this context */
+ }
+ else {
+ ScrArea *sa;
+
+ for (sa = screen->areabase.first; sa; sa = sa->next)
+ if (sa == handler->op_area)
+ break;
+ if (sa == NULL) {
+ /* when changing screen layouts with running modal handlers (like render display), this
+ * is not an error to print */
+ if (handler->manipulator_map == NULL)
+ printf("internal error: modal manipulator-map handler has invalid area\n");
+ }
+ else {
+ ARegion *ar;
+ CTX_wm_area_set(C, sa);
+ for (ar = sa->regionbase.first; ar; ar = ar->next)
+ if (ar == handler->op_region)
+ break;
+ /* XXX no warning print here, after full-area and back regions are remade */
+ if (ar)
+ CTX_wm_region_set(C, ar);
+ }
+ }
+ }
+}
+
+bool WM_manipulatormap_cursor_set(const wmManipulatorMap *mmap, wmWindow *win)
+{
+ for (; mmap; mmap = mmap->next) {
+ wmManipulator *manipulator = mmap->mmap_context.highlighted_manipulator;
+ if (manipulator && manipulator->get_cursor) {
+ WM_cursor_set(win, manipulator->get_cursor(manipulator));
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void wm_manipulatormap_set_highlighted_manipulator(
+ wmManipulatorMap *mmap, const bContext *C, wmManipulator *manipulator,
+ unsigned char part)
+{
+ if ((manipulator != mmap->mmap_context.highlighted_manipulator) ||
+ (manipulator && part != manipulator->highlighted_part))
+ {
+ if (mmap->mmap_context.highlighted_manipulator) {
+ mmap->mmap_context.highlighted_manipulator->state &= ~WM_MANIPULATOR_HIGHLIGHT;
+ mmap->mmap_context.highlighted_manipulator->highlighted_part = 0;
+ }
+
+ mmap->mmap_context.highlighted_manipulator = manipulator;
+
+ if (manipulator) {
+ manipulator->state |= WM_MANIPULATOR_HIGHLIGHT;
+ manipulator->highlighted_part = part;
+
+ if (C && manipulator->get_cursor) {
+ wmWindow *win = CTX_wm_window(C);
+ WM_cursor_set(win, manipulator->get_cursor(manipulator));
+ }
+ }
+ else {
+ if (C) {
+ wmWindow *win = CTX_wm_window(C);
+ WM_cursor_set(win, CURSOR_STD);
+ }
+ }
+
+ /* tag the region for redraw */
+ if (C) {
+ ARegion *ar = CTX_wm_region(C);
+ ED_region_tag_redraw(ar);
+ }
+ }
+}
+
+wmManipulator *wm_manipulatormap_get_highlighted_manipulator(wmManipulatorMap *mmap)
+{
+ return mmap->mmap_context.highlighted_manipulator;
+}
+
+void wm_manipulatormap_set_active_manipulator(
+ wmManipulatorMap *mmap, bContext *C, const wmEvent *event, wmManipulator *manipulator)
+{
+ if (manipulator && C) {
+ manipulator->state |= WM_MANIPULATOR_ACTIVE;
+ mmap->mmap_context.active_manipulator = manipulator;
+
+ if (manipulator->opname) {
+ wmOperatorType *ot = WM_operatortype_find(manipulator->opname, 0);
+
+ if (ot) {
+ /* first activate the manipulator itself */
+ if (manipulator->invoke && manipulator->handler) {
+ manipulator->invoke(C, event, manipulator);
+ }
+
+ WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &manipulator->opptr);
+
+ /* we failed to hook the manipulator to the operator handler or operator was cancelled, return */
+ if (!mmap->mmap_context.active_manipulator) {
+ manipulator->state &= ~WM_MANIPULATOR_ACTIVE;
+ /* first activate the manipulator itself */
+ if (manipulator->interaction_data) {
+ MEM_freeN(manipulator->interaction_data);
+ manipulator->interaction_data = NULL;
+ }
+ }
+ return;
+ }
+ else {
+ printf("Manipulator error: operator not found");
+ mmap->mmap_context.active_manipulator = NULL;
+ return;
+ }
+ }
+ else {
+ if (manipulator->invoke && manipulator->handler) {
+ manipulator->invoke(C, event, manipulator);
+ }
+ }
+ WM_cursor_grab_enable(CTX_wm_window(C), true, true, NULL);
+ }
+ else {
+ manipulator = mmap->mmap_context.active_manipulator;
+
+
+ /* deactivate, manipulator but first take care of some stuff */
+ if (manipulator) {
+ manipulator->state &= ~WM_MANIPULATOR_ACTIVE;
+ /* first activate the manipulator itself */
+ if (manipulator->interaction_data) {
+ MEM_freeN(manipulator->interaction_data);
+ manipulator->interaction_data = NULL;
+ }
+ }
+ mmap->mmap_context.active_manipulator = NULL;
+
+ if (C) {
+ WM_cursor_grab_disable(CTX_wm_window(C), NULL);
+ ED_region_tag_redraw(CTX_wm_region(C));
+ WM_event_add_mousemove(C);
+ }
+ }
+}
+
+wmManipulator *wm_manipulatormap_get_active_manipulator(wmManipulatorMap *mmap)
+{
+ return mmap->mmap_context.active_manipulator;
+}
+
+/** \} */ /* wmManipulatorMap */
+
+
+/* -------------------------------------------------------------------- */
+/** \name wmManipulatorMapType
+ *
+ * \{ */
+
+wmManipulatorMapType *WM_manipulatormaptype_find(
+ const struct wmManipulatorMapType_Params *mmap_params)
+{
+ for (wmManipulatorMapType *mmaptype = manipulatormaptypes.first; mmaptype; mmaptype = mmaptype->next) {
+ if (mmaptype->spaceid == mmap_params->spaceid &&
+ mmaptype->regionid == mmap_params->regionid &&
+ STREQ(mmaptype->idname, mmap_params->idname))
+ {
+ return mmaptype;
+ }
+ }
+
+ return NULL;
+}
+
+wmManipulatorMapType *WM_manipulatormaptype_ensure(
+ const struct wmManipulatorMapType_Params *mmap_params)
+{
+ wmManipulatorMapType *mmaptype = WM_manipulatormaptype_find(mmap_params);
+
+ if (mmaptype) {
+ return mmaptype;
+ }
+
+ mmaptype = MEM_callocN(sizeof(wmManipulatorMapType), "manipulatortype list");
+ mmaptype->spaceid = mmap_params->spaceid;
+ mmaptype->regionid = mmap_params->regionid;
+ BLI_strncpy(mmaptype->idname, mmap_params->idname, sizeof(mmaptype->idname));
+ BLI_addhead(&manipulatormaptypes, mmaptype);
+
+ return mmaptype;
+}
+
+void wm_manipulatormaptypes_free(void)
+{
+ for (wmManipulatorMapType *mmaptype = manipulatormaptypes.first; mmaptype; mmaptype = mmaptype->next) {
+ BLI_freelistN(&mmaptype->manipulator_grouptypes);
+ }
+ BLI_freelistN(&manipulatormaptypes);
+}
+
+/**
+ * Initialize keymaps for all existing manipulator-groups
+ */
+void wm_manipulators_keymap(wmKeyConfig *keyconf)
+{
+ wmManipulatorMapType *mmaptype;
+ wmManipulatorGroupType *mgrouptype;
+
+ /* we add this item-less keymap once and use it to group manipulator-group keymaps into it */
+ WM_keymap_find(keyconf, "Manipulators", 0, 0);
+
+ for (mmaptype = manipulatormaptypes.first; mmaptype; mmaptype = mmaptype->next) {
+ for (mgrouptype = mmaptype->manipulator_grouptypes.first; mgrouptype; mgrouptype = mgrouptype->next) {
+ wm_manipulatorgrouptype_keymap_init(mgrouptype, keyconf);
+ }
+ }
+}
+
+/** \} */ /* wmManipulatorMapType */
+
diff --git a/source/blender/windowmanager/manipulators/wm_manipulator_wmapi.h b/source/blender/windowmanager/manipulators/wm_manipulator_wmapi.h
new file mode 100644
index 00000000000..c5008cef896
--- /dev/null
+++ b/source/blender/windowmanager/manipulators/wm_manipulator_wmapi.h
@@ -0,0 +1,90 @@
+/*
+ * ***** 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) 2016 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/windowmanager/manipulators/wm_manipulator_wmapi.h
+ * \ingroup wm
+ *
+ * \name Manipulators Window Manager API
+ * API for usage in window manager code only. It should contain all functionality
+ * needed to hook up the manipulator system with Blender's window manager. It's
+ * mostly the event system that needs to communicate with manipulator code.
+ *
+ * Only included in wm.h and lower level files.
+ */
+
+
+#ifndef __WM_MANIPULATOR_WMAPI_H__
+#define __WM_MANIPULATOR_WMAPI_H__
+
+struct wmEventHandler;
+struct wmManipulatorMap;
+struct wmOperatorType;
+struct wmOperator;
+
+
+/* -------------------------------------------------------------------- */
+/* wmManipulator */
+
+typedef void (*wmManipulatorSelectFunc)(struct bContext *, struct wmManipulator *, const int);
+
+struct wmManipulatorGroup *wm_manipulator_get_parent_group(const struct wmManipulator *manipulator);
+
+/* -------------------------------------------------------------------- */
+/* wmManipulatorGroup */
+
+void MANIPULATORGROUP_OT_manipulator_select(struct wmOperatorType *ot);
+void MANIPULATORGROUP_OT_manipulator_tweak(struct wmOperatorType *ot);
+
+void wm_manipulatorgroup_attach_to_modal_handler(
+ struct bContext *C, struct wmEventHandler *handler,
+ struct wmManipulatorGroupType *mgrouptype, struct wmOperator *op);
+
+/* -------------------------------------------------------------------- */
+/* wmManipulatorMap */
+
+void wm_manipulatormap_delete(struct wmManipulatorMap *mmap);
+void wm_manipulatormaptypes_free(void);
+
+void wm_manipulators_keymap(struct wmKeyConfig *keyconf);
+
+void wm_manipulatormaps_handled_modal_update(
+ bContext *C, struct wmEvent *event, struct wmEventHandler *handler,
+ const struct wmOperatorType *ot);
+void wm_manipulatormap_handler_context(bContext *C, struct wmEventHandler *handler);
+
+struct wmManipulator *wm_manipulatormap_find_highlighted_manipulator(
+ struct wmManipulatorMap *mmap, bContext *C,
+ const struct wmEvent *event, unsigned char *part);
+void wm_manipulatormap_set_highlighted_manipulator(
+ struct wmManipulatorMap *mmap, const bContext *C,
+ struct wmManipulator *manipulator, unsigned char part);
+struct wmManipulator *wm_manipulatormap_get_highlighted_manipulator(struct wmManipulatorMap *mmap);
+void wm_manipulatormap_set_active_manipulator(
+ struct wmManipulatorMap *mmap, bContext *C,
+ const struct wmEvent *event, struct wmManipulator *manipulator);
+struct wmManipulator *wm_manipulatormap_get_active_manipulator(struct wmManipulatorMap *mmap);
+
+#endif /* __WM_MANIPULATOR_WMAPI_H__ */
+
diff --git a/source/blender/windowmanager/wm.h b/source/blender/windowmanager/wm.h
index 2f06ddab1e8..3dd294128e2 100644
--- a/source/blender/windowmanager/wm.h
+++ b/source/blender/windowmanager/wm.h
@@ -34,6 +34,8 @@
struct wmWindow;
struct ReportList;
+#include "manipulators/wm_manipulator_wmapi.h"
+
typedef struct wmPaintCursor {
struct wmPaintCursor *next, *prev;
diff --git a/source/blender/windowmanager/wm_event_system.h b/source/blender/windowmanager/wm_event_system.h
index efc01b1f8a8..abab7c55f44 100644
--- a/source/blender/windowmanager/wm_event_system.h
+++ b/source/blender/windowmanager/wm_event_system.h
@@ -68,7 +68,8 @@ typedef struct wmEventHandler {
/* drop box handler */
ListBase *dropboxes;
-
+ /* manipulator handler */
+ struct wmManipulatorMap *manipulator_map;
} wmEventHandler;
/* custom types for handlers, for signalling, freeing */
diff --git a/source/blender/windowmanager/wm_event_types.h b/source/blender/windowmanager/wm_event_types.h
index 3085f138846..9d34bc24e6c 100644
--- a/source/blender/windowmanager/wm_event_types.h
+++ b/source/blender/windowmanager/wm_event_types.h
@@ -339,6 +339,8 @@ enum {
EVT_DROP = 0x5023,
EVT_BUT_CANCEL = 0x5024,
+ /* could become manipulator callback */
+ EVT_MANIPULATOR_UPDATE = 0x5025,
/* ********** End of Blender internal events. ********** */
};
diff --git a/source/blenderplayer/bad_level_call_stubs/CMakeLists.txt b/source/blenderplayer/bad_level_call_stubs/CMakeLists.txt
index 0e570e19258..d2c2129532a 100644
--- a/source/blenderplayer/bad_level_call_stubs/CMakeLists.txt
+++ b/source/blenderplayer/bad_level_call_stubs/CMakeLists.txt
@@ -35,11 +35,12 @@ set(INC
../../blender/blenloader
../../blender/makesdna
../../blender/makesrna
+ ../../../intern/glew-mx
../../../intern/guardedalloc
)
set(INC_SYS
-
+ ${GLEW_INCLUDE_PATH}
)
set(SRC
diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c
index d8a4ddc8d4f..aabcad65750 100644
--- a/source/blenderplayer/bad_level_call_stubs/stubs.c
+++ b/source/blenderplayer/bad_level_call_stubs/stubs.c
@@ -165,7 +165,6 @@ struct wmWindowManager;
#include "../blender/editors/include/ED_mesh.h"
#include "../blender/editors/include/ED_node.h"
#include "../blender/editors/include/ED_object.h"
-#include "../blender/editors/include/ED_particle.h"
#include "../blender/editors/include/ED_render.h"
#include "../blender/editors/include/ED_screen.h"
#include "../blender/editors/include/ED_space_api.h"
@@ -179,6 +178,8 @@ struct wmWindowManager;
#include "../blender/editors/include/UI_resources.h"
#include "../blender/editors/include/UI_view2d.h"
#include "../blender/freestyle/FRS_freestyle.h"
+#include "../blender/gpu/GPU_immediate.h"
+#include "../blender/gpu/GPU_matrix.h"
#include "../blender/python/BPY_extern.h"
#include "../blender/render/extern/include/RE_engine.h"
#include "../blender/render/extern/include/RE_pipeline.h"
@@ -410,9 +411,6 @@ void ED_fsmenu_entry_set_path(struct FSMenuEntry *fsentry, const char *name) RET
char *ED_fsmenu_entry_get_name(struct FSMenuEntry *fsentry) RET_NULL
void ED_fsmenu_entry_set_name(struct FSMenuEntry *fsentry, const char *name) RET_NONE
-struct PTCacheEdit *PE_get_current(struct Scene *scene, struct Object *ob) RET_NULL
-void PE_current_changed(struct Scene *scene, struct Object *ob) RET_NONE
-
/* rna keymap */
struct wmKeyMap *WM_keymap_active(struct wmWindowManager *wm, struct wmKeyMap *keymap) RET_NULL
struct wmKeyMap *WM_keymap_find(struct wmKeyConfig *keyconf, const char *idname, int spaceid, int regionid) RET_NULL
@@ -536,7 +534,6 @@ bool ED_space_image_check_show_maskedit(struct Scene *scene, struct SpaceImage *
bool ED_texture_context_check_world(const struct bContext *C) RET_ZERO
bool ED_texture_context_check_material(const struct bContext *C) RET_ZERO
bool ED_texture_context_check_lamp(const struct bContext *C) RET_ZERO
-bool ED_texture_context_check_particles(const struct bContext *C) RET_ZERO
bool ED_texture_context_check_others(const struct bContext *C) RET_ZERO
bool ED_text_region_location_from_cursor(SpaceText *st, ARegion *ar, const int cursor_co[2], int r_pixel_co[2]) RET_ZERO
@@ -783,4 +780,13 @@ void COM_execute(RenderData *rd, Scene *scene, bNodeTree *editingtree, int rende
bool RE_RenderResult_is_stereo(RenderResult *res) RET_ZERO
void uiTemplateImageViews(uiLayout *layout, struct PointerRNA *imfptr) RET_NONE
+/* GPU */
+void gpuMatrixBegin3D_legacy(void) RET_NONE
+void gpuMatrixEnd() RET_NONE
+void gpuMultMatrix3D(const float m[4][4]) RET_NONE
+void gpuTranslate3fv(const float vec[3]) RET_NONE
+void gpuScale3fv(const float vec[3]) RET_NONE
+void gpuRotateAxis(float deg, char axis) RET_NONE
+void immBindBuiltinProgram(GPUBuiltinShader shader_id) RET_NONE
+
#endif // WITH_GAMEENGINE
diff --git a/source/creator/creator.c b/source/creator/creator.c
index a59a45f885c..076be40ce94 100644
--- a/source/creator/creator.c
+++ b/source/creator/creator.c
@@ -64,7 +64,6 @@
#include "BKE_node.h"
#include "BKE_sound.h"
#include "BKE_image.h"
-#include "BKE_particle.h"
#include "IMB_imbuf.h" /* for IMB_init */
@@ -402,7 +401,6 @@ int main(
RE_engines_init();
init_nodesystem();
- psys_init_rng();
/* end second init */
diff --git a/source/creator/creator_args.c b/source/creator/creator_args.c
index c3c76a0d1d3..21586d162e5 100644
--- a/source/creator/creator_args.c
+++ b/source/creator/creator_args.c
@@ -1186,13 +1186,13 @@ static int arg_handle_depsgraph_use_new(int UNUSED(argc), const char **UNUSED(ar
return 0;
}
-static const char arg_handle_basic_shader_glsl_use_new_doc[] =
-"\n\tUse new GLSL basic shader"
+static const char arg_handle_basic_shader_use_legacy_doc[] =
+"\n\tUse legacy (non-GLSL) basic shader"
;
-static int arg_handle_basic_shader_glsl_use_new(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
+static int arg_handle_basic_shader_use_legacy(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
{
- printf("Using new GLSL basic shader.\n");
- GPU_basic_shader_use_glsl_set(true);
+ printf("Using legacy (non-GLSL) basic shader.\n");
+ GPU_basic_shader_use_glsl_set(false);
return 0;
}
@@ -1830,7 +1830,7 @@ void main_args_setup(bContext *C, bArgs *ba, SYS_SystemHandle *syshandle)
CB_EX(arg_handle_debug_mode_generic_set, gpumem), (void *)G_DEBUG_GPU_MEM);
BLI_argsAdd(ba, 1, NULL, "--enable-new-depsgraph", CB(arg_handle_depsgraph_use_new), NULL);
- BLI_argsAdd(ba, 1, NULL, "--enable-new-basic-shader-glsl", CB(arg_handle_basic_shader_glsl_use_new), NULL);
+ BLI_argsAdd(ba, 1, NULL, "--enable-legacy-basic-shader", CB(arg_handle_basic_shader_use_legacy), NULL);
BLI_argsAdd(ba, 1, NULL, "--verbose", CB(arg_handle_verbosity_set), NULL);
diff --git a/source/gameengine/Ketsji/BL_BlenderShader.cpp b/source/gameengine/Ketsji/BL_BlenderShader.cpp
index f112ec54e8a..fd9a038143c 100644
--- a/source/gameengine/Ketsji/BL_BlenderShader.cpp
+++ b/source/gameengine/Ketsji/BL_BlenderShader.cpp
@@ -169,7 +169,7 @@ void BL_BlenderShader::Update(const RAS_MeshSlot & ms, RAS_IRasterizer* rasty )
rasty->GetViewMatrix().getValue(&viewmat[0][0]);
float auto_bump_scale = ms.m_pDerivedMesh!=0 ? ms.m_pDerivedMesh->auto_bump_scale : 1.0f;
- GPU_material_bind_uniforms(gpumat, obmat, viewmat, obcol, auto_bump_scale, NULL);
+ GPU_material_bind_uniforms(gpumat, obmat, viewmat, obcol, auto_bump_scale);
mAlphaBlend = GPU_material_alpha_blend(gpumat, obcol);
}